I've had to do a little VBScript recently, and many scripts that I've seen use this variable strComputer which, on the surface anyway, seems pointless. It's typically set to ".", and then used in a string concatenation like so:
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Why is this done, when one could simply write Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")? I see this all over the place and it mystifies me.
As #false pointed out in the comments to the question, the purpose is to make the computer whose WMI service you want to access configurable.
. is a shortcut for the local computer. If you're certain that your script will only ever be connecting to the local computer there is indeed no benefit to be gained from a configurable computername, and you're better off just merging the . into the moniker:
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
However, if you need the ability to run the script against remote hosts, you can for instance make the host configurable via a commandline argument:
strComputer = "." 'default to localhost
If WScript.Arguments.Exists("ComputerName") Then
strComputer = WScript.Arguments.Named("ComputerName")
End If
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
'do stuff with objWMIService
or read a list of hostnames from a file:
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile("C:\computerlist.txt")
Do Until f.AtEndOfStream
strComputer = f.ReadLine
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
'do stuff with objWMIService
Loop
f.Close
Related
What is use of line:
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
in vbscript code.
This will create a WMI object that provides you with the objects, methods and properties needed to be able to communicate with the different parts of the OS.
So, using your snippet, you could for example query the status of every service:
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery("Select * from Win32_Service")
For Each objService in colRunningServices
MsgBox objService.Name & " - " & objService.State
Next
You aren't limited to services, you can access registry settings, active process, etc. I use it often at work to help manage our Windows environment.
A few resources:
http://msdn.microsoft.com/en-us/library/aa394585(v=vs.85).aspx
http://technet.microsoft.com/en-us/library/ee176998.aspx
I'm working on a script that renames a folder on a remote pc. But it it's not working.
Iff I execute the script nothing happens. I use a modified version of the Hey Scripting Guy blog. If I use normal pathnames (c:\data) instead of remotepath names (\\"& strcomputer &"C$\data) it works. But if i use remote pathnames nothing happens.
Do you guys know whats wrong?
strComputer = "hostname"
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colFolders = objWMIService.ExecQuery _
("Select * From Win32_Directory Where Name = '\\\\"& strComputer &"C$\\Data'")
For Each objFolder in colFolders
strNewName = objFolder.Name & ".old"
objFolder.Rename strNewName
Next
When you connect with WMI you don't use a UNC path with Win32_Directory (since it's local to that WMI repository).
So use ("Select * From Win32_Directory Where Name = 'C:\\Data'")
You should be able to accomplish your task using the FileSystemObject...
strComputer = "hostname"
strFolderName = "\\"& strComputer &"\C$\Data"
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strFolderName) Then
Set objFolder = objFSO.GetFolder(strFolderName)
strNewName = objFolder.Name & ".old"
objFolder.Name = strNewName
End If
This query runs fine on my local machine:
strComputer = "."
drive = "C:"
path = "\\path\\to\\local\\folder\\"
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery("Select * From CIM_DataFile Where Path = '"&path&"' and drive='"&drive&"'")
If colFiles.Count < 1 Then
Wscript.Echo "Folder does not exist"
Else
Wscript.Echo "Folder does exist"
End If
But when I try to query a mapped network drive, the program fails with 'Folders does not exist'. Yet I am sure it is the correct path to the file.
The only parts that change are:
drive = "Z:"
path = "\\path\\to\\mapped\\drive\\folder\\"
Any clues as to why this would not work?
Trying to map drives on a remote computer via WMI will fail, though there is a workaround. Thanks to Frank White's inspirational code, a fully fleshed process now exists to map a drive on a remote computer via WMI using a command prompt and passing explicit credentials.
https://stackoverflow.com/a/11948096/1569434
So to debug this I ran the following:
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService.ExecQuery("Select * from CIM_Datafile Where Drive = 'Z:'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
This resulted in the error 'remote procedure call failed', which I understand means that the mapped drive does not support WMI.
I'd like to use VBScript to check if the Spooler service is started and if not start it, the code below checks the service status but I need some help modifying this so I can check if it is started.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery _
("Select * from Win32_Service")
For Each objService in colRunningServices
Wscript.Echo objService.DisplayName & VbTab & objService.State
Next
Many thanks
Steven
How about something like this. This command will start it if it isn't already running. No need to check in advance.
Dim shell
Set shell = CreateObject("WScript.Shell")
shell.Run "NET START spooler", 1, false
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colRunningServices = objWMIService.ExecQuery _
("select State from Win32_Service where Name = 'Spooler'")
For Each objService in colRunningServices
If objService.State <> "Running" Then
errReturn = objService.StartService()
End If
Next
Note you can also use objService.started to check if its started.
Just for the completeless, here's an alternative variant using the Shell.Application object:
Const strServiceName = "Spooler"
Set oShell = CreateObject("Shell.Application")
If Not oShell.IsServiceRunning(strServiceName) Then
oShell.ServiceStart strServiceName, False
End If
Or simply:
Set oShell = CreateObject("Shell.Application")
oShell.ServiceStart "Spooler", False ''# This returns False if the service is already running
I have this VBScript code to terminate one process
Const strComputer = "."
Dim objWMIService, colProcessList
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'Process.exe'")
For Each objProcess in colProcessList
objProcess.Terminate()
Next
It works fine with some processes, but when it comes to any process runs under SYSTEM, it can't stop it.
Is there is anything I need to add to kill the process under SYSTEM?
The way I have gotten this to work in the past is by using PsKill from Microsoft's SysInternals. PsKill can terminate system processes and any processes that are locked.
You need to download the executable and place it in the same directory as the script or add it's path in the WshShell.Exec call. Here's your sample code changed to use PsKill.
Const strComputer = "."
Set WshShell = CreateObject("WScript.Shell")
Dim objWMIService, colProcessList
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcessList = objWMIService.ExecQuery("SELECT * FROM Win32_Process WHERE Name = 'Process.exe'")
For Each objProcess in colProcessList
WshShell.Exec "PSKill " & objProcess.ProcessId
Next
Try explicit assert debug privilege {impersonationLevel=impersonate,(debug)}:
Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate,(debug)}!\\.\root\CIMV2")
Set procs = wmi.ExecQuery("SELECT * FROM Win32_Process WHERE Name='SearchIndexer.exe'", , 48)
For Each proc In procs
proc.Terminate
Next