0

我正在尝试在 c# 中运行一个 powershell 脚本,其中包含以下命令:Get-Credential

我可以使用 Process Command 运行该文件:

 public static void RunFile(string ps1File)
        {
            
            var startInfo = new ProcessStartInfo()
            {
                FileName = "powershell.exe",
                Arguments = $"-NoProfile -ExecutionPolicy unrestricted -file \"{ps1File}\"",
                UseShellExecute = false,
                CreateNoWindow = true
            };
            try
            {
                Process P = Process.Start(startInfo);
                P.WaitForExit();
                var result = P.ExitCode;
                System.Diagnostics.Debug.WriteLine("Error: " + result);
            }
            catch (Exception e)
            {
                throw;
            }
        }

但是我没有得到 PS 返回值。所以我正在尝试 System.Management.Automation 但现在我遇到了 PS 窗口没有出现的问题,我得到了直接的错误代码:

public async static void RunFileTest(string ps1File) {

    PowerShell ps = PowerShell.Create();

    //PowerShell ps = PowerShell.Create();
    if (File.Exists(ps1File)) {

        ScriptBlock sb = ScriptBlock.Create(System.IO.File.ReadAllText(ps1File));
        System.Diagnostics.Debug.WriteLine("SB: " + sb.ToString());


        // execute the script and await the result.
        //var results = await ps.InvokeAsync().ConfigureAwait(false);

        //var results = ps.Invoke();

        PSCommand new1 = new PSCommand();
        
        
        ps.Commands = new1;

        var results = ps.Invoke();

        foreach (var result in results)
        {
            Console.WriteLine(result); //<-- result NOT results
            System.Diagnostics.Debug.WriteLine("Error: " + result.ToString());
        }

        System.Diagnostics.Debug.WriteLine("Errors: " + results);
    } else
    {
        System.Diagnostics.Debug.WriteLine("Error: " + "No File");
    }
}

有没有办法运行 PS 文件并从 get-credential 获取窗口但没有 PowerShell 窗口?

谢谢斯蒂芬


编辑:看来,当我使用第一个函数 RunFile 时,我必须使用 exit 而不是 return 来设置正确的退出代码,但是无论如何,最好使用内置 powershell 函数

4

1 回答 1

0

据我所知,如果您以不可见 PowerShell 窗口的方式从 C# 调用 PowerShell,则无法从该窗口显示任何提示。

我们解决这个问题的方法是事先询问用户凭据并将它们作为参数传递给 PS 脚本。您甚至可以将敏感数据(如密码)作为SecureString.

using System;
using System.Security;

public static class ConsoleHelper
{
    /// <summary>
    /// Replaces user input with '*' characters
    /// </summary>
    /// <returns>User input as SecureString</returns>
    public static SecureString GetPassword(string message) =>
        GetString(message, GetPasswordReader);

    public static string GetNotEmptyString(string message) =>
        GetString(message, (str) => !string.IsNullOrWhiteSpace(str));

    public static string GetString(string message, Func<string, bool> validator = null) =>
        GetString(message, Console.ReadLine, validator);

    private static T GetString<T>(string message, Func<T> reader, Func<T, bool> validator = null)
    {
        T value;
        while (true)
        {
            Console.Write(message + ": ");
            value = reader();
            if (validator?.Invoke(value) != false)
            {
                break;
            }
        }

        return value;
    }

    private static SecureString GetPasswordReader()
    {
        var pass = new SecureString();
        ConsoleKey key;
        do
        {
            var keyInfo = Console.ReadKey(intercept: true);
            key = keyInfo.Key;

            if (key == ConsoleKey.Backspace && pass.Length > 0)
            {
                Console.Write("\b \b");
                pass.RemoveAt(pass.Length - 1);
            }
            else if (!char.IsControl(keyInfo.KeyChar))
            {
                Console.Write("*");
                pass.AppendChar(keyInfo.KeyChar);
            }
        } 
        while (key != ConsoleKey.Enter);
        Console.WriteLine();

        return pass;
    }
}

使用示例:

var scriptCommand = new Command(formExporterScriptPath)
{
    Parameters =
    {
        { "User", ConsoleHelper.GetNotEmptyString("Enter username") },
        { "Password", ConsoleHelper.GetPassword("Enter password") },
    }
};

using (var powershell = PowerShell.Create())
{
    powershell.Commands.AddCommand(scriptCommand);
    powershell.Invoke();

    Console.ForegroundColor = ConsoleColor.DarkGray;
    foreach (var result in powershell.Streams.Information)
    {
        Console.WriteLine(result.MessageData.ToString());
    }

    if (powershell.Streams.Error.Any())
    {
        Console.ForegroundColor = ConsoleColor.DarkRed;
        foreach (var result in powershell.Streams.Error)
        {
            Console.WriteLine(result.Exception.Message);
        }
    }

    Console.ResetColor();
}
于 2020-11-15T08:37:13.650 回答