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.
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.)
Here is method b, that doesn't require elevated rights or Registry modification rights.
Using Process.Start
launch this and add the relevant initial -command
or -file
args.
%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy bypass
Here is another technique, http://dmitrysotnikov.wordpress.com/2008/06/27/powershell-script-in-a-bat-file/
That relies on executing by encoding it first and passing int through the -EncodedCommand
arg of powershell.exe, which appears to bypass execution policy.
You could try something like the following
using ( new Impersonator( "Username", "DomainName", "Password" ) )
{
using (RunspaceInvoke invoker = new RunspaceInvoke())
{
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
}
}
Here is a link you can look at to get an idea as an example, Class For Impersonating a User.
来源:https://stackoverflow.com/questions/13479838/how-to-run-powershell-scripts-from-c-sharp