Question

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#?

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

Was it helpful?

Solution

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

alt text

then, code below should work for you. API description is here: 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

OTHER TIPS

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/.

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.

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.

// 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.

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

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.

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top