VBScript: Windows Service remote starten und stoppen

Dank der WMI-Schnittstelle ist es möglich ein Skript zu schreiben, das auf einem remote System einen Service überwacht und bei Bedarf auch neu starten oder stoppen kann.


Dim objWMIService
Dim lServices
Dim strService: strService = "MeinService"
Dim strComputer: strComputer ="."

Set objWMIService = objSWbemLocator.ConnectServer("10.0.200.33", "root\cimv2", _
"Benutzer", _
"Passwort", _
"","")


Set lServices = objWMIService.ExecQuery("Select * from Win32_Service Where Name='" & strService & "'")
For Each objService In lServices
    Select Case objService.State
     case "Stopped" 'start service
          errReturn = objService.StartService()
     case "Paused" 'resume service
          errReturn = objService.ResumeService()
     case "Running" 'nothing todo
          wscript.echo objService.Name & " with ID " & objService.ProcessId & " is already started."
     End Select
Next

Anmerkung zu den Codezeilen:

  • 03 Achtung: bei der Definition des Servicenamen handelt es sich nicht um den Anzeigenamen sondern um den Dienstnamen
  • 06 Remote WMI Service initiieren (auch lokaler möglich)
  • 12 Mit einer WQL Abfrage wird der gesuchte Dienst selektiert um dann mit diesem Arbeiten zu können
  • 14 Status des Dienstes abfragen (Mögliche Werte sind: “Stopped”, “Start Pending”, “Stop Pending”, “Running”, “Continue Pending”, “Pause Pending”, “Paused”, “Unknown”)
Eigenschaften des Dienstes Anwendungsverwaltung
Bei der WQL-Abfrage den Dienstnamen verwenden und nicht den Anzeigenamen

Nützliche Links:

Managing Windows with WMI
WMI Query Language (WQL)
Win32_Service Class Proberties

WMI Scripting Primer: Part 1
WMI Scripting Primer: Part 2
WMI Scripting Primer: Part 3

VBScript: Microsoft DNS-Server Einträge bearbeiten

Mit Hilfe der “DNS WMI Services” kann der Microsoft DNS Server verwaltet werden. Dies ermöglicht das Erstellen von Skripts zum Hinzufügen, Löschen oder Editieren von Zonen und Records.

Um mit den “DNS WMI Klassen” zu arbeiten sind folgende Schritte notwendig:

  1. WMI Service initiieren (remote oder lokal)
  2. Mit Hilfe des WMI Service kann dann die benötigte “DNS WMI Klasse” instanziiert werden

Lokalen WMI Service initiieren:


Dim objWMIService: Set objWMIService = GetObject("winmgmts:\\" & "." & "\root\MicrosoftDNS")

Remote WMI Service initiieren:


Dim objSWbemLocator: Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator") 
Dim objWMIService: Set objWMIService = objSWbemLocator.ConnectServer(hostIP, _ 
		"root\MicrosoftDNS", _ 
		username, _ 
		password, _ 
		"", _ 
		"") 	

Die Parameter:

  • hostIP = IP des DNS-Server
  • username = Benutzername
  • password = Passwort

Neue “Primary-Zone” erstellen:


Dim objDNSZone: Set objDNSZone = objWMIService.Get("MicrosoftDNS_Zone")
objDNSZone.CreateZone(zoneName,0)

Bedeutung der Parameter:

  • zoneName = Name der neuen Zone (monsterli.ch, switch.ch, usw.)
  • 0 = Zone des Typs: “primary zone”

Neue “Secondary-Zone” erstellen:


Dim objDNSZone: Set objDNSZone = objWMIService.Get("MicrosoftDNS_Zone")
objDNSZone.CreateZone(zoneName,1,false,zoneName & "dns",array(nsMasterIP))

Dabei sind die Parameter:

  • zoneName = Name der neuen Zone (Domain)
  • 1 = Zone des Typs: “secondary zone”
  • false = keine “AD integrated zone”
  • zoneName & “dns” = Name der Zonendatei
  • array(nsMasterIP) = Array mit der IP des primären Server dieser Zone

Neuer A-Record erstellen:


Dim objItem: Set objItem = objWMIService.Get("MicrosoftDNS_AType")
objItem.CreateInstanceFromPropertyData(masterDNSServer, zoneName, subZoneName , 1, 600, hostIP)

Die Parameter:

  • masterDNSServer = IP des primären Server
  • zoneName = Name der Zone (Domain)
  • subZoneName = gewünschter Hostname (www, mail, ftp… usw.)
  • 1 = Record Class IN (Internet)
  • 600 = TTL in Sekunden
  • hostIP = IP-Adresse des Hosts

Um weitere Records wie NS, MX, CNAME, usw. zu erstellen, muss einfach die “DNS WMI Class” geändert werden.

Zone löschen:

Um eine bestehende Zone zu löschen wird mit Hilfe der “.Get” Funktion des WMI-Service die Zone selektiert und gelöscht.


Dim objServer: set objServer = objWMIService.Get("MicrosoftDNS_Server.name="".""")
Dim objItem: Set objItem = objWMIService.Get("MicrosoftDNS_Zone.ContainerName=""" & zoneName & """,DnsServerName=""" & objServer.name & """,Name=""" &  zoneName & """")
if isObject(objItem) then
	objItem.delete_
end if

Benutzte Parameter:

  • zoneName = Name der Zone die gelöscht werden soll
  • objServer.name = Name des verwendeten DNS-Server
  • zoneName = Name der Zone die gelöscht werden soll

Nützliche Links

DNS WMI Provider Samples—Managing DNS Zones

VBScript: Text von UTF-8 nach Windows-1252 konvertieren mit dem ADO Stream-Objekt

Soll ein Text, der als UTF-8 codiert wurde, in eine andere Zeichencodierung umgewandelt werden, kann dazu das ADO Stream-Objekt verwendet werden. Die hier verwendete Codierung “Windows-1252” ist eine Untermenge des ISO-8859-1 Character Sets.


'/***
' @brief convert a utf-8 text to an Windows-1252 text
' @param utf8xml, value
' @return text with Windows-1252 character set
'***/
Function UTF8TOISO(byval utf8xml)
On Error Resume Next

Dim objStream
const adTypeText = 2

Set objStream = CreateObject( "ADODB.Stream" )
Set objStreamISO = CreateObject( "ADODB.Stream" )

objStream.Type = adTypeText
objStream.Charset = "utf-8"
objStream.Open

'write data to stream
objStream.WriteText utf8xml
objStream.Position = 0

objStreamISO.Type = adTypeText
objStreamISO.Charset = "Windows-1252"
objStreamISO.Open
objStreamISO.WriteText objStream.ReadText
objStream.Position = 0

If Err Then
UTF8TOISO = ""
Else
UTF8TOISO = objStreamISO.ReadText
End If

objStream.Close
objStreamISO.Close
Set objStream = Nothing
Set objStreamISO = Nothing
End Function

Die verwendeten Properties und Funktionen des Stream-Objekts sind:

  • .Open  Öffnet den Stream
  • .Close  Schliesst den Stream
  • .Charset  Legt fest, welche Zeichencodierung verwendet werden soll
  • .Type  Definiert ob es ein Binär- oder Textstream ist
  • .WriteText  Schreibt Textdaten in den Stream
  • .ReadText  Liest Textdaten vom Stream
  • .Position  Legt die Position im Stream fest (in Bytes)

Diese Funktion lässt sich auch leicht modifizieren, wenn der konvertierte Text in einer Datei gespeichert werden soll. Dazu muss nur die Funktion “.SaveToFile(filename, adSaveCreateOverWrite)” des ADO Stream aufgerufen werden.

Text UTF-8 codiert in einer Datei speichern

Um einen Text UTF-8 codiert in einer Datei zu speichern kann folgender Code verwendet werden:


'/***
' @brief save a text UTF-8 coded in a file
' @param textToSave, value
' @param filename, the name of the file to create
' @return true on no error or false on error
'***/
Function saveFileAsUTF8(byval textToSave, byval filename)
	On Error Resume Next
    Dim objStream
	const adTypeText = 2
	Const adSaveCreateOverWrite = 2
    
    Set objStream = CreateObject( "ADODB.Stream" )
	objStream.Charset = "utf-8"
	objStream.Mode = adModeReadWrite	
	objStream.Type = adTypeText
	objStream.Open
	
	'write data to stream and save to file
    objStream.WriteText textToSave	
	objStream.Flush
	objStream.Position = 0	
	objStream.SaveToFile filename, adSaveCreateOverWrite	
    
    If Err Then
        ISOTOUTF8 = false
    Else
		ISOTOUTF8 = true
    End If	

    objStream.Close
    Set objStream = Nothing
End Function

'Aufruf der Funktion
call saveFileAsUTF8("Die bunte Welt besteht aus einem grünen Wald, einer hässlichen Geschichte und dem öffentlichen Grund...", "D:\tmp\ASP\utf8.txt")

Einbinden von Skripts in VBScript-Dateien

Beim Arbeiten mit Skripts (.vbs Dateien) gelangt man oft an den Punkt, an dem Funktionen bereits in mehreren anderen Skripts erstellt und verwendet wurden. Dabei wäre es praktisch, wenn man im neuen Skript nur noch eine Funktionssammlung einbinden könnte um die bereits erstellten Funktionen zu verwenden.

Der VBScript-Code zum Einbinden von Dateien:


Sub Include(Byval filename)
  Dim codeToInclude
  Dim FileToInclude

  Const OpenAsDefault = -2
  Const FailIfNotExist = 0
  Const ForReading = 1
  Const OpenFileForReading = 1
  Dim FSO: Set FSO = CreateObject("Scripting.FileSystemObject")

  'Check for existance of include
  If Not FSO.FileExists(filename) Then
    wscript.Echo "Include file not found."
	Set FSO = Nothing
    Exit Sub
  End If

  'open file to include
  Set FileToInclude = FSO.OpenTextFile(filename, ForReading, _
  FailIfNotExist, OpenAsDefault)

  'read all contet of the file
  codeToInclude = FileToInclude.ReadAll
  
  'close file after reading
  FileToInclude.Close
 
  'now cleanup the unused objects
  Set FSO = Nothing
  Set FileToInclude = Nothing

  'now execute code from include file
  ExecuteGlobal codeToInclude
End Sub

Ein kleines Beispiel mit 2 Skript-Dateien:

Die Datei “include.vbs” enthält eine Funktion “hello()”, welche “Hello %name%” ausgibt:


sub hello(Byval person)
	wscript.echo "Hello " & person
end sub

Das Hauptskript ist in der Datei “sayHello.vbs” und bindet die Datei “include.vbs” mit der obigen Funktion ein.


call Include("include.vbs")
call hello("Thomas")

Nach dem Aufruf der Funktion “hello()”, erscheint wie erwartet “Hello Thomas” als Output. Somit wurde die Funktion “hello()” erfolgreich eingebunden.

Herunterladen der Demo-Dateien

Mit VBScript OS Version bestimmen

Dieses Skript kann verwendet werden um die Server OS Version zu bestimmen. Das Skript liefert das Resultat für Windows 2000, Windows 2003, Windows 2008. Es kann jedoch auf einfache Weise erweitert werden, damit auch Client Versionen zurückgeliefert werden.


'/*
'	check windows version
'	return: 
'			win2k for windows 2000
'			win2k3 for windows 2003
'			win2k8 for windows 2008
'			unknown if the os is older / newer
'*/
function getOSVersion()
	strWinVersion = ""
	set objWMIService = GetObject("winmgmts:" _
		& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
	Set colOperatingSystems = objWMIService.ExecQuery _
		("Select * from Win32_OperatingSystem")
	For Each objOperatingSystem in colOperatingSystems
			strWinVersion = objOperatingSystem.Version
	Next

	'/**/	
	strMajor = left(strWinVersion,3)
	strOS = ""
	SELECT CASE strMajor
	case "5.0"
		'WScript.Echo "Windows 2000"
		strOS = "win2k"
	case "5.2"
		'WScript.Echo "Windows 2003"
		strOS = "win2k3"
	case "6.0"
		'WScript.Echo "Windows 2008"	
		strOS = "win2k8"
	case else
		'WScript.Echo "Windows x?" & "(" & strWinVersion & ")"
		strOS = "unknown"
	end select
	getOSVersion = strOS
End Function