Reputation: 3788
In Visual Studio you can set an option "Additional Manifest Files" in C++ projects in order to merge an additional manifest file into the default application manifest.
We use this option with a shared "compatibility manifest" that only includes a list of supported OS versions:
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
<application>
<supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/> <!--app support for Windows Vista -->
<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/> <!--app support for Windows 7 -->
<supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/> <!--app support for Windows 8 -->
<supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/> <!--app support for Windows 8.1 -->
</application>
</compatibility>
</assembly>
Now we would like to embed that shared manifest also into existing WinForms/WPF applications, so that it merges with the existing application manifest files. Is that possible with C# projects? We would like to avoid defining this list of OSes in every project.
Upvotes: 13
Views: 1778
Reputation: 22301
You can insert mt
into the build process by defining custom targets that merge the manifests before inclusion in the exe. Add the following targets to your project file, then add additional manifests as <AdditionalManifestToMerge
items.
Targets:
<Target Name="GenerateComFreeManifestItems" Condition="'@(AdditionalManifestToMerge)' != ''">
<PropertyGroup>
<Win32ManifestPreMerge>$(Win32Manifest)</Win32ManifestPreMerge>
<Win32Manifest>$(IntermediateOutputPath)app_merged.manifest</Win32Manifest>
<MtPath Condition="'$(MtPath)' == ''">C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x86\mt.exe</MtPath>
</PropertyGroup>
</Target>
<Target Name="GenerateComFreeManifest" BeforeTargets="CoreCompile" DependsOnTargets="GenerateComFreeManifestItems"
Condition="'@(AdditionalManifestToMerge)' != ''"
Inputs="@(AdditionalManifestToMerge);$(Win32ManifestPreMerge)"
Outputs="$(Win32Manifest)">
<Exec Command=""$(MtPath)" -manifest "$(Win32ManifestPreMerge)"@(AdditionalManifestToMerge -> ' "%(Identity)"') -out:"$(Win32Manifest)"" />
<ItemGroup>
<FileWrites Include="$(Win32Manifest)" />
</ItemGroup>
</Target>
Item(s):
<ItemGroup>
<AdditionalManifestToMerge Include="..\path\to.dll.manifest" />
</ItemGroup>
Note: This is a bit fragile since it depends on the location of mt.exe being consistent on each machine. I'm sure there is a proper way to find it - but google has failed me (see Path to SignTool.exe or "Windows Kits" directory when using Visual Studio 2012 for some bad options)
Upvotes: 0
Reputation: 12007
You can use a post-build action calling the ManifestTool mt.exe (from the Windows SDK) to add or update a manifest:
mt.exe -updateresource:"myapp.exe";#1 -manifest "additional.manifest"
See MT command line for more information.
Note that when you opted to sign the assembly, you have to re-sign it after this modification:
sn.exe -R "myapp.exe" "mykey.snk"
Upvotes: 0