There is a great way to get the current user's AppData folder path:

string applicationDataPath = Environment.GetFolderPath( Environment.SpecialFolder.ApplicationData); 

The method is good because it does not depend on the real location of the user folder, the OS version and the like.

Actually, I would like to see a way to get the path to AppData not only for the current user, but for anyone, if I have this user's login line.

    1 answer 1

    The task was harder than expected :-)

    First of all, you need to use P / Invoke, there is no built-in .NET path. For example, you can use the SHGetKnownFolderPath function with a suitable KNOWNFOLDERID . It connects like this .

    You will need AccessToken , which can be obtained using the LogonUser function as described in the example here :

     public class FolderDemo { [DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)] public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken); [DllImport("kernel32.dll", CharSet = CharSet.Auto)] public extern static bool CloseHandle(IntPtr handle); [DllImport("shell32.dll")] public static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath); // If you incorporate this code into a DLL, be sure to demand FullTrust. [PermissionSetAttribute(SecurityAction.Demand, Name = "FullTrust")] public static void Main(string[] args) { // Get the user token for the specified user, domain, and password // using the unmanaged LogonUser method. // The local machine name can be used for the domain name to // impersonate a user on this machine. string domainName = ...; string userName = ...; string userPassword = ...; const int LOGON32_PROVIDER_DEFAULT = 0; //This parameter causes LogonUser to create a primary token. const int LOGON32_LOGON_INTERACTIVE = 2; IntPtr handle; // Call LogonUser to obtain a handle to an access token. bool returnValue = LogonUser(userName, domainName, userPassword, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, out handle); if (!returnValue) return; try { // судя по всему, можно объявить SHGetKnownFolderPath // поинтеллектуальнее, чтобы не понадобилось маршалирование вручную IntPtr pPath; if (SHGetKnownFolderPath(KnownFolder.LocalAppData, 0, handle, out pPath) == 0) { string path = Marshal.PtrToStringUni(pPath); Marshal.FreeCoTaskMem(pPath); // тут строку можно использовать } } finally { // обязательно! а то останемся с правами другого юзера CloseHandle(handle); } } } 

    The KnownFolder class KnownFolder see here , the part you are interested in is:

     public static class KnownFolder { public static readonly Guid LocalAppData = new Guid("F1B32785-6FBA-4FCF-9D55-7B8E7F157091"); public static readonly Guid LocalAppDataLow = new Guid("A520A1A4-1780-4FF6-BD18-167343C5AF16"); public static readonly Guid RoamingAppData = new Guid("3EB685DB-65F9-4CF6-A03A-E3EF65729F3D"); // ... } 

    It seems you can override SHGetKnownFolderPath so that you do not manually call FreeCoTaskMem :

     [DllImport("shell32.dll")] public static extern int SHGetKnownFolderPath( [MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out String path); ... string path; if (SHGetKnownFolderPath(KnownFolder.LocalAppData, 0, handle, out path) == 0) { // тут строку можно использовать } 

    But I am not 100% sure that interop is always full of surprises.

    • It seems that not IntPtr.Zero, and handle. - AlexeyM am
    • @AlexeyM: sure, thanks! For the sake of this handle, in fact, all the previous code and started. Fixed. - VladD