realpath() Gegenstück für Windows (Pfad auf der der Shortcut zeigt)



  • Hallo,

    ich möchte mit der WinAPI einen Verweis auflösen, also den Pfad in einen String boxen, auf der er verweist.

    Boost.Filesystem ist kaputt was das betrifft.

    Ich habe GetFinalPathNameByHandle() gefunden, aber bevor ich das benutze, brauch ich das File Handle.

    Dann fand ich noch CreateFile() , ich glaub das ist das Richtige, bekomme soweit auch ein valides Handle zurück.

    Aber wenn ich GetFinalPathNameByHandle() mit dem Handle füttere, bekomme ich irgendwie nicht das Resultat, das ich mir wünsche.

    Ich schreibe folgenden Code:

    int main(){
    	HANDLE handle = CreateFile("C:/pfad/zum/shortcut.lnk", 0, 0, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT, 0);
    
    	if(handle == INVALID_HANDLE_VALUE)
    		return -1;
    
    	char file_path[4096];
    	DWORD size = GetFinalPathNameByHandle(handle, file_path, sizeof(file_path), 0);
    
    	if(size == std::strlen(file_path)){
    		std::cout << "get final path name succeeded\n";
    		std::cout << file_path << '\n';
    	}
    }
    

    Die Ausgabe lautet jedoch

    get final path name succeeded
    \\?\<der übergebene pfad>
    

    Und das ist nicht richtig. Ich will den Real Path, nicht den Pfad zum Link.
    Wie mach ich das mit der WinAPI?

    Der Pfad den ich angebe ist korrekt. Er ist korrekt.

    Ich such das realpath() Gegenstück für Windows. Warum muss das so schwer sein.

    Kann mir wer helfen?





  • GetFullPathName() liefert mir auch nur den Pfad zum Shortcut.

    Und _fullpath ist fürs resolven von relativen zu absoluten Pfaden du Nase.

    Auch mit os.path.realpath() unter Python bekomm ich nur den Pfad zum Shortcut.

    Windows ist echt soon Mischt ee.





  • Danke für den Verweis, das Teil musste ich leicht modifizieren, damit es überhaupt kompiliert. Schlussendlich bekomm ich aber doch nur einen leeren String.

    // ResolveIt - Uses the Shell's IShellLink and IPersistFile interfaces 
    //             to retrieve the path and description from an existing shortcut. 
    //
    // Returns the result of calling the member functions of the interfaces. 
    //
    // Parameters:
    // hwnd         - A handle to the parent window. The Shell uses this window to 
    //                display a dialog box if it needs to prompt the user for more 
    //                information while resolving the link.
    // lpszLinkFile - Address of a buffer that contains the path of the link,
    //                including the file name.
    // lpszPath     - Address of a buffer that receives the path of the link
    //                target, including the file name.
    // lpszDesc     - Address of a buffer that receives the description of the 
    //                Shell link, stored in the Comment field of the link
    //                properties.
    
    #include <windows.h>
    #include <shobjidl.h>
    #include <shlguid.h>
    #include <strsafe.h>
    #include <stdexcept>
    
    HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPSTR lpszPath, int iPathBufferSize) 
    { 
        HRESULT hres; 
        IShellLink* psl; 
        char szGotPath[MAX_PATH]; 
        char szDescription[MAX_PATH]; 
        WIN32_FIND_DATA wfd; 
    
        *lpszPath = 0; // Assume failure 
    
        // Get a pointer to the IShellLink interface. It is assumed that CoInitialize
        // has already been called. 
        hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, (LPVOID*)&psl); 
        if (SUCCEEDED(hres)) 
        { 
            IPersistFile* ppf; 
    
            // Get a pointer to the IPersistFile interface. 
            hres = psl->QueryInterface(IID_IPersistFile, (void**)&ppf); 
    
            if (SUCCEEDED(hres)) 
            { 
                WCHAR wsz[MAX_PATH]; 
    
                // Ensure that the string is Unicode. 
                MultiByteToWideChar(CP_ACP, 0, lpszLinkFile, -1, wsz, MAX_PATH); 
    
                // Add code here to check return value from MultiByteWideChar 
                // for success.
    
                // Load the shortcut. 
                hres = ppf->Load(wsz, STGM_READ); 
    
                if (SUCCEEDED(hres)) 
                { 
                    // Resolve the link. 
                    hres = psl->Resolve(hwnd, 0); 
    
                    if (SUCCEEDED(hres)) 
                    { 
                        // Get the path to the link target. 
                        hres = psl->GetPath(szGotPath, MAX_PATH, (WIN32_FIND_DATA*)&wfd, SLGP_SHORTPATH); 
    
                        if (SUCCEEDED(hres)) 
                        { 
                            // Get the description of the target. 
                            hres = psl->GetDescription(szDescription, MAX_PATH); 
    
                            if (SUCCEEDED(hres)) 
                            {
                                hres = StringCbCopy(lpszPath, iPathBufferSize, szGotPath);
                                if (SUCCEEDED(hres))
                                {
    								throw std::runtime_error{szGotPath}; // angekommen
                                    // Handle success
                                }
                                else
                                {
                                    // Handle the error
                                }
                            }
                        }
                    } 
                } 
    
                // Release the pointer to the IPersistFile interface. 
                ppf->Release(); 
            } 
    
            // Release the pointer to the IShellLink interface. 
            psl->Release(); 
        } 
        return hres; 
    }
    
    #include <iostream>
    
    int main() try{
    	if(CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED) != S_OK){
    		std::cerr << "CoInitializeEx() failed.\n";
    		std::getchar();
    		return -1;
    	}
    
    	char buffer[4000];
    	ResolveIt(GetActiveWindow(), "C:/path/to/shortcut.lnk", buffer, 3999);
    	std::cout << std::strlen(buffer) << ":" << buffer << std::endl;
    	std::getchar();
    }
    
    catch(const std::exception& err){
    	std::cerr << std::strlen(err.what()) << '\n';
    	std::cerr << "hooray?\n";
    	std::cerr << err.what() << '\n';
    	std::getchar();
    #define HOORAY 0
    	return HOORAY;
    }
    


  • Ääh, lpszPath und szGotPath sind beide leer.



  • sin schrieb:

    .... du Nase.

    Lös dein Problem doch selber du Nase! Ich kenn die Lösung, sag sie dir aber nicht!



  • Returnwert vs. exception ist ja immer ein Thema, aber im Erfolgsfall eine Ausnahme zu werfen eher die Seltenheit (zumal in dem Beispiel die Ressourcen nicht freigegeben werden können).
    Falls es irgendwen doch interessieren sollte:

    #include <shobjidl.h>
    #include <shlguid.h>
    #include <atlbase.h> 
    
    HRESULT ResolveLnk(HWND hwnd, const TCHAR* lnkFile, TCHAR* path, size_t pathLen) 
    {
    	*path = 0;
    
    	CComPtr<IShellLink> psl;
    	HRESULT hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_IShellLink, reinterpret_cast<void**>(&psl));
    	if (SUCCEEDED(hres)) 
    	{
    		CComPtr<IPersistFile> ppf;
    		hres = psl->QueryInterface(IID_IPersistFile, reinterpret_cast<void**>(&ppf));
    		if (SUCCEEDED(hres))
    		{
    #		ifdef UNICODE
    			const WCHAR* wsz = lnkFile;
    #		else
    			WCHAR wsz[MAX_PATH];
    			if(!MultiByteToWideChar(CP_ACP, 0, lnkFile, -1, wsz, MAX_PATH))
    			{
    				// hier sollte reagiert werden...	
    			}
    #		endif
    			hres = ppf->Load(wsz, STGM_READ);
    			if (SUCCEEDED(hres))
    			{
    				hres = psl->Resolve(hwnd, 0);
    				if (SUCCEEDED(hres))
    				{
    					hres = psl->GetPath(path, pathLen, nullptr, 0);
    				}
    			}
    		}
    	}
    	return hres;
    }
    

Anmelden zum Antworten