如何从C#作为非提升用户运行PowerShell脚本

时间:2022-10-26 02:32:00

I'm trying to run a PowerShell script from a C# application and I need the script to run when my C# app is running as a non-admin user (e.g. Network Service or some other domain account).

我正在尝试从C#应用程序运行PowerShell脚本,我需要在我的C#app作为非管理员用户(例如网络服务或其他域帐户)运行时运行该脚本。

Previously, I was using the following code:

以前,我使用以下代码:

using (RunspaceInvoke invoker = new RunspaceInvoke())
{
    // load the powershell module
    invoker.Invoke("Import-Module MyModule");

    // run the cmdlet defined in the module 
    invoker.Invoke("MyCmdlet");
}

I don't know whether this is the best approach for running cmdlets defined in a module (please teach me if there's a better way!). In any case, this works perfectly if I'm running as an administrative user. I tried running this as Network Service, however, and I got an unfriendly error in the constructor of RunspaceInvoke:

我不知道这是否是运行模块中定义的cmdlet的最佳方法(如果有更好的方法,请教我!)。无论如何,如果我作为管理用户运行,这将完美地运行。我尝试将其作为网络服务运行,但是,我在RunspaceInvoke的构造函数中遇到了一个不友好的错误:

Requested registry access is not allowed.

不允许请求的注册表访问。

Is there a way I can run my PowerShell cmdlets as a non-elevated user such as Network Service? I do not need or desire to access the registry. The cmdlet itself also does not require elevated privileges.

有没有办法可以将我的PowerShell cmdlet作为非提升用户运行,例如网络服务?我不需要或不希望访问注册表。 cmdlet本身也不需要提升权限。

4 个解决方案

#1


2  

We use a version of the below. The "script" parameter is the PS script to run. We use this from a custom command line so that we can mix c# commands with some written in PS. "results" can be used to capture the evaluation of your script. The "out-default" line means that the output of the PS script is written to the console. A version of this can instead capture the output to a TextBox or similar if you have a WinForm of WPF app.

我们使用以下版本。 “script”参数是要运行的PS脚本。我们从自定义命令行使用它,以便我们可以将c#命令与PS中编写的命令混合使用。 “结果”可用于捕获脚本的评估。 “out-default”行表示PS脚本的输出被写入控制台。如果你有一个WPF应用程序的WinForm,它的一个版本可以将输出捕获到TextBox或类似的。

public void run(string script)
{
    IEnumerable<PSObject> results;
    var config = RunspaceConfiguration.Create();
    var host = new ScriptHost();
    using (var runspace = RunspaceFactory.CreateRunspace(host, config))
    {
        runspace.Open();
        runspace.SessionStateProxy.SetVariable("prog", this);

        using (var pipeline = runspace.CreatePipeline())
        {
            if (!string.IsNullOrEmpty(scriptPath))
                pipeline.Commands.AddScript(string.Format("$env:path = \"{0};\" + $env:path", scriptPath));

            pipeline.Commands.AddScript(script);

            var outDefault = new Command("out-default");
            outDefault.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
            pipeline.Commands.Add(outDefault);

            results = pipeline.Invoke();
        }
    }
}

#2


0  

more on lkaso answer

更多关于lkaso的回答

this shows you how to run it as anybody, not just admin. YOu have to run it as somebody, the service is running as a heavily restricted account that cannot do anything.

这将向您展示如何以任何人身份运行它,而不仅仅是管理员。你必须以某人的身份运行它,该服务作为一个严格限制的帐户运行,无法做任何事情。

or run the service itself as joe user

或者将服务本身作为joe用户运行

#3


0  

Can you use SysInternals procmon tool to see what Registry access it's trying to accomplish? Maybe that will give you some insight as to what you could do to solve the problem.

你可以使用SysInternals procmon工具来查看它试图完成的Registry访问吗?也许这将为您提供一些有关如何解决问题的见解。

#4


-1  

I think that this entry will answer your question.

我认为此条目将回答您的问题。

#1


2  

We use a version of the below. The "script" parameter is the PS script to run. We use this from a custom command line so that we can mix c# commands with some written in PS. "results" can be used to capture the evaluation of your script. The "out-default" line means that the output of the PS script is written to the console. A version of this can instead capture the output to a TextBox or similar if you have a WinForm of WPF app.

我们使用以下版本。 “script”参数是要运行的PS脚本。我们从自定义命令行使用它,以便我们可以将c#命令与PS中编写的命令混合使用。 “结果”可用于捕获脚本的评估。 “out-default”行表示PS脚本的输出被写入控制台。如果你有一个WPF应用程序的WinForm,它的一个版本可以将输出捕获到TextBox或类似的。

public void run(string script)
{
    IEnumerable<PSObject> results;
    var config = RunspaceConfiguration.Create();
    var host = new ScriptHost();
    using (var runspace = RunspaceFactory.CreateRunspace(host, config))
    {
        runspace.Open();
        runspace.SessionStateProxy.SetVariable("prog", this);

        using (var pipeline = runspace.CreatePipeline())
        {
            if (!string.IsNullOrEmpty(scriptPath))
                pipeline.Commands.AddScript(string.Format("$env:path = \"{0};\" + $env:path", scriptPath));

            pipeline.Commands.AddScript(script);

            var outDefault = new Command("out-default");
            outDefault.MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
            pipeline.Commands.Add(outDefault);

            results = pipeline.Invoke();
        }
    }
}

#2


0  

more on lkaso answer

更多关于lkaso的回答

this shows you how to run it as anybody, not just admin. YOu have to run it as somebody, the service is running as a heavily restricted account that cannot do anything.

这将向您展示如何以任何人身份运行它,而不仅仅是管理员。你必须以某人的身份运行它,该服务作为一个严格限制的帐户运行,无法做任何事情。

or run the service itself as joe user

或者将服务本身作为joe用户运行

#3


0  

Can you use SysInternals procmon tool to see what Registry access it's trying to accomplish? Maybe that will give you some insight as to what you could do to solve the problem.

你可以使用SysInternals procmon工具来查看它试图完成的Registry访问吗?也许这将为您提供一些有关如何解决问题的见解。

#4


-1  

I think that this entry will answer your question.

我认为此条目将回答您的问题。