PSDllCompiler.psm1
using namespace System using namespace System.Text #Requires -Version 3.0 <# .SYNOPSIS Compiles Powershell Class Modules into C# Dlls .DESCRIPTION Compiles Powershell Class Modules into C# Dlls. The Compiled File can be imported by Powershell using "using assembly .\Path.dll" or even with other .NET languages like C# by adding the dll in references and importing it with "using static ExampleName;" .PARAMETER Path *.ps1 or *.psm1 script containing only a class and namespaces .PARAMETER ScriptDefinition a string containing the class code .PARAMETER OutputAssembly path where the *.cs or *.dll file will be saved .PARAMETER DebugMode Enables the GetPowershell() Method as well as access to both ClassHandlers and more .EXAMPLE Compile-Dll -Path .\example.psm1 -OutputAssembly .\example.dll .EXAMPLE Compile-Dll -Path .\example.psm1 -OutputAssembly .\example.cs .EXAMPLE $example = ' class ExampleClass { ExampleClass() {} [string] $Name [string] SayHello() { return "Hello" + $this.Name } } ' Compile-Dll -ScriptDefinition $example -OutputAssembly .\ExampleClass.dll #> function Compile-Dll { [CmdletBinding()] param ( [string]$Path, [Parameter(ValueFromPipeline)] [string]$ScriptDefinition, [string]$OutputAssembly, [switch]$DebugMode ) [Version]$Compiler_Version = "1.0.0" #Update Check Write-Output "`nChecking for Updates...`n" try {$Compiler_Version_Newest = (Find-Module "PSDllCompiler").Version} catch { Write-Output "Cannot reach update server!`n" $Compiler_Version_Newest = $Compiler_Version } if ($Compiler_Version -lt $Compiler_Version_Newest) { Write-Output "New update found!, use 'Update-Module PSDllCompiler'`n" foreach($i in 0..5) { Write-Output "Resuming in $(5 - $i)" Start-Sleep 1 $i++ } } if ($Path) {$Content = Get-Content $Path -Raw} elseif ($ScriptDefinition) {$Content = $ScriptDefinition} else {throw "Provide a input code using -Path or -ScriptDefinition !"} if (!$OutputAssembly) {throw "Provide a output path location using -OutputAssembly !"} $Content_Lines = $Content.Split("`n") Invoke-Expression $Content #Add Class foreach ($Class_Name in ($Content_Lines | Select-String "class" | Where-Object {!([string]$_).Contains("(")} | ForEach-Object {([string]$_).Split(" ")[1]})) { Write-Output "`nCompiling $Class_Name..." $Class_Constructors += Invoke-Expression "[$Class_Name].DeclaredConstructors" $Class_Methods += Invoke-Expression "[$Class_Name].DeclaredMethods" | Where-Object {!($_.Name.Contains("get_") -or $_.Name.Contains("set_"))} $Class_Properties = Invoke-Expression "[$Class_Name].DeclaredProperties" [string[]]$Class_Namespaces_CSharp = @("using System.Collections;", "using System.Management.Automation;", "using System.Text;") [string]$Class_Constructors_CSharp = "" [string]$Class_Methods_CSharp = "" [string]$Class_Properties_CSharp = "" [string]$Class_Handler_CSharp = "" [string]$Class_Static_Handler_CSharp = "" [hashtable[]]$Class_Handler_Properties = @() [hashtable[]]$Class_Static_Handler_Properties = @() [string]$Class_Powershell = "" [string]$Class_Csharp = "" #Powershell Class--------------------------------------------------------------------------------- $Class_Powershell += $Content $Class_Powershell += "`n`n" + '$Global:Class = [' + "$Class_Name]`n" $Class_Powershell += '$Global:Class_Constructed = $null' + "`n`n" #Class Constructors------------------------------------------------------------------------------- foreach ($constructor in $Class_Constructors) { [string]$CsConstructor = " " $CsConstructor += "public $Class_Name (" $CsConstructor += "$([string]($constructor.GetParameters() -join ", ")))`n {`n " $CsConstructor += "object[] Arguments = { $([string]($constructor.GetParameters().Name -join ", ")) };`n`n " $CsConstructor += "_ClassHandler($('"' + $Class_Name + '"'), Arguments);" $CsConstructor += "`n }`n`n" $Class_Constructors_CSharp += $CsConstructor } #Class Methods------------------------------------------------------------------------------------ foreach ($method in $Class_Methods) { [string]$CsNamespace = "" $CsNamespace = "using $($method.ReturnType.Namespace);" if (!$Class_Namespaces_CSharp.Contains($CsNamespace)) {$Class_Namespaces_CSharp += $CsNamespace} [string]$CsMethod = " " switch ($method) { {$_.IsPublic} {$CsMethod += "public "} {$_.IsPrivate} {$CsMethod += "private "} {$_.IsStatic} {$CsMethod += "static "} } $CsMethod += "$($method.ReturnType) " $CsMethod += "$($method.Name) (" $CsMethod += "$([string]($method.GetParameters() -join ", ")))`n {`n " $CsMethod += "object[] Arguments = { $([string]($method.GetParameters().Name -join ", ")) };`n`n " if ($method.IsStatic) { if ($method.ReturnType.Name -eq "Void") {$CsMethod += "_StaticClassHandler($('"' + $method.Name + '"'), Arguments);"} else {$CsMethod += "return ($($method.ReturnType))_StaticClassHandler($('"' + $method.Name + '"'), Arguments);"} } else { if ($method.ReturnType.Name -eq "Void") {$CsMethod += "_ClassHandler($('"' + $method.Name + '"'), Arguments);"} else {$CsMethod += "return ($($method.ReturnType))_ClassHandler($('"' + $method.Name + '"'), Arguments);"} } $CsMethod += "`n }`n`n" $Class_Methods_CSharp += $CsMethod } #Class Properties--------------------------------------------------------------------------------- foreach ($property in $Class_Properties) { [string]$CsNamespace = "" $CsNamespace = "using $($property.PropertyType.Namespace);" if (!$Class_Namespaces_CSharp.Contains($CsNamespace)) {$Class_Namespaces_CSharp += $CsNamespace} [string]$CsProperty = "" ($Content_Lines | Select-String "hidden" -SimpleMatch).LineNumber | ForEach-Object { if (([string[]]($Content_Lines[($_ - 1)..($Content_Lines.Count)] | Select-String "\$"))[0].Contains("$" + $property.Name)) { $CsProperty += " private " } } if (!$CsProperty) {$CsProperty += " public "} if ($property.GetMethod.IsStatic -or $property.SetMethod.IsStatic) { $CsProperty += "static " $Class_Static_Handler_Properties += @{$property.Name = $property.PropertyType} } else {$Class_Handler_Properties += @{$property.Name = $property.PropertyType}} $CsProperty += "$($property.PropertyType) $($property.Name) { get; set; }`n`n" $Class_Properties_CSharp += $CsProperty } #_ClassHandler------------------------------------------------------------------------------------ [string]$CsClassHandler = "" $CsClassHandler += ' public object _ClassHandler(string Method, object[] Arguments) { if (_Powershell.Commands.Commands.Count == 0) { CreatePowershell(); } string Script = Encoding.UTF8.GetString(Convert.FromBase64String("cGFyYW0gKFtzdHJpbmddJE1ldGhvZCwgW29iamVjdFtdXSRBcmd1bWVudHMsIFtoYXNodGFibGVdJFByb3BlcnRpZXMsIFtib29sXSRJc1N0YXRpYykNCkNsYXNzSGFuZGxlciAtTWV0aG9kICRNZXRob2QgLUFyZ3VtZW50cyAkQXJndW1lbnRzIC1Qcm9wZXJ0aWVzICRQcm9wZXJ0aWVzIC1Jc1N0YXRpYyAkSXNTdGF0aWM=")); Hashtable Properties = new Hashtable();' foreach ($property in $Class_Handler_Properties) { $CsClassHandler += "`n Properties.Add($('"' + $property.Keys + '"'), $($property.Keys));`n" } $CsClassHandler += ' _Powershell.Commands.Commands.Clear(); _Powershell.AddScript(Script); _Powershell.AddArgument(Method); _Powershell.AddArgument(Arguments); _Powershell.AddArgument(Properties); _Powershell.AddArgument(false); //IsStatic Hashtable returnproperties = _Powershell.Invoke()[0].BaseObject as Hashtable; ' foreach ($property in $Class_Handler_Properties) { $CsClassHandler += "`n $($property.Keys) = ($($property.Values))returnproperties[$('"' + $property.Keys + '"')];" } $CsClassHandler += "`n`n return returnproperties" + '["RETURN"];' + "`n }`n`n" $Class_Handler_CSharp = $CsClassHandler #_StaticClassHandler------------------------------------------------------------------------------ [string]$CsStaticClassHandler = "" $CsStaticClassHandler += ' public static object _StaticClassHandler(string Method, object[] Arguments) { if (_Powershell.Commands.Commands.Count == 0) { CreatePowershell(); } string Script = Encoding.UTF8.GetString(Convert.FromBase64String("cGFyYW0gKFtzdHJpbmddJE1ldGhvZCwgW29iamVjdFtdXSRBcmd1bWVudHMsIFtoYXNodGFibGVdJFByb3BlcnRpZXMsIFtib29sXSRJc1N0YXRpYykNCkNsYXNzSGFuZGxlciAtTWV0aG9kICRNZXRob2QgLUFyZ3VtZW50cyAkQXJndW1lbnRzIC1Qcm9wZXJ0aWVzICRQcm9wZXJ0aWVzIC1Jc1N0YXRpYyAkSXNTdGF0aWM=")); Hashtable Properties = new Hashtable();' foreach ($property in $Class_Static_Handler_Properties) { $CsStaticClassHandler += "`n Properties.Add($('"' + $property.Keys + '"'), $($property.Keys));`n" } $CsStaticClassHandler += ' _Powershell.Commands.Commands.Clear(); _Powershell.AddScript(Script); _Powershell.AddArgument(Method); _Powershell.AddArgument(Arguments); _Powershell.AddArgument(Properties); _Powershell.AddArgument(true); //IsStatic Hashtable returnproperties = _Powershell.Invoke()[0].BaseObject as Hashtable; ' foreach ($property in $Class_Static_Handler_Properties) { $CsStaticClassHandler += "`n $($property.Keys) = ($($property.Values))returnproperties[$('"' + $property.Keys + '"')];" } $CsStaticClassHandler += "`n`n return returnproperties" + '["RETURN"];' + "`n }`n" $Class_Static_Handler_CSharp = $CsStaticClassHandler #Finishing CSharp Class--------------------------------------------------------------------------- [string]$CsClass = "" $CsClass += $Class_Namespaces_CSharp -join "`n" $CsClass += "`n`npublic class $Class_Name`n{`n " $CsClass += "private static PowerShell _Powershell = PowerShell.Create();`n`n " if ($DebugMode) {$CsClass += "public static object GetPowershell() { return _Powershell; }`n`n "} if ($DebugMode) {$CsClass += "public "} else {$CsClass += "private "} $CsClass += 'static string _Base64Class = "' + [Convert]::ToBase64String([Encoding]::UTF8.GetBytes($Class_Powershell)) + '";' + "`n`n " $CsClass += 'private static void CreatePowershell() { string PlainClass = Encoding.UTF8.GetString(Convert.FromBase64String(_Base64Class)); string ClassHandler = Encoding.UTF8.GetString(Convert.FromBase64String("ZnVuY3Rpb24gQ2xhc3NIYW5kbGVyIChbc3RyaW5nXSRNZXRob2QsIFtvYmplY3RbXV0kQXJndW1lbnRzLCBbaGFzaHRhYmxlXSRQcm9wZXJ0aWVzLCBbYm9vbF0kSXNTdGF0aWMpIHsNCiAgICANCiAgICBmdW5jdGlvbiBSZXR1cm5IYW5kbGVyIChbb2JqZWN0XSRSZXR1cm5WYWx1ZSwgW3N0cmluZ1tdXSRFeGlzdGluZ1Byb3BlcnRpZXMsIFtzd2l0Y2hdJElzU3RhdGljKSB7DQoNCiAgICAgICAgJHRhYmxlICs9IEB7UkVUVVJOID0gJFJldHVyblZhbHVlfQ0KDQogICAgICAgIGlmICgkSXNTdGF0aWMpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRwcm9wZXJ0eSBpbiAkRXhpc3RpbmdQcm9wZXJ0aWVzKSB7DQogICAgICAgICAgICAgICAgJHRhYmxlICs9IEB7JHByb3BlcnR5ID0gJENsYXNzOjokcHJvcGVydHl9DQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgICBmb3JlYWNoICgkcHJvcGVydHkgaW4gJEV4aXN0aW5nUHJvcGVydGllcykgew0KICAgICAgICAgICAgICAgICR0YWJsZSArPSBAeyRwcm9wZXJ0eSA9ICRHbG9iYWw6Q2xhc3NfQ29uc3RydWN0ZWQuJHByb3BlcnR5fQ0KICAgICAgICAgICAgfQ0KICAgICAgICB9DQogICAgICAgIHJldHVybiAkdGFibGUNCiAgICB9DQoNCiAgICBpZiAoJElzU3RhdGljKSB7DQogICAgICAgIA0KICAgICAgICBpZiAoJFByb3BlcnRpZXMuR2V0RW51bWVyYXRvcigpLk1vdmVOZXh0KCkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRwcm9wZXJ0eSBpbiAkUHJvcGVydGllcykgew0KICAgICAgICAgICAgICAgICRHbG9iYWw6Q2xhc3M6OigkcHJvcGVydHkuS2V5cykgPSAkcHJvcGVydHkuVmFsdWVzDQogICAgICAgICAgICB9DQogICAgICAgIH0NCiAgICAgICAgaWYgKCRBcmd1bWVudHMgLWFuZCAkTWV0aG9kKSB7DQogICAgICAgICAgICAkcmV0dXJudmFsdWUgPSAkR2xvYmFsOkNsYXNzOjokTWV0aG9kLkludm9rZSgkQXJndW1lbnRzKQ0KICAgICAgICB9DQogICAgICAgIGVsc2VpZiAoJE1ldGhvZCkgew0KICAgICAgICAgICAgJHJldHVybnZhbHVlID0gJEdsb2JhbDpDbGFzczo6JE1ldGhvZCgpDQogICAgICAgIH0NCiAgICAgICAgUmV0dXJuSGFuZGxlciAtUmV0dXJuVmFsdWUgJHJldHVybnZhbHVlIC1FeGlzdGluZ1Byb3BlcnRpZXMgJFByb3BlcnRpZXMuS2V5cyAtSXNTdGF0aWMNCiAgICB9DQogICAgZWxzZWlmICgkTWV0aG9kIC1lcSAkR2xvYmFsOkNsYXNzLk5hbWUpIHsNCiAgICAgICAgaWYgKCRBcmd1bWVudHMpIHsNCiAgICAgICAgICAgICRHbG9iYWw6Q2xhc3NfQ29uc3RydWN0ZWQgPSBOZXctT2JqZWN0ICRHbG9iYWw6Q2xhc3MuTmFtZSAkQXJndW1lbnRzDQogICAgICAgIH0NCiAgICAgICAgZWxzZSB7DQogICAgICAgICAgICAkR2xvYmFsOkNsYXNzX0NvbnN0cnVjdGVkID0gTmV3LU9iamVjdCAkR2xvYmFsOkNsYXNzLk5hbWUNCiAgICAgICAgfQ0KICAgICAgICBSZXR1cm5IYW5kbGVyIC1SZXR1cm5WYWx1ZSAiTlVMTCIgLUV4aXN0aW5nUHJvcGVydGllcyAkUHJvcGVydGllcy5LZXlzDQogICAgfQ0KICAgIGVsc2Ugew0KICAgICAgICBpZiAoJFByb3BlcnRpZXMuR2V0RW51bWVyYXRvcigpLk1vdmVOZXh0KCkpIHsNCiAgICAgICAgICAgIGZvcmVhY2ggKCRwcm9wZXJ0eSBpbiAkUHJvcGVydGllcykgew0KICAgICAgICAgICAgICAgICRHbG9iYWw6Q2xhc3NfQ29uc3RydWN0ZWQuKCRwcm9wZXJ0eS5LZXlzKSA9ICRwcm9wZXJ0eS5WYWx1ZXMNCiAgICAgICAgICAgIH0gIA0KICAgICAgICB9ICAgIA0KICAgICAgICBpZiAoJEFyZ3VtZW50cyAtYW5kICRNZXRob2QpIHsNCiAgICAgICAgICAgICRyZXR1cm52YWx1ZSA9ICRHbG9iYWw6Q2xhc3NfQ29uc3RydWN0ZWQuJE1ldGhvZC5JbnZva2UoJEFyZ3VtZW50cykNCiAgICAgICAgfQ0KICAgICAgICBlbHNlaWYgKCRNZXRob2QpIHsNCiAgICAgICAgICAgICRyZXR1cm52YWx1ZSA9ICRHbG9iYWw6Q2xhc3NfQ29uc3RydWN0ZWQuJE1ldGhvZCgpDQogICAgICAgIH0NCiAgICAgICAgUmV0dXJuSGFuZGxlciAtUmV0dXJuVmFsdWUgJHJldHVybnZhbHVlIC1FeGlzdGluZ1Byb3BlcnRpZXMgJFByb3BlcnRpZXMuS2V5cw0KICAgIH0NCn0=")); _Powershell.AddScript(PlainClass); _Powershell.AddScript(ClassHandler); _Powershell.Invoke(); }' + "`n`n" $CsClass += $Class_Static_Handler_CSharp $CsClass += $Class_Handler_CSharp $CsClass += " //Visible Class`n`n" $CsClass += $Class_Constructors_CSharp $CsClass += $Class_Properties_CSharp $CsClass += $Class_Methods_CSharp $CsClass += "}" $Class_Csharp += $CsClass } #Writing Class_CSharp----------------------------------------------------------------------------- if ($OutputAssembly.Contains(".dll")) { Add-Type -TypeDefinition $Class_Csharp -OutputAssembly $OutputAssembly | Out-Null } elseif ($OutputAssembly.Contains(".cs")) { New-Item -Path $OutputAssembly -Value $Class_Csharp | Out-Null } Write-Output "`nSucesss, exitet with code:" return 0 } |