windows GetShortPathName 不可预知的结果

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/843843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 12:26:29  来源:igfitidea点击:

GetShortPathName unpredictable results

c++windowswinapi

提问by Mike Trader

GetShortPathName() is not working as I expect on XP SP3

GetShortPathName() 在 XP SP3 上无法正常工作

http://msdn.microsoft.com/en-us/library/aa364989(VS.85).aspx

http://msdn.microsoft.com/en-us/library/aa364989(VS.85).aspx

Is returning the input string for paths like:

正在返回路径的输入字符串,例如:

C:\Test\LongFolderNameToTestWith\BinarySearch.ini

exactly as sent?

完全按照发送?

Yet:

然而:

C:\Documents and Settings\LocalService\NTUSER.DAT

Does make short names for the path, so I know I am calling the API correctly.

确实为路径命名了短名称,所以我知道我正确地调用了 API。

However:

然而:

C:\Documents and Settings\LocalService\BinarySearch.ini

Does not make a short name out of the filename, but does make short names for the path!?

不会从文件名中创建短名称,但会为路径创建短名称!?

Could someone help me understand this behavior and perhaps suggest a workaround.

有人可以帮助我理解这种行为,并可能提出解决方法。

Added:

添加:

I need to be able to make an 8.3 Path/filename to pass to a legacy app

我需要能够制作 8.3 路径/文件名以传递给旧版应用程序

How can this be done?

如何才能做到这一点?

Added: SOLUTION

补充:解决方案

After MUCH reading/experimenting, it seems that the only reliable way to do this is using automation:

经过大量阅读/实验后,似乎唯一可靠的方法是使用自动化:

' ------------------------------------------------------------
' Library Name:      Microsoft Scripting Runtime 1.0
' Library File:      C:\WINDOWS\system32\scrrun.dll
' ------------------------------------------------------------
' Version Info:
' -------------
' Company Name:      Microsoft Corporation
' File Description:  Microsoft (R) Script Runtime
' File Version:      5.7.0.16599
' Internal Name:     scrrun.dll
' Legal Copyright:   Copyright (C) Microsoft Corp. 1996-2006, All Rights Reserved
' Original Filename: scrrun.dll
' Product Name:      Microsoft (R) Script Runtime
' Product Version:   5.7.0.16599
' ------------------------------------------------------------
' ProgID:            Scripting.FileSystemObject
' Interface Name:    ScriptingFileSystemObject
'
' Interface Prefix:  Scripting

This works.

这有效。

A simple implementation in BASIC would be:

BASIC 中的一个简单实现是:

$PROGID_ScriptingFileSystemObject = "Scripting.FileSystemObject"

Interface Dispatch ScriptingFileSystemObject
    Member CALL GetFile  <&H0000271C>(IN FilePath   AS STRING<&H00000000>) AS ScriptingIFile
    Member CALL GetFolder<&H0000271D>(IN FolderPath AS STRING<&H00000000>) AS ScriptingIFolder 
END Interface

Interface Dispatch ScriptingFile
    Member GET ShortPath<&H000003EA>() AS STRING
    Member GET ShortName<&H000003E9>() AS STRING    
END Interface

Interface Dispatch ScriptingFolder
    Member GET ShortPath<&H000003EA>() AS STRING
    Member GET ShortName<&H000003E9>() AS STRING
END Interface


'-----------------------------------------------------------------------------      
FUNCTION FileShortPath( BYVAL sPathnFile AS STRING, sShort AS STRING ) AS LONG

  LOCAL vResult, vFilePath AS Variant

  LOCAL fso   AS ScriptingFileSystemObject
  LOCAL oFile AS ScriptingFile


    IF LEN(sPathnFile) = 0 THEN EXIT FUNCTION  ' Nothing sent

    SET fso   = NEW ScriptingFileSystemObject IN $PROGID_ScriptingFileSystemObject
    IF IsNothing(fso) THEN FUNCTION = -1 : EXIT FUNCTION

    SET oFile = NEW ScriptingFile             IN $PROGID_ScriptingFileSystemObject
    IF IsNothing(oFile) THEN FUNCTION = -2 : EXIT FUNCTION     


    vFilePath = sPathnFile 

    vResult = Empty
    OBJECT CALL fso.GetFile(vFilePath) TO vResult

    SET oFile = vResult 
    IF IsNothing(oFile) THEN FUNCTION = -3 : EXIT FUNCTION 

    vResult = Empty
    Object GET oFile.ShortName TO vResult
    sShort = VARIANT$(vResult) 

    vResult = Empty
    Object GET oFile.ShortPath TO vResult
    sShort = VARIANT$(vResult) 

    IF LEN(sShort) THEN FUNCTION = 1 ' Success

END FUNCTION

Thank you all for your suggestions.

谢谢大家的建议。



I am still trying to find a way to reliably make an 8.3 Path/filename.

我仍在尝试找到一种可靠地制作 8.3 路径/文件名的方法。

Is there any way to do this apart from using GETSHORTPATHNAME?

除了使用GETSHORTPATHNAME 之外,还有什么方法可以做到这一点吗?

Solved. See above

解决了。看上面

It seems that MS has continued support for this for COM deciples only... why it is now unreliable in the C API remains a mystery.

似乎 MS 仅继续支持 COM deciples ......为什么它现在在 C API 中不可靠仍然是个谜。

回答by Steven

It is because the file name does not have an existing short name and XP SP3 is not automatically creating a short name for the file.

这是因为文件名没有现有的短名称,而且 XP SP3 不会自动为文件创建短名称。

You can check this registry setting (if it exists) to see what it is currently set to.

您可以检查此注册表设置(如果存在)以查看它当前的设置。

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

When NtfsDisable8dot3NameCreation is set to 1 you will get the following behaviour:

当 NtfsDisable8dot3NameCreation 设置为 1 时,您将获得以下行为:

If a folder/file already has a short name, for example "Program Files", then it will return the short name for that folder/file. But if a short name doesn't exist, you will instead get the long name for the file as it is the only name that exists for that object. If short names are disabled then there is no short name to get.

如果文件夹/文件已有短名称,例如“Program Files”,则它将返回该文件夹/文件的短名称。但是,如果短名称不存在,您将获得文件的长名称,因为它是该对象唯一存在的名称。如果禁用短名称,则无法获取短名称。

回答by jdigital

According to the documentation cited earlier, short names will be generated only if the NtfsDisable8dot3NameCreation is 0. If the value was changed, you may have some files/directories with only long names. This would explain why your call to GetShortPathName can short names for the directory and long names for the file.

根据前面引用的文档,仅当 NtfsDisable8dot3NameCreation 为 0 时才会生成短名称。如果更改了值,您可能会有一些只有长名称的文件/目录。这将解释为什么您对 GetShortPathName 的调用可以为目录短名称和长名称。

I haven't been able to confirm this but I suspect there may be special logic in Windows that always creates short names for critical directories such as "Documents and Settings" because some ancient programs might break if this were not done.

我无法确认这一点,但我怀疑 Windows 中可能存在特殊逻辑,总是为关键目录(例如“文档和设置”)创建短名称,因为如果不这样做,一些古老的程序可能会中断。

回答by jdigital

Have you tried SetFileShortName?

你试过SetFileShortName吗?