Query Mapped Network Drive - windows

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.

Related

Vbscript rename a remote folder

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

Echo whether a process is running on a range of remote computers

I'm trying to create a script that will connect to remote computers within an IP address range and then echo which of those is running the explorer.exe process.
When I run the script within a small range (10.2.1.1 - 10.2.1.10), I know that 10.2.1.4 is offline and that 10.2.1.9 and 10.2.1.10 are not Windows based computers and should therefore echo "Explorer.exe is not running" however that doesn't seem to be the case. They appear to return the same result of the previous server. For instance, 10.2.1.3 has 3 instances of Explorer.exe and echo's 3 times, I then get the same result for 10.2.1.4 which is offline.
My script is as follows:
On Error Resume Next
intStartingAddress = InputBox("Please enter a starting address: (e.g. 1)", "Starting Address")
intEndingAddress = InputBox("Please enter an ending address: (e.g. 254)", "Ending Address")
strSubnet = InputBox("Please enter a subnet excluding the last octet: (e.g. 10.2.1.)", "Subnet")
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colProcess = objWMIService.ExecQuery("Select * From Win32_Process Where Name = 'Explorer.exe'")
For Each objProcess in colProcess
If colProcess.Count > 0 Then
Wscript.Echo strComputer & " Explorer.exe is running."
Else
Wscript.Echo strComputer & " Explorer.exe is not running."
End If
Next
Next
Wscript.Echo "That's all folks!"
What makes you believe that non-Windows computers would respond to WMI queries in the first place? For most non-Windows computers the statement
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
will simply fail, because they don't support WMI (which is short for Windows Management Instrumentation). Because of this error, the objWMIService object remains the same as it was in the previous loop cycle, so your subsequent instructions query the same host you did before. You never see the error, though, because it's masked by the global On Error Resume Next.
This can be mitigated by removing the global On Error Resume Next and changing this loop:
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
...
Next
into something like this:
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = Nothing
On Error Resume Next
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
On Error Goto 0
If Not objWMIService Is Nothing Then
...
Else
WScript.Echo strComputer & " cannot be accessed."
End If
Next
You can distinguish between unreachable computers and computers that don't appear to be running Windows by combining the above with a ping test:
Set wmi = GetObject("winmgmts://./root/cimv2")
qry = "SELECT * FROM Win32_PingStatus WHERE Address='" & strComputer & "'"
For Each ping In wmi.ExecQuery(qry)
reachable = (0 = ping.StatusCode)
Next
If reachable Then
If objWMIService Is Nothing Then
'computer is not running Windows
Else
'computer is running Windows
End If
Else
'computer is offline
End If
First: I would move the colProcess.Count check to occur before the colProcess loop. If there are no collections in the object you will not get an echo response.
Second: I would test for a value within the WMI query such as ProcessID and check if it is Null or if it does have a value, meaning that it is actually running.
intStartingAddress = InputBox("Please enter a starting address: (e.g. 1)", "Starting Address")
intEndingAddress = InputBox("Please enter an ending address: (e.g. 254)", "Ending Address")
strSubnet = InputBox("Please enter a subnet excluding the last octet: (e.g. 10.2.1.)", "Subnet")
For i = intStartingAddress to intEndingAddress
strComputer = strSubnet & i
Set objWMIService = Nothing
On Error Resume Next
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
On Error Goto 0
If objWMIService Is Nothing Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
Set colProcess = objWMIService.ExecQuery("Select * From Win32_Process Where Name = 'Explorer.exe'")
If colProcess.Count = 0 Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
For Each objProcess in colProcess
If IsNull(objItem.ProcessID) Or Not IsNumeric(objItem.ProcessID) Then
Wscript.Echo strComputer & " Explorer.exe is not running."
Else
Wscript.Echo strComputer & " Explorer.exe is running. (Process ID: " & objItem.ProcessID & ")"
End If
Next
End If
End If
Next
Wscript.Echo "That's all folks!"
EDIT:
Modified Script to take into account the WMI Query will fail on Non-Windows Operating Systems as pointed out by Ansgar Wiechers.

Start Service with VBscript

I am trying to have this script take a text file running and stopped services before a reboot and start any services that did not automatically start after the machine starts back up. The script that gets the list of service names, state and startmode and creates a comma separated text file line by line works fine. Here it is for reference (taken from the interwebs, lost the link in my travels. Modified slightly.):
Const ForAppending = 2
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objLogFile = objFSO.CreateTextFile("service_list.txt", _
ForWriting, True)
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colListOfServices = objWMIService.ExecQuery("Select * from Win32_Service")
For Each objService in colListOfServices
objLogFile.Write objService.Name & ","
objLogFile.Write objService.StartMode & ","
objLogFile.Write objService.State
objLogFile.Writeline
Next
objLogFile.Close
This next bit reads the file line by line, compares the state of all of the services with the state of the services that were recorded before the machine was shut down. If they match, do nothing, if they are different, start the service:
Const ForReading = 1
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objServiceName = objWMIService.get("Win32_Service.Name='" & ServiceName & "'")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("\\some path\service_list.txt",ForReading,True,-2)
Do Until objFile.AtEndOfStream
fLine = Split(objFile.ReadLine,",")
'wscript.echo fLine(2)
if InStr(fLine(2),"Running") then
'wscript.echo "it was running!"
if objServiceName.Started then
'do nothing
else
'Set servicetostart = objWMIService.ExecQuery ("Select " & ServiceName & " from Win32_Service Where Name ='Alerter'")
'servicetostart.StartService()
'Result = objServiceName.StartService
'If 0 <> Result Then
' wscript.echo "Start " & ServiceName & " error:" & Result
'End If
objServiceName.StartService
'wscript.echo Servicename & "could not start with error: " & Result
end if
end if
'wscript.echo objServiceName
Loop
As of right now I am recieving an error whenever it actually tries to start the service. I receive a "Provider Failure code:80041004 Source:SWbemObjectEX". I have been looking through the posts about this error and attempting the fixes suggested. Also, as you can see, I have been trying variations, but I am afraid I am merely guessing.
So to my question, what is causing the "Provider Failure"? I have looked up these information for the Win32_Service Class here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa394418%28v=vs.85%29.aspx#methods
and looked up the method here:
http://msdn.microsoft.com/en-us/library/windows/desktop/aa393660%28v=vs.85%29.aspx
But have been unable to work out where the I am going wrong.
Thanks,
Joe
on a side note, the service I am testing, ie. making sure the service is starting, creating the text file, then stopping the service and running the "start service" code is Windows Defender. The service name is "WinDefend".
FINAL WORKING CODE:
Const ForReading = 1
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("\\vmware-host\Shared Folders\Documents\Biffduncan\Monthly Server Maintanence\service_list.txt",ForReading,True,-2)
Do Until objFile.AtEndOfStream
fLine = Split(objFile.ReadLine,",")
Set objService = objWMIService.get("Win32_Service.Name='" & fLine(0) & "'")
if InStr(fLine(2),"Running") then
'wscript.echo "it was running!"
if objService.Started then
'do nothing
else
Result = objService.StartService()
if Result <> 0 then
wscript.echo "The service: " & objService.Name & " did not start with error: " & Result
else
wscript.echo "Service " & objService.Name & " started"
end if
end if
end if
Loop
Error code 0x80041004 means that the WMI provider encountered an error after it was already initialized. The error code doesn't say anything about the cause of the error, though, nor does it provide any details. Try running WBEMTest or WMIDiag to track down the error. Also check the eventlog for related errors/warnings. If everything else fails, try rebuilding the WMI repository.
As for your code, the first thing I'd do is strip it down to the bare minimum, to avoid potential error sources:
Set wmi = GetObject("winmgmts://./root/cimv2")
Set svc = wmi.Get("Win32_Service.Name='WinDefend'")
rc = svc.StartService
WScript.Echo rc
Also, I wouldn't recommend writing the service status to a file at some random point in time, and then try starting services according to the contents of that file. There is no guarantee that the start mode hasn't been changed since the file was created, or that the service is even installed anymore.
Whether or not a service should be started is indicated by its StartMode property, so just check those services that are set to Auto. Services set to Manual will be started by the system on demand, so there's no need to launch them just because they were running when you took the snapshot.
qry = "SELECT * FROM Win32_Service WHERE StartMode='Auto'"
For Each svc In wmi.ExecQuery(qry)
If Not svc.Started Then svc.StartService
Next

Scripting.FileSystemObject and ..lnk file

I'm looping in a folder to get all files inside it
Scripting.FileSystemObject doesn't seem to see that a file named ..lnk exist
is there a way to fix that?
thanks
Looping through a folder using WMI also seems to find *.lnk files. Try this example:
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colFiles = objWMIService. _
ExecQuery("Select * from CIM_DataFile where Drive = 'C:' And Path = '\\Temp\\'")
For Each objFile in colFiles
Wscript.Echo objFile.Name
Next
I hope this helps.
/ Frank
it seem that I made a mistake while creating my test environment, I created a folder instead of a file.
now it's working.

Mount/Unmount USB drives with VBSCript

I am looking for a way to mount\unmount a USB flash drive using VBScript. This is the closest I was able to get.
Sub EjectDrive(strDrive)
On Error Resume Next
CONST SSF_DRIVES = 17
Set objShell = CreateObject("Shell.Application")
Set objDrive = objShell.Namespace(SSF_DRIVES).ParseName(strDrive)
objDrive.InvokeVerb "E&ject"
End Sub
This will work on Windows Server 2003, but not NT/2000/XP/Vista unfortunately.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery _
("Select * From Win32_Volume Where Name = 'E:\\'")
For Each objItem in colItems
objItem.Dismount(True, True)
Next
From Dismount a Volume.
Take a look at this thread, its talks about using the mountvol.exe command line tool to mount/unmount a drive, and it should work for USB flash drives, or there is also a program called deveject. Se this thread for more info: http://social.msdn.microsoft.com/Forums/en-US/csharpgeneral/thread/d2e5d16e-e7c9-48ef-88b8-3abf6e638384
You can popup the eject dialog by using something like this. I am not sure if it possible to unmount a specific device.
Set WshShell = WScript.CreateObject("WScript.Shell")
intReturn = WshShell.Run("RunDll32.exe shell32.dll,Control_RunDLL hotplug.dll", 1, TRUE)

Resources