To finalize the export and deployment story from the previous blog post, given that we were working in a high-availability environment with multiple servers. And for those who are familiar with BizTalk Server, we need to:
- Register in the BizTalk Server databases the assemblies only once in any of the servers – this was done with the previous PowerShell script: Install and register assemblies in a BizTalk Application with PowerShell (Part II)
- We need to install the assemblies into the Global Assembly Cache (GAC) on all servers.
This task is relatively simple. More importantly, it does not require a strict installation order. As a result, it runs faster than registering assemblies in the product database.
You could reuse the previous PowerShell script on these machines. However, that approach is heavier. Therefore, on servers where you only need to install DLLs in the Global Assembly Cache (GAC), using a lightweight script is a better option.
📝 One-Minute Brief
This is a PowerShell script that goes to a folder containing assemblies and install them in the Global Assembly Cache (GAC).
We could do it in a bulk process and GAC the assemblies for all applications in a single script, but I chose to do it in a controlled fashion.
Here is a sample of the script:
# Collect DLLs
$files = Get-ChildItem -LiteralPath $SourceFolder -Filter *.dll -File -Recurse:$Recurse
if (-not $files -or $files.Count -eq 0) {
Write-Warning "No DLLs found in: $SourceFolder"
return
}
$results = @()
# Detect edition (Desktop == Windows PowerShell/.NET Framework)
$onDesktop = ($PSVersionTable.PSEdition -eq 'Desktop' -or $PSVersionTable.PSVersion.Major -le 5)
# Try .NET Framework Publish API first when on Desktop
$publisher = $null
if ($onDesktop) {
try {
[void][Reflection.Assembly]::Load("System.EnterpriseServices")
$publisher = New-Object System.EnterpriseServices.Internal.Publish
} catch {
Write-Warning "Could not create System.EnterpriseServices.Internal.Publish in this session. Will try gacutil.exe."
}
}
if ($publisher) {
foreach ($f in $files) {
try {
$publisher.GacInstall($f.FullName)
$results += [pscustomobject]@{ File=$f.FullName; Method="Publish.GacInstall"; Result="GACed" }
Write-Host "GACed: $($f.Name)" -ForegroundColor Green
} catch {
$results += [pscustomobject]@{ File=$f.FullName; Method="Publish.GacInstall"; Result="ERROR: $($_.Exception.Message)" }
Write-Warning "Failed: $($f.Name) -> $($_.Exception.Message)"
}
}
"`n===== SUMMARY ====="; $results | Format-Table -AutoSize
return
}
# Fallback: locate gacutil.exe
$gacutil = $null
$probeRoots = @(
'C:\Program Files (x86)\Microsoft SDKs\Windows',
'C:\Program Files (x86)\Microsoft Visual Studio',
'C:\Program Files\Microsoft SDKs\Windows'
)
foreach ($root in $probeRoots) {
if (Test-Path $root) {
$found = Get-ChildItem -Path $root -Filter gacutil.exe -Recurse -ErrorAction SilentlyContinue |
Sort-Object FullName -Unique |
Select-Object -First 1 -ExpandProperty FullName
if ($found) { $gacutil = $found; break }
}
}
if (-not $gacutil) {
throw @"
No valid GAC installer found:
- System.EnterpriseServices.Internal.Publish unavailable (likely PowerShell 7+ or missing .NET Framework)
- gacutil.exe not found in common SDK/VS locations
Fixes:
- Run in **Windows PowerShell 5.1** (x64) as Administrator; or
- Install Windows SDK / VS Build Tools to get **gacutil.exe**.
"@
}
Write-Host "Using gacutil: $gacutil" -ForegroundColor Cyan
foreach ($f in $files) {
try {
# Use Start-Process; do NOT pipe a null path (pre-validated above)
$p = Start-Process -FilePath $gacutil -ArgumentList @('/if', $f.FullName) -NoNewWindow -Wait -PassThru
if ($p.ExitCode -eq 0) {
$results += [pscustomobject]@{ File=$f.FullName; Method="gacutil /if"; Result="GACed" }
Write-Host "GACed: $($f.Name)" -ForegroundColor Green
} else {
$results += [pscustomobject]@{ File=$f.FullName; Method="gacutil /if"; Result="ERROR: ExitCode $($p.ExitCode)" }
Write-Warning "Failed: $($f.Name) -> ExitCode $($p.ExitCode)"
}
} catch {
$results += [pscustomobject]@{ File=$f.FullName; Method="gacutil /if"; Result="ERROR: $($_.Exception.Message)" }
Write-Warning "Failed: $($f.Name) -> $($_.Exception.Message)"
}
}
With this, all assemblies will be installed in the GAC within a few minutes.
Download
THIS POWERSHELL SCRIPT IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND.
You can download the PowerShell Script used from GitHub here:
Hope you find this helpful! If you enjoyed the content or found it useful, and wish to support our efforts to create more, you can contribute to purchasing a Star Wars Lego set for my son!