マニフェストファイルをC++プロジェクトに追加する

もくじ
https://tera1707.com/entry/2022/02/06/144447

やりたいこと

マニフェストファイル」をC++アプリ(exe)に適用したい。

C#だったら、プロジェクトを右クリックして、追加 > マニフェストファイル、みたいに簡単にできるのに、C++はできない。どうしたらいいのか?

前提

  • VS2022 Community

やったこと

C#で追加したマニフェストC++プロジェクトにコピーしてきて適用する、みたいなやり方をした。
下記の通り。

C#プロジェクトでマニフェストを追加する。
※追加の仕方はこちら参照。

C#で追加したマニフェストファイルをコピーしてくる。
(今回はvcxprojファイルと同じ階層にコピーした)

追加したまんまの状態だと下記のような内容だった。

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="WindowMessageSender.app"/>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false" />
            </requestedPrivileges>
        </security>
    </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10. 
      It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
      For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </application>
  </compatibility>
  
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
    </windowsSettings>
  </application>
</assembly>

コピーしたら、

ヘッダーファイル > リソースファイル を右クリック > 追加 > 既存の項目 を選択する。

これで、マニフェストが適用された。

ビルドをすると、上記内容のマニフェストがexeに適用される。

マニフェスト適用前と後の確認

exeに適用されたマニフェストを出力できるツール(mt.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" uiAccess="false"></requestedExecutionLevel>
      </requestedPrivileges>
    </security>
  </trustInfo>
</assembly>

適用後はこれ。

PerMonitorV2が適用されている。

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly manifestVersion="1.0"
    xmlns="urn:schemas-microsoft-com:asm.v1">
    <assemblyIdentity version="1.0.0.0" name="WindowMessageSender.app"></assemblyIdentity>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="false"></requestedExecutionLevel>
            </requestedPrivileges>
        </security>
    </trustInfo>
    <ms_asmv3:application xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3"
        xmlns="urn:schemas-microsoft-com:asm.v3">
        <ms_asmv3:windowsSettings xmlns:ms_asmv3="urn:schemas-microsoft-com:asm.v3">
            <ms_windowsSettings2016:dpiAwareness xmlns:ms_windowsSettings2016="http://schemas.microsoft.com/SMI/2016/WindowsSettings"
                xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</ms_windowsSettings2016:dpiAwareness>
        </ms_asmv3:windowsSettings>
    </ms_asmv3:application>
    <ms_compatibility:compatibility xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1"
        xmlns="urn:schemas-microsoft-com:compatibility.v1">
        <ms_compatibility:application xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1">
            <ms_compatibility:supportedOS xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"></ms_compatibility:supportedOS>
        </ms_compatibility:application>
    </ms_compatibility:compatibility>
</assembly>

vcxprojと重複する設定項目をマニフェストに書くとエラーになる?

上で適用したマニフェストで、UiAccess=falseのところだけtrueに変えて、ビルドしてみる。 (下記のようにした。)

<?xml version="1.0" encoding="utf-8"?>
<assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1">
  <assemblyIdentity version="1.0.0.0" name="WindowMessageSender.app"/>
    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2">
        <security>
            <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3">
                <requestedExecutionLevel level="asInvoker" uiAccess="true" />
            </requestedPrivileges>
        </security>
    </trustInfo>
  <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <application>
      <!-- The ID below informs the system that this application is compatible with OS features first introduced in Windows 10. 
      It is necessary to support features in unpackaged applications, for example the custom titlebar implementation.
      For more info see https://docs.microsoft.com/windows/apps/windows-app-sdk/use-windows-app-sdk-run-time#declare-os-compatibility-in-your-application-manifest -->
      <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </application>
  </compatibility>
  
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAwareness xmlns="http://schemas.microsoft.com/SMI/2016/WindowsSettings">PerMonitorV2</dpiAwareness>
    </windowsSettings>
  </application>
</assembly>

そうするとビルド時に、下記のようにmt.exeでエラーになった。

推測だが、vcxprojの中で「UiAccess=false」にしているため、マニフェストの設定と喧嘩して、エラーになってるのではと思う。
(falseにしているとエラー起きないので)

備考

できたことはできたのだが、正しいのかどうかわからない。
やり方的には正しくない雰囲気バリバリ(C#マニフェストをパクってくるところとか)なのだが、

マニフェストとvcxprojでの設定は、どちらも行うようにはできてない気がする?
 (「マニフェスト」がC++の設定よりも新しい概念で、同時に使うものではないのかも??)

ただ、一応できたものはできたのでメモっておく。