如何从C#运行PowerShell脚本

5
我正在尝试使用C#运行一个PowerShell脚本,但是一直没有成功。以下是我的函数代码:

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();
}

我遇到的错误如下:

无法访问注册表项 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell'。

我该如何解决这个问题?我看过一些模拟用户身份的想法,但是没有找到好的模拟示例。我希望以管理员身份运行此脚本。

我已经做了以下声明:

[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);

我已经创建了以下内容用于模拟身份的函数:
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);
}

我创建了一个函数,用作委托:

private static void GIncognito(params object[] args)
{
    RunspaceInvoke scriptInvoker = new RunspaceInvoke();
    scriptInvoker.Invoke("Set-ExecutionPolicy Unrestricted");
}

我已经修改了我的方法:

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();
}

结果是......同样的错误,告诉我无法访问注册表键。

回复:无法访问注册表键-- 您必须使用可以修改注册表键的帐户,或者使用一种技术,该技术不涉及从正在运行的PowerShell实例内部更改执行策略。 - MatthewMartin
@Lajos:这样做的冒名顶替有点过头了......你所需做的只是更改 Set-ExecutionPolicy 使用的作用域......请参见我下面的答案。 - JaredReisinger
3个回答

2
这里是方法b,不需要提升权限或注册表修改权限。使用Process.Start启动它,并添加相关的初始-command-file参数。

%SystemRoot%\system32\WindowsPowerShell\v1.0\powershell.exe -ExecutionPolicy bypass

这里是另一种技术,http://dmitrysotnikov.wordpress.com/2008/06/27/powershell-script-in-a-bat-file/,它依赖于首先对其进行编码并通过-EncodedCommand参数传递给powershell.exe执行,这似乎可以绕过执行策略。

我正试图运行一个Git命令,但是如果我按照这种方式做,它会要求输入用户名和密码。问题在于我想让它完全自动化。如果需要用户名或密码,则每次执行都需要人工干预。那我能否将其完全自动化呢?谢谢。 - Lajos Arpad
Git 询问用户名密码还是 Windows 凭据?你的脚本文件里有什么? - MatthewMartin
git 超出了我的经验范围。我猜你正在受到 git 提示凭据的影响,也许这可以帮助你:http://superuser.com/questions/338511/how-do-i-disable-password-prompts-when-doing-git-push-pull - MatthewMartin
我已经编辑了我的问题。我尝试实现一个模拟方法。我不知道哪里出了问题,但肯定有些地方不对。 - Lajos Arpad

1
默认的Set-ExecutionPolicy命令尝试设置全局值。您只想在C#应用程序范围内更改设置,因此应将-Scope Process选项添加到命令中。使用Get-Help Set-ExecutionPolicy -detailed可以查看此信息:注意:要更改默认(LocalMachine)范围的执行策略,请使用“以管理员身份运行”选项启动Windows PowerShell。 它还描述了-Scope选项。这样做的好处是,它影响从您的C#应用程序运行的脚本的执行策略,并且不会不必要地更改默认PowerShell行为的执行策略。 (因此,它更安全,特别是如果您可以保证应用程序运行的脚本的有效性。)

0
你可以尝试像下面这样的东西。
using ( new Impersonator( "Username", "DomainName", "Password" ) )
{
    using (RunspaceInvoke invoker = new RunspaceInvoke())
    {
        invoker.Invoke("Set-ExecutionPolicy Unrestricted");
    }
}

这里有一个链接可以作为示例供您参考,模拟用户的类


谢谢您的帖子。为了做到这一点,我需要使用Impersonator类,但我不知道在哪里可以找到它或如何实现它。我没有找到下载链接,只有一个指向另一个页面的链接,其中描述了模拟器,但也无法下载,只能共享该功能。我应该注册网站才能下载这些吗? - Lajos Arpad
看起来像这样的代码:https://dev59.com/_2kw5IYBdhLWcg3waZ34 - MatthewMartin
请查看Matthew Martin发布的链接。希望这些信息能帮助您入门。以下是我最初发布的链接,以防初始帖子中的链接无法使用:http://www.codeproject.com/Articles/10090/A-small-C-Class-for-impersonating-a-User - MethodMan
好的,现在我遇到了以下错误:请求的注册表访问被拒绝。 - Lajos Arpad
你是否有足够的权限/权利来运行一个PowerShell脚本? - MethodMan
显示剩余5条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接