Mount/Unmount USB drives with VBSCript - 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)

Related

Is there a way to identify which USB port a mass storage drive uses?

I am trying to identify which port a USB mass storage is connected to.
Here is my scenario. I have a vbscript program that monitors the USB mass storage drive plug-ins and do some routines on them and its process flow needs to know which port the drive was connected to.
So far I am not able to find a link between the USB events, the identified usb mass storage drive and the port on the computer (for eg., Location - Port_#0001.Hub_#0006 as shown in Windows device manager->usb controllers->USB mass storage). My search was mainly using 'VbsEdit' tool by connecting a storage device and stepping through the available snippets.
Sub Monitor_usb_storage_events()
Dim WsShell,strComputer,wmi, wmiEvent,usb,objDisk,fileSys,colDisks,Drive
Set WsShell = CreateObject("WScript.Shell")
strComputer = "."
Set wmi = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set wmiEvent = wmi.ExecNotificationQuery("select * from __InstanceOperationEvent within 1 where TargetInstance ISA 'Win32_PnPEntity' and TargetInstance.Description='USB Mass Storage Device'")
While True
Set usb = wmiEvent.NextEvent()
Select Case usb.Path_.Class
Case "__InstanceCreationEvent"
'WScript.Echo("USB device found")
Set colDisks = wmi.ExecQuery _
("SELECT * FROM Win32_LogicalDisk")
For Each objDisk in colDisks
If objDisk.DriveType = 2 Then
Set fileSys = CreateObject("Scripting.FileSystemObject")
For Each Drive In fileSys.Drives
If Drive.IsReady Then
'*Need port number where this drive is connected*
End If
Next
End If
Next
Case "__InstanceDeletionEvent"
'WScript.Echo("USB device removed")
Case "__InstanceModificationEvent"
'WScript.Echo("USB device modified")
End Select
Wend
End Sub
Here is a script I've had a for while that queries the Win32_USBControllerDevice and then returns the dependent devices.
Option Explicit
Dim strComputer: strComputer = "."
Dim objWMIService: Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Dim colDevices: Set colDevices = objWMIService.ExecQuery _
("Select * From Win32_USBControllerDevice")
Dim objDevice
For Each objDevice in colDevices
Dim strDeviceName: strDeviceName = objDevice.Dependent
strDeviceName = Replace(strDeviceName, """", "")
Dim arrDeviceNames: arrDeviceNames = Split(strDeviceName, "=")
strDeviceName = arrDeviceNames(1)
Dim colUSBDevices: Set colUSBDevices = objWMIService.ExecQuery _
("Select * From Win32_PnPEntity Where DeviceID = '" & strDeviceName & "'")
Dim objUSBDevice
For Each objUSBDevice in colUSBDevices
Wscript.Echo objUSBDevice.Description
WScript.Echo objUSBDevice.PnPDeviceID
Next
Next
If you combined this with your __InstanceOperationEvent WMI query you should be able to modify the above script to query the DeviceID returned in the matched Win32_PnPEntity instance.
You can get the DeviceID in your above script using:
strDeviceName = usb.TargetInstance.DeviceID

Unable to kill a process in Windows 8.1 through VBScript

I am using the below piece of code to terminate all the instances of the application for e.g. Notepad. But it is not getting executed in Windows 8.1 (32 bit OS). It is working fine with Windows 7 (64 bit OS) and Windows 10 (32 bit OS). Can some one please help me to get rid of this?
Analysis:
It was failing at line: For Each objProcess In colProcess
Even after introducing the line in the below code its failing: Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
Code:
Function KillAll1(ProcessName)
Dim objWMIServicde, colProcess
Dim strComputer, strList, p
strComputer = "."
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set objProcess = GetObject("winmgmts:root\cimv2:Win32_Process")
Set colProcess = objWMIService.ExecQuery("Select * from Win32_Process Where Name like '" & ProcessName & "'")
For Each objProcess In colProcess
objProcess.Terminate
Next
End Function
KillAll1("notepad.exe")

Listing printers on remote machines. Not seeing the same results as I would if I were logged on locally as the user

My script is supposed to list all the printers installed on a remote machine and write that data to a text file while designating if the printer is Local or Network. When I run the script against my local machine with my profile logged on I get the following results:
Local
Microsoft XPS Document Writer
Network
\\PrintServer\PT-NJ-CPR-B-CORPIT-1
Network
\\PrintServer\PT-NJ-CPR-B-ITTEMP-1
Network
\\PrintServer\CPR5A26D1A
These results are exactly what I want however when I run the same script against a remote machine I still get results but they seem to be for a more generic user
Local
Send To OneNote 2010
Local
Microsoft XPS Document Writer
Local
Fax
My question is how do I customize my script to truly impersonate the logged on user thus returning me the full results even from a remote machine?
Const ForAppending = 8
Const ForReading = 1
Dim WshNetwork, objPrinter, intDrive, intNetLetter, fso
Set fso = CreateObject("Scripting.FileSystemObject")
Set InputFile = fso.OpenTextFile("C:\xVBS Scripts\Printer Scripts\Computers.txt", 1)
Do Until InputFile.AtEndOfStream
strComputer = InputFile.ReadLine
Set WshNetwork = CreateObject("WScript.Network")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colInstalledPrinters = objWMIService.ExecQuery("Select * from Win32_Printer")
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
For Each objItem in colItems
UserName = objItem.UserName
arrUserName = Split(UserName, "\", -1, 1)
varUserName = arrUserName(1)
Next
filOutput = varUserName & ".txt"
If objFSO.FileExists(filOutput) Then
objFSO.DeleteFile(filOutput)
End If
Set objOutputFile = objFSO.OpenTextFile (filOutput, ForAppending, True)
For Each objPrinter in colInstalledPrinters
If objPrinter.Attributes And 64 Then
strPrinterType = "Local"
strTest = Left(objPrinter.Name, 2)
objOutputFile.WriteLine(strPrinterType)
objOutputFile.WriteLine(objPrinter.Name)
objOutputFile.WriteLine(vbNewLine)
Else
strPrinterType = "Network"
strTest = Left(objPrinter.Name, 2)
objOutputFile.WriteLine(strPrinterType)
objOutputFile.WriteLine(objPrinter.Name)
objOutputFile.WriteLine(vbNewLine)
End If
Next
Wscript.Sleep 1500
MsgBox "Printer mapping report is located" & vbNewLine & "in the following directory: " & filOutput , vbInformation, "Report Located At"
WshShell.Run "Notepad " & filOutput,1,False
Loop
InputFile.Close
Wscript.Quit
I dont think there is an actual answer to this. The more I learn about VB Script and Powershell it appears as if WMI is most useful when run interactively. It doesn't know how to process users who are not currently logged in. I bypass this problem by running the script as a GPO Link/Enforced that calls the script as a log on script. – JRN just now edit

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

Query Mapped Network Drive

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.

Resources