如何在PowerShell脚本中加载.dll文件避免出现TypeNotFound错误
问题根因
你遇到的报错本质是PowerShell的解析阶段先于执行阶段的设计机制导致的:
- PowerShell运行脚本前会先扫描整份脚本的所有内容,校验类型引用、语法合法性
- 你把
Add-Type加载WinSCP DLL的逻辑写在了CreateSession函数内部,要等到函数实际运行才会执行加载逻辑 - 但解析阶段扫描到
[WinSCP.Protocol]的时候,DLL还没被加载,自然会抛出类型找不到的错误,和DLL本身是否正常无关,这也是很多开发者容易踩的共性坑。
可直接运行的解决方案
方案1:把DLL加载逻辑移到脚本最顶部(最省心)
不要把加载DLL的逻辑放在类、函数内部,脚本运行第一块逻辑就完成DLL加载,后续所有类型引用都可以正常识别:
# 脚本开头优先加载WinSCP DLL,加载失败直接抛出错误终止运行 Add-Type -Path (Join-Path $PSScriptRoot "\winscp\WinSCPnet.dll") -ErrorAction Stop # 后续再定义类、函数等业务逻辑 class SftpClient { $sessionOptions $session [void] CreateSession() { try { # 此时DLL已经加载完成,类型可以正常识别 $this.sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = [WinSCP.Protocol]::Sftp HostName = "替换为你的SFTP地址" UserName = "替换为SFTP用户名" Password = "替换为SFTP密码" SshHostKeyFingerprint = "替换为主机密钥指纹" } $this.session = New-Object WinSCP.Session $this.session.Open($this.sessionOptions) } catch { throw $_ } } } # 测试调用 $client = [SftpClient]::new() $client.CreateSession()
方案2:不调整代码结构,用字符串形式指定枚举值
如果你的代码架构不允许把加载逻辑提到顶部,也可以直接用枚举的字符串值代替类型引用,WinSCP会自动完成类型转换,不需要解析阶段提前识别类型:
[void] CreateSession() { try { # 仍然在函数内部加载DLL Add-Type -Path (Join-Path $PSScriptRoot "\winscp\WinSCPnet.dll") -ErrorAction Stop # 用字符串"Sftp"代替[WinSCP.Protocol]::Sftp $this.sessionOptions = New-Object WinSCP.SessionOptions -Property @{ Protocol = "Sftp" HostName = "替换为你的SFTP地址" UserName = "替换为SFTP用户名" Password = "替换为SFTP密码" SshHostKeyFingerprint = "替换为主机密钥指纹" } } catch { throw $_ } }
关于模块清单的疑问
你不需要专门创建模块清单才能加载DLL,只有当你需要把DLL封装成可复用的PowerShell模块对外发布的时候,才需要编写psd1格式的模块清单。单脚本场景直接用Add-Type加载就完全够用,不需要额外的冗余操作。
内容的提问来源于stack exchange,提问作者CamParker
相关产品推荐
相关产品推荐

