从 cmd.exe 运行时
powershell .\scripts\scriptname.ps1
Run Code Online (Sandbox Code Playgroud)
其中有一行将纯文本转换为安全字符串
[securestring]$secString = ConvertTo-SecureString $SampleString -AsPlainText -Force
Run Code Online (Sandbox Code Playgroud)
我收到错误:
ConvertTo-SecureString : The 'ConvertTo-SecureString' command was found in the module 'Microsoft.PowerShell.Security', but the module could not be loaded. For more information, run 'Import-Module Microsoft.PowerShell.Security'.
Run Code Online (Sandbox Code Playgroud)
但是,如果我直接在 powershell 中打开/运行脚本,它运行正常吗?
如果我尝试手动导入模块,我会得到:
Import-Module : The following error occurred while loading the extended type data file: Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member AuditToString is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member AccessToString is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member Sddl is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member Access is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member Group is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member Owner is already present.
Error in TypeData "System.Security.AccessControl.ObjectSecurity": The member Path is already present.
Run Code Online (Sandbox Code Playgroud)
Powershell版本是
Major Minor Build Revision
----- ----- ----- --------
5 1 22621 963
Run Code Online (Sandbox Code Playgroud)
mkl*_*nt0 11
从(或批处理文件)调用 Windows PowerShell CLI 的症状意味着您已从powershell.exePowerShell ( Core ) 7+启动。cmd.execmd.exe
换句话说:调用链是:
pwsh.exe) -> cmd.exe-> Windows PowerShell ( powershell.exe)从 PowerShell(核心)到 Windows PowerShell 的这种间接调用是问题所在:它使后者使用前者的定义$env:PSModulePath,因此导致尝试加载不兼容的 PowerShell(核心)模块。
这种间接调用会绕过直接调用时内置于 PowerShell (Core) 的逻辑powershell.exe(从 中动态删除特定于 PowerShell (Core) 的条目$env:PSModulePath),因此需要解决方法:
根据GitHub 问题 #18530,解决方案是(暂时)重置PSModulePath环境变量:
:: From cmd.exe (a batch file).
set "PSModulePath="
powershell .\scripts\scriptname.ps1
Run Code Online (Sandbox Code Playgroud)
笔记:
正如js2010 所指出的,当定义PSModulePath了特定于进程的值时,按原样powershell.exe使用该值,这是有问题的:除非该值包含标准位置,否则可能无法发现所需的模块。
相比之下,pwshPowerShell (Core) 7+ CLI 在这方面更加智能:它会自动确保所有标准位置的存在,即使进程级值不包含它们。
$env:PSModulePath如何确定有效值的确切规则很复杂;它们被记录为概念about_PSModulePath帮助主题的一部分。
请注意,即使是默认$env:PSModulePath值也会将标准当前用户模块位置放在第一位,从而可以覆盖标准 cmdlet。
在这两个版本中,都可以首先放置其他位置:
隐式地,在 Windows PowerShell 中,通过定义按原样确定有效值的进程级值,如所讨论的。
明确地,在 PowerShell 7+ 中,通过在进程级值的末尾包含当前用户位置。