This blog post explains one way to code sign your internal applications along with their installers. Code signing your applications and installers provide a UAC friendly user experience during installation, uninstall, and when your legacy applications may need to run with administrative privileges (more about admin privileges below).
UAC Friendly Installation Experience
The below image pictures a user friendly UAC dialog, complete with Program name, Verified publisher. If you internal applications are not code signed, the user will get a warning dialog, with a bizarre program name, and Verified publisher set to unknown.
I don’t know about you, but I would rather condition my users to see UAC friendly dialogs, rather than the warning dialog. Next thing you know, they have “accidently” approved a UAC warning that could cause you a big problem.
If you are signing applications that are not internal to your organization, the content surrounding certificates and the guidance surrounding signtool.exe may violate your organizations code signing rules or procedures.
This blog post is about code signing internal applications that will be used within your organization.
Code Signing Certificate
The first order of business is to get a code signing certificate installed on machines that will build your internal applications. You can see from the below image, that my certificate server gmcx-Security-CA has issued a code signing certificate and that I have imported that certificate into the “Personal” Store under the “Certificates” folder.
To be honest, creating a code signing certificate that did not have my name on it, instead had our organization’s name is was bit of a PIA and required creating a certificate template on the certificate server that allowed me to do this. I found this TechNet article very helpful:
After you create the certificate, export it and import it on all machines under the users “Personal” store as above.
For example, I have this certificate installed on our two developer machines and on the build server.
Configuring the Solution (executable projects)
There are several ways to configure actions that take place during MSBuilds. I have chosen the “batch file” method because it is very easy to implement and debug. You could leverage one of two out-of-the-box build Tasks or create your own build task, but I chose “batch files” for the above reasons.
Notice that I have checked these batch files into source control. This ensures that all machines can build the solution correctly.
If your scenario requires code signing the debug build, the below batch file uses the signtool.exe program to code sign the .exe program. You “could” also pass in command line parameters to the batch file that would include the folder name of the target along with the target name. I’ve kept this simple to make it easier to understand all the pieces.
Notice that I didn’t have to specify a certificate, password, etc. This is because I only have one code signing certificate installed on my machine. The “/a” switch instructs signtool to automatically pick the code signing certificate from my “Personal” store.
call “C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”
call signtool sign /a “C:\Projects\GMC\Src\GMC\bin\Debug\GMC.exe”
AfterBuildTasksRelease.bat and the Gotcha
Now time for a nasty gotcha. This little beast cost me about 2 hours trying to figure out why, every time I did a Release build using the Setup project to build and create the install package that the .exe the installer installed was not longer signed.
Read this thread on the Windows Dev Center for full details:
Setup project strips digital signature from exe target
Now that you have read the above thread, you’ll fully understand why when creating a release build, you must code sign the .exe under the \obj and \bin folders.
The signtool… commands sign my .exe. Let me call out one additional signtool switch you need to mind when signing your .exe.
You should also specify the “/t” switch. This will time stamp your .exe so the user knows when the .exe was built.
Configuring Visual Studio 2010 to Use the above Batch Files During a Build
- Open the Build Events dialog from the .exe project’s properties tab.
- Change the “Run the post-build event” option to “When the build updates the project output.”
- Enter the above text in the “Post-build event command line” text box.
This will run one of the two batch files based on the configuration, Debug or Release.
Building the Solution
Like many of you, I don’t build my Release builds within Visual Studio. Some use a build server, others build them from the command line to allow other tasks to be accomplished.
Below is a fragment of a batch file that I use when building a release build. The devenv… command rebuilds my solution. Notice the “/rebuild” switch instead of the “/build” switch.
The signtool… command signs my .msi installer that the Setup project built. Let me call out two additional signtool switches you need to mind.
It is important that you specify the “/d” switch for your .msi installers. If you scroll back up to the top of this blog post and view the UAC image, you’ll notice the Program name matches the text in the below “/d” switch. If you don’t specify this, your user will see some bizarre text.
You should also specify the “/t” switch. This will time stamp your installer so the user knows when the installer was built.
call “C:\Program Files\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”
devenv /rebuild Release /project GMC_Setup C:\Projects\GMC\Gmc.sln
signtool sign /a /d “GMC for Office 2010 Setup” /t http://timestamp.comodoca.com/authenticode
… additional tasks
Legacy Applications Running on Windows 7 and Above
My company has a legacy Windows Forms application that was written during the days of Windows XP. My company like many other enterprises never installed Windows Vista. Recently we installed Windows 7 on our enterprise desktops.
Well the legacy enterprise applications I’ve inherited do things are are not UAC friendly. For example, writing to the \Program Files folder and other tasks that are now under Windows 7 considered taboo.
Being a good Enterprise Administrator and Developer, I want all my clients running Windows 7 with UAC set to the Default setting and for my users to learn about the UAC feature and its benefits; this will provide them a safer computing environment here at work and at home.
Microsoft has documented UAC here: http://msdn.microsoft.com/en-us/library/windows/desktop/aa511445.aspx
Microsoft and bloggers have documented a number of strategies for dealing with UAC and legacy applications. Turning UAC off or limiting its capabilities should not be considered a good option.
I was not willing to take on the risk of modifying our legacy applications, so I run my few enterprise applications with an embedded application manifest that tells the operating system this application requires administrator privileges to execute. All of our users are administrators on their local computer.
Example Application Manifest
Notice the the below application manifest that the “requestExecutionLevel” is “requireAdministrator.”
<?xml version=”1.0″ encoding=”UTF-8″ standalone=”yes”?>
<assembly xmlns=”urn:schemas-microsoft-com:asm.v1″ manifestVersion=”1.0″>
<assemblyIdentity version=”126.96.36.199″ processorArchitecture=”X86″ name=”GMC” type=”win32″/>
To embed the above application manifest you need to use the mt.exe program. I placed the below command at the top of my two batch files, AfterBuildTasksDebug.bat and AfterBuildTasksRelease.bat.
You’ll need to edit the paths and .exe name as well as the manifest name.
call “C:\Program Files\Microsoft SDKs\Windows\v7.0A\bin\mt.exe” -manifest
For those of you that have the need or desire to code sign your internal enterprise applications, I hope this blog post will help you avoid the long learning curve.
Have a great day,
Just a grain of sand on the worlds beaches.