假设我有一个简单的PowerShell脚本:
1..3 | Write-Host
答案 0 :(得分:19)
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脚本会有些困难和尴尬,因为有几个因素 - 主要是流水线和参数绑定 - 与普通方法调度略有不同。
您可以使用C#中从PowerShell脚本返回的对象。从V3开始,如果在C#中使用dynamic
关键字,则可以在PSObject
实例上访问属性,调用脚本方法等,就像在任何其他对象上一样。在V3之前,您必须使用psobj.Properties['SomeProperty']
之类的API。