损坏的 winapi 可执行清单

Posted

技术标签:

【中文标题】损坏的 winapi 可执行清单【英文标题】:Corrupted winapi executable manifest 【发布时间】:2016-09-21 12:32:42 【问题描述】:

我正在开发一个使用 XML 文件的 Qt 应用程序。为了提高性能,我使用 pugixml 解析器而不是 Qt 的 dom 解析器。编译后,我的应用程序和所有依赖项(dll文件,帮助程序)被打包为一个winapi应用程序的资源,以创建单个exe文件。

在我需要将 QString::toStdString() 替换为 QString::toStdWString() 之前,一切正常。其原因是将名称中带有扩展字母 (ąęśćłóźżń) 的文件读入 pugixml。我运行 pugixml::document::load_file() 之前通过 Qt 递归目录循环加载的数据。包含文件名的QStrings 转换为std::wstring,然后转换为const wchar_t*qstring.toStdWString().c_str()

strings 替换为wstrings 后,解压后的可执行文件运行良好。但是,打包后,最终的 .exe 文件有一个损坏的清单,如下所示:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker"/>
      </requestedPrivileges>
    </security>
  </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!--The ID below indicates application support for Windows Vista -->
      <supportedOS Id="e2011457-1546-43c5-a5fe-008deee3d3f0"/>
      <!--The ID below indicates below indicates application support for Windows
 7 -->
      <supportedOS Id="35138b9a-5d96-4fbd-8e2d-a2440225f93a"/>
      <!--The ID below indicates application support for Windows 8 -->
      <supportedOS Id="4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38"/>
      <!--The ID below indicates application support for Windows 8.1 -->
      <supportedOS Id="1f676c76-80e1-4239-95bb-83d0f6d0da78"/>
      <!--The ID below indicates application support for Windows 10 -->
      <supportedOS Id="8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a"/>
    </application>
  </compatibili

我使用的是 Windows 7 64 位,使用 MinGw -w64 shell 编译。最终包的 makefile 如下所示:

all: final.exe

final.exe: sad.o res.o
    g++ -o final.exe -static-libgcc sad.o res.o resource.o -lcomctl32 -lshlwapi -mwindows

sad.o: sad.cpp
    g++ -c sad.cpp

res.o: sad.rc resource.h resource.cpp
    windres sad.rc res.o
    g++ -c resource.cpp

clean:
    rm -f *o final.exe

res.o包含windres打包的程序和所有依赖项,sad.cpp包含从资源调用我的应用程序的winapi程序。

【问题讨论】:

什么是损坏的清单? 它包含在问题中。 XML 在所有节点关闭之前停止 然后我们需要查看生成清单资源的代码。 ...以及用于提取清单的代码(或工具)。 没有生成清单的代码。我猜 gcc 会生成一些默认清单。为了提取清单,我使用了带有 -m 选项的 sigcheck 程序 【参考方案1】:

不确定是什么导致了问题,似乎是编译器错误,但是可以通过从包含有效清单的 xml 文件中创建 winapi 资源来解决此问题。我将描述该过程以供将来参考。

创建一个新的 manifest.rc 文件,如下所示:

#include <windows.h>
RT_MANIFEST BINARY  MOVEABLE PURE "manifest.xml"

然后创建一个包含有效清单 XML 文件的 manifest.xml 文件并添加到 Makefile:

manifest.o: manifest.rc
    windres manifest.rc manifest.o

不要忘记将 manifest.o 添加到 Makefile 中的主程序配方:

final.exe: sad.o res.o manifest.o
    g++ -o final.exe -static-libgcc sad.o res.o resource.o manifest.o -lcomctl32 -lshlwapi -mwindows

【讨论】:

以上是关于损坏的 winapi 可执行清单的主要内容,如果未能解决你的问题,请参考以下文章

Spring Boot 可执行 jar “无效或损坏的 jar 文件”

如何创建清单文件以将我的可执行文件/插件指向我的特定版本的 Qt.dll?

我如何知道可执行文件是不是被增量链接?

IntelliJ Spring Boot:如何创建可执行的 jar

C/C++语言编译生产可执行的二进制文件的过程??求大神详尽解释,

发布时在 clickonce 应用程序中签署可执行文件