Big's Homepage
21.07.2024
Sonnenaufgang 03:30
Sonnenuntergang 19:04
Tageslänge 15:33
 
Wissen
Links
Fun
Freizeit
Region
Reisen
Buidl
Impressum
Datenschutz

Grundlagen   Beispiele   Tools   Probleme   Links  

VB Script Grundlagen  

VB Script ist eine sehr leistungsfähige Scriptsprache für moderne Windows Betriebssysteme. Windows XP hat den Visual Basic Interpreter standardmäßig dabei. Für andere Betriebssystem ist er nachinstallierbar. Es gibt 2 unterschiedliche Interpreter für vbs Dateien.
cscript  - Standardausgabe auf der Kommandozeile
wscript - Standardausgabe als Windows MessageBox Fenster

Start am einfachsten mit:
cscript test.vbs    in der Kommandozeile (Ausführen \ cmd)

Wer die 2 Infozeilen nicht gebrauchen kann, verwendet: cscript //Nologo test.vbs
 

Beispiele  

Beispiele

Domäne, Computername und User anzeigen
Programm starten
Programm starten und Priorität ändern
Programm mit höherer Priorität starten
Die Priorität eines Prozesses für einen bestimmten Service ändern
Äbhängigkeiten eines Dienstes anzeigen (Dependencies)
CPU Infos
Betriebssystem Infos
Listenstarter - Run Once
E-Mail Sender
Timestamp einer Datei ändern
DOS Fehlercode (Errorlevel) Beschreibung ermitteln
Check Version
Read Textfile (ANSI or Unicode)
Ping mit WMI
BIOS Info - Zeige alle Infos der Objektinstanz


Domäne, Computername und User anzeigen
Als einfache Übung nur ein paar Informationen anzeigen:
Set oWSH = CreateObject("WScript.Network")
WScript.Echo "Domäne = " & oWSH.UserDomain
WScript.Echo "Computername = " & oWSH.ComputerName
WScript.Echo "Benutzername = " & oWSH.UserName


Download

Programm starten
Startet Programme und meldet Statuscode zurück...

Dim oShell, oExec
Set oShell   = CreateObject("WScript.Shell")
Set oNotepad = oShell.Exec("notepad")
Set oCalc    = oShell.Exec("calc")

Do While oNotepad.Status = 0
  WScript.Sleep 1000
Loop

WScript.Echo oNotepad.Status
WScript.Echo oCalc.Status

Download

Programm starten und Priorität ändern
Startet ein Programm und ändern die Prozesspriorität. Das ganze ist nützlich wenn man durch einen rechnintensiven Hintergrundprozess sich nicht in der Arbeit einschränken lassen will.

sProgram2run="c:\windows\notepad.exe"
sProgramEXE = LCase(Mid(sProgram2run,InStrRev(sProgram2run,"\")+1))
sComputer = "."
Const Low = 64
Set oShell = WScript.CreateObject("WScript.Shell")
oShell.Run sProgram2run

Set oWMI= GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & sComputer & "\root\cimv2")
set colProcesses = oWMI.ExecQuery ("Select * from Win32_Process where Name='" & sProgramEXE & "'")
For Each objProcess in colProcesses
  i=i+1
  y=objProcess.SetPriority(Low)
  if y<>0 then wscript.echo "Error: " & y
next
wscript.echo "Found " & i & " processes named " & sProgramEXE


'So, das wars auch schon, hier noch zur Referenz:
'RealTime = 128
'High = 256
'Above_Normal = 32768
'Normal = 32
'Below_Normal = 16384
'Low = 64

'Und die Return Codes von SetPriority
'0 Successful completion
'2 Access denied
'3 Insufficient Privilege
'8 Unknown Failure
'9 Path Not Found
'21 Invalid Parameter

Download

Oder gleich mit höherer Priorität starten
Oder gleich mit der angegebenen Priorität starten:
Const ABOVE_NORMAL = 32768
Set oWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set objStartup = oWMI.Get("Win32_ProcessStartup")
Set objConfig = objStartup.SpawnInstance_
objConfig.PriorityClass = ABOVE_NORMAL
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
objProcess.Create "Notepad.exe", Null, objConfig, intProcessID

Download

Die Priorität eines Prozesses für einen bestimmten Service ändern
(Bsp.: WUA - Windows Update Agent auf Prio Low setzen)

Oft wäre ganz nett wenn man die Priorität eines Services (dt: Dienst) ändern könnte.
So einfach ist des aber nicht immer.
Zuerst muß man zu einem Service die zugehörige 'handelsübliche' ;-) Prozess ID ermitteln.
Dann kann man die Priorität diese Prozesses ändern.

Hier ein Bespiel mit dem man den zuständigen Prozess für den Automatische Update Dienst auf Niedrig setzt.
Dazu sind allerdings Systemrechte notwendig (System User). Dazu ruft man die CMD mit psxec -s cmd auf. (aus PSTools von SysInternals.Com)
Dim objWMI, objServiceList, objService, objProcessList, objProcess
Dim intProcID, intRet
Dim strServiceName

strServiceName = "wuauserv"
intPriority    = 64          '64 - Low, siehe oben

Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set objServiceList = objWMI.ExecQuery ("Select * from Win32_Service where Name='" & strServiceName & "'")
For Each objService in objServiceList
  intProcID = objService.ProcessId
  If intProcID<>0 Then
    WScript.Echo "Found service " & sService & " with Process ID " & intProcID
    set objProcessList = objWMI.ExecQuery ("Select * from Win32_Process where ProcessId='" & intProcID & "'")
    For Each objProcess in objProcessList
      intRet=objProcess.SetPriority(intPriority)
      If intRet=0 Then
        WScript.Echo "Changed priority of Process ID " & intProcID & " to level " & intPriority & " without error."
      Else
        WScript.Echo "Changing priority of Process ID " & intProcID & " returns code " & intRet & "."
      End If
    Next
  Else
    WScript.Echo "No " & strService & " service found."
  End If
Next
Download

In dem Fall 'serviced' der svchost.exe Prozess eine ganze Reihe von Diensten.
Um alle Dienste dieser svchost.exe Instanz anzuzeigen dient das folgende Script:
Zuerst wird die Prozess ID des WUA Dienstes gesucht. Dann werden alles Dienste mit der selben Prozess ID gesucht.
strService = "wuauserv"
Set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
Set objServiceList = objWMI.ExecQuery ("Select * from Win32_Service where Name='" & sService & "'")
For Each objService in objServiceList
  intProcID = objService.ProcessId
  If intProcID<>0 Then
    wscript.echo "Found service " & sService & " with Process ID " & intProcID
  Else
    wscript.echo "No " & sService & " service found."
  End If
Next
Set objServiceList = objWMI.ExecQuery ("Select * from Win32_Service where ProcessID='" & intProcID & "'")
intProcCounter=0
For Each objService in objServiceList
  intProcCounter = intProcCounter+1
  intProcID      = objService.ProcessId
  strOut         = objService.Name
  intLeer        = 20-Len(strOut)
  if intLeer<1 then intLeer=0
  WScript.Echo strOut & Space(intLeer) & "   " & objService.PathName
Next
wscript.echo "Found " & intProcCounter & " Processes"
Download

Will man andere Dienste nicht beeinflussen, muß man den Typ des Dienstes in der Registry ändern:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\wuauserv Type=0x10  (Standard=0x20 - jeweils Hex, siehe Microsoft)
Anschließend den Dienst stoppen und neu starten...

Es ist auch mit Hilfe des Befehls sc möglich einen Dienst - z.B. den Windows Update Agent zu separieren:
sc config wuauserv type= own
sc stop wuauserv
sc start wuauserv
Das Leerzeichen nach type= nicht vergessen! Der Dienst wird dann

WUA - Servicetyp und Prozesspriorität ändern
Hier das Komplettpaket um den Windows Update Agent in einer eigenen Instanz von svchost.exe laufen zu lassen und anschließend die Prozess Priorität auf  Low zu ändern:
Zum Start (Prio ändern funktioniert nur mit Systemuser Rechten, siehe oben) - z.B. psexec -s cscript change_wua_priority.vbs (korrekten Pfad voranstellen)
Download  change_wua_priority.vbs



Abhängigkeiten (Dependencies) eines Dienstes anzeigen
Wie kann man mit Hilfe von WMI die Abhängigkeiten eines Dienstes herausfinden?

Ok, wie findet man es überhaupt so raus? Start > Ausführen > compmgmt.msc > Dienste & Anwendungen > Dienste - einen Dienst auswählen und dann auf Abhängigkeiten klicken. Screenshot
sService="Winmgmt"

If WScript.Arguments.Count = 1 Then
  If WScript.Arguments(0) = "/?" Then
    WScript.Echo "Service Dependencies - shows all antencedents and dependents of a service" & vbNewLine
    WScript.Echo WScript.ScriptName & " <service name>"
  Else
    sService = WScript.Arguments(0)
  End If
End If

Set oWMI         = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")

'Antencedents
Set oServiceList = oWMI.ExecQuery("Associators of {Win32_Service.Name='" & sService & "'} WHERE AssocClass=Win32_DependentService Role=Antecedent" )
sOut = sOut & "Antecedents of Service " & sService & ":" & vbNewLine
For each oService in oServiceList
  sOut = sOut & " " & oService.Name & vbNewLine
Next

'Dependents
sOut = sOut & "Dependents of Service " & sService & vbNewLine
Set oServiceList = oWMI.ExecQuery("Associators of {Win32_Service.Name='" & sService & "'} WHERE AssocClass=Win32_DependentService Role=Dependent" )
For each oService in oServiceList
  sOut = sOut & " " & oService.Name & vbNewLine
Next

WScript.Echo sOut

Download

CPU Infos
Einige Informationen über die CPU mittels WMI auslesen.

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_Processor",,48)
For Each objItem in colItems
    Wscript.Echo "CPU Name:  " & objItem.Name
    Wscript.Echo "Socket:    " & objItem.SocketDesignation
    Wscript.Echo "Max_Speed: " & objItem.MaxClockSpeed & " MHz"
Next

Download

Betriebssystem Infos
Einige Informationen über das Betriebssysteme anzeigen (auch mit WMI)

strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Set colItems = objWMIService.ExecQuery("SELECT * FROM Win32_OperatingSystem",,48)
For Each objItem in colItems
  Wscript.Echo "Caption: " & objItem.Caption
  Wscript.Echo "Version: " & objItem.Version
  Wscript.Echo "CSDVersion: " & objItem.CSDVersion
  Wscript.Echo "OSLanguage: " & objItem.OSLanguage
  Wscript.Echo "CountryCode: " & objItem.CountryCode
  Wscript.Echo "SystemDrive: " & objItem.SystemDrive
  Wscript.Echo "WindowsDirectory: " & objItem.WindowsDirectory
  Wscript.Echo "SystemDirectory: " & objItem.SystemDirectory
Next

Download

Listenstarter - Run Once
Manchmal ist es nötig auf bestimmten Clients irgendetwas umzustellen. Oft hat man dazu eine Liste von Computernamen auf denen ein Script einmal ausgeführt werden soll. Hier ist eine einfache Möglichkeit die mit nur einer Liste auskommt.
Man schreibt alle betroffenen Clients in die Textdatei, das Script schreibt in die Textdatei die erledigten Clients.

Download VBS Datei  Download Beispiel Liste


E-Mail Sender
Mit Hilfe von ein paar Zeilen CScript kann man ganz leicht eine E-Mail senden...
Ach ja, sogar Attachments kann man anfügen: oEmail.AddAttachment "C:\Scripts\Output.txt"

Set oEmail = CreateObject("CDO.Message")
oEmail.From = "meineemail@absender.de"
oEmail.To = "zieladresse@ibins.de"
oEmail.Subject = "Automatic CScript E-Mail"
oEmail.Textbody = "This E-Mail was sent by CScript" & vbNewLine & "www.bigerl.de"
oEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/sendusing")  = 2
oEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserver") = "post.strato.de"
oEmail.Configuration.Fields.Item ("http://schemas.microsoft.com/cdo/configuration/smtpserverport") = 25
oEmail.Configuration.Fields.Update
oEmail.Send

Download

Timestamp einer Datei ändern
Mit Hilfe von ein paar Zeilen CScript kann man auch ganz leicht den DateLastModified Zeitstempel einer Datei ändern.
Das folgende Beispiel liest aus dem Verzeichnis a den Timestamp aller Dateien und schreibt ihn auf die Zieldatei im Verzeichnis b wenn die Zieldatei existiert.
sSrcFolder = "c:\temp\a\"

sTrgFolder = "c:\temp\b\"

Set oFS   = CreateObject("Scripting.FileSystemObject")

Set oSrcFolder = oFS.GetFolder(sSrcFolder)
Set oFiles     = oSrcFolder.Files
For Each oFile in oFiles
  If oFS.FileExists(sTrgFolder & oFile.Name) Then fReDateFile sTrgFolder & oFile.Name, oFile.DateLastModified
Next

Function fReDateFile(sFilepath, sTimestamp)
    Dim oApp, oFolder, oFileX

    iPosSep = InStrRev(sFilepath,"\")
    sFolder = Left(sFilepath,iPosSep)
    sFile   = Mid (sFilepath,iPosSep+1)
    Set oApp = CreateObject("Shell.Application")
    Set oFolder = oApp.NameSpace(sFolder)
    Set oFileX  = oFolder.ParseName(sFile)
    oFileX.ModifyDate = sTimestamp

    Set oApp    = Nothing
    Set oFolder = Nothing
    Set oFileX  = Nothing    
End Function

Download

DOS Fehlercode (Errorlevel) Beschreibung ermitteln
Mit Hilfe dieser Funktion kann man die Beschreibung eines Fehlercodes in einer Variablen speichern. (Ausgabe des DOS Befehls: net helpmsg 2)
Die Funktion Replace sorgt dafür das Ergebnis in einer Zeile steht.

WScript.Echo "Beschreibung des Fehlercodes 2: " & fGetErrorDesc(2)

Function fGetErrorDesc(iErrNumber)
  Dim oWSHGED, oExecGED
  Set oWSHGED  = CreateObject("WScript.Shell")
  Set oExecGED = oWSHGED.Exec("net helpmsg " & iErrNumber)
  If Not oExecGED.StdOut.AtEndOfStream Then fGetErrorDesc = Replace(oExecGED.StdOut.ReadAll, vbNewline,"")
  If Not oExecGED.StdErr.AtEndOfStream Then fGetErrorDesc = Replace(oExecGED.StdErr.ReadAll, vbNewline,"")
End Function

Download

Check Version
Mit Hilfe dieser Funktion kann man leicht eine Version überprüfen. Versionsangaben sind meist 4 Zahlen durch einen Punkt getrennt.
Dadurch kann einfach geprüft werden ob bestimmt Mindestvorraussetzungen von Systemkomponenten erfüllt sind.

Function fCheckVersion(sCurVersion, sMinVersion)
'Returncode: -1 = error, 0 = current version is older, 1 = equal, 2 = current version is newer
  Dim bOlder, bNewer, aCurVersion, aMinVersion
  fCheckVersion = 1
  If Len(sCurVersion) > 0 AND Len(sMinVersion) > 0 Then
    aCurVersion = Split(sCurVersion, ".")
    aMinVersion = Split(sMinVersion, ".")
    If UBound(aCurVersion) = 3 OR UBound(aMinVersion) = 3 Then
      For i = 0 To UBound(aCurVersion)
        If CInt(aCurVersion(i)) < CInt(aMinVersion(i)) Then bOlder = 1
        If CInt(aCurVersion(i)) > CInt(aMinVersion(i)) Then bNewer = 1
        If bOlder OR bNewer Then Exit For
      Next
    End If
  Else
    fCheckVersion = -1
  End If
  If bOlder then fCheckVersion = 0
  If bNewer then fCheckVersion = 2
End Function

Download

Read Textfile (ANSI or Unicode)
Mit Hilfe des richtigen Parameters erkennt VBScript automatisch ob es sich um ANSI oder Unicode formatierte Textdateien handelt.
Die letzte Zahl der OpenTextFile Methode bestimmt das Format: ANSI (normaler Text), -1 = Unicode, -2 = Automatisch Erkennung

Set oFS   = CreateObject("Scripting.FileSystemObject")
Set oFile = oFS.OpenTextFile("C:\temp\textfile.txt", 1, ,-2)
Download
Ping mit WMI
Mit Hilfe von WMI kann man einen Ping ausführen. (zum prüfen ob ein bestimmtes Netzwerk Gerät ansprechbar ist)

Set oWMI  = GetObject("WinMgmts:\\.\root\CIMV2")
Set oPing = oWMI.ExecQuery("Select * From Win32_PingStatus where Address = 'localhost'")

For Each oStatus in oPing
  If IsNull(oStatus.StatusCode) OR oStatus.StatusCode<>0 Then
    WScript.Echo "Client offline"
  Else
    Wscript.Echo "Client ONLINE"
    Wscript.Echo "Response Time: " & oStatus.ResponseTime
    Wscript.Echo "TTL:           " & oStatus.ResponseTimeToLive
    Wscript.Echo "IP Address:    " & oStatus.ProtocolAddress
  End If
Next
Download
BIOS Infos - Beispiel für Show Instance of a object
Mit Hilfe der Methode getObjectText_ kann der komplette Inhalt einer Objektinstanz ausgegeben werden:

Set oWMI = GetObject("winmgmts:\\.")
sWQL = "Select * From Win32_BIOS"
Set oItems = oWMI.ExecQuery(sWQL)

For Each oItem In oItems
  WScript.Echo oItem.getObjectText_
Next

Download Beispiel

Tools  

Fiese Problemchen  

  • Shell Exec funktioniert nicht
  • Set oShell = CreateObject("WScript.Shell")
    Set oExec = oShell.Exec("\\server.de\share\a.vbs")
    Richtig ist:
    Set oExec = oShell.Exec("cscript.exe \\server.de\share\a.vbs")
  • If Then funktioniert nicht
  • iA = 23
    iB = "22"
    If iA < iB Then WScript.Echo "go"
    Hier hilft:
    iB = CInt("22")

Links  

Und noch mehr Links...

MSDN & TechNet Referenzen: