2016-12-04 49 views
2

在Windows 10版本1607,过程可以使用清单属性(https://msdn.microsoft.com/en-us/library/windows/desktop/aa365247.aspx#maxpath如何以编程方式检查当前进程是否在Windows上识别长路径?

我如何编程方式检查如果调用过程是漫长的道路知道现在选择在长路径的认识?请注意,由于Windows版本大于等于1607的情况,单独检查操作系统版本或注册表项的值是不够的,因此系统范围内的长路径被禁用,并且该过程不适用于长路径。

+3

读线之间的文档测试,我认为理论是,你不需要知道。你能勾画出你认为这可能是一个问题的原因吗? –

+0

要警告用户长路径不可用,并因此可能会出现不正确的行为。这是一个库项目,所以启用长路径的清单资源不一定存在。否则,它只是一个操作系统版本检查。 –

+0

,但是如果使用格式为'\\?\\'的长路径,即使在XP中也是真正可用的路径 – RbMm

回答

0

ntdll(在win10 1607中)导出下一个API BOOLEAN NTAPI RtlAreLongPathsEnabled(); - 所以你可以调用它。它返回TRUE如果LongPaths启用

这里代码尖晶石 - 如果RtlAreLongPathsEnabled返回false - STATUS_NAME_TOO_LONG(c0000106)返回

enter image description here

系统需要Win32的路径转换为NT路径之前,在任何文件中的函数使用它,哪个调用内核。这通过呼叫RtlDosPathNameTo*NtPathName*完成。此功能,如果看到该路径超过MAX_PATH(〜) - 称为RtlAreLongPathsEnabled()并继续工作,只有当功能返回TRUE。如果为false - 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 , 0, 0, 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, 0, OPEN_ALWAYS, 0, 0); 

      if (hFile != INVALID_HANDLE_VALUE) 
      { 
       CloseHandle(hFile); 
       return ; 
      } 
     } 
    } 

    GetLastError(); 
} 

和清单与<ws2:longPathAware>true</ws2:longPathAware>测试,并在注册表中LongPathsEnabled==0。它失败了?然后在没有清单的情况下进行测试,但在注册表中使用LongPathsEnabled==1。工作?

如果让我在Windows 10版本1607构建14393.0

+1

这似乎没有考虑到清单,不幸的是... –

+0

@JakePetroules - 你想确定它从运行过程还是如何?你是否尝试使用清单'longPathAware = true'创建应用程序并检查它?在我的测试中,这没有帮助。和研究表明,尽管MSDN – RbMm

+1

是真的没有使用,但是我想确定是否为当前正在运行的进程启用了长路径,并且我可以看到MSDN中的清单片段不会影响RtlAreLongPathsEnabled API调用的输出,也不会影响CreateDirectoryW似乎与我刚刚测试的266个字符的路径一起工作。 –

相关问题