When I use $(TargetPath)
in my PostBuildEvent
for a .NET8 console project for the purpose of using signtool
I find that it refers to the file .dll
file and not the file .exe.
It makes sense to sign the .dll
file as it is the actual program. But what MSBuild constant can I use to get the target exe?
At the moment I am doing it like this (lines split for clarity):
echo "$(SignToolPath)signtool.exe" sign
/d "$(TargetPath)"
/fd SHA256
/du "https://www.xyz.co.uk"
/f "d:\My Certificate.pfx"
/p "password"
/t "http://timestamp.sectigo.com"
/v "$(OutDir)"
echo "$(SignToolPath)signtool.exe" sign
/d "$(OutDir)\$(TargetFramework)\$(AssemblyName).exe"
/fd SHA256
/du "https://www.xyz.co.uk"
/f "d:\My Certificate.pfx"
/p "password"
/t "http://timestamp.sectigo.com"
/v "$(OutDir)"
Running the command requested in the comments, I can see (in this order):
<!-- Force .dll extension for .NETCoreApp and .NETStandard projects even if output type is exe. -->
<TargetExt Condition="'$(TargetExt)' == ''">.dll</TargetExt>
<PropertyGroup>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='exe'">.exe</TargetExt>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='winexe'">.exe</TargetExt>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='appcontainerexe'">.exe</TargetExt>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='library'">.dll</TargetExt>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='module'">.netmodule</TargetExt>
<TargetExt Condition="'$(TargetExt)' == '' and '$(OutputType)'=='winmdobj'">.winmdobj</TargetExt>
</PropertyGroup>
Dotnet Core builds a cross-platform DLL containing your app's code and then create a stub executable for the targeted platform that will call the entry point in the DLL.
https://learn.microsoft.com/en-us/dotnet/core/deploying/#publish-framework-dependent
Since your app's code is compiled into a DLL, $(TargetPath)
will refer to the DLL. To determine whether your app was compiled as a DLL and a stub executable, you can use the $(UseAppHost)
property. It will be set to true
if a stub executable was created, or be blank. To then access the path of the stub executable, you can use $(AssemblyName)$(_NativeExecutableExtension)
.
I got this information from searching through the output from dotnet build -pp
.
To sign both the output DLLs and the stub executables, I'd use something like this:
<Target Name="Code Signing" AfterTargets="PostBuildEvent">
<PropertyGroup>
<SignTimestampUrl>http://timestamp.digicert.com</SignTimestampUrl>
<SignCertName>Name of my cert</SignCertName>
<SignToolPath>$(MSBuildProgramFiles32)\Microsoft SDKs\ClickOnce\SignTool\signtool.exe</SignToolPath>
<SignCommand>"$(SignToolPath)" sign /a /n "$(SignCertName)" /t $(SignTimestampUrl)</SignCommand>
</PropertyGroup>
<Exec Command="$(SignCommand) "$(TargetPath)"" />
<Exec Condition="$(UseAppHost) == 'true'" Command="$(SignCommand) "$(TargetDir)$(AssemblyName)$(_NativeExecutableExtension)"" />
</Target>