简体   繁体   English

PowerShell 使用 .Net Core 和 Hyper-V 进行远程处理

[英]PowerShell Remoting with .Net Core and Hyper-V

I am attempting to write a .NET Core program that remotely connects to a Windows 2019 server running in Hyper-V.我正在尝试编写一个远程连接到在 Hyper-V 中运行的 Windows 2019 服务器的 .NET 核心程序。 I've poured through the literature and I finally got my code to compile and run but receive no output.我翻阅了文献,终于得到了可以编译和运行的代码,但没有收到 output。 It seems that it is just running the commands in a local PowerShell isntance.它似乎只是在本地 PowerShell 实例中运行命令。 Any guidance would be helpful.任何指导都会有所帮助。

        string password = "password123";
        var securePassword = new SecureString();

        foreach (char c in password)
        {
            securePassword.AppendChar(c);
        }

        string userName = "Administrator";

        PSCredential creds = new PSCredential(userName, securePassword);
        Runspace runspace = RunspaceFactory.CreateRunspace();


        PowerShell powershell = PowerShell.Create();
        PSCommand command = new PSCommand();
        command.AddCommand("New-PSSession");
        command.AddParameter("VMName", "PSRemote");
        command.AddParameter("Credential", creds);
        powershell.Commands = command;
        runspace.Open();
        Collection<PSSession> result = powershell.Invoke<PSSession>();
        Console.WriteLine(result);

        powershell = PowerShell.Create();
        command = new PSCommand();
        command.AddCommand("Set-Variable");
        command.AddParameter("Name", "ra");
        command.AddParameter("Value", result[0]);
        powershell.Commands = command;
        powershell.Runspace = runspace;
        powershell.Invoke();

        powershell = PowerShell.Create();
        command = new PSCommand();
        command.AddScript("Import-PSSession -Session $ra");
        powershell.Commands = command;
        powershell.Runspace = runspace;
        powershell.Invoke();

        powershell = PowerShell.Create();
        command = new PSCommand();
        command.AddScript("Get-WUList");
        powershell.Commands = command;
        powershell.Runspace = runspace;
        var results = powershell.Invoke();
        foreach (var psobject in results)
        {
            Console.WriteLine(psobject);
        }
        runspace.Close();

There are people much, much better with C# here than myself here, but here is a quick sample that I have used to demo using PowerShell.有人在这里使用 C# 比我自己要好得多,但这里有一个快速示例,我曾经使用 PowerShell 进行演示。 Your main issue here I think is creating a new instance of PowerShell every time you run a new command.我认为您的主要问题是每次运行新命令时都会创建 PowerShell 的新实例。 Hope that helps.希望有帮助。

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace PoshSample {
    public class AD {
        // Properties
        public PowerShell Posh;
        public string[] PSModule = new string[] { "activedirectory" };

        public Init() {
            Posh = NewPowerShellSession(PSModule);

            // Calling Functions - Add multiple ones with parameters if you need to chain commands like you would via the pipeline
            IDictionary<String, Object> functions = new Dictionary<String, Dictionary<String, Object>>();
            IDictionary<String, Object> parameters = new Dictionary<String, Object>();
            parameters.Add("Filter", "*");
            parameters.Add("SearchBase", "OU=SomeOtherOU,OU=topOU,DC=blah,DC=com");
            functions.Add("Get-ADGroup", parameters)
            var adGroups = RunPosh(function, "Name", true);

            // Other commands here.
        }

        private PowerShell NewPowerShellSession(String[] PSModule = null)
        {
            // Define our PowerShell Session
            PowerShell powerShell = PowerShell.Create();
            Runspace runspace;

            // Add the PSModule if required
            if (PSModule != null)
            {
                InitialSessionState initial = InitialSessionState.CreateDefault();
                initial.ImportPSModule(PSModule);
                runspace = RunspaceFactory.CreateRunspace(initial);
            }
            else
            {
                runspace = RunspaceFactory.CreateRunspace();
            }
            runspace.Open();
            powerShell.Runspace = runspace;
            return powerShell;
        }

        // Run a PowerShell function - Set Async to true to wait for output. False is for functions where you are not expecting anything to be returned.
        private Collection<PSObject> RunPosh(Dictionary<String, Dictionary<String, Object>> Commands, String Property = null, bool Async = false)
        {
            // Sleep two seconds before proceeding - this is important, but I am not sure why. Stumbled on it a long time ago.
            Posh.AddCommand("Start-Sleep").AddParameter("Seconds", 2).AddStatement();

            // Run our command adding the parameters one by one and then pipe in to Out-String.
            foreach (KeyValuePair<String, Dictionary<String, Object>> c in Commands)
            {
                string PoshCommand = c.Key;
                Posh.AddCommand(PoshCommand);
                Dictionary<String, Object> Parameters = c.Value;
                if (Parameters != null)
                {
                    foreach (var key in Parameters.Keys)
                    {
                        Posh.AddParameter(key, Parameters[key]);
                    }
                }
            }

            // List a selected property
            if (Property != null)
            {
                Posh.AddCommand("Select-Object").AddParameter("ExpandProperty", Property);
            }

            if (Async)
            {
                // Invoke our command asynchronously and return the objects.
                IAsyncResult async = Posh.BeginInvoke();
                var returnCollection = new Collection<PSObject>();
                foreach (PSObject obj in Posh.EndInvoke(async))
                {
                    returnCollection.Add(obj);
                }
                Posh.Commands.Clear();
                return returnCollection;
            }
            else
            {
                Posh.Invoke();
                Posh.Commands.Clear();
                return null;
            }
        }
    }
}

By the way, I am not 100% sure on this one, but you may be able to set your variable via the Runspace rather than running another command.顺便说一句,我不是 100% 确定这一点,但您可以通过运行空间设置变量,而不是运行另一个命令。 SessionStateProxy . 会话状态代理

Posh.Runspace.SessionStateProxy.SetVariable(string, object)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM