读取应用程序的清单文件?

45

有没有一种简单的方法读取一个应用程序已经嵌入的清单文件?

我在考虑使用备用数据流的方式?

10个回答

51

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

10
这个帮助信息有些错误(会误导人)。一般来说,.exes文件的嵌入式清单在资源#1中,而.dlls文件的清单则在资源#2中。但无论如何,如果你在#1中找不到清单资源,应该检查#2而不是假设它不存在。 - Wedge
其实我是故意从当前应用程序中读取清单的:“提取自己清单的简单示例”。你的方法也可以工作;-) - Roger Lipscombe
UnlockResourceFreeResource都已经过时。 - ghord
我从3.0开始就一直在编写Windows程序;老习惯难改 :) - Roger Lipscombe

36

您可以使用命令行清单工具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

4
-out:con 用于将输出结果打印到控制台 :) - Martin Connell
我在使用Microsoft Visual Studio 2019时遇到了错误:mt.exe: 命令行错误 c10100a9:必须指定对输入清单的某些操作(即使只是将输入导向输出)。 - mzabaluev
3
回应自己:我在 PowerShell 中运行了这条命令,并且需要为 inputresource 参数中使用的语法进行一些转义,方法如下:mt.exe "-inputresource:dll_with_manifest.dll;#1" -out:extracted.manifest - mzabaluev

33

在记事本中打开该文件。这个东西是纯文本。

屏幕截图


2
哈哈,这个命令在Linux或BSD上也可以用'less'命令。谢谢。 - don bright
这是一个非常有用的技巧,只需快速验证其中的内容即可。谢谢。 - StayOnTarget

12

这里有一个清单查看工具,点击这里 -- 我不知道作者是否会提供源代码。


4

如果 Resource Tuner 支持 x64 代码就更好了,但是截至今天,它仍然只支持 32 位应用程序。Resource Hacker(最新的公共测试版)支持 x86 和 x64,可以从这里下载:http://angusj.com/resourcehacker/


2

最简单的查看/编辑已编译应用程序中清单的方法是使用资源调整工具:

http://www.restuner.com/tour-manifest.htm

在某些情况下,它比来自微软的mt.exe更强大,并且是一种可视化工具。


1

在 Roger 的代码基础上稍作修改,这是我使用的代码。它假设清单文件位于 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);

0

0
作为一个小提示:请记住,清单文件也可以是与应用程序同名的独立文件(通过“.manifest”扩展名进行扩展)。
因此,如果您想查看运行时实际使用的清单文件,必须考虑这一点。

-1

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接