如何实现PowerShell内存加载运行所有.NET应用的通用方案?
通用适配所有.NET程序的内存加载解决方案
原代码的问题在于硬编码了入口类为Program、方法为Main,这只适用于默认模板生成的.NET Framework项目,无法覆盖所有.NET程序的入口点情况。要实现通用适配,核心是利用.NET程序集自身的入口点元数据来获取正确的启动方法,而非手动猜测类名和方法名。
具体实现步骤
- 跳过手动查找
Program类和Main方法的逻辑,直接通过$assembly.EntryPoint获取程序集定义的入口点方法 - 自动适配入口方法的参数签名:判断入口方法是否需要传入
string[]类型的参数,再决定调用时传入的参数值 - 针对Windows窗体/WPF程序,确保在单线程单元(STA)下运行(可选,避免部分窗体程序启动异常)
修改后的完整PowerShell代码
# Note: This must be an executable or DLL compiled for .NET $Path = "C:\Users\sadettin\desktop\tok.exe" # Get Base64-encoded representation of the bytes that make up the assembly. $bytes = [System.IO.File]::ReadAllBytes($Path) $string = [System.Convert]::ToBase64String($bytes) # ... # Convert the Base64-encoded string back to a byte array, load # the byte array as an assembly, and save the object representing the # loaded assembly for later use. $bytes = [System.Convert]::FromBase64String($string) $assembly = [System.Reflection.Assembly]::Load($bytes) # 通用获取入口点方法 $entryPointMethod = $assembly.EntryPoint if (-not $entryPointMethod) { throw "当前程序集未定义可执行的入口点" } # 适配入口方法的参数需求 $invokeArgs = $null $paramTypes = $entryPointMethod.GetParameters().Type if ($paramTypes -contains [string[]]) { # 传入空的命令行参数数组,也可根据需要自定义参数 $invokeArgs = (, [string[]] @()) } # 针对窗体程序,确保在STA线程执行(解决部分WPF/WinForms启动异常) if ($entryPointMethod.DeclaringType.BaseType.FullName -match 'System.Windows.Forms.Form|System.Windows.Application') { $staThread = New-Object System.Threading.Thread({ $entryPointMethod.Invoke($null, $invokeArgs) }) $staThread.SetApartmentState([System.Threading.ApartmentState]::STA) $staThread.Start() $staThread.Join() } else { # 控制台程序直接调用 $entryPointMethod.Invoke($null, $invokeArgs) }
关键说明
Assembly.EntryPoint的作用:这个属性直接返回程序集编译时指定的入口方法,不管类名是什么、方法是否公开,完全符合.NET程序规范,是最可靠的入口点获取方式- 参数适配逻辑:通过检查方法的参数类型,自动决定是否传入
string[]参数,避免因参数不匹配导致的调用失败 - STA线程处理:Windows窗体和WPF程序要求在单线程单元(STA)中运行,否则可能出现控件创建失败、UI无响应等问题,加入线程处理能覆盖这类场景
内容的提问来源于stack exchange,提问作者NoobCoding
相关产品推荐
相关产品推荐

