How to get the Local AppData directory for all Windows users within a .NET application

Local AppData is a directory within the Windows operating system where software applications can store data that is specific to the current user. Getting the location of the Local AppData directory for the current user within a .NET application is straightforward. However, currently, there isn’t a .NET API that allows you to get the Local AppData directory for other users.

If you’re looking for a way to get the Local AppData directory for all Windows users from within your .NET application, this post will show how you can achieve this.

Local AppData

As mentioned in the introduction, the Local AppData directory is where application data relating to a specific Windows user is typically located. When developing applications that run natively on Windows devices, it is best practice to store user data here, as opposed to cruder approaches such as creating directories and files at the root of the user’s system drive for example.

Location

A separate Local AppData directory exists for each Windows user and is located within a parent directory called ‘AppData’ which is a hidden item. This means that users will typically not see this directory when browsing through their other user files unless they have changed their view options within File Explorer (or another preferred file manager) to show hidden items.

A typical example of the path to the Local AppData directory for a specific user (Jonathan) is as follows.

C:\Users\Jonathan\AppData\Local

You can access your own version of the Local AppData directory by pasting the following environment variable text either into the File Explorer location bar or into the ‘Run’ dialog (WIN + R).

%localappdata%

Contents

Below is an example of the typical contents of the Local AppData directory.

Local AppData directory sample contents

As you can see from the above screenshot, the Local AppData directory will typically contain sub-directories that represent the name of the software company that is storing the application data. This is a good practice to adhere to when developing your own applications. In other instances the name of the application itself is used as the directory name, sometimes this is the same as the company name.

Current user code

To retrieve the Local AppData directory for the current user in a .NET application, the following code will work just fine.

string localAppDataPath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
 
Console.WriteLine(localAppDataPath);
// Sample output: C:\Users\Jonathan\AppData\Local

However, what if you need to get the Local AppData directory for every user?

To achieve this on Windows devices, we need to turn to the Registry.

Registry

Since .NET doesn’t expose an API for retrieving the Local AppData directory for other users, we will need to retrieve this information from the Windows Registry.

Registry values relating to various Windows ‘Shell Folders’ can be found at the following location within the Registry.

HKEY_USERS\$SID$\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders

Note that $SID$ is a placeholder that represents the Security Identifier of the user. This will be different for each Windows user.

Below is a screenshot of the Registry Editor which shows an example of the Registry values that can typically be found within the ‘Shell Folders’ Registry key.

Registry sample Shell Folders key contents
Registry sample Shell Folders key contents

Note that I have highlighted the ‘Local AppData’ Registry value in the above screenshot and the Security Identifier has been redacted from the Registry path.

The above screenshot shows the Shell Folders for one particular user. To get the Shell Folders for another user we would simply select the Security Identifier for the other user and then navigate down the same path in the Registry.

So how do we pull this data from the Registry in our .NET code?

We’ll look at this in the following section.

Code solution

To retrieve the Local AppData directory for each Windows user, the following C# method can be used.

/// <summary>
/// Gets the Local AppData directory path for all Windows users.
/// </summary>
/// <returns>A collection of Local AppData paths</returns>
public IEnumerable<string> GetLocalAppDataPaths()
{
    if (!OperatingSystem.IsWindows())
    {
        throw new PlatformNotSupportedException("The Registry is only supported on Windows.");
    }
 
    const string shellFoldersKeyName   = @"HKEY_USERS\$SID$\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders";
    const string localAppDataValueName = "Local AppData";
 
    var keys  = Registry.Users.GetSubKeyNames();
    var paths = new List<string>();
 
    foreach (var key in keys)
    {
        var localAppDataPath = Registry.GetValue(
            shellFoldersKeyName.Replace("$SID$", key),
            localAppDataValueName,
            null) as string;
 
        if (!string.IsNullOrWhiteSpace(localAppDataPath))
        {
            paths.Add(localAppDataPath);
        }
    }
 
    return paths;
}

Note that your application must be running with administrative privileges to be able to access the Registry.

Since the Registry is only supported on Windows, the GetLocalAppDataPaths method first of all checks that the code is running on a Windows operating system and if not it throws a PlatformNotSupportedException.

The Registry.Users field is used to get the Security Identifiers for all users via the GetSubKeyNames method.

The Security Identifiers are iterated through and the Registry.GetValue method is used to retrieve a value for the specified key name and value name in the Registry. The last parameter specifies the default value that is returned if a value cannot be found. Providing there is a value, it will be added to a list of paths.

Lastly, the Local AppData directory paths are returned to the caller.

Note that if you were to replace the localAppDataValueName constant and provide a value of ‘AppData’ instead, the code would retrieve the Roaming AppData directory for each user e.g. C:\Users\Jonathan\AppData\Roaming

Output

Below is an example of calling the GetLocalAppDataPaths method and the associated Console output.

var localAppDataPaths = GetLocalAppDataPaths();
 
foreach (var path in localAppDataPaths)
{
    Console.WriteLine(path);
}
// Sample output // ------------------------------- // C:\Users\Jonathan\AppData\Local // C:\Users\David\AppData\Local

A line should be output for each interactive Windows user. You will find that the Registry.Users.GetSubKeyNames method call returns several key names that don’t map to interactive Windows users i.e. users that can physically log in. These other key names are mapped to system users or serve other purposes such as tracking file extension metadata.

Summary

In this post, I covered how to retrieve the Local AppData directory for all users on a Windows device.

I started by discussing what the Local AppData directory is used for and provided examples of its contents, how to get the location of the directory for the current user, and how to view the location of the directory for different users within the Registry.

I then looked at how the location of the Local AppData directory of all Windows users can be retrieved from the Registry within a .NET application, using a C# method that leverages the fields and methods of the Registry class.


I hope you enjoyed this post! Comments are always welcome and I respond to all questions.

If you like my content and it helped you out, please check out the button below 🙂

Comments