This is the fifth article in my series about setting up and working with your Dexterity Development Environments.
If you have not read the previous articles, please do so first using the links below:
- #Dexterity Development Environments – Part 1: Installation
- #Dexterity Development Environments – Part 2: Setting up Projects
- #Dexterity Development Environments – Part 3: Single Code Base
- #Dexterity Development Environments – Part 4: Creating Chunk Files
Disclaimer: This is the Musgravion principles of development machine setup. It is not the only method but it has worked for me for many years and has been fine tuned during my career. Feel free to use it if it works for you.
In the previous article we discussed automating the chunking process and backing up. In this article we will cover creating and signing of Dictionary Assemblies.
Dictionary Assembly DLLs
Best practice for distributing Dexterity based product dictionaries as chunk files is to now also distribute the Dictionary Assembly DLL files created by the DAG.exe (Dictionary Assembly Generator) tool. These assembly files can be used by Visual Studio Tools to address resources and scripts in the Dexterity dictionary. For GP 2015 or later, an additional assembly is generated when the Dexterity product contains Service Based Architecture (SBA) Service Procedures which are exposed as web services.
If your product has a Visual Studio Tools Addin or offers Service Procedures, you will need to “DAG” your dictionary, but it is best practice to always create the assemblies, so that they are available for other developers if needed.
You should also be signing any DLL files you generate as well as using a Code Signing or Authenticode Certificate to add both SHA-1 and SHA-256 digital signatures. The DLLs should be dual signed with both SHA-1 for older operating systems and SHA-256 for Windows 8 onwards.
Signing your code
To avoid having to go through the steep learning curve that I had to, here are the steps to signing your code.
Create a Strong Name Key
Using the .Net Framework Strong Name Utility, create the .SNK file that will be used to sign your product. You can use the same key file for all versions of your product. The commands below can be used:
cd C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools sn -k 1024 c:\DexXX00\Project\Project.snk
Purchase a Code Signing Certificate
I used GoDaddy to purchase a Code Signing Certificate, but you can use any provider you wish. To request the certificate you will need to provide a Certificate Signing Request (CSR) which I generated using the online CSR Generator tool.
Your Certificate will be provided as a file with a name being the 16 hexadecimal digits representing the Certificate’s Serial Number and the extension .spc (Software Publisher Certificate).
Locate the Tools needed
You will need some tools to prepare your Certificate for use when signing. I located all the tools and then placed them into a folder which is included in the PATH environment variable to make them available from any command prompt. I used the WinZip folder: C:\Program Files\WinZip
You will need pvk.exe which I downloaded from PVK file information. Download the pvktools.zip file using the “Win32 binary here” link.
You will also need pvk2pfx.exe and signtool.exe which should be located in the following folder:
C:\Program Files (x86)\Microsoft SDKs\Windows\v7.1A\Bin
Copy the three tools to a folder that is in the PATH to make them easy to use.
Create .key text file
Using Notepad.exe, copy the section from the CSR between and including “—–BEGIN RSA PRIVATE KEY—–” and “—–END RSA PRIVATE KEY—–” and save this with the same file name with the .key extension.
Convert .key text file to .pvk file
Create the Private Key (pvk) file using the pvk.exe tool and the following command:
pvk -in 0123456789ABCDEF.key -strong -out 0123456789ABCDEF.pvk -topvk
Combine the .pvk & .spc files into .pfx file
Use the pvk2pfx.exe tool to combine the certificate file with the private key file to create the encrypted certificate (pfx) file. You will need to use a password which you must remember as it will be needed when signing the files.
pvk2pfx -pvk 0123456789ABCDEF.pvk -spc 0123456789ABCDEF.spc -pi <Password> -pfx 0123456789ABCDEF.pfx
Once you have the .pfx file and the password, you can archive the intermediary files as they will not be needed again.
Signing your files
To sign the DLL files created by the Dictionary Assembly Generator tool you will need commands like the examples below. Note that the actual commands are included in the scripts provided later in the article.
signtool sign /f 0123456789ABCDEF.pfx /p <Password> /t http://timestamp.comodoca.com/authenticode <Filenames> signtool sign /fd sha256 /td sha256 /as /f 0123456789ABCDEF.pfx /p <Password> /tr http://timestamp.comodoca.com/authenticode <Filenames>
You can use any Timestamp server, but I found that the one from comodoca.com was most reliable and supports both SHA-1 and SHA-256 signing.
Elevating permissions for Batch Files
The final script for this article copies the signed DLL files to the default location in the C:\Program Files (x86) folder so that any Visual Studio Tools projects using the DLLs can locate them in the default install location for Microsoft Dynamics GP. To be able to copy the files to this location the script needs to be “Run as Administrator”.
Original, the batch file would fail if permissions were not elevated, but now I use some nifty code to automatically ask to elevate and then re-run the batch file with elevated permissions. Details of this method can be found at the links below:
- How to Create a Batch File that will Automatically Run as Administrator
- Launch Batch Scripts as Administrator (with GUI UAC prompt)
Creating, Signing and Copying your Dictionary Assemblies
We have finally got to the exciting part of the article with the batch file script that pulls everything together. It will perform the following actions for you:
- Elevate permissions if required
- Copy your Dexterity Chunk file to the application folder
- Delete any old DLL and XML files
- Run Dynamics.exe to extract the Chunk file
- Run the DAG.exe to generate the dictionary assemblies with a strong key
- Sign the assemblies with SHA-1 Code Signing Certificate
- Sign the assemblies with SHA-256 Code Signing Certificate
- Copy the generated and signed files to your development folder
- Copy the generated and signed files to the application folder
- Copy the generated and signed files to the default install folder
So here it is ….
DAG.BAT
@echo off cls echo Must Run as Administrator - ProjectName echo. :: BatchGotAdmin (Run as Admin code starts) REM --> Check for permissions >nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system" REM --> If error flag set, we do not have admin. if '%errorlevel%' NEQ '0' ( echo Requesting administrative privileges... goto UACPrompt ) else ( goto gotAdmin ) :UACPrompt echo Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs" echo UAC.ShellExecute "%~s0", "", "", "runas", 1 >> "%temp%\getadmin.vbs" "%temp%\getadmin.vbs" exit /B :gotAdmin if exist "%temp%\getadmin.vbs" ( del "%temp%\getadmin.vbs" ) pushd "%CD%" CD /D "%~dp0" :: BatchGotAdmin (Run as Admin code ends) CD C:\DexXX00\Project copy Project.cnk C:\DynXX00\*.* CD C:\DynXX00 if exist Application.ProjectName.dll del Application.ProjectName.dll if exist Application.ProjectName.xml del Application.ProjectName.xml if exist Application.ProjectName.Metadata.dll del Application.ProjectName.Metadata.dll if exist Application.ProjectName.Metadata.xml del Application.ProjectName.Metadata.xml Dynamics.exe Dynamics.set /CNKONLY echo Creating Signed DLL C:\DexXX00\DAG.EXE 5261 /M /N:ProjectName /S:C:\DexXX00\Project\Project.snk if errorlevel 1 goto error signtool sign /f 0123456789ABCDEF.pfx /p <Password> /t http://timestamp.comodoca.com/authenticode Application.ProjectName.dll if errorlevel 1 goto error if exist Application.ProjectName.Metadata.dll signtool sign /f 0123456789ABCDEF.pfx /p <Password> /t http://timestamp.comodoca.com/authenticode Application.ProjectName.Metadata.dll if errorlevel 1 goto error signtool sign /fd sha256 /td sha256 /as /f 0123456789ABCDEF.pfx /p <Password> /tr http://timestamp.comodoca.com/authenticode Application.ProjectName.dll if errorlevel 1 goto error if exist Application.ProjectName.Metadata.dll signtool sign /fd sha256 /td sha256 /as /f 0123456789ABCDEF.pfx /p <Password> /tr http://timestamp.comodoca.com/authenticode Application.ProjectName.Metadata.dll if errorlevel 1 goto error copy /y Application.ProjectName.dll C:\DexXX00\Project\Application.ProjectName.dll copy /y Application.ProjectName.xml C:\DexXX00\Project\Application.ProjectName.xml if exist Application.ProjectName.Metadata.dll copy /y Application.ProjectName.Metadata.dll C:\DexXX00\Project\Application.ProjectName.Metadata.dll if exist Application.ProjectName.Metadata.xml copy /y Application.ProjectName.Metadata.xml C:\DexXX00\Project\Application.ProjectName.Metadata.xml CD C:\DexXX00\Project echo Copying to Application Folder if exist "C:\DynXX00\Application.ProjectName.dll" attrib -r "C:\DynXX00\Application.ProjectName.dll" if exist "C:\DynXX00\Application.ProjectName.Metadata.dll" attrib -r "C:\DynXX00\Application.ProjectName.Metadata.dll" copy /y Application.ProjectName.dll "C:\DynXX00" copy /y Application.ProjectName.xml "C:\DynXX00" if exist Application.ProjectName.Metadata.dll copy /y Application.ProjectName.Metadata.dll "C:\DynXX00" if exist Application.ProjectName.Metadata.xml copy /y Application.ProjectName.Metadata.xml "C:\DynXX00" echo Copying to Program Files. if not exist "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" md "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" if exist "C:\Program Files (x86)\Microsoft Dynamics\GP2016\Application.ProjectName.dll" attrib -r "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX\Application.ProjectName.dll" if exist "C:\Program Files (x86)\Microsoft Dynamics\GP2016\Application.ProjectName.Metadata.dll" attrib -r "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX\Application.ProjectName.Metadata.dll" copy /y Application.ProjectName.dll "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" copy /y Application.ProjectName.xml "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" if exist Application.ProjectName.Metadata.dll copy /y Application.ProjectName.Metadata.dll "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" if exist Application.ProjectName.Metadata.xml copy /y Application.ProjectName.Metadata.xml "C:\Program Files (x86)\Microsoft Dynamics\GPXXXX" CD C:\DexXX00\Project :end goto exit :error pause goto exit :exit
Note: You will need to find and replace the DexXX00, DynXX00, GPXXXX and Project folders, as well as the Project and ProjectName files and the 0123456789ABCDEF.pfx certificate file. You will also need to replace the <Password> placeholder.
Stay tuned for the next article on automating more of the distribution process.
David
This article was originally posted on http://www.winthropdc.com/blog.
What is the purpose of these keys? What bad things will happen if we do not use these keys?
LikeLike
Hi Bruce.
That’s a good question. So why is it best practice to strong sign and codesign your DLL files?
Security: Codesigning guarantees that the DLL file has not be edited, hacked or compromised in any way.
Convenience: If you ship a DLL without signing, it will probably be blocked by Windows until the user for each workstation manually unblocks it via the Properties dialog. When blocked the DLL will cause the Dynamics GP client to crash on start up.
Web Client: Visual Studio Tools Addin DLL files that you want to work with the Web Client need to be codesigned otherwise they will not work.
Courtesy: As a developer, it is better that I create my dictionary assemblies and sign them as coming from me, so that they are available when Visual Studio Tools developer needs them.
Consistency: Microsoft creates all the codesigned Dictionary Assemblies for all the products they ship, so I think you should do the same.
Let me know what you think.
David
LikeLike