zoukankan      html  css  js  c++  java
  • 解析快捷方式指向的文件

    参考网址

      https://docs.microsoft.com/zh-cn/windows/desktop/api/msi/nf-msi-msigetshortcuttargetw

      https://docs.microsoft.com/zh-cn/windows/desktop/api/msi/nf-msi-msigetcomponentpathw

      还有n多从百度上搜索的网页

    前言

      本文只针对用api方式解析指向本地其他文件的lnk文件, 其他的比如通过暴力解析lnk文件在此不再赘述

    解析的核心逻辑

      目前, windows上共有两种格式的link文件, 因此针对不同的格式, 要用不同的解析api.

      一种是msi生成的格式, 要用到 MsiGetShortcutTarget 跟MsiGetShortcutTarget 这俩函数组合来进行解析; 另一种就是之前的需要通过 IShellLink接口来进行解析.

      按照msdn上的说明, 对于所有的链接文件, 要先使用第一种方法进行解析, 当解析失败并且链接文件存在的情况下, 再用第二种方法来进行解析

      代码如下(有些头文件可能不是必须的):

      1 #include <windows.h>
      2 #include <ShObjIdl.h>
      3 #include <Shlobj.h>
      4 #include <shlwapi.h>
      5 #include <pathcch.h>
      6 #include <msi.h>
      7 #include <io.h>
      8 #include <iostream>
      9 #include <string>
     10 #include <vector>
     11 #include <algorithm>
     12 #include <cctype>
     13 #include <set>
     14 
     15 #pragma comment(lib,"Shlwapi.lib")
     16 #pragma comment(lib,"Pathcch.lib")
     17 #pragma comment(lib,"Msi.lib")
     18 struct AppInfoInStartMenu_t
     19 {
     20     std::wstring name_;
     21     std::wstring ExeFullPath_;
     22     std::wstring path_;
     23 };
     24 bool ResolveShortcut(const std::wstring &linkFile, AppInfoInStartMenu_t &info)
     25 {
     26     static const DWORD pathMaxLen = MAX_PATH * 2;
     27     static wchar_t szTmp[pathMaxLen] = { 0 };
     28 
     29     if (linkFile.empty() || linkFile.size() >= pathMaxLen)
     30         return false;
     31 
     32     size_t strLen1 = (size_t)linkFile.size();
     33     memset(szTmp, 0, pathMaxLen * 2);
     34     memcpy(szTmp, linkFile.c_str(), strLen1 * 2);
     35     std::transform(szTmp, szTmp + strLen1, szTmp, ::tolower);
     36 
     37     wchar_t *ext = NULL;
     38     HRESULT hr = PathCchFindExtension(szTmp, strLen1 + 1, &ext);
     39     if (hr != S_OK || wcscmp(ext, L".lnk"))
     40         return false;
     41     const wchar_t *fileName = PathFindFileName(szTmp);
     42     if (fileName == szTmp// 没有找到文件名的指针 
     43         || fileName >= ext)
     44         return false;
     45     //link文件名
     46     info.name_ = std::wstring(linkFile.c_str() + (fileName - szTmp), ext - fileName);
     47 
     48     bool result = false;
     49     wchar_t productCodeStr[39] = { 0 };
     50     wchar_t szComponentCodeStr[39] = { 0 };
     51     // ret的值msdn上居然没有说明!!! 不过测试几个发现貌似就是System Error里面定义的, ERROR_SUCCESS means right;
     52     UINT ret = MsiGetShortcutTargetW(linkFile.c_str(), productCodeStr, NULL, szComponentCodeStr);
     53     if(ERROR_SUCCESS == ret)
     54     {
     55         //看了看msdn,INSTALLSTATE_SOURCE这个没看懂是什么意思, 剩下的就只有INSTALLSTATE_LOCAL 代表正确了
     56         // 下面这一段是动态申请的buffer, 频繁调用的的话,感觉容易造成内存碎片化
     57 //        DWORD bufSize = 0;
     58 //         INSTALLSTATE  ret2 = MsiGetComponentPathW(productCodeStr, szComponentCodeStr, NULL, &bufSize);
     59 //         if (INSTALLSTATE_LOCAL != ret2)
     60 //             return false;
     61 // 
     62 //         bufSize++;
     63 //         wchar_t *truePath = new wchar_t[bufSize];
     64 //         if (!truePath)
     65 //             return false;
     66 //         ret2 = MsiGetComponentPathW(productCodeStr, szComponentCodeStr, truePath, &bufSize);
     67 //         delete[] truePath;
     68 
     69         DWORD bufSize = pathMaxLen;
     70         memset(szTmp, 0, pathMaxLen * 2);
     71         INSTALLSTATE  ret2 = MsiGetComponentPathW(productCodeStr, szComponentCodeStr, szTmp, &bufSize);
     72         if (INSTALLSTATE_LOCAL != ret2)
     73             return false;
     74         wprintf(L"%s
    ", szTmp);
     75         result = true;
     76     }
     77     else
     78     {
     79         IShellLinkW *psl = NULL;
     80         IPersistFile *ppf = NULL;
     81         do
     82         {
     83             HRESULT hr = S_FALSE;
     84             hr = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&psl));
     85             if (hr != S_OK)
     86                 break;
     87 
     88             hr = psl->QueryInterface(&ppf);
     89             if (hr != S_OK)
     90                 break;
     91 
     92             hr = ppf->Load(linkFile.c_str(), STGM_READ);
     93             if (hr != S_OK)
     94                 break;
     95 
     96             //指向的路径
     97             memset(szTmp, 0, pathMaxLen * 2);
     98             hr = psl->GetPath(szTmp, MAX_PATH, NULL, SLGP_RAWPATH);
     99             if (hr != S_OK)
    100                 break;
    101             result = true;
    102         } while (false);
    103         if (ppf)
    104             ppf->Release();
    105         if (psl)
    106             psl->Release();
    107     }
    108 
    109     //填充返回的其他数据
    110     if (result)
    111     {
    112         result = false;
    113         info.ExeFullPath_ = szTmp;
    114         hr = PathCchRemoveFileSpec(szTmp, strLen1 + 1);
    115         if (hr == S_OK)
    116         {
    117             info.path_ = szTmp;
    118             result = true;
    119         }
    120     }
    121     return result;
    122 }
  • 相关阅读:
    需求规格说明书
    团队作业—选题报告
    Department and Student
    软件工程第一次团队作业
    第二次作业——个人项目实战
    软件工程实践2017第一次作业
    第七次作业--项目需求分析
    玩下软工项目,第一轮--全局Context的获取,SQLite的建立与增删改查,读取用户通话记录信息
    软工实践结对编程第二次作业
    java--由一道选择题研究数值越界
  • 原文地址:https://www.cnblogs.com/talenth/p/9873028.html
Copyright © 2011-2022 走看看