问题
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.
回答1:
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.)
回答2:
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.
回答3:
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