1

I need to access contents in the folder %AppData%\Roaming\Microsoft.

This usually works fine by doing the following:

Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "Microsoft");

The problem is that now the explorer lets you change the location of %AppData% by right clicking the Roaming folder and setting the location to some other place. However, this doesn't change the location of the Microsoft folder, which will remain in the original %AppData%.

I've thought about doing something like this:

string roaming = "C:\Users\" + Environment.UserName + @"\AppData\Roaming";

Though this just looks bad and looks like it could break easily. Any suggestions?

FailedShack
  • 91
  • 4
  • 11
  • It's not *all* of the Microsoft folder. Certain folders can't be redirected outside of the roaming profile, such as "Microsoft\Credentials", "Microsoft\Crypto", "Microsoft\Protect", and "Microsoft\System Certificates". If you need these, they're in the default location relative to the user-profile directory: `Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), @"AppData\Roaming")`. That's better than hard-coding "C:\Users\" in the context of roaming user profiles. – Eryk Sun Jun 03 '19 at 18:28
  • @eryksun Yeah, it's precisely the Crypto folder I'm trying to access. – FailedShack Jun 03 '19 at 22:09
  • Note: "AppData\Roaming" is only correct on Vista and later, not XP. – Anders Jun 04 '19 at 01:04

2 Answers2

1

I don't know if .NET can do it but WinAPI can. PInvoke SHGetFolderPath with the SHGFP_TYPE_DEFAULT flag:

using System;
using System.Runtime.InteropServices;

namespace Test { class TestApp {
public class WinApi
{
  public const int CSIDL_APPDATA = 0x1a;
  public const int SHGFP_TYPE_DEFAULT = 1;
  [DllImport("shell32.dll")]
  public static extern int SHGetFolderPath(IntPtr hwnd, int csidl, IntPtr hToken, uint flags, [Out] System.Text.StringBuilder Path);
}

[STAThread]
static void Main() 
{
  System.Text.StringBuilder builder = new System.Text.StringBuilder(260);
  int result = WinApi.SHGetFolderPath(IntPtr.Zero, WinApi.CSIDL_APPDATA, IntPtr.Zero, WinApi.SHGFP_TYPE_DEFAULT, builder);
  string path = "";
  if (result == 0) path = builder.ToString();
  Console.WriteLine(string.Format("{0}:{1}", result, path));
}
} }
Anders
  • 97,548
  • 12
  • 110
  • 164
  • With [`SHGetKnownFolderPath`](https://learn.microsoft.com/en-us/windows/desktop/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath), the flag is `KF_FLAG_DEFAULT_PATH`. This API function requires Vista or later. (Anyone still using long-dead XP, or even Vista, is outside of my scope. I don't have any VMs with these dead systems for testing code.) – Eryk Sun Jun 04 '19 at 09:17
  • Indeed .NET does not currently provide a way to retrieve this information. I noticed there's another overload of `Environment.GetFolderPath`, which internally calls `SHGetKnownFolderPath`, that takes option flags but it's missing the default path one. [I've opened an API proposal for them do add it.](https://github.com/dotnet/corefx/issues/38253).I'm going to mark this as the correct answer, also if you only care about Vista and above, I would use @eryksun's suggestion, since `SHGetFolderPath` is deprecated. [.NET example here.](https://stackoverflow.com/a/4495081/9737456). – FailedShack Jun 06 '19 at 10:48
0

You can try use following code to access %AppData%\Roaming\Microsoft:

string appData= Environment.ExpandEnvironmentVariables("%AppData%");
string roamingMicrosoft = Path.Combine(appData, @"Microsoft");

But I'm not really sure if Windows changes environment variable %AppData% by default when user changes path to AppData by it own.

Lemm
  • 196
  • 1
  • 9
  • %appdata% **is** the roaming folder, appending Roaming would certainly be wrong. – Anders Jun 04 '19 at 10:55
  • @Anders thanks for correcting me, i fixed it in answer. I didn't get that path "%AppData%\Roaming\Microsoft" that is specified in top of post is invalid and used it for Path.Combine – Lemm Jun 04 '19 at 11:04
  • Looks like the %AppData% variable does change. [Screenshot.](https://i.imgur.com/nlr6x92.png) – FailedShack Jun 04 '19 at 17:59