In einem Windows-Netzwerk kann ohne weiteres, hat man denn die Rechte, von außen auf einen PC zugegriffen und verwaltet werden. Microsoft bietet hier einige Möglichkeiten. Zum einen gibt es WMI (Windows Management Instrumentation) zum anderen kann man auch ohne weiteres auf die Windows-Registrierung per Remote zu greifen.
Hierfür habe ich zwei Klassen zusammengebastelt, welche die für mich relevante Daten von einem Remote PC auslesen. Ich generiere mir so eine Liste über Software- und Hardwareausstattung sowie Informationen über das Betriebsystem es Computers.
Damit der Zugriff von außen für möglich ist braucht man Adminrechte auf dem fremden PC, sollte in der Windows-Domäne für einen Administrator kein Thema sein. Die Firewall sollte nicht zu restriktiv eingestellt sein. Die Ports 135 für WMI und 445 für den Registry Zugriff müssen frei sein.
In den Klassen, wird bevor irgendeine Anfrage gesendet wurde, zu erst überprüft ob diese Ports zu erreichen sind. Wie in den Beispielen an den IF-Bedingungen zu sehen ist. Zur Veranschaulichung der Funktionweise steht unter den Downloads eine kleine VB.NET Anwendung bereit.
Zum Einbinden der WMI-Klassen mus ein Verweis auf System.Management vorhanden.
x64 und 32Bit Installationen
Microsoft stellt 32Bit Anwendungen unter einem 64Bit Betriebssystem quasi eine eigene Umgebung zur Verfügung. Dazu werden unter anderem auch die Installationroutinen "umgeleitet". Wird also eine Anwendung installiert so werden alle Informationen der Installation unter SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall abgelegt. Für 32-Bit Anwendung wird hingeben der Zweig SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall genutzt.
Methoden, Eigenschften
clsRegSoftware.vb
- CheckRegistryMode:Soll nur x86 und x64 oder beide Registry-Pfade durchsucht werden (default:beide)
- CheckOnlineStatus:Soll vor einer Anfrage überprüft werden ob die benötigten Ports geöffnet sind (default:true)
- SoftwareItems.DisplayName: Name der installierten Software
- SoftwareItems.DisplayVersion: Version der Software*
- SoftwareItems.RegistryMode: 0 für x86, 1 für x64
- SoftwareItems.ParentDisplayName: Updates werden meistens geschachtelt. Der Wert gibt das dazugehörte Programm (DisplayName) an*
* stehen nicht zwingend immer zur Verfügung
clsWMI.vb
- CheckOnlineStatus:Soll vor einer Anfrage überprüft werden ob die benötigten Ports geöffnet sind (default:true)
- Connected:Wurde erfolgreich eine Verbindung aufgebaut?
- User.ClearCurrentLoggedIn: Username ohne Domäne oder PCName
- User.CurrentLoggedIn: kompletter Username mit Domäne und PCName
- CPU.Name: Name des Processors
- CPU.Speed: Geschwindigkeit in MHZ
- SystemOS.Name: Betriessystemname
- SystemOS.Version: Versionsnummer des Betriebssystem
- SystemOS.ServicePack: ServicePack Version
- Memory.MegaByte: kompletter Arbeitsspeicher in MB
- Memory.Banks: eingebaute Speicherbänke MB; getrennt durch | (z.B. 512|512)
- Graphic.Name: Name der Grafikkarte
- Graphic.RAM: interner Speicher der Grafikkarte
- Graphic.DriverVersion: Version des installierten Grafikkartentreibers
Beispiele
'Read installed software over registry
Dim SoftItem As New clsRegSoftware("hostname or ip") 'localhost possible
If SoftItem.GetInfo() = True Then
For Each SoftwareItem In SoftItem.SoftwareItems
MsgBox(SoftwareItem.DisplayName)
Next
End If
'read pc details over wmi
Dim wmi As New clsWMI("hostname or ip") 'localhost possible
If wmi.connect = True Then
MsgBox(WMI.CPU.Name)
End IfKlassen-Diagramme
Quelltext
clsRegSoftware.vb
Imports System.Net.Sockets
Imports Microsoft.Win32
Public Class clsRegSoftware
Dim _ComputerName As String
Dim _CheckOnlineStatus As Boolean = True
Dim _SoftwareItems As New List(Of sSoftwareItem)
Dim _CheckRegistryMode As enumCheckRegistryMode = enumCheckRegistryMode.Both
Enum enumRegistryMode
[default] = 0
WoW64 = 1
End Enum
Public Enum enumCheckRegistryMode
Both = 0
defaultOnly = 1
WoW64Only = 2
End Enum
Public Sub New(ByVal ComputerName As String)
_ComputerName = ComputerName
End Sub
'''<summary>Check if Remote Manchine is running and accessible; default = true</summary>
Public WriteOnly Property CheckOnlineStatus() As Boolean
Set(ByVal value As Boolean)
_CheckOnlineStatus = value
End Set
End Property
'''<summary>
''' Which RegistryKeys should use to get Software Information (default both)
''' Both=ALL
''' defaultOnly=SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
''' WoW64Only=SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
''' </summary>
Public WriteOnly Property CheckRegistryMode() As enumCheckRegistryMode
Set(ByVal value As enumCheckRegistryMode)
_CheckRegistryMode = value
End Set
End Property
'''<summary>
'''Read Remote registry
''' </summary>
'''<returns>return false if pc offline</returns>
Function GetInfo() As Boolean
If _CheckOnlineStatus = True Then
If IfOnline() = False Then Return False
End If
If _CheckRegistryMode = enumCheckRegistryMode.Both Or _CheckRegistryMode = enumCheckRegistryMode.defaultOnly _
Then ReadUninstall(enumRegistryMode.default)
If _CheckRegistryMode = enumCheckRegistryMode.Both Or _CheckRegistryMode = enumCheckRegistryMode.WoW64Only _
Then ReadUninstall(enumRegistryMode.WoW64)
Return True
End Function
Public ReadOnly Property SoftwareItems() As List(Of sSoftwareItem)
Get
Return _SoftwareItems
End Get
End Property
'' <summary>
'' Removes double space characters.
'' </summary>
''<param name="text">The text.</param>
''<returns></returns>
Private Function RemoveDoubleSpaceCharacters(ByVal text As String)
Return System.Text.RegularExpressions.Regex.Replace(text, "[ ]+", " ")
End Function
Private Sub ReadUninstall(ByVal rRegistryMode As enumRegistryMode)
Dim key As String = ""
Select Case rRegistryMode
Case enumRegistryMode.default
key = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Case enumRegistryMode.WoW64
key = "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
End Select
Dim RemoteRegistry As RegistryKey
Dim UninstallItems() As String
Try
RemoteRegistry = RegistryKey.OpenRemoteBaseKey(RegistryHive.LocalMachine, _ComputerName)
Dim RemoteRegistryUninstallNode As RegistryKey = RemoteRegistry.OpenSubKey(key)
If Not IsNothing(RemoteRegistryUninstallNode) Then
UninstallItems = RemoteRegistryUninstallNode.GetSubKeyNames()
For i As Integer = 0 To UninstallItems.Length - 1
Dim SoftwareItem As RegistryKey = RemoteRegistry.OpenSubKey(key & "\" & UninstallItems(i))
Dim SoftwareDisplayName As String = RemoveDoubleSpaceCharacters(SoftwareItem.GetValue("DisplayName", "unknown"))
If Not SoftwareDisplayName = "unknown" And SoftwareDisplayName.Length > 0 Then
Dim ItemHolder As New sSoftwareItem
ItemHolder.DisplayName = SoftwareDisplayName
ItemHolder.RegistryMode = rRegistryMode
ItemHolder.DisplayVersion = SoftwareItem.GetValue("DisplayVersion", "")
ItemHolder.ParentDisplayName = SoftwareItem.GetValue("ParentDisplayName", "")
_SoftwareItems.Add(ItemHolder)
End If
Next
End If
Catch ex As Exception
MsgBox(ex.Message)
End Try
End Sub
Private Function IfOnline() As Boolean
Try
Dim client As New TcpClient
client.LingerState = New LingerOption(False, 1)
client.Connect(_ComputerName, 445)
client.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
Public Class sSoftwareItem
Dim _DisplayName As String = ""
Dim _DisplayVersion As String = ""
Dim _ParentDisplayName As String = ""
Dim _RegistryMode As enumRegistryMode = enumRegistryMode.default
Property ParentDisplayName() As String
Get
Return _ParentDisplayName
End Get
Set(ByVal value As String)
_ParentDisplayName = value
End Set
End Property
Property DisplayName() As String
Get
Return _DisplayName
End Get
Set(ByVal value As String)
_DisplayName = value
End Set
End Property
Property DisplayVersion() As String
Get
Return _DisplayVersion
End Get
Set(ByVal value As String)
_DisplayVersion = value
End Set
End Property
Property RegistryMode() As enumRegistryMode
Get
Return _RegistryMode
End Get
Set(ByVal value As enumRegistryMode)
_RegistryMode = value
End Set
End Property
End Class
End ClassclsWMI.vb
Imports System.Management
Public Class clsWMI
Dim myManagementScope As New System.Management.ManagementScope
Private _isConnected As Boolean = False
Private _CheckOnlineStatus As Boolean = True
Private _MaschineName As String
Public Sub New(ByVal MaschineName As String)
_MaschineName = MaschineName
End Sub
ReadOnly Property Connected() As Boolean
Get
Return _isConnected
End Get
End Property
'''<summary>Check if Remote Manchine is running and accessible; default = true</summary>
Public WriteOnly Property CheckOnlineStatus() As Boolean
Set(ByVal value As Boolean)
_CheckOnlineStatus = value
End Set
End Property
Function connect() As Boolean
Try
If _CheckOnlineStatus = True Then
If IfOnline(_MaschineName) = False Then Return False
End If
Dim myConnectionOptions As New ConnectionOptions
With myConnectionOptions
.Impersonation = ImpersonationLevel.Impersonate
'* Use next line for XP
'.Authentication = System.Management.AuthenticationLevel.Packet
'* Use next line for Win prior XP
.Authentication = AuthenticationLevel.Connect
End With
'* Replace the "." with an actual servername for remote connection
myManagementScope = New ManagementScope("\\" & _MaschineName & "\root\cimv2", myConnectionOptions)
'* connect to WMI namespace
myManagementScope.Connect()
If myManagementScope.IsConnected = False Then
'MsgBox("Could not connect to WMI namespace")
myManagementScope = Nothing
_isConnected = False
Return False
End If
_isConnected = True
Return True
Catch ex As Exception
_isConnected = False
Return False
End Try
End Function
Private Function IfOnline(ByVal _ComputerName As String) As Boolean
Try
Dim client As New System.Net.Sockets.TcpClient
client.LingerState = New System.Net.Sockets.LingerOption(False, 1)
client.Connect(_ComputerName, 135)
client.Close()
Return True
Catch ex As Exception
Return False
End Try
End Function
Private Function Search(ByVal sql As String) As ManagementObjectCollection
Dim myObjectSearcher As New System.Management.ManagementObjectSearcher( _
myManagementScope.Path.ToString, sql)
'* execute query
Return myObjectSearcher.Get()
'* list packages installed
End Function
Function CPU() As WmiValueCPU
Dim back As New WmiValueCPU
If myManagementScope.IsConnected = True Then
For Each myObject As ManagementObject In Search("Select Name,Caption,SocketDesignation,MaxClockSpeed from Win32_Processor")
back.Name = RemoveDoubleSpaceCharacters(myObject.GetPropertyValue("Name").ToString)
back.Speed = myObject.GetPropertyValue("MaxClockSpeed")
Next
End If
Return back
End Function
Function Memory() As WmiValueMemory
Dim back As New WmiValueMemory
Dim splitter As String = ""
If myManagementScope.IsConnected = True Then
For Each myObject As ManagementObject In Search("Select Capacity from WIN32_PhysicalMemory")
Dim bRAM As Integer = Math.Round(myObject.GetPropertyValue("Capacity") / 1024 / 1024, 0)
If bRAM > 1 Then
back.Banks = back.Banks & splitter & bRAM
back.MegaByte += bRAM
splitter = "|"
End If
Next
End If
Return back
End Function
Function Graphic() As WmiValueGraphic
Dim back As New WmiValueGraphic
If myManagementScope.IsConnected = True Then
For Each myObject As ManagementObject In Search("Select Caption,AdapterRAM,DriverVersion from Win32_VideoController WHERE DeviceID='VideoController1'")
back.Name = RemoveDoubleSpaceCharacters(myObject.GetPropertyValue("Caption"))
back.RAM = Math.Round(myObject.GetPropertyValue("AdapterRAM") / 1024 / 1024, 0)
back.DriverVersion = myObject.GetPropertyValue("DriverVersion")
Next
End If
Return back
End Function
Function SystemOS() As WmiValueSystemOS
Dim back As New WmiValueSystemOS
If myManagementScope.IsConnected = True Then
For Each myObject As ManagementObject In Search("Select Caption,Version,CSDVersion from Win32_OperatingSystem")
back.Name = myObject.GetPropertyValue("Caption")
back.Version = myObject.GetPropertyValue("Version")
back.ServicePack = myObject.GetPropertyValue("CSDVersion")
Next
End If
Return back
End Function
Function User() As WmiValueUser
Dim back As New WmiValueUser
If myManagementScope.IsConnected = True Then
For Each myObject As ManagementObject In Search("Select * from Win32_ComputerSystem")
back.CurrentLoggedIn = myObject.GetPropertyValue("UserName")
back.ClearCurrentLoggedIn = Me.ClearUserName(back.CurrentLoggedIn)
Next
End If
Return back
End Function
Private Function ClearUserName(ByVal str As String) As String
If Not IsNothing(str) Then
If str.Contains("\") Then
Return str.Remove(0, str.LastIndexOf("\") + 1)
Else
Return str
End If
End If
Return str
End Function
'' <summary>
'' Removes double space characters.
'' </summary>
''<param name="text">The text.</param>
''<returns></returns>
Private Function RemoveDoubleSpaceCharacters(ByVal text As String)
Return System.Text.RegularExpressions.Regex.Replace(text, "[ ]+", " ")
End Function
Structure WmiValueUser
Dim CurrentLoggedIn As String
Dim ClearCurrentLoggedIn As String
End Structure
Structure WmiValueCPU
Dim Name As String
Dim Speed As String
End Structure
Structure WmiValueMemory
Dim Banks As String
Dim MegaByte As String
End Structure
Structure WmiValueGraphic
Dim Name As String
Dim RAM As String
Dim DriverVersion As String
End Structure
Structure WmiValueSystemOS
Dim Name As String
Dim Version As String
Dim ServicePack As String
End Structure
End Class


Disqus - noscript
@pokermaster2007
einfach z.B. auf die \\hostname oder ip\c$ Freigabe mit dem entsprechenden Benutzer verbinden
Für Zugriff auf remote Computer forlgende kleine Änderungen, dann klappt das auch im Domänenfreien umfeld:
With myConnectionOptions '.EnablePrivileges = True .Impersonation = ImpersonationLevel.Impersonate .Authentication = AuthenticationLevel.Default
If _MaschineName <> "." Then .Username = _UserName .Password = _Password End If End With
In search() noch eine kleine Änderung:
Dim myObjectSearcher As New System.Management.ManagementObjectSearcher(myManagementScope.Path.ToString, sql) myObjectSearcher.Scope = myManagementScope'Interessanterweise wird im konstruktor der scope nicht übergeben