Ship Assemblies Inside Your PowerShell

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
        }
    }
}