windows 如何在 C# 中访问 WinRM

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3771920/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-15 15:17:49  来源:igfitidea点击:

How to access WinRM in C#

c#windowswmiremote-management

提问by Mark

I'd like to create a small application that can collect system information (Win32_blablabla) using WinRM as opposed to WMI. How can i do that from C#?

我想创建一个可以使用 WinRM 而不是 WMI 收集系统信息 (Win32_blablabla) 的小型应用程序。我怎样才能从 C# 做到这一点?

The main goal is to use WS-Man (WinRm) as opposed to DCOM (WMI).

主要目标是使用 WS-Man (WinRm) 而不是 DCOM (WMI)。

采纳答案by serge_gubenko

I guess the easiest way would be to use WSMAN automation. Reference wsmauto.dll from windwos\system32 in your project:

我想最简单的方法是使用 WSMAN 自动化。在您的项目中从 windwos\system32 引用 wsmauto.dll:

alt text

替代文字

then, code below should work for you. API description is here: msdn: WinRM C++ API

那么,下面的代码应该适合你。API 说明在这里:msdn:WinRM C++ API

IWSMan wsman = new WSManClass();
IWSManConnectionOptions options = (IWSManConnectionOptions)wsman.CreateConnectionOptions();                
if (options != null)
{
    try
    {
        // options.UserName = ???;  
        // options.Password = ???;  
        IWSManSession session = (IWSManSession)wsman.CreateSession("http://<your_server_name>/wsman", 0, options);
        if (session != null)
        {
            try
            {
                // retrieve the Win32_Service xml representation
                var reply = session.Get("http://schemas.microsoft.com/wbem/wsman/1/wmi/root/cimv2/Win32_Service?Name=winmgmt", 0);
                // parse xml and dump service name and description
                var doc = new XmlDocument();
                doc.LoadXml(reply);
                foreach (var elementName in new string[] { "p:Caption", "p:Description" })
                {
                    var node = doc.GetElementsByTagName(elementName)[0];
                    if (node != null) Console.WriteLine(node.InnerText);
                }
            }
            finally
            {
                Marshal.ReleaseComObject(session);
            }
        }
    }
    finally
    {
        Marshal.ReleaseComObject(options);
    }
}

hope this helps, regards

希望这有帮助,问候

回答by wlscaudill

I've got an article that describes an easy way to run Powershell through WinRM from .NET at http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.

我在http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/ 上有一篇文章描述了一种从 .NET 通过 WinRM 运行 Powershell 的简单方法。

The code is in a single file if you want to just copy it and it's also a NuGet package that includes the reference to System.Management.Automation.

如果您只想复制代码,则代码位于单个文件中,它也是一个 NuGet 包,其中包含对 System.Management.Automation 的引用。

It auto manages trusted hosts, can run script blocks, and also send files (which isn't really supported but I created a work around). The returns are always the raw objects from Powershell.

它自动管理受信任的主机,可以运行脚本块,还可以发送文件(实际上并不支持,但我创建了一个解决方法)。返回值始终是来自 Powershell 的原始对象。

// this is the entrypoint to interact with the system (interfaced for testing).
var machineManager = new MachineManager(
    "10.0.0.1",
    "Administrator",
    MachineManager.ConvertStringToSecureString("xxx"),
    true);

// will perform a user initiated reboot.
machineManager.Reboot();

// can run random script blocks WITH parameters.
var fileObjects = machineManager.RunScript(
    "{ param($path) ls $path }",
    new[] { @"C:\PathToList" });

// can transfer files to the remote server (over WinRM's protocol!).
var localFilePath = @"D:\Temp\BigFileLocal.nupkg";
var fileBytes = File.ReadAllBytes(localFilePath);
var remoteFilePath = @"D:\Temp\BigFileRemote.nupkg";
machineManager.SendFile(remoteFilePath, fileBytes);

Hope this helps, I've been using this for a while with my automated deployments. Please leave comments if you find issues.

希望这会有所帮助,我已经在我的自动化部署中使用了一段时间。如果您发现问题,请发表评论。

回答by Daniel

I would like to note that this shows an interop error by default in Visual Studio 2010.
c.f. http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be-embedded-use-the-applicable-interface-instead.aspx

我想指出,这在 Visual Studio 2010 中默认显示互操作错误。
参见http://blogs.msdn.com/b/mshneer/archive/2009/12/07/interop-type-xxx-cannot-be -embedded-use-the-applicable-interface-instead.aspx

There appear to be two ways to solve this. This first is documented in the article listed above and appears to be the correct way to handle the problem. The pertinent changes for this example is:

似乎有两种方法可以解决这个问题。这首先记录在上面列出的文章中,并且似乎是处理问题的正确方法。此示例的相关更改是:

WSMan wsManObject = new WSMan(); This is in lieu of IWSMan wsman = new WSManClass(); which will throw the error.

WSMan wsManObject = new WSMan(); 这代替了 IWSMan wsman = new WSManClass(); 这将引发错误。

The second resolution is to go to the VS2010—>Solution Explorer—>Solution—>Project—>References and select WSManAutomation. Right click or hit Alt-Enter to access the properties. Change the value of the "Embed Interop Types" property of the wsmauto reference.

第二种解决方法是进入VS2010—>Solution Explorer—>Solution—>Project—>References,选择WSManAutomation。右键单击或按 Alt-Enter 以访问属性。更改 wsmauto 引用的“嵌入互操作类型”属性的值。