#Dexterity Development Environments – Part 5: Creating Dictionary Assemblies


David Meego - Click for blog homepageThis 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:

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:

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.

Advertisements

6 thoughts on “#Dexterity Development Environments – Part 5: Creating Dictionary Assemblies

    • 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

      Like

Please post feedback or comments

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s