假设我有一个简单的 PowerShell 脚本:
1..3 | Write-Host
- PowerShell 如何处理它?
- 它是构建内存中的程序集还是一些临时的 .dll 文件?
- 我可以使用一些工具(例如 ILSpy、VS、WinDbg)检查这个程序集和 MSIL 吗?
- PowerShell 是否以相同的方式处理文件脚本和 REPL 命令行输入(即编译/解释)?
- 我可以将此编译后的程序集与 C# 和其他 .Net 语言一起使用吗?
- PS 脚本可以编译成原生二进制代码吗?
最佳答案
PowerShell V2 和更早版本从不编译脚本,它总是通过解析树中的虚拟“eval”方法进行解释。
PowerShell V3 及更高版本将解析树(AST)编译为 LINQ 表达式树,然后将其编译为 bytecode ,然后进行解释。
如果脚本执行16次,则脚本为JIT - 在后台编译,一旦JIT编译完成,解释后的代码将不会被使用。这同样适用于循环:如果循环迭代 16 次,则循环体将被 JIT 编译,并且循环体将尽早从解释转换为 JIT 编译。
许多操作,如访问成员或调用 C# 方法,总是在小型动态方法中进行 JIT 编译。这些动态站点针对 PowerShell 的动态特性进行了优化,以适应不同类型的按需输入。
JIT 编译的代码托管在“匿名方法”程序集中,无法保存。用WinDbg , 你可以反汇编 IL生成的代码。
将编译后的 IL 代码保存为 DLL 不太可能,因为生成的代码依赖于事件对象。从技术上讲,PowerShell 可以生成可以保存为 DLL 的代码,但尚未实现。
脚本和 REPL(交互式命令提示符)的工作方式完全相同。
请注意,如果 PowerShell 确实生成了程序集,它仍然需要安装编译脚本的 PowerShell 版本,您无法生成完全可移植的 exe。
从其他语言调用 PowerShell 脚本会有些困难和笨拙,因为有几个因素 - 主要是流水线和参数绑定(bind) - 与普通方法调度有些不同。
您可以在 C# 中使用从 PowerShell 脚本返回的对象。从 V3 开始,如果您在 C# 中使用 dynamic
关键字,您可以在 PSObject
上访问属性、调用脚本方法等。例如,就像您对任何其他对象所做的那样。在 V3 之前,您必须使用像 psobj.Properties['SomeProperty']
这样的 API。
关于c# - PowerShell 是否编译脚本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34202462/