Setup project strips digital signature from exe target
-
Friday, January 23, 2009 8:38 PM
I'm using Visual Studio 2008 to develop an application that integrates with QuickBooks. For added security, my exe file is signed so that QuickBooks can verify that my application is safe to access the QuickBooks company file. I'm using signtool in a post build step to sign the exe. This appears to be working fine: after the application is built, the exe assembly is signed with my code signing certificate.
I'm using a standard VS 2008 setup project to package this applicaiton for distribution. I'm also signing the MSI output using signtool, and that appears to be working fine. However, when I install the application from the MSI file, I find that the exe assembly is not longer signed! It appears to be exactly the same assembly with the digital signature removed.
In looking at the output from a "rebuild all" on the setup project, I can see that the signtool successfully signes the exe file before the setup project starts to build. So it appears that the digital signature is being removed as part of the MSI build process.
Is there a way I can build a signed exe and package it in an MSI file using a Visual Studio setup project?
All Replies
-
Friday, January 23, 2009 11:25 PMMy guess is that the file being signed and the file being picked up by the setup project are different files. Could this be an obj vs. bin problem, or maybe inconsistent configs (for example, maybe you added the "debug" project output group to the setu pproject, but you're only signing the "release" config)
-- Mike -
Sunday, January 25, 2009 12:06 AM
I double checked the output exe file, the output path setting on the setup project, and the project build settings on both projects. Everything checks out, and the exe is definitely signed. It doesn't look like there's been any mixup in this area.
It was good to double-check this though. Thanks for the suggestion.
-
Tuesday, January 27, 2009 8:44 AMModerator
Hi Paul Keister,
Do you mean you sign your exe with signtool not Visual Studio? I think you can sign your application with the signing function in Visual Studio "Signing" page. When Visual Studio rebuild the MSI package, it will recompile the project before build the package. You can see the process in Output window. The newly compiled assembly will replace the previous one. I think this may cause the issue.
Please use the signing function in Visual Studio, take this for reference.
http://msdn.microsoft.com/en-us/library/ms247123(VS.80).aspxSincerely,
Kira Qian
Please mark the replies as answers if they help and unmark if they don't.- Marked As Answer by Kira QianModerator Friday, January 30, 2009 8:08 AM
- Unmarked As Answer by Paul Keister Saturday, January 31, 2009 1:06 AM
-
Saturday, January 31, 2009 1:12 AM
Kira,
Thank you for your input. I am not trying to sign the assemply with a strong key file, I am tring to sign it with a code signing certificate from the certificate store. From what I can see, the signing page of a VS 2008 project allows me to sign the project click once manifest with a certificate, but the only option for signing an assembly is to use a strong name key file.
A strong name only is not adequate for this situation, because the code publisher must be verified.
Also, your speculation about the rebuild is interesting. However, if this were true then the file that was left behind after the MSI rebuilt would not be signed, correct? I can tell you that this is not the case. After I rebuild the MSI in release configuration, the relase directory contains a signed binary.
One theory I have is that the MSI build process is grabbing the binary image before the signing tool is executed. However, project output window during the MSI build does not support this theory either.
-
Thursday, May 07, 2009 1:30 PMHi Paul,
I'm having the same problem at the moment! Did you find an solution?
Greetings
Gerrit Horeis -
Sunday, May 10, 2009 6:31 AM
No, my exe is still not signed :-(
-
Sunday, June 28, 2009 2:52 AM
hi there,I stopped to this thread before finding elsewhere an example I used as reference to write necessary code and what to implement in order to do sign the .exe and the .msi for our Visual Studio 2008 Setup Project and I joined the 2 contents at the end of this post.I hope that will help anyone!Let me know,Regards,Jean-Guillaume Isabelle______________________________Content of the "PostBuildEvent" (this setting is in "Deployment Project Properties")set BuiltOuputPath=$(BuiltOuputPath) set ProjectDir=$(ProjectDir) call $(ProjectDir)makeSign.bat
Content of "makeSign.bat" located on my project root [ $(ProjectDir) ]@echo off rem Signing tool and SDKs part. set MSSDKsRoot=c:\Program Files\Microsoft SDKs set signtoolexe="%MSSDKsRoot%\Windows\v6.0A\bin\signtool.exe" rem Certificate part. rem This .pfx is an Export from my Certificate Store of a Signing Certificate rem issued from the Intranet Certificate Service that include the private key encrypted using password 12345 set mycert="%ProjectDir%RAjgisabelle_CodeSigningIII.pfx" set mycertpasswd="12345" rem Signing information Part. set mySigningDescription="Jgisabelle MyProduct Environment Installer" set mySigningDescriptionUrl="http://intranet.jgisabellesoft.com/EnvironmentInstaller" rem note. "BuiltOuputPath" and "ProjectDir" batch variables has to come from the PostBuildEvent $(BuiltOuputPath) and $(ProjectDir) rem which look like that: rem PostBuildEvent start { rem set BuiltOuputPath=$(BuiltOuputPath) rem set ProjectDir=$(ProjectDir) rem call $(ProjectDir)makeSign.bat rem PostBuildEvent end } rem signing part. rem WE USUALLY SHOULDN'T CHANGE THAT UNLESS YOU KNOW WHAT YOU ARE DOING ;) rem sign the .exe %signtoolexe% sign /f %mycert% /p %mycertpasswd% /d %mySigningDescription% /du %mySigningDescriptionUrl% /q %1%2\setup.exe rem sign the .msi %signtoolexe% sign /f %mycert% /p %mycertpasswd% /d %mySigningDescription% /du %mySigningDescriptionUrl% /q %BuiltOuputPath% IF NOT ERRORLEVEL 0 GOTO ERRORSIGNING rem sign the .exe %signtoolexe% sign /f %mycert% /p %mycertpasswd% /d %mySigningDescription% /du %mySigningDescriptionUrl% %3 rem sign the .msi %signtoolexe% sign /f %mycert% /p %mycertpasswd% /d %mySigningDescription% /du %mySigningDescriptionUrl% %BuiltOuputPath% IF NOT ERRORLEVEL 0 GOTO ERRORSIGNING exit /B 0 :ERRORSIGNING exit /B 1
JGI- Edited by Jean-GUIllaume Sunday, June 28, 2009 2:54 AM type, formatting
-
Wednesday, August 19, 2009 7:47 AMHello Paul,
Have you found a solution yet? I'm experiencing the same problem.
I'm also using the signtool.exe to sign all assemblies in a post-build event with a command like:
"C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bin\signtool" sign /f "Key.pfx" /p password "$(TargetPath)"
I also have a default setup that includes the project output of the main assembly.
Instead of the signtool I also tried to use the 'Sign the assembly' project setting. This setting accepts a .pfx file to sign the assembly, but displays an error message when using our code signing file. So this is not a valid option.
The signature-losing-problem is not bound to the building of the MSI only. Our solution consists of several projects that make use of one another. When I set that the post-build event should be executed 'When the build updates the project output', then assemblies that are referenced by other projects will also loose their signature. Setting the option to 'On successful build' solves this problem, but I'm not exactly sure why. Somehow the signature gets lost when the assembly is copied from one output directory to the other.
I know that a digital signature will be gone when a file is changed (but not when it is copied). When I open a dll in Visual Studio I can change, for instance, the copyright information and when I save the dll, the signature is gone. So maybe something like that is happening when building the setup.
When trying to find out what was happening, I built the setup without rebuilding the other projects. The last change time of the assembly was 17:01 and had a digital signature. After that I built the setup at 17:05 and ran it. The assembly in the Program Files directory had a last change time of 17:01, but the digital signature was gone. So unfortunatly it does not seem like the assembly is changed...
The reason of signing the assemblies is that we are trying to get a Windows Logo for our application. Because code signing is needed for that, I'd expect that it would be a standard procedure in VS2008. Unfortunatly support for code signing is lacking in VS2008 in my opninion.
Kind regards,
Gerbrand Stap -
Wednesday, August 19, 2009 10:43 AM
I have looked into this problem a litte further and found a solution, although it is not a very pretty one.
Instead of adding the project output of the main project to the setup, I added the .exe file (assembly). Visual Studio detects all dependencies it detected when the project output was added, so it looks like adding the file works the same. Even custom install actions seem to function properly after changing them to the .exe (if you don't forget to pass the right parameters). After some small changes like changing shortcuts and icons and adding the .exe.config, I had a functioning setup. And with the difference that I did not loose my digital signatures after install.
The only downside of this solution (as far as I can see) is that there is no distinction between Debug and Release. I added the .exe from the Release folder, so accidentally building the setup in Debug will result in a setup with Release files from the last Release build. But a setup should in my case always be a Release build, so this is not a big problem.
So it seems that Visual Studio does something to Project Outputs that it does not to Files added to a setup. Maybe this is something for Microsoft to take a look at?
-- Update (September 1, 2009) --
This workaround is not needed, see ajhuddymsdn's post.- Proposed As Answer by Gerbrand Stap Wednesday, August 19, 2009 10:43 AM
- Edited by Gerbrand Stap Thursday, October 01, 2009 9:22 AM
-
Tuesday, September 22, 2009 6:21 PMHi Gerbrand,
Your workaround behaved as advertised. It would be perfect if it could switch from release to debug along with the setup configuration.
Thanks
Mario -
Monday, September 28, 2009 11:02 PM
When your setup project includes the 'Primary Output' of another project in the solution, the setup project uses the compiled output from [ProjectName]\obj\[PlatformName]\Release\[YourProgram.exe]
So...in your executable project, add the following to the post build (modify as needed)
call signtool.exe sign /f "$(SolutionDir)Certificate.pfx" /p YourPassword "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)\$(TargetFileName)"
And in any dependend projects of the executable, add the following post build command (modify as needed):
call signtool.exe sign /f "$(SolutionDir)Certificate.pfx" /p YourPassword "$(TargetPath)"
Hope this helps. It works for me.- Proposed As Answer by Mario Montes Tuesday, September 29, 2009 11:58 AM
- Marked As Answer by Paul Keister Tuesday, October 26, 2010 5:09 AM
-
Tuesday, September 29, 2009 11:58 AM
Thanks!
Mario -
Thursday, October 01, 2009 9:21 AM
Thanks for the hint!
Signing the assembly in the obj directory solves the problem and also explains why the executing the post build event 'When the build updates the project output' is not sufficient. I understand now that building a project takes the following steps:
1. if( change )
compile and put result in obj
2. copy assembly from obj to bin
3. if( post build needed )
execute post build
When a project is not changed and the assembly in the obj directory is not signed, it will overwrite the (signed) assembly in the bin directory. And the assembly will not be signed when the post build is set to 'When the build updates the project output'. Unfortunately an event can not be executed between steps 2 and 3. So now I sign all the assemblies in both the obj and bin directories (which are the same at that point) and this is done 'When the build updates the project output'. This way building is faster when (almost) nothing has been changed.
Because of this change my setup project could be changed back to its original configuration. So my 'not so pretty' solution can be ignored. -
Thursday, February 25, 2010 7:56 PMThanks for documenting this. I had been tearing my hair out trying to figure out why this was happening.
It seems very unfortunate that a moderator or MVP has not contributed to this in a year nor did they have this solution when they did contribute.
Very helpful. My deployed assemblies are now signed.
George -
Thursday, March 25, 2010 5:30 PM
-
Monday, September 27, 2010 9:29 PM
Thanks to everyone (ajhuddymsdn, Jean-Guillaume Isabelle, and Gerbrand Stap, etc) who provided information for this post. I've seen this problem posted on a lot of forums, but this was the only one that provided the answer. It is greatly appreciated.
John.
-
Wednesday, October 06, 2010 4:32 PM
Thank you for the info, ajhuddymsdn. This solved my problem too!
It also raises the question of why we should end up with 2 copies of our executables. Why do we need bin AND obj?
-
Tuesday, October 19, 2010 2:25 PMThank you for pressing through to find a better solution than the "not pretty" one! This helps me tremendously!
Paul Fuller -
Friday, April 13, 2012 6:15 PM
This is still broken in Visual Studio 2010 SP1.
Microsoft - PLEASE FIX THIS BUG.
Karl
Cheers, Karl - patterns & practices team, http://karlshifflett.wordpress.com/
-
Friday, April 13, 2012 6:18 PM
Mike,
This bug is still in VS 2010 SP1. Can you please have this bug fixed.
Thanks,
Karl
Cheers, Karl - patterns & practices team, http://karlshifflett.wordpress.com/
-
Wednesday, April 18, 2012 3:57 PM
Hi Kira Qian,
I am facing a similar problem , the installer project that gets built after my code is compiled and signed is replacing the files by re-building the code again.
Why do you think the installer is again building all .csproj files, I just used /build option with devenv.exe from command line to build the .vdproj (installer project). I am using msbuid.xml to run from command line.From what I analyzed it looks like I need to stop the setup project (.vdproj) from doing a re-building everything again, how to do that. Appreciate your help.
-
Wednesday, April 03, 2013 9:41 AM
When your setup project includes the 'Primary Output' of another project in the solution, the setup project uses the compiled output from [ProjectName]\obj\[PlatformName]\Release\[YourProgram.exe]
So...in your executable project, add the following to the post build (modify as needed)
call signtool.exe sign /f "$(SolutionDir)Certificate.pfx" /p YourPassword "$(ProjectDir)obj\$(PlatformName)\$(ConfigurationName)\$(TargetFileName)"
And in any dependend projects of the executable, add the following post build command (modify as needed):
call signtool.exe sign /f "$(SolutionDir)Certificate.pfx" /p YourPassword "$(TargetPath)"
Hope this helps. It works for me.I just add the exact same problem with a ClickOnce package and .NET 4 executable (under VS 2012)
Your solution works very well, thanks !


