GetShortPathName непредсказуемые результаты

GetShortPathName() не работает, как я ожидаю, в XP SP3

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

Возвращает входную строку для таких путей, как:

C:\Test\LongFolderNameToTestWith\BinarySearch.ini

точно как прислали?

Пока что:

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

Делает короткие имена для пути, поэтому я знаю, что правильно вызываю API.

Однако:

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

Не делает короткое имя из имени файла, но делает короткие имена для пути!?

Может ли кто-нибудь помочь мне понять это поведение и, возможно, предложить обходной путь.

Добавлено:

Мне нужно создать путь/имя файла 8.3 для передачи в устаревшее приложение

Как это можно сделать?

Добавлено: РЕШЕНИЕ

После БОЛЬШОГО чтения/экспериментирования кажется, что единственный надежный способ сделать это - использовать автоматизацию:

' ------------------------------------------------------------
' 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

Это работает.

Простая реализация на 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

Спасибо всем за ваши предложения.


Я все еще пытаюсь найти способ надежно создать путь/имя файла 8.3.

Есть ли способ сделать это, кроме использования GETSHORTPATHNAME?

Решено. См. выше

Похоже, что MS продолжает поддерживать это только для деципилов COM... почему теперь это ненадежно в C API, остается загадкой.


person Mike Trader    schedule 09.05.2009    source источник
comment
Можете ли вы опубликовать код дословно, который вас беспокоит?   -  person dirkgently    schedule 09.05.2009
comment
DWORD WINAPI GetShortPathName(__in LPCTSTR lpszLongPath, __out LPTSTR lpszShortPath, __in DWORD cchBuffer); но, как уже упоминалось, вызов здесь не проблема...   -  person Mike Trader    schedule 09.05.2009
comment
Объявление функции не очень помогает. Если вы можете привести краткий пример, который воспроизводит вашу проблему, это может помочь.   -  person dirkgently    schedule 09.05.2009


Ответы (4)


Это связано с тем, что имя файла не имеет существующего короткого имени, а XP SP3 автоматически не создает короткое имя для файла.

Вы можете проверить этот параметр реестра (если он существует), чтобы узнать, какой он установлен в данный момент.

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

Когда для NtfsDisable8dot3NameCreation установлено значение 1, вы получите следующее поведение:

Если у папки/файла уже есть короткое имя, например «Program Files», то будет возвращено короткое имя для этой папки/файла. Но если короткое имя не существует, вместо этого вы получите длинное имя файла, поскольку это единственное имя, которое существует для этого объекта. Если короткие имена отключены, получить короткое имя невозможно.

person Steven    schedule 09.05.2009
comment
Да, я посмотрел на это, он установлен на 1, но я предположил, что этот параметр позволяет создавать все имена файлов NTFS как 8.3 на диске и везде (что явно нежелательно). Когда вы говорите о создании короткого имени для файла, вы имеете в виду создание нового имени файла 8.3 на жестком диске или просто создание его для возврата при вызове GetShortPathName()? Если этот флаг управляет этим, то почему он возвращает 8.3 для некоторых путей, если установлено значение 1? - person Mike Trader; 09.05.2009
comment
Я добавил дополнительную информацию к моему ответу. GetShortPathName() не будет создавать короткое имя, когда создание короткого имени отключено, поэтому вы получаете короткие имена только в том случае, если они уже существуют. - person Steven; 09.05.2009
comment
Ах ха. Спасибо. И поэтому, просто чтобы прояснить область действия этого параметра, я не собираюсь с этого момента находить каждый файл, который я создаю на жестком диске, с коротким именем, верно? - person Mike Trader; 10.05.2009

Согласно приведенной ранее документации, короткие имена будут генерироваться только в том случае, если NtfsDisable8dot3NameCreation равен 0. Если значение было изменено, у вас могут быть некоторые файлы/каталоги только с длинными именами. Это объясняет, почему ваш вызов GetShortPathName может содержать короткие имена для каталога и длинные имена для файла.

Я не смог подтвердить это, но я подозреваю, что в Windows может быть особая логика, которая всегда создает короткие имена для важных каталогов, таких как «Документы и настройки», потому что некоторые старые программы могут сломаться, если этого не сделать.

person jdigital    schedule 09.05.2009
comment
Документы и настройки, скорее всего, создаются во время установки, еще до того, как у вас появится возможность отключить генерацию имен 8.3. Для этого не потребуется особой магии. - person MSalters; 12.06.2009

Пробовали ли вы SetFileShortName?

person jdigital    schedule 16.06.2009
comment
Спасибо. Хорошая идея... msdn.microsoft.com/en- us/library/tes8ehwe(VS.85).aspx (возможно, COM-объект, использующий pInvoke) — предполагается, что у меня есть ShortName для установки. Как надежно сделать короткое имя в XP? - person Mike Trader; 16.06.2009
comment
en.wikipedia.org/wiki/8.3_filename обсуждает набор соглашений для коротких имен файлов. . Реализуйте это в цикле, в котором вы проверяете код возврата SetFileShortName, и если это не удается, увеличивайте счетчик в конце и повторяйте попытку. - person jdigital; 16.06.2009

Я знаю это такой старый пост, но жизнь живет в спине. Итак, вот я исследую то же самое.

Как указано в https://support.microsoft.com/en-gb/help/121007/how-to-disable-8-3-file-name-creation-on-ntfs-partitions.

Windows Vista, Windows Server 2008, Windows 7, Windows Server 2008 R2, Windows 8 и Windows Server 2012

Чтобы отключить создание имени 8.3 во всех разделах NTFS, введите набор поведения fsutil.exe disabled8dot3 1 в командной строке с повышенными привилегиями и нажмите клавишу ВВОД.

Эта операция вступает в силу немедленно (перезагрузка не требуется).

Заметки

Если том не указан, операция обновляет значение реестра:

  • 0 — включить создание имени 8dot3 на всех томах в системе.
  • 1 — отключить создание имени 8dot3 на всех томах в системе.
  • 2 - Установите создание имени 8dot3 для каждого тома.
  • 3 - Отключить создание имени 8dot3 на всех томах, кроме системного.
person Bitart    schedule 25.06.2020