I am running the Powershell script from my C# code. The same code is working for the .net 4.7.2 framework application, But when I use the same code within the same solution for the .net8 application, the same script is giving the below exception while invoking this script.
File C:workPowershellSampleAppDotNet8binDebugnet8.0PS.ps1
cannot be loaded because running scripts is disabled on this system
Code:
public void RunScript(string scriptPath, Dictionary<string, object> parameters)
{
using (var ps = PowerShell.Create())
{
ps.AddCommand(scriptPath);
foreach (var param in parameters)
{
ps.AddParameter(param.Key, param.Value);
}
var results = ps.Invoke();
foreach (var result in results)
{
Console.WriteLine(result);
}
if (ps.Streams.Error.Count > 0)
{
foreach (var error in ps.Streams.Error)
{
Console.WriteLine($"Error: {error}");
}
}
}
}
I have tried checking the Execution policies as well, they are below.
PS C:WINDOWSsystem32> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Bypass
LocalMachine Bypass
The only difference between the two projects is that the .net8 application refers to Microsoft.PowerShell.SDK and the .net 4.7.2 is referring the DLL from GAC (……WindowsMicrosoft.NETassemblyGAC_MSILSystem.Management.Automationv4.0_3.0.0.0__31bf3856ad364e35System.Management.Automation.dll)
PS Script:
param (
[string]$name,
[string]$username,
[SecureString]$password
)
# Converting SecureString to plain text for display (for demonstration purposes)
if ($null -ne $securePassword) {
$plainPassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto([System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($password))
}
else {
# Write-Error "Secure password cannot be null."
}
# Write-Host "Name: $name"
# Write-Host "Username: $username"
# Write-Host "Password: $plainPassword"
# Creating a custom object to return
$result = [PSCustomObject]@{
Name = $name
Username = $username
Password = $plainPassword
}
# Returning the object
Write-Output $result
Complete Error:
C:workPowershellSampleAppDotNet8binDebugnet8.0>SampleAppDotNet8.exe
Unhandled exception. System.Management.Automation.PSSecurityException:
File C:workPowershellSampleAppDotNet8binDebugnet8.0PS.ps1
cannot be loaded because running scripts is disabled on this system.
For more information, see about_Execution_Policies at
https://go.microsoft.com/fwlink/?LinkID=135170. —>
System.UnauthorizedAccessException: File
C:workPowershellSampleAppDotNet8binDebugnet8.0PS.ps1 cannot be
loaded because running scripts is disabled on this system. For more
information, see about_Execution_Policies at
https://go.microsoft.com/fwlink/?LinkID=135170. — End of inner
exception stack trace — at
System.Management.Automation.Runspaces.PipelineBase.Invoke(IEnumerable
input) at System.Management.Automation.Runspaces.Pipeline.Invoke()
at
System.Management.Automation.PowerShell.Worker.ConstructPipelineAndDoWork(Runspace
rs, Boolean performSyncInvoke) at
System.Management.Automation.PowerShell.Worker.CreateRunspaceIfNeededAndDoWork(Runspace
rsToUse, Boolean isSync) at
System.Management.Automation.PowerShell.CoreInvokeHelper[TInput,TOutput](PSDataCollection1 input, PSDataCollection
1 output, PSInvocationSettings settings) at
System.Management.Automation.PowerShell.CoreInvoke[TInput,TOutput](PSDataCollection1 input, PSDataCollection
1 output, PSInvocationSettings settings) at
System.Management.Automation.PowerShell.CoreInvoke[TOutput](IEnumerable
input, PSDataCollection1 output, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke(IEnumerable input, PSInvocationSettings settings) at System.Management.Automation.PowerShell.Invoke() at PowershellAdvance.PowerShellService.RunScript(String scriptPath, Dictionary
2 parameters) in
C:workPowershellPowershellParamsResolverPowerShellService.cs:line
24 at PowershellAdvance.PowerShellScriptRunner.RunAsync(String
jsonString, String scriptPath) in
C:workPowershellPowershellParamsResolverPowerShellScriptRunner.cs:line
26 at SampleAppDotNet8.Program.Main(String[] args) in
C:workPowershellSampleAppDotNet8Program.cs:line 26 at
SampleAppDotNet8.Program.(String[] args)
So Do I need to handle calling the PS differently in the .net8 application?
6
The two PowerShell editions,
- the legacy, ships-with-Windows Windows PowerShell edition (
powershell.exe
, whose latest and final version is 5.1.x, which is based on .NET Framework)
vs. - the install-on-demand, cross-platform PowerShell (Core) 7 edition (
pwsh
, version 7.x, based on .NET (Core)),
have separate execution policies.
Each edition has its own SDK for hosting PowerShell in a custom application.
- See this answer for the NuGet packages to choose.
The execution policies of the respective stand-alone edition apply to SDK projects too, with the exception of the LocalMachine
policy of a stand-alone PowerShell 7 installation (note that while Windows PowerShell is guaranteed to be present on an given machine, the install-on-demand PowerShell 7 is not).
- See this answer for details.
However, the best solution is not to rely on a preconfigured execution policy to begin with, and instead, as part of your project, use an SDK method to set the execution policy dynamically, for the current process only, as follows (this is the equivalent of using Set-ExecutionPolicy -Scope Process RemoteSigned -Force
) – this makes your application work predictably, irrespective of whether a stand-alone PowerShell 7 installation is also present and, if so, irrespective of what its configuration is:
// Create an initial default session state.
var iss = InitialSessionState.CreateDefault2();
// Set its script-file execution policy (for the current session (process) only).
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.RemoteSigned;
// Create a PowerShell instance with a runspace based on the
// initial session state and run a sample script to show
// that the process-level policy took effect.
using (PowerShell ps = PowerShell.Create(iss))
{
Console.WriteLine(
ps.AddScript(@"Get-ExecutionPolicy -List | Out-String").Invoke()[0]
);
}
1
Great, @nimizen’s comment helped me in finding the solution. I installed the Powershell 7.4.5 version. Then I checked the Execution Policy in PS7, it was set to Undefined for the CurrentUser. Although its shown as RemoteSigned in my PS5 (I still need to explore this, why so?)
PS C:workPowershellSampleAppDotNet8> Get-ExecutionPolicy -List
Scope ExecutionPolicy
----- ---------------
MachinePolicy Undefined
UserPolicy Undefined
Process Undefined
CurrentUser Undefined
LocalMachine RemoteSigned
Then I changed it to RemoteSigned and it worked for me.