Deploying assemblies to GAC
Overview
In the previous post Deploying database scripts, I’ve written about reason why it can be necessary to create own SQL views, stored procedures or functions and how they can be deployed. This time it’s about deploying assemblies to the GAC.
A plugin package contains all necessary assemblies. If the application is transferred to another environment, a used plugin is transferred too. If a plugin action is executed the assemblies are loaded dynamically from the database. So, everything is fine, at least in most cases. I encountered only two exceptions:
- A plugin action is executed in a timeout
The WebCon.Workflow.Service executed the plugin action. This caused aCould not load file or assembly 'Newtonsoft.Json,...
exception. I was advised to deploy the assembly to the GAC by the WEBCON Support team. This was in 2020, so could be different with BPS 2021. - Using Razor
I’m using Razor, more precisely, the RazorEngine in a plugin. I’m no expert on how Razor works but, in the end, I needed a physical file for each assembly which is used in a template. As mentioned above, plugin assemblies don’t have a physical file, therefore I needed to deploy the assemblies used within a template to the GAC.
Taking advantage of document template processes
Document template processes work like dictionary processes. When a document template process is transported, you can choose whether the templates will be exported or imported. In combination with the Run a PowerShell script action we can transport the assemblies and deploy them to the GAC.
- The document template processes does not store templates in the original meaning but assemblies.
- Upon path transition the assemblies are deployed to the GAC.
This allows a controlled deployment of the required assemblies.
Interesting, but WHY?
If you are wondering why I’m going to such length and what’s the benefit of all this, here are my reasons:
- I have an auditable history of these deployments
- I’m in the consultancy business so it’s likely that I need to deploy those assemblies not only to our environments but to those of our customers too.
- I can provide an explanation why an assembly is necessary and can act if this reason is no longer valid.
Application Artifact deployment
Using the process Assembly deployment
The application Artifact deployment
contains the document template process Assembly deployment
. This process stores the assemblies which should be deploy to (activate) or removed from (deactivate) the GAC. I kept the activate/deactivate wording to keep in line with other dictionary processes. Once the path Trigger update
is executed the following will happen:
- A one-minute timeout will be triggered, which send a mail to the application supervisor, that it has been triggered.
- The timeout will deploy the assembly or remove it from the GAC. This depends on the
Active
flag is set. Upon completion theDeployed
checkbox will be set accordingly, and the application supervisor will receive a ‘success’ mail. The assembly will be deployed to each defined server. - If this fails, an error path will be executed which will send a mail to the application supervisor.
Info: During the development I noticed that a failure of the deployment doesn’t necessarily trigger the error path. Therefore the ‘success’ mail is sent.
In addition to these paths there’s another one Prepare for export
. The reason for this is explained in the chapter [Transferring the assemblies(#transferring-the-assemblies).
Each action changes the State
, these are:
- Only saved
- Update triggered
- Update executed
- Update failed
- Ready for export
Transferring the assemblies
You have two options to move the assemblies from one environment to another. Either as a part of the application package or using the export/import functionality on the report.
Before you can export the templates though, you have to execute the Prepare for export
path. This is available as a quick path.
This will remove the Base64 string from the workflow instance. It’s necessary because an excel cell can store round about 32k characters. Even so this is a lot, it’s not enough. The string of Newtonsoft.Json.dll is about 871k long.
After you have imported the assemblies or deployed the package you have to trigger the update. This can be done selecting all (1) and executing the Mass activate/deactivate with deployment
action on the report.
Setup
After importing the application package you have to do the following:
- Set an application supervisor, who will receive the mails.
- Grant privileges, ok this is obvious.
- Most importantly, activate remote PowerShell, if you have multiple servers in your environment. This was already the case in my environment. If it’s not setup in yours, you could take a look here:
- Set the login and password for each PowerShell action. They are stored as templates for easy access.
- Define on which environment local users or AD users are used by changing the values of the
UsesLocalAccount
process constant.
GAC deployment/removal explanation
The assembly is deployed to the GAC using the Run a PowerShell script
action. The script will deploy the assembly to each configured target server, for the current environment, this requires a few prerequisites which are listed in chapter Setup
The script creates a physical copy of the ‘attachment’ in the temp folder which will be removed again after execution. This file will be used for deployment or removal from the GAC. The physical file is created using the CONTENT AS BASE64
function.
Using this string the file is created on the (remote) server. The file is deployed to the GAC using GACInstall or removed with GACRemove. This requires administrative privileges, therefore it is checked, whether the provided credentials are valid, and that the user has administrative privileges on the executing server. These credentials are validated for a local machine account as well as a domain account.
Warning: The credential validation will behave the same, as the user itself would enter his credentials. If the credentials are wrong, and the script is executed repeatable, the account will be locked.
During the tests on my low performance development machine the Base64 encoding took a lot of time. Getting the Base64 encoded string and executing the script took so long, that the path transition was aborted after one minute. As a solution I moved the encoding to the Trigger update
path and saved the value to a field.
There are six different actions. The reason for this is, that there should could be different users for each environment whit administrative privileges. Therefore, there have to be three actions. I distinguished install and uninstall to make it visible in the history which actions was executed. The script itself is the same in each action.
Remarks
Contained Business entities
Unfortunately, the package contains three business entities. Make sure that you don’t overwrite yours during the import.
Insufficient privileges
As mention in Setup it’s necessary that the username and passwords have been provided. In addition the user has to be an administrator on the target servers. Otherwise it’s not possible to deploy the assemblies to the GAC.
Script development
The script development was done mostly outside of BPS. I added the script itself here. The first part of the script contains lines used for development using the ISE (1). All lines below can be copied from/to the PowerShell action within WEBCON BPS (2).
The initial lines are used for development and contain the binary information of Newtonsoft.Json.dll in base 64 format. These are characters and copying the whole script to BPS will freeze or even kill it. Likewise, the assignment of the Base64 string to the PowerShell variable (1) should be removed before clicking on show (2).
The target assignments had to be moved outside of the if clause, because the BPS variables won’t be replaced otherwise. The BPS variables for fields are {FIELDNUMBER}
(1), which could be a valid PowerShell expression. The other variables (2) have a prefix, so they can be replaced within scopes.
Download
If you would like the application template or to take a look at the script, you can go over to the GitHub repository.
The application package does not contain any assemblies.
Comments