When running from cmd.exe
powershell .\scripts\scriptname.ps1
Which has a line to convert plain text to secure string
[securestring]$secString = ConvertTo-SecureString $SampleString -AsPlainText -Force
I get error:
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'.
However if I open / run the script direct in powershell it runs fine?
If I try to import the module manually I get:
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.
Powershell version is
Major Minor Build Revision
----- ----- ----- --------
5 1 22621 963
The symptom of your call to powershell.exe
, the Windows PowerShell CLI, from cmd.exe
(or a batch file) implies that you've launched cmd.exe
from PowerShell (Core) 7+.
In other words: the chain of calls is:
pwsh.exe
) -> cmd.exe
-> Windows PowerShell (powershell.exe
)This indirect call from PowerShell (Core) to Windows PowerShell is the problem: It makes the latter use the former's definition of the $env:PSModulePath
and therefore results in attempts to load - incompatible - PowerShell (Core) modules.
Such an indirect call bypasses the logic that is built into PowerShell (Core) when directly invoking powershell.exe
(dynamic removal of PowerShell (Core)-specific entries from $env:PSModulePath
) and therefore requires a workaround:
Per GitHub issue #18530, the solution is to (temporarily) reset the PSModulePath
environment variable:
:: From cmd.exe (a batch file).
set "PSModulePath="
powershell .\scripts\scriptname.ps1
Note:
As js2010 points out, when a process-specific value for PSModulePath
is defined, powershell.exe
uses this value as-is, which is problematic: unless the value includes the standard locations, required modules may not be discoverable.
By contrast, pwsh
, the PowerShell (Core) 7+ CLI, is smarter about this: It automatically ensures the presence of all standard locations, even if a process-level value doesn't include them.
The exact rules for how the effective $env:PSModulePath
value is determined are complex; they are documented as part of the conceptual about_PSModulePath
help topic.
Note that even the default $env:PSModulePath
values place the standard current-user module location first, making it possible to override standard cmdlets.
In both editions it is possible to place additional locations first:
implicitly, in Windows PowerShell, by defining a process-level value that determines the effective value as-is, as discussed.
explicitly, in PowerShell 7+, by including the current-user location in the process-level value, at the end.