Hvordan får man navnet på en fil fra et filhåndtag i Windows ved hjælp af C?

Indlæg af Hanne Mølgaard Plasc

Problem



Jeg forsøger at hente et filnavn fra et givet filhåndtag.


Jeg har set, at GetFileInformationByHandle kunne være nyttigt, men den struktur, den returnerer, indeholder ikke filnavnoplysninger (http://msdn.microsoft.com/en-us/library/aa363788\%28v=VS.85\%29.aspx ). [7] [8]


Hvordan kan jeg gøre dette?


REDIGERE:


Jeg har forsøgt at installere Windows FileID API'erne for at få GetFileInformationByHandleEx til at fungere på Windows XP.
Men når du inkluderer fileextd.h får jeg følgende fejl


c:programmimicrosoft visual studio 9.0vcincludefileextd.h(16) : error C2011: '\_FILE\_INFO\_BY\_HANDLE\_CLASS' : 'enum' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13900) : see declaration of '\_FILE\_INFO\_BY\_HANDLE\_CLASS'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(32) : error C2011: '\_FILE\_BASIC\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13917) : see declaration of '\_FILE\_BASIC\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(40) : error C2011: '\_FILE\_STANDARD\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13925) : see declaration of '\_FILE\_STANDARD\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(48) : error C2011: '\_FILE\_NAME\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13933) : see declaration of '\_FILE\_NAME\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(53) : error C2011: '\_FILE\_RENAME\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13938) : see declaration of '\_FILE\_RENAME\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(60) : error C2011: '\_FILE\_ALLOCATION\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13945) : see declaration of '\_FILE\_ALLOCATION\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(64) : error C2011: '\_FILE\_END\_OF\_FILE\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13949) : see declaration of '\_FILE\_END\_OF\_FILE\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(68) : error C2011: '\_FILE\_STREAM\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13953) : see declaration of '\_FILE\_STREAM\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(76) : error C2011: '\_FILE\_COMPRESSION\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13961) : see declaration of '\_FILE\_COMPRESSION\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(85) : error C2011: '\_FILE\_ATTRIBUTE\_TAG\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13970) : see declaration of '\_FILE\_ATTRIBUTE\_TAG\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(90) : error C2011: '\_FILE\_DISPOSITION\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13975) : see declaration of '\_FILE\_DISPOSITION\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(94) : error C2011: '\_FILE\_ID\_BOTH\_DIR\_INFO' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(13979) : see declaration of '\_FILE\_ID\_BOTH\_DIR\_INFO'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(130) : error C2011: '\_FILE\_ID\_TYPE' : 'enum' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(14026) : see declaration of '\_FILE\_ID\_TYPE'
c:programmimicrosoft visual studio 9.0vcincludefileextd.h(135) : error C2011: 'FILE\_ID\_DESCRIPTOR' : 'struct' type redefinition
        c:programmimicrosoft sdkswindowsv6.1includewinbase.h(14032) : see declaration of 'FILE\_ID\_DESCRIPTOR'
c:documents and settingslabdocumentivisual studio 2008projectssandboxsandboxfuncs\_files.cpp(26) : error C2079: 'lpFileInformation' uses undefined struct '\_FILE\_NAME\_INFO'
c:documents and settingslabdocumentivisual studio 2008projectssandboxsandboxfuncs\_files.cpp(35) : error C2228: left of '.FileName' must have class/struct/union
        type is 'int'


Fra følgende kode:


#include <windows.h>
#include <fileextd.h>

LPVOID GetFileNameFromHandle(HANDLE hFile) {
    FILE\_NAME\_INFO lpFileInformation;
    BOOL bWorked;

    bWorked = GetFileInformationByHandleEx(
        hFile,
        FileNameInfo,
        &lpFileInformation,
        sizeof(FILE\_NAME\_INFO));

    return lpFileInformation.FileName;
}

Bedste reference


Hej, hvis du har brug for filnavn fra at håndtere, kan du læse denne ms artikel http://msdn.microsoft.com/en-us/library/aa366789(VS.85).aspx
eller brug denne GetFileInformationByHandleEx [9]

Andre referencer 1


BOOL    GetFileNameFromHandle(HANDLE hFile, TCHAR *pszFileName, const unsigned int uiMaxLen)
{
    pszFileName[0]=0;

    std::unique\_ptr<BYTE[]> ptrcFni(new BYTE[\_MAX\_PATH * sizeof(TCHAR) + sizeof(FILE\_NAME\_INFO)]);
    FILE\_NAME\_INFO *pFni = reinterpret\_cast<FILE\_NAME\_INFO *>(ptrcFni.get());

    BOOL b = GetFileInformationByHandleEx(hFile, 
                                        FileNameInfo,
                                        pFni,
                                        sizeof(FILE\_NAME\_INFO) + (\_MAX\_PATH * sizeof(TCHAR)) );
    if ( b )
    {
#ifdef  \_UNICODE
         wcsncpy\_s(pszFileName, 
                min(uiMaxLen, (pFni->FileNameLength / sizeof(pFni->FileName[0])) + 1 ), 
                pFni->FileName, 
                \_TRUNCATE);
#else
        strncpy\_s(pszFileName, 
                min(uiMaxLen, (pFni->FileNameLength / sizeof(pFni->FileName[0])) + 1), 
                CW2A(pFni->FileName), 
                \_TRUNCATE);
#endif
    }
    return b;
}

Andre referencer 2


Der er en korrekt måde at gøre dette på, som virker på Windows XP, både på filer og mapper. Jeg har forklaret det i et andet indlæg her.

Andre referencer 3


Hvor fik du filhåndtaget fra? Hvis du er sikker på at det ikke er et navngivet rørhåndtag, kan du bruge NtQueryObject til at søge filnavnet. [11]

Andre referencer 4


For Vista og se nærmere på GetFinalPathNameByHandle (som mehrdad skrev) [12]


Det er mere bekvemt IMO og tillader mere tilpasning end GetFileInformationByHandleEx, og det fjerner besværet med at allokere en [[... 5]] struktur med brugerdefineret størrelse. [13]


Eksempel:


DWORD size = GetFinalPathNameByHandleW(handle, NULL, 0, VOLUME\_NAME\_DOS);
if (size == 0) return L"(NOT FOUND)";
std::wstring fname(size, L'0');
size = GetFinalPathNameByHandleW(handle, &fname.front(), size, VOLUME\_NAME\_DOS);


Bemærk , den vil udfylde \? til det tilbagevendende navn.


(Jeg brugte C ++ std :: wstring for at undgå C-kedeplade til hukommelseshåndtering. Brug malloc til dine behov).