【问题标题】:reading an application's manifest file?读取应用程序的清单文件?
【发布时间】:2010-09-30 01:39:13
【问题描述】:

是否有一种简单的方法可以读取应用程序已经嵌入的清单文件?

我在考虑替代数据流的思路?

【问题讨论】:

    标签: c++ windows visual-c++ manifest


    【解决方案1】:

    Windows 清单文件是 Win32 资源。换句话说,它们嵌入到 EXE 或 DLL 的末尾。您可以使用 LoadLibraryEx、FindResource、LoadResource 和 LockResource 来加载嵌入的资源。

    这是一个提取自己的清单的简单示例...

    BOOL CALLBACK EnumResourceNameCallback(HMODULE hModule, LPCTSTR lpType,
        LPWSTR lpName, LONG_PTR lParam)
    {
        HRSRC hResInfo = FindResource(hModule, lpName, lpType);
        DWORD cbResource = SizeofResource(hModule, hResInfo);
    
        HGLOBAL hResData = LoadResource(hModule, hResInfo);
        const BYTE *pResource = (const BYTE *)LockResource(hResData);
    
        TCHAR filename[MAX_PATH];
        if (IS_INTRESOURCE(lpName))
            _stprintf_s(filename, _T("#%d.manifest"), lpName);
        else
            _stprintf_s(filename, _T("%s.manifest"), lpName);
    
        FILE *f = _tfopen(filename, _T("wb"));
        fwrite(pResource, cbResource, 1, f);
        fclose(f);
    
        UnlockResource(hResData);
        FreeResource(hResData);
    
        return TRUE;   // Keep going
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        const TCHAR *pszFileName = argv[0];
    
        HMODULE hModule = LoadLibraryEx(pszFileName, NULL, LOAD_LIBRARY_AS_DATAFILE);
        EnumResourceNames(hModule, RT_MANIFEST, EnumResourceNameCallback, NULL);
        FreeLibrary(hModule);
        return 0;
    }
    

    或者,您可以使用 Windows SDK 中的 MT.EXE:

    >mt -inputresource:dll_with_manifest.dll;#1 -out:extracted.manifest
    

    【讨论】:

    • 这有点不正确(帮助具有误导性)。通常 .exe 在资源 #1 中具有嵌入式清单,而 .dll 在资源 #2 中具有清单。无论如何,如果您在 #1 中找不到清单资源,请检查 #2 而不是假设它不存在。
    • 实际上我是故意从当前应用程序中读取清单:“提取自己的清单的简单示例”。你的方法也行;-)
    • UnlockResourceFreeResource are obsolete
    • 我从 3.0 开始就开始编写 Windows 了;旧习惯很难改掉:)
    【解决方案2】:

    您可以使用命令行清单工具mt.exe 提取/替换/合并/验证清单,它是 Windows SDK 的一部分:

    C:\Program Files\Microsoft SDKs\Windows\v6.1>mt /?
    Microsoft (R) Manifest Tool version 5.2.3790.2075
    ...
    > To extract manifest out of a dll:
    mt.exe -inputresource:dll_with_manifest.dll;#1 -out:extracted.manifest
    

    不同地点:

    • C:\Program Files\Microsoft SDKs\Windows\v6.1\bin
    • C:\Program Files (x86)\Windows Kits\10\bin\10.0.18362.0\x86

    【讨论】:

    • -out:con 输出到控制台:)
    • 这导致我在使用 Microsoft Visual Studion 2019:mt.exe 时出错:命令行错误 c10100a9:必须指定对输入清单的某些操作(即使只是将输入通过管道传输到输出)
    • 响应自我:我在 PowerShell 中运行了这个命令行,它需要对 inputresource 参数中使用的语法进行一些转义,如下所示:mt.exe "-inputresource:dll_with_manifest.dll;#1" -out:extracted.manifest
    【解决方案3】:

    在记事本中打开文件。内容是纯文本。

    【讨论】:

    • 大声笑,这也适用于 linux 或 bsd 中的“less”命令。谢谢
    • 这是一个非常有用的技巧,可以快速验证其中的内容。谢谢
    【解决方案4】:

    有一个清单查看器工具可用here -- 不知道作者是否会提供源代码。

    【讨论】:

      【解决方案5】:

      如果 Resource Tuner 支持 x64 代码,那就太好了,但截至今天,它仍然只适用于 32 位应用程序。 Resource Hacker(最新的公开测试版)确实支持 x86 和 x64,可从此处获得: http://angusj.com/resourcehacker/

      【讨论】:

        【解决方案6】:

        在已编译的应用程序中查看/编辑清单的最简单方法是使用 Resource Tuner: http://www.restuner.com/tour-manifest.htm

        在某些情况下,它比 MS 的 mt.exe 更强大,而且它是一个可视化工具。

        【讨论】:

          【解决方案7】:

          根据 Roger 的代码,这是我使用的代码。它假定 Manifest 位于 id #1。我猜这是 .exe 的默认设置。请参阅 Wedge 的评论,如果您正在使用 DLL,您可能还需要检查 id #2。

              HMODULE module = ::LoadLibraryEx(pathname, NULL, LOAD_LIBRARY_AS_DATAFILE);
              if (module == NULL)
                  return false;
              HRSRC resInfo = ::FindResource(module, MAKEINTRESOURCE(1), RT_MANIFEST); // resource id #1 should be the manifest
              if (resInfo) {
                  HGLOBAL resData = ::LoadResource(module, resInfo);
                  DWORD resSize = ::SizeofResource(module, resInfo);
                  if (resData && resSize) {
                      const char *res = (const char *)::LockResource(resData); // the manifest
                      if (res) {
                          // got the manifest
                      }
                      ::UnlockResource(resData);
                  }
                  ::FreeResource(resData);
              }
              ::FreeLibrary(module);
          

          【讨论】:

            【解决方案8】:

            通过从项目中删除开发人员许可证 (*_TemporaryKey.pfx) 或更改 .pfx 的名称来解决此问题。

            【讨论】:

              【解决方案9】:

              附带提醒:请记住,清单也可以是与应用同名的独立文件(由“.manifest”扩展)。

              所以如果你想检查在运行时真正使用了哪个清单,必须考虑到这一点。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2016-08-04
                • 2011-12-28
                • 1970-01-01
                • 1970-01-01
                • 2013-10-21
                • 2021-09-27
                相关资源
                最近更新 更多