在尝试解析CommonDocuments
目录时,我得到了一个有点奇怪的错误。它一直解析到错误的目录,在CommonDocuments目录被重定向/移动到一个新的位置使用Windows资源管理器(属性->路径从上下文菜单)。
一个最小的工作代码片段应该是:
namespace CommonDocumentsTest
{
class Program
{
private static readonly Guid CommonDocumentsGuid = new Guid("ED4824AF-DCE4-45A8-81E2-FC7965083634");
[Flags]
public enum KnownFolderFlag : uint
{
None = 0x0,
CREATE = 0x8000,
DONT_VERFIY = 0x4000,
DONT_UNEXPAND= 0x2000,
NO_ALIAS = 0x1000,
INIT = 0x800,
DEFAULT_PATH = 0x400,
NOT_PARENT_RELATIVE = 0x200,
SIMPLE_IDLIST = 0x100,
ALIAS_ONLY = 0x80000000
}
[DllImport("shell32.dll")]
static extern int SHGetKnownFolderPath([MarshalAs(UnmanagedType.LPStruct)] Guid rfid, uint dwFlags, IntPtr hToken, out IntPtr pszPath);
static void Main(string[] args)
{
KnownFolderFlag[] flags = new KnownFolderFlag[] {
KnownFolderFlag.None,
KnownFolderFlag.ALIAS_ONLY | KnownFolderFlag.DONT_VERFIY,
KnownFolderFlag.DEFAULT_PATH | KnownFolderFlag.NOT_PARENT_RELATIVE,
};
foreach (var flag in flags)
{
Console.WriteLine(string.Format("{0}; P/Invoke==>{1}", flag, pinvokePath(flag)));
}
Console.ReadLine();
}
private static string pinvokePath(KnownFolderFlag flags)
{
IntPtr pPath;
SHGetKnownFolderPath(CommonDocumentsGuid, (uint)flags, IntPtr.Zero, out pPath); // public documents
string path = System.Runtime.InteropServices.Marshal.PtrToStringUni(pPath);
System.Runtime.InteropServices.Marshal.FreeCoTaskMem(pPath);
return path;
}
}
}
预期行为:
输出D:TestDocuments
输出C:UsersPublicDocuments
没有;P/Invoke = => C: 公共用户文档
DONT_VERFIY ALIAS_ONLY;P/Invoke = =>
NOT_PARENT_RELATIVE DEFAULT_PATH;P/Invoke = => C: 公共用户文档
正确的值存储在Windows注册表(HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionExplorerShell FoldersCommon Documents)中,但SHGetKnownFolderPath
(或Environment.GetFolderPath
)不返回
操作系统:Windows 7 Professional x64
.NET框架v4.0.30319应用程序编译为x86 CPU
我试过了:
- 重新启动应用程序
- 重新启动计算机
- 呼叫
Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments);
- 直接调用Win32-API SHGetKnownFolderPath
编辑2 复制步骤:
- 在您的计算机上停用UAC[并重新启动!)
- 转到C:UsersPublic
- 右键单击"公共文件"文件夹并选择
Properties
- 选择"路径"选项卡
- 点击"移动……',并在
D:
驱动器上选择一个名为TestDocuments
的(新)文件夹 - 点击"应用"
- 接受将所有文件移动到最小的新位置应用以上
tl;dr:行为是设计出来的,只有在x64操作系统上运行为x86 cpu 编译的程序集时才会出现
长版:Environment.GetFolderPath(Environment.SpecialFolder.CommonDocuments)
访问Windows注册表的32位hive .
文件夹的实际路径保存在64位的hive中。该问题已被转发给Windows团队,可能会在Windows的未来版本中修复。
解决方案使用以下代码创建一个控制台应用程序,并为ANY CPU
编译它static void Main(string[] args)
{
Console.WriteLine("{0}", Environment.GetFolderPath(System.Environment.SpecialFolder.CommonDocuments));
}
然后从主应用程序调用它:
Process proc = new Process();
ProcessStartInfo info = new ProcessStartInfo("myConsoleApp.exe");
// allow output to be read
info.RedirectStandardOutput = true;
info.RedirectStandardError = true;
info.UseShellExecute = false;
proc.StartInfo = info;
proc.Start();
proc.WaitForExit();
string path = proc.StandardOutput.ReadToEnd();
这将启动ANY CPU可执行文件,该文件只输出到标准输出的所需路径。然后在主应用程序中读取输出,并获得实际路径。