2010-09-22 6 views
13

Mi piacerebbe creare una piccola applicazione in grado di raccogliere informazioni di sistema (Win32_blablabla) utilizzando WinRM anziché WMI. Come posso farlo da C#?Come accedere a WinRM in C#

L'obiettivo principale è utilizzare WS-Man (WinRm) anziché DCOM (WMI).

risposta

13

Immagino che il modo più semplice sarebbe utilizzare l'automazione WSMAN. Riferimento wsmauto.dll da Windwos \ System32 nel progetto:

alt text

poi, codice qui sotto dovrebbe funzionare per voi. Descrizione API è qui: 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); 
    } 
} 

speranza che questo aiuti, riguarda

1

Vorrei notare che questo mostra un errore di interoperabilità per impostazione predefinita 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

Sembra che ci siano due modi per risolvere questo problema. Questo primo è documentato nell'articolo elencato sopra e sembra essere il modo corretto per gestire il problema. Le modifiche pertinenti per questo esempio sono:

WSMan wsManObject = new WSMan(); Questo è in sostituzione di IWSMan wsman = new WSManClass(); che genererà l'errore.

La seconda risoluzione è di andare a VS2010-> Esplora soluzioni-> Soluzione-> Progetto-> Riferimenti e selezionare WSManAutomation. Fai clic con il pulsante destro del mouse o premi Alt-Invio per accedere alle proprietà. Modificare il valore della proprietà "Incorpora tipi di interoperabilità" del riferimento wsmauto.

3

Ho un articolo che descrive un modo semplice per eseguire Powershell tramite WinRM da .NET a http://getthinktank.com/2015/06/22/naos-winrm-windows-remote-management-through-net/.

Il codice è in un singolo file se si desidera copiarlo ed è anche un pacchetto NuGet che include il riferimento a System.Management.Automation.

Gestisce automaticamente host attendibili, può eseguire blocchi di script e anche inviare file (che non è supportato ma ho creato un problema). I ritorni sono sempre gli oggetti grezzi di 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); 

Spero che questo aiuti, ho utilizzato questo per un po 'con le mie distribuzioni automatizzate. Si prega di lasciare commenti se trovate problemi.