How to run PowerShell scripts from C#
c#, impersonation, powershell, registry
Solution
The default `Set-ExecutionPolicy` command attempts to set the machine-wide value. You only want to change the setting within the scope of your C# application, so you should add the `-Scope Process` option to the command.
Using `Get-Help Set-ExecutionPolicy -detailed` reveals this information:
NOTE: To change the execution policy for the default (LocalMachine) scope, start Windows PowerShell with the "Run as administrator" option.
... and it also describes the `-Scope` option.
This has the advantage of only impacting the execution policy for scripts run from your C# application, and it doesn't unnecessarily change the execution policy for the default PowerShell behavior. (So it's a lot safer, especially if you can make guarantees about the validity of the scripts your application runs.)
Problem
I am trying to run a PowerShell script with C#, but I don't have any success. Here is my function: ``` private void ExecutePowerShellCommand(string scriptfile) { RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); RunspaceInvoke scriptInvoker = new RunspaceInvoke(); scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); Pipeline pipeline = runspace.CreatePipeline(); //Here's how you add a new script with arguments Command myCommand = new Command(scriptfile); //CommandParameter testParam = new CommandParameter("key", "value"); //myCommand.Parameters.Add(testParam); pipeline.Commands.Add(myCommand); // Execute PowerShell script pipeline.Invoke(); } ``` This is the error I get: Access to the registry key 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell' is denied. How can I solve this issue? I have seen ideas for impersonation, but I didn't seem to find any good examples to impersonate. I would like to run this script as an administrator. I have made the following declarations: ``` [DllImport("advapi32.dll")] private static extern bool LogonUser(string lpszUsername, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, ref IntPtr phToken); [DllImport("kernel32.dll")] private static extern bool CloseHandle(IntPtr handle); public delegate void IncognitoDelegate(params object[] args); ``` I have created the following function for impersonation: ``` public static void Impersonate(IncognitoDelegate incognitoDelegate, params object[] args) { System.IntPtr token = new IntPtr(); WindowsIdentity wi; if (LogonUser("myusername", "", "mypassword", 8, 0, ref token)) { wi = new WindowsIdentity(token); WindowsImpersonationContext wic = wi.Impersonate(); incognitoDelegate(args); wic.Undo(); } CloseHandle(token); } ``` I have created a function which is used as a delegate: ``` private static void GIncognito(params object[] args) { RunspaceInvoke scriptInvoker = new RunspaceInvoke(); scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); } ``` And I have modified my method: ``` private void ExecutePowerShellCommand(string scriptfile) { RunspaceConfiguration runspaceConfiguration = RunspaceConfiguration.Create(); Runspace runspace = RunspaceFactory.CreateRunspace(runspaceConfiguration); runspace.Open(); Impersonate(new Util.IncognitoDelegate(GIncognito)); //RunspaceInvoke scriptInvoker = new RunspaceInvoke(); //scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted"); Pipeline pipeline = runspace.CreatePipeline(); //Here's how you add a new script with arguments Command myCommand = new Command(scriptfile); //CommandParameter testParam = new CommandParameter("key", "value"); //myCommand.Parameters.Add(testParam); pipeline.Commands.Add(myCommand); // Execute PowerShell script pipeline.Invoke(); } ``` The result was... ... the very sam error, telling me I can't access registry keys.