windows read the target of shortcut file in c++

前端 未结 2 1131
無奈伤痛
無奈伤痛 2020-12-17 02:46

How to read the target of shortcut file on windows. Tried using boost::read_symlink which throws exception saying \"the file or directory is not a reparse point\" message.

相关标签:
2条回答
  • 2020-12-17 02:53

    A Windows .lnk file is not a symbolic link. It is a shortcut file. You use the IShellLink interface to manipulate it.

    The documentation contains the following example demonstrating how to resolve a shortcut file.

    // 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 "stdafx.h"
    #include "windows.h"
    #include "shobjidl.h"
    #include "shlguid.h"
    #include "strsafe.h"
    
    HRESULT ResolveIt(HWND hwnd, LPCSTR lpszLinkFile, LPWSTR lpszPath, int iPathBufferSize) 
    { 
        HRESULT hres; 
        IShellLink* psl; 
        WCHAR szGotPath[MAX_PATH]; 
        WCHAR 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))
                                {
                                    // 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; 
    }
    
    0 讨论(0)
  • 2020-12-17 02:59

    Here's more compact version of David's code, with ATL (included with Visual Studio).

    #define CHECK( hr ) { const HRESULT __hr = ( hr ); if( FAILED( __hr ) ) return __hr; }
    
    HRESULT resolveShortcutTarget( HWND wnd, const CString& lnk, CString& target )
    {
        // Get a pointer to the IShellLink interface. It is assumed that CoInitialize has already been called. 
        CComPtr<IShellLink> psl;
        CHECK( psl.CoCreateInstance( CLSID_ShellLink, nullptr, CLSCTX_INPROC_SERVER ) );
    
        // Get a pointer to the IPersistFile interface. 
        CComPtr<IPersistFile> ppf;
        CHECK( psl->QueryInterface( IID_PPV_ARGS( &ppf ) ) );
    
        // Load the shortcut. 
        CHECK( ppf->Load( lnk, STGM_READ ) );
    
        // Resolve the link. 
        CHECK( psl->Resolve( wnd, 0 ) );
    
        // Get the path to the link target. 
        const HRESULT hr = psl->GetPath( target.GetBufferSetLength( MAX_PATH ), MAX_PATH, nullptr, 0 );
        target.ReleaseBuffer();
        return hr;
    }
    
    0 讨论(0)
提交回复
热议问题