This code generates a function that will load the assembly into the current PowerShell session. Yes it's a dumb idea but when your team lead tells you "we can't copy a dll file to every server your script needs to run on.", this is what happens:
<#
.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
}
}
}