0

我正在尝试创建一个函数,该函数将接受嵌入在我的项目中的指定 .ps1 文件,但我不太确定如何更改我的代码来满足这一点。

我已经在我的新 .NET 6 C# WPF 应用程序中编写了这个,该应用程序基于一个 VB.net 遗留应用程序,它执行类似的操作:

using System;
using System.Linq;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Windows;

public class PowerShellStuff
{
    private readonly string PS_UserName = "";
    private readonly string PS_Password = "";
    private Runspace? runspace;
    private PowerShell? pipeline;
    public void ConnectToExchange()
    {
        System.Security.SecureString securePassword = new System.Security.SecureString();
        foreach (char c in PS_Password)
        {
            securePassword.AppendChar(c);
        }
        PSCredential? credential = new(PS_UserName, securePassword);
        WSManConnectionInfo? connectionInfo = new(new Uri("https://outlook.office365.com/powershell-liveid/"), "http://schemas.microsoft.com/powershell/Microsoft.Exchange", credential)
        {
            AuthenticationMechanism = AuthenticationMechanism.Basic,
            MaximumConnectionRedirectionCount = 2
        };
        using (runspace = RunspaceFactory.CreateRunspace(connectionInfo))
        {
            using (pipeline = PowerShell.Create())
            {
                runspace.Open();
                pipeline.Runspace = runspace;
            }
        }
    }
    public Collection<PSObject> RunScript(PSCommand command)
    {
        if (runspace == null)
        {
            try
            {
                ConnectToExchange();
                pipeline = PowerShell.Create();
                pipeline.Runspace = runspace;
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message, "User Information", MessageBoxButton.OK, MessageBoxImage.Error);
            }
        }

        if (runspace.RunspaceStateInfo.State != RunspaceState.Opened)
            runspace.Open();

        pipeline.Commands.Clear();
        Command comand = new Command(command.Commands[0].ToString());
        for (int i = 0; i <= command.Commands[0].Parameters.Count - 1; i++)
            comand.Parameters.Add(command.Commands[0].Parameters[i]);

        pipeline.Commands.AddCommand(comand);

        Collection<PSObject> results;
        try
        {
            results = pipeline.Invoke();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message, "User Information", MessageBoxButton.OK, MessageBoxImage.Error);
        }

        return results;
    }

}

这是它在 VB.net 中的使用方式:

Dim command As New PSCommand
command.AddCommand("").AddParameter("", "")...
RunScript(command)

我遇到的问题是我什至无法在 C# 中使用上述内容,因为它失败了Non-invocable member 'PSCommand.Commands' cannot be used like a method.

我的目标是拥有一个函数,我可以使用它来使用 .ps1 脚本的结果填充 DataTable,例如DataTable dt = new DataTable(RunScript(Resources.MyScript.ps1)),以及一个不会返回任何数据而只执行带有少量参数的 SET 命令的函数,我想它会遵循相同的标准作为 VB.net 代码command.AddCommand("").AddParameter("", "")...

这是我第一次在 C# 中从头开始使用 PowerShell,因为过去我只对现有的 VB.net 代码进行了简单的更改,我以此为基础编写了这个......

编辑1:

显然 C# 新手...感谢前两位评论者,解决了执行上述代码的问题,但仍然不确定如何使用我现有的运行空间和管道执行 .ps1 文件并填充数据表。

4

1 回答 1

0

昨天我应该在这里给你一个例子,但最后却破坏了另一个几年前的线程。又来了,呵呵:)

我也在努力让 PS 脚本在我的应用程序中运行,并让它在一周前运行。在这里,我在远程计算机上启动一个脚本来弹出一个 Windows Toast 通知。

在我通过 NuGet 下载并安装 PowerShell SDK 包之前,我没有让这个脚本完全工作。希望其中一些可以使您走上正确的轨道。

在此处输入图像描述

在下面的屏幕截图中,您可以看到我还在“调试”窗口中获得了脚本生成的输出。由于某种原因,即使在脚本中设置了详细首选项,也未捕获详细输出。我必须通过将语句放在带有引号的脚本中来捕获输出,如下所示:

“操作系统版本显示名称:$OsVersion”

在此处输入图像描述

using System;
using System.Diagnostics;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Collections.ObjectModel;
using System.Net;
using System.Net.NetworkInformation;
using System.Text;
using System.Threading;
using System.Threading.Tasks;



namespace WindowsToasts
{
 
    public class WindowsToast
    {

        public void Send_WindwsUpdateToast(string computerName)
        {
            InitialSessionState initialSessionState = InitialSessionState.CreateDefault();
            initialSessionState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Unrestricted;
            using Runspace runspace = RunspaceFactory.CreateRunspace(initialSessionState);
            runspace.Open();

            using PowerShell powerShell = PowerShell.Create(runspace);
         
            string PSPath = @"C:\temp\ToastText.ps1";

            powerShell.AddCommand("Invoke-Command");
            powerShell.AddParameter("ComputerName", computerName);
            powerShell.AddParameter("File", PSPath);

            Collection<PSObject> PSOutput = powerShell.Invoke();
    
            foreach (PSObject outputItem in PSOutput)
            {
                // if null object was dumped to the pipeline during the script then a null object may be present here
                if (outputItem != null)
                {
                    Debug.WriteLine($"Output line: [{outputItem}]");
                }
            }

        }

    }
}
于 2021-11-07T10:23:11.497 回答