gpt4 book ai didi

c# - 在 .NET Core 3.0 中从 C# 执行提升的 powershell 脚本

转载 作者:行者123 更新时间:2023-12-03 00:06:02 25 4
gpt4 key购买 nike

我正在从 C# 代码调用一个自我提升的 powershell 脚本。该脚本会重置 DNS 设置。
从未提升的 powershell 调用该脚本时,该脚本工作正常,但从 C# 代码调用时不起作用,不会引发异常。
我的执行策略暂时设置为不受限制,并且我以管理员身份运行 Visual Studio。

有谁知道出了什么问题?

C#:

    class Program
{
static void Main(string[] args)
{

var pathToScript = @"C:\Temp\test.ps1";
Execute(pathToScript);

Console.ReadKey();


}
public static void Execute(string command)
{
using (var ps = PowerShell.Create())
{
var results = ps.AddScript(command).Invoke();
foreach (var result in results)
{
Console.WriteLine(result.ToString());
}
}
}


}

脚本:
# Get the ID and security principal of the current user account
$myWindowsID = [System.Security.Principal.WindowsIdentity]::GetCurrent();
$myWindowsPrincipal = New-Object System.Security.Principal.WindowsPrincipal($myWindowsID);

# Get the security principal for the administrator role
$adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator;

# Check to see if we are currently running as an administrator
if ($myWindowsPrincipal.IsInRole($adminRole))
{
# We are running as an administrator, so change the title and background colour to indicate this
$Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)";
$Host.UI.RawUI.BackgroundColor = "DarkBlue";
Clear-Host;
}
else {
# We are not running as an administrator, so relaunch as administrator

# Create a new process object that starts PowerShell
$newProcess = New-Object System.Diagnostics.ProcessStartInfo "PowerShell";

# Specify the current script path and name as a parameter with added scope and support for scripts with spaces in it's path
$newProcess.Arguments = "& '" + $script:MyInvocation.MyCommand.Path + "'"

# Indicate that the process should be elevated
$newProcess.Verb = "runas";

# Start the new process
[System.Diagnostics.Process]::Start($newProcess);

# Exit from the current, unelevated, process
Exit;
}

# Run your code that needs to be elevated here...
Set-DnsClientServerAddress -InterfaceIndex 9 -ResetServerAddresses

最佳答案

正如您刚刚确定的那样,主要 问题是您的系统上禁用了脚本执行 ,需要(至少)对 PowerShell 的进程级进行更改 execution policy ,如以下 C# 代码所示,它调用
Set-ExecutionPolicy -Scope Process -ExecutionPolicy Bypass在调用脚本文件( *.ps1 )之前:

  • 对于 使用初始 session 状态设置每个进程执行策略的替代方法 ,见 this answer .
  • 下面的方法原则上可以用于持续改变当前用户的执行策略 ,即通过替换 .AddParameter("Scope", "Process").AddParameter("Scope", "CurrentUser")
  • 警告:当使用 PowerShell (Core) 7+ SDK 时,对本地机器策略 ( .AddParameter("Scope", "LocalMachine") ) 的持续更改 - 需要以提升(以管理员身份)运行 - 只有该 SDK 项目才能看到;见 this answer详情。


  • 警告:如果当前用户/机器的执行策略由 GPO(组策略对象)控制,则不能以编程方式覆盖 - 既不能按进程覆盖,也不能永久覆盖(除非通过 GPO 更改)。
      class Program
    {
    static void Main(string[] args)
    {

    var pathToScript = @"C:\Temp\test.ps1";
    Execute(pathToScript);

    Console.ReadKey();

    }

    public static void Execute(string command)
    {
    using (var ps = PowerShell.Create())
    {

    // Make sure that script execution is enabled at least for
    // the current process.
    // For extra safety, you could try to save and restore
    // the policy previously in effect after executing your script.
    ps.AddCommand("Set-ExecutionPolicy")
    .AddParameter("Scope", "Process")
    .AddParameter("ExecutionPolicy", "Bypass")
    .Invoke();

    // Now invoke the script and print its success output.
    // Note: Use .AddCommand() (rather than .AddScript()) even
    // for script *files*.
    // .AddScript() is meant for *strings
    // containing PowerShell statements*.
    var results = ps.AddCommand(command).Invoke();
    foreach (var result in results)
    {
    Console.WriteLine(result.ToString());
    }

    // Also report non-terminating errors, if any.
    foreach (var error in ps.Streams.Error)
    {
    Console.Error.WriteLine("ERROR: " + error.ToString());
    }

    }
    }

    }
    请注意 代码还报告任何非终止错误 脚本可能已通过 stderr(标准错误输出流)报告。
    没有 Set-ExecutionPolicy调用,如果执行策略不允许(未签名)脚本执行,PowerShell 将通过其错误流 ( .Streams.Error ) 报告非终止错误而不是抛出异常。
    如果您已检查 .Streams.Error首先,您会更早地发现问题的具体原因。
    所以:
  • 使用PowerShell SDK时,除了依赖/捕捉异常,还要检查.Streams.Error确定是否发生了(至少形式上不太严重的)错误。

  • PowerShell 脚本的潜在问题:
  • 在从 PowerShell 脚本返回之前,您无需等待提升的进程终止。
  • 您没有捕获提升进程的输出,您必须通过 .RedirectStandardInput.RedirectStandardError System.Diagnostics.ProcessStartInfo 的属性实例,然后让你的脚本输出结果。
  • this answer如何做到这一点。

  • 以下代码的简化版本解决了第一点,并调用了 powershell.exe CLI通过 -ExecutionPolicy Bypass也。
  • 如果您使用的是 Windows PowerShell SDK,这应该不是必需的(因为 C# 代码中的执行策略已更改),但如果您使用的是 PowerShell [Core] SDK,则可能是必要的,因为这两个PowerShell 版本具有单独的执行策略设置。

  • # Check to see if we are currently running as an administrator
    $isElevated = & { net session *>$null; $LASTEXITCODE -eq 0 }
    if ($isElevated)
    {
    # We are running as an administrator, so change the title and background color to indicate this
    $Host.UI.RawUI.WindowTitle = $myInvocation.MyCommand.Definition + "(Elevated)"
    $Host.UI.RawUI.BackgroundColor = "DarkBlue"
    Clear-Host
    }
    else {
    # We are not running as an administrator, so relaunch as administrator

    # Create a new process object that starts PowerShell
    $psi = New-Object System.Diagnostics.ProcessStartInfo 'powershell.exe'

    # Specify the current script path and name as a parameter with and support for scripts with spaces in its path
    $psi.Arguments = '-ExecutionPolicy Bypass -File "{0}"' -f
    $script:MyInvocation.MyCommand.Path

    # Indicate that the process should be elevated.
    $psi.Verb = 'RunAs'
    # !! For .Verb to be honored, .UseShellExecute must be $true
    # !! In .NET Framework, .UseShellExecute *defaults* to $true,
    # !! but no longer in .NET Core.
    $psi.UseShellExecute = $true

    # Start the new process, wait for it to terminate, then
    # exit from the current, unelevated process, passing the exit code through.
    exit $(
    try { ([System.Diagnostics.Process]::Start($psi).WaitForExit()) } catch { Throw }
    )

    }

    # Run your code that needs to be elevated here...
    Set-DnsClientServerAddress -InterfaceIndex 9 -ResetServerAddresses

    关于c# - 在 .NET Core 3.0 中从 C# 执行提升的 powershell 脚本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61138425/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com