为何直接运行TestFile1.ps1报错,通过TestFile2.ps1运行及后续执行却正常?
PowerShell类型加载异常问题解析
脚本内容
TestFile1.ps1
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") Add-Type -AssemblyName System.Windows.Forms class ButtonContainer { [System.Windows.Forms.Button] $button } # 打印Button类型信息 [System.Windows.Forms.Button] echo "Hello World, prove the code got this far."
TestFile2.ps1
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") Add-Type -AssemblyName System.Windows.Forms .\TestFile1.ps1
实际执行现象
PS [Path Here]> .\TestFile1.ps1 At [Path Here]\TestFile1.ps1:6 char:6 + [System.Windows.Forms.Button] $button + ~~~~~~~~~~~~~~~~~~~~~~~~~~~ Unable to find type [System.Windows.Forms.Button]. + CategoryInfo : ParserError: (:) [], ParseException + FullyQualifiedErrorId : TypeNotFound PS [Path Here]> .\TestFile2.ps1 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False Button System.Windows.Forms.ButtonBase Hello World, prove the code got this far. PS [Path Here]> .\TestFile1.ps1 IsPublic IsSerial Name BaseType -------- -------- ---- -------- True False Button System.Windows.Forms.ButtonBase Hello World, prove the code got this far.
疑问
- 为何直接执行TestFile1.ps1会出现
Unable to find type [System.Windows.Forms.Button]错误,而通过TestFile2.ps1调用执行则无该错误? - 为何成功运行TestFile2.ps1后,直接执行TestFile1.ps1也不再产生相同错误?
问题解答
针对疑问1
PowerShell处理脚本时,类定义会在脚本执行前完成预解析。直接运行TestFile1.ps1时,ButtonContainer类的定义会被优先解析,此时加载System.Windows.Forms程序集的代码还未执行,解析器找不到目标类型,因此抛出错误。
而通过TestFile2.ps1调用时,TestFile2会先执行加载程序集的代码,将System.Windows.Forms程序集载入当前PowerShell会话。之后调用TestFile1.ps1时,预解析类定义的阶段,会话中已经存在该程序集,自然能找到对应的类型,不会报错。
针对疑问2
PowerShell会话中加载的程序集是全局生效的,只要会话不关闭,已加载的程序集就会持续存在。运行TestFile2.ps1时,System.Windows.Forms程序集已经被载入当前会话,后续直接运行TestFile1.ps1时,预解析类定义阶段能直接找到已加载的类型,因此不再报错。
内容的提问来源于stack exchange,提问作者Alex Apel
相关产品推荐
相关产品推荐

