PowerShell Cmdlet中使用System.Security.Cryptography.ProtectedData遇加载错误
PowerShell Cmdlet 依赖加载问题排查与解决
问题场景
我创建了一个基于net8.0的C# PowerShell Cmdlet项目,Cmdlet内部调用System.Security.Cryptography.ProtectedData.Protect()方法。Xunit测试中Cmdlet运行完全正常,但在pwsh控制台导入模块时,出现找不到System.Security.Cryptography.ProtectedData程序集的错误。
执行命令:
Import-Module .\TestProtectedDataPowershell.dll Test-ProtectData -NotSecret "some text here"
抛出System.IO.FileNotFoundException异常,提示找不到版本为9.0.0.0的对应程序集。已确认Xunit测试和控制台使用的PowerShell版本均为7.4.6,尝试将System.Security.Cryptography.ProtectedData.dll复制到输出目录也无效,但直接在pwsh中调用该类却能正常运行,项目已安装对应NuGet包。
问题
- 为何Xunit测试正常但控制台运行失败?
- 如何让控制台正常运行?是否需要psd1文件声明依赖?
问题1:Xunit测试正常但控制台运行失败的原因
- Xunit测试框架会自动处理项目依赖的程序集解析,它会从项目的NuGet包目录或构建输出的依赖目录中查找所需程序集,无需额外配置就能加载
System.Security.Cryptography.ProtectedData。 - PowerShell控制台导入单DLL模块时,仅会在当前目录、系统全局程序集缓存(GAC)或PowerShell默认搜索路径中查找依赖。而
System.Security.Cryptography.ProtectedData作为NuGet包依赖,默认不会被复制到输出目录根目录(除非配置特定复制策略),且PowerShell不会自动遍历子目录查找依赖,因此找不到该程序集。 - 直接在pwsh中调用该类正常,是因为PowerShell 7.4.6本身的运行时依赖包含该程序集,或能从系统已安装的.NET运行时自动解析,但单独编译的Cmdlet DLL依赖解析规则不同。
问题2:控制台正常运行的解决方法
方法1:使用模块清单(psd1文件)声明依赖(推荐)
这是PowerShell模块的规范做法:
- 生成psd1文件,在
RequiredAssemblies字段中明确指定System.Security.Cryptography.ProtectedData.dll的路径(若复制到输出目录,直接写文件名即可)。示例:
@{ RootModule = 'TestProtectedDataPowershell.dll' RequiredAssemblies = @('System.Security.Cryptography.ProtectedData.dll') # 其他模块元数据(如版本、作者等)可按需补充 }
- 确保
System.Security.Cryptography.ProtectedData.dll与psd1、Cmdlet DLL在同一目录,导入模块时使用psd1文件:
Import-Module .\TestProtectedDataPowershell.psd1
方法2:修改项目配置,强制复制依赖到输出目录
在项目的csproj文件中添加以下配置,确保NuGet依赖的程序集被复制到输出目录:
<PropertyGroup> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> </PropertyGroup>
构建后,依赖的程序集会被复制到输出目录,PowerShell导入DLL时即可自动找到。
方法3:手动加载依赖程序集(临时测试用)
导入Cmdlet DLL前,先手动加载依赖:
Add-Type -Path .\System.Security.Cryptography.ProtectedData.dll Import-Module .\TestProtectedDataPowershell.dll
此方法仅适合临时验证,不推荐用于生产环境。
内容的提问来源于stack exchange,提问作者Daniel
相关产品推荐
相关产品推荐

