Last active
May 31, 2018 20:05
-
-
Save sean-m/21c1260f2c5c4add9df73c46fdf7bb8c to your computer and use it in GitHub Desktop.
Helper function for wrapping DLL assembly in PowerShell so it can more easily be placed in version control and loaded within a script.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function GenAsmLoader { | |
<# | |
.Synopsis | |
Helper function for wrapping DLL assembly in PowerShell so it | |
can more easily be placed in version control and loaded within a script. | |
.DESCRIPTION | |
The ability to ship binary modules inside of a script file can be nice | |
if working in an environment that does not allow external dependencies. | |
This is a way around that by allowing you to bundle .Net DLL libraries inside | |
PowerShell code and providing a function that may be called to load the | |
library as an Assembly object with .Net's Reflection facilities. | |
.EXAMPLE | |
GenAsmLoader -AssemblyPath ".\NetNativeHelper.dll" -FunctionName "LoadNativeNetHelper" -Comment "Loads NetNativeHelper namespace." | Out-File LoadNativeHelper.ps1 | |
#> | |
param ( | |
[OutputType([string])] | |
[Parameter(Mandatory=$true, Position=0)] | |
$AssemblyPath, | |
[Parameter(Mandatory=$true, Position=1)] | |
$FunctionName, | |
[Parameter(Mandatory=$true, Position=2)] | |
$Comment, | |
[Parameter(Mandatory=$false, Position=3)] | |
[string]$MinDotNetVersion='4', | |
[Parameter(Mandatory=$false, Position=4)] | |
[string]$OutFile | |
) | |
process { | |
if (-not (Test-Path $AssemblyPath)) { | |
throw New-Object System.IO.FileNotFoundException "Cannot find: $AssemblyPath" | |
} | |
$base_code = @" | |
<# | |
{1} | |
#> | |
function {0} {{ | |
begin {{ | |
## Helper function for converting byte[] to Assembly object | |
if (-not ([System.Management.Automation.PSTypeName]'AsmHelper').Type) {{ | |
Add-Type -Language CSharp -TypeDefinition @" | |
using System; | |
using System.Reflection; | |
public static class AsmHelper {{ | |
public static Assembly LoadAsm(byte[] AsmBytes) {{ | |
return Assembly.Load(AsmBytes); | |
}} | |
public static Assembly LoadAsm(string AsmString) {{ | |
if (String.IsNullOrEmpty(AsmString)) {{ throw new System.Exception("Must pass assembly as Base64 encoded string."); }} | |
return LoadAsm(Convert.FromBase64String(AsmString)); | |
}} | |
}} | |
`"@ | |
}} | |
}} | |
process {{ | |
if (-not (`$PSVersionTable.CLRVersion.Major -ge {4})) {{ | |
throw "Need .Net {4} or greater" | |
}} | |
`$local:asm = "{2}" | |
`$local:asm_sha256 = "{3}" | |
if ([System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([Convert]::FromBase64String(`$local:asm))) -replace "-","" -eq `$local:asm_sha256) {{ | |
Import-Module -Assembly `$([AsmHelper]::LoadAsm(`$local:asm)) | |
}} | |
else {{ | |
throw "Could not load assembly! Checksum failed, byte string corrupt." | |
}} | |
}} | |
}} | |
"@ | |
$asm_string = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes($AssemblyPath)) | |
$asm_hash = [System.BitConverter]::ToString([System.Security.Cryptography.SHA256]::Create().ComputeHash([Convert]::FromBase64String($asm_string))) -replace "-","" | |
$code = [String]::Format($base_code, $FunctionName, $Comment, $asm_string, $asm_hash, $MinDotNetVersion) | |
if (-not [String]::IsNullOrEmpty($OutFile)) { | |
try { | |
New-Item -Force -Type File -Path $OutFile | |
$code | Out-File -Encoding ascii -FilePath $OutFile | |
"Export-ModuleMember -Function $FunctionName" | Out-File -Append -Encoding ascii -FilePath $OutFile | |
} | |
catch { | |
throw $_ # this is just so if an exception is encountered, it abandons writing to the file all together | |
} | |
} | |
else { | |
return $code | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment