Bezdepbonusu7Программирование: статьи и ответы

Вопрос

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

Автор вопроса: Mike TraderОтветов: 4

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, остается загадкой.

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

windowsc++winapi

Ответы

Ответ 1 · рейтинг 11 · Steven

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

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

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation

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

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

Ответ 2 · рейтинг 2 · jdigital

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

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

Ответ 3 · рейтинг 2 · jdigital

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

Ответ 4 · Bitart

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

Как указано в 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 на всех томах, кроме системного.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы