如何以编程方式检查调用进程是否具有长路径感知功能?请注意,仅检查操作系统版本或注册表项的值是不够的,因为Windows版本≥1607的情况下,系统范围内禁用长路径,并且长路径不显示该过程.
解决方法
这里代码spinet – 如果RtlAreLongPathsEnabled返回false – 返回STATUS_NAME_TOO_LONG(c0000106)
系统需要将Win32路径转换为NT路径,然后才能在任何调用内核的文件函数中使用它.这是通过调用RtlDosPathNameTo * NtPathName *来完成的.这个函数,如果看到该路径超过MAX_PATH(〜) – 称为RtlAreLongPathsEnabled()并且仅在函数返回TRUE时继续工作.如果错误 – STATUS_NAME_TOO_LONG返回.
RtlAreLongPathsEnabled的代码很简单 – 当第一次调用时 – 它检查注册表(并且只有注册表)并保存结果.根本不寻求表现.这里确切的功能代码:
BOOLEAN RtlAreLongPathsEnabled() { static BOOLEAN init; static BOOLEAN elp; if (!init) { init = true; HANDLE hKey; KEY_VALUE_PARTIAL_INFORMATION kvpi; STATIC_OBJECT_ATTRIBUTES(FileSystemRegKeyName,"\\registry\\MACHINE\\SYSTEM\\CurrentControlSet\\Control\\FileSystem"); if (0 <= ZwOpenKey(&hKey,KEY_READ,&FileSystemRegKeyName)) { STATIC_UNICODE_STRING(LongPathRegKeyValue,"LongPathsEnabled"); if (0 <= ZwQueryValueKey(hKey,&LongPathRegKeyValue,KeyValuePartialInformation,&kvpi,sizeof(kvpi),&kvpi.TitleIndex) && kvpi.Type == REG_DWORD && kvpi.DataLength == sizeof(DWORD)) { elp = *(DWORD*)kvpi.Data != 0; } ZwClose(hKey); } } return elp; }
所以我的结论 – 在当前构建的长路径行为仅依赖于注册表设置,绝对不依赖于应用程序清单,尽管MSDN.
对于下来的选票 – 对我来说简直有趣 – 有人来自你构建测试应用程序(有和没有清单)并自己测试,或者你只能阅读文档?
对于那些发现自己很困难,或者懒得自己编写代码的人.你可以用这段代码测试:
BOOL CreateFolder(LPCWSTR lpPathName) { return CreateDirectoryW(lpPathName,0) || GetLastError() == ERROR_ALREADY_EXISTS; } void LPT() { WCHAR name[128],path[0x8000],*c; if (!SHGetFolderPath(0,CSIDL_PROFILE,path)) { *name = '\\'; __stosw((PUSHORT)name + 1,'3',RTL_NUMBER_OF(name) - 2); name[RTL_NUMBER_OF(name) - 1] = 0; c = path + wcslen(path); int n = 4; do { memcpy(c,name,sizeof(name)); c += RTL_NUMBER_OF(name) - 1; if (!CreateFolder(path)) { break; } } while (--n); if (!n) { wcscpy(c,L"\\1.txt"); HANDLE hFile = CreateFileW(path,FILE_GENERIC_WRITE,FILE_SHARE_VALID_FLAGS,OPEN_ALWAYS,0); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); return ; } } } GetLastError(); }
并使用< ws2:longPathAware> true< / ws2:longPathAware>进行测试在清单中,LongPathsEnabled == 0在注册表中.它失败了?然后测试它没有清单但在注册表中使用LongPathsEnabled == 1.工作?
如果是这样我在Windows 10上测试.版本1607. build 14393.0
在win10 1709实现改变了:现在RtlAreLongPathsEnabled非常简单:
BOOLEAN RtlAreLongPathsEnabled() { return NtCurrentTeb()->ProcessEnvironmentBlock->IsLongPathAwareProcess; }
在以前的版本中是: