2009-05-09 3 views
4

GetShortPathName() не работает, как я ожидал на XP SP3GetShortPathName непредсказуемые результаты

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 Path/filename.

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

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

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

+0

Можете ли вы опубликовать код, который вас беспокоит? – dirkgently

+0

DWORD WINAPI GetShortPathName ( __in LPCTSTR lpszLongPath, __out LPTSTR lpszShortPath, __in типа DWORD cchBuffer ); , но, как уже упоминалось, вызов здесь не является проблемой ... –

+0

Объявление функции не очень помогает. Если вы можете предоставить короткий пример, который воспроизводит вашу проблему, это может помочь. – dirkgently

ответ

9

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

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

HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Control \ FileSystem \ NtfsDisable8dot3NameCreation

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

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

+0

Да, я посмотрел на это, он установлен в 1, но я предположил, что этот параметр позволяет создавать имена файлов NTFS как 8.3 на диске и везде (что явно нежелательно). Когда вы говорите «создание короткого имени для файла», вы имеете в виду создание нового имени файла 8.3 на HD или просто создание для возврата в вызов GetShortPathName()? Если этот флаг управляет этим, то почему он возвращает 8.3 для некоторых путей при установке в 1? –

+0

Я добавил дополнительную информацию к своему ответу. GetShortPathName() не будет создавать короткое имя при закрытии короткого имени, поэтому вы получите только короткие имена, если они уже существуют. – Steven

+0

А-ха. Спасибо. И так, чтобы быть ясными о масштабах этого параметра, я не собираюсь найти каждый файл, который я создаю на жестком диске, с коротким именем, следовательно, правильно? –

2

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

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

+2

«Документы и настройки», скорее всего, созданы во время установки, прежде чем у вас даже будет возможность отключить генерацию имен 8.3. Это не потребует особой магии. – MSalters

2

Вы попробовали SetFileShortName?

+0

Спасибо. Хорошая идея ... http://msdn.microsoft.com/en-us/library/tes8ehwe(VS.85).aspx (возможно, объект COM с использованием pInvoke) - предполагает, что у меня есть ShortName для установки. Как я могу сделать короткое имя в XP? –

+0

http://en.wikipedia.org/wiki/8.3_filename обсуждает набор условных обозначений для коротких имен файлов. Реализуйте это в цикле, в котором вы проверяете код возврата SetFileShortName, и если он терпит неудачу, увеличьте счетчик в конце и повторите попытку. – jdigital

Смежные вопросы