Sign in to follow this  
Followers 0
ptrex

USB drive Monitor Example

43 posts in this topic

#1 ·  Posted (edited)

USB Monitor - using WMI Event notification

Some one in the Support Section asked if it was possible to have a notification if a USB drive was Connected / Disconnected.

Well here is an example using the WMI Event notification :

$strComputer = "."
$objWMIService = ObjGet("winmgmts:" & $strComputer & "rootcimv2")

$colEvents = $objWMIService.ExecNotificationQuery _
("Select * From __InstanceOperationEvent Within 5 Where " _
& "TargetInstance isa 'Win32_LogicalDisk'")

While 1
$objEvent = $colEvents.NextEvent
If $objEvent.TargetInstance.DriveType = 2 Then
Select
Case $objEvent.Path_.Class()="__InstanceCreationEvent"
Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been added." & @CR)
Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
Consolewrite("Drive " & $objEvent.TargetInstance.DeviceId & "has been removed."& @CR)
EndSelect
EndIf
WEnd

Enjoy !!

ptrex

Edited by ptrex

Share this post


Link to post
Share on other sites



I just wanted to say thanks. This will really help me on one of my projects. I'll be sure to mention you in the credits.

Share this post


Link to post
Share on other sites

I plan to. All the stuff I've done from my site in Autoit I've put the source code out for.

Share this post


Link to post
Share on other sites

#5 ·  Posted (edited)

I think I like your way...I've been doing mine like this: run through all the drive letters and check for changes in drivestatus...just make sure to skip floppy drives :-)

for $i = 1 to 25
    $aDriveStatus[$i] = DriveStatus(chr($i+65) & ":\")
Next
while 1
    for $i = 1 to 25
        $sDriveStatus = DriveStatus(chr($i+65) & ":\")
        if $aDriveStatus[$i] <> $sDriveStatus then
            $aDriveStatus[$i] = $sDriveStatus
            if $sDriveStatus = "READY" Then 
            ;CODE TO RUN
            EndIf
        EndIf
    Next
WEnd

I'll give yours a try tonight

Edited by sshrum

Sean Shrum :: http://www.shrum.net

All my published AU3-based apps and utilities

'Make it idiot-proof, and someone will make a better idiot'

 

Share this post


Link to post
Share on other sites

Hey,

It seems to work well but its grinding my floppy drive all the time.

Any ideas for a fix?

Cheers


Z

Share this post


Link to post
Share on other sites

it's because the current query ask for all the drives

so if you want to just monitor the removable drive, try this

$strComputer = "."
 $objWMIService = ObjGet("winmÛ]ÎÌLÉÌLÉ][ÝÈ [È ÌÍÜÝÛÛ]   [È ][ÝÉÌLÜÛÝ ÌL6×c"gV÷C² ¢b33c¶6öÄWfVçG2Òb33c¶ö&¥tÔ6W'f6RäWV4æ÷Ff6FöåVW'( ÅÕ½ÐíM±Ð¨É½´}}%¹Íѹ=ÁÉÑ¥½¹Ù¹Ð]¥Ñ¡¥¸Ô]¡ÉÅÕ½Ðì|(       & "TargetInstance isa 'Win32_LogicalDisk' and &quotÈÈ   [È ][ÝÕÙ][Ý[ÙK]UHH][ÝÈ
BÚ[HBb33c¶ö&¤WfVçBÒb33c¶6öÄWfVçG2äæWDWfVç@¢bb33c¶ö&¤WfVçBåF&vWDÍѹ¹É¥ÙQåÁôÈQ¡¸(M±Ð(
ÍÀÌØí½©Ù¹Ð¹ath_.Class()="__InstanceCreationEvent"
                ConsolewriJ ][ÝÑ]H    ][ÝÈ  [È ÌÍÛØ][Ù][Ý[ÙK]XÙRY  [È ]÷C¶2&VVâFFVBâgV÷C²fײ5"¢66Rb33c¶ö&¤WfVçBåFòä6ÍÌ ¤ôÅÕ½Ðí}}%¹Íѹ±Ñ¥½¹Ù¹ÐÅÕ½Ðì(
½¹Í½±ÝÉ¥Ñ ÅÕ½;Drive " & $objEvent.TargetInstance.DeviceId & "has Y[[[ÝY][ÝÉ[ÈÔB[Ù[XÝ[YÑ[

the drivetype = 2 is the removable drive

for more information take a look at this :

http://msdn2.microsoft.com/en-us/library/aa394173.aspx


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

#8 ·  Posted (edited)

Thank you very much now i can implement this to secure my computer from unwanted UFD activity. I hope this will help, thanks again! :).

Say why is my floppy drive still grinding even using the latest script?

Edited by Elkie

Share this post


Link to post
Share on other sites

simple : you ask the logical drive class, so it queries all the disk before filter it, wherever you place this filter, i think. your floppy is usb connected ?


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

simple : you ask the logical drive class, so it queries all the disk before filter it, wherever you place this filter, i think. your floppy is usb connected ?

Nope, that's the problem i use coventional floppy controller, but when i run the script it keep running the floppy drive every 5 sec

Share this post


Link to post
Share on other sites

#11 ·  Posted (edited)

Nope, that's the problem i use coventional floppy controller, but when i run the script it keep running the floppy drive every 5 sec

cheers ptrex

I too had this problem with the script. However, I've found a fix.

Instead of the initial query searching within the 'Win32_LogicalDisk' WMI I've created a different query which checks 'Win32_PnPEntity'

$colEvents = $objWMIService.ExecNotificationQuery _

("Select * From __InstanceOperationEvent Within 5 Where " _

& "TargetInstance isa 'Win32_PnPEntity' and " _

& "(TargetInstance.Description = 'USB FloppyDisk Drive' or " _

& "TargetInstance.Description = 'CD-ROM Drive' or " _

& "TargetInstance.Description = 'Disk Drive')" )

You could also check for 'Generic Volume'. The description filters completely depend on what you wish to search on.

-----------------------

I've expanded on the original script to automatically disconnect the USB device if the logged on user is not a member of a particular Active Directory group.

This amalgamates this script and another script created by 'arcker':

http://www.autoitscript.com/forum/index.ph...=disconnect+USB

with some additional tweaking to suit my needs:

When the:

Case $objEvent.Path_.Class()="__InstanceCreationEvent"

occurs I then run :

$objWMIService.ExecQuery("Select * From Win32_LogicalDisk Where DriveType = 2" )

(this will of course still cause the Floppy disk to trigger, but this will only occur once. I was hopping to find a WMI query other than win32_logicaldisk that would give me the drive letter for the particular USB device, so far I can't find it).

a FOR...NEXT loops through the results and checks if the user is allowed to use the device.

So far, so good. I've tested quite a few USB drives and all have been detected and disconnected.

The reference material used to create the queries are:

Microsoft Script Guy: http://www.microsoft.com/technet/scriptcen...06/hey0213.mspx

WMI queries: http://msdn2.microsoft.com/en-us/library/aa394173.aspx

and, if you ever want to find out what the 'descriptions' are to other USB devices that are connected which the script misses you can use the Microsoft vb script: http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx

If anyone is interested (once I've completed the script and improved my lousy coding :) ) I'll post the complete script.

Edited by UglyBob

"My God, you're looking hideously ugly today, Ugly Bob."

Share this post


Link to post
Share on other sites

hehe excellent for a first try !

i don't understand understand pnpentity but i will take a look for sure !

i've provide a script that continuosly monitor the usb drive but... there is more simple

you can just :

- verify AD group membership

- unload possible connected key by my script provided (eject key)

- block by registry

- block by ntfs (calc or better, win32_logicalfilesetsecuritydescriptor)

please post your script either, it sounds really interesting.


-- Arck System _ Soon -- Ideas make everything

"La critique est facile, l'art est difficile"

Projects :

[list] [*]Au3Service : Run your exe as service V3 / Updated 29/07/2013 Get it Here [/list]

Share this post


Link to post
Share on other sites

Hmmh, interesting indeed, at first i thought i could use CMI_USBDisk or something for the WMI script but it's not working at all. I'll try it thanks,

Share this post


Link to post
Share on other sites

#14 ·  Posted (edited)

@UglyBob

Good job !!

You did quit some investigation on this matter.

When you have some code running please post it in this thread, so others can benifit of it as well.

Good to see you get inspired by this !! :)

; http://www.microsoft.com/technet/scriptcenter/resources/qanda/mar05/hey0315.mspx

$strComputer = "."

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
$colDevices = $objWMIService.ExecQuery ("Select * From Win32_USBControllerDevice")

For $objDevice in $colDevices
    $strDeviceName = $objDevice.Dependent
    $strQuotes = Chr(34)
    $strDeviceName = StringReplace($strDeviceName, $strQuotes, "")
    $arrDeviceNames = StringSplit($strDeviceName, "=")
    $strDeviceName = $arrDeviceNames[2]
    $colUSBDevices = $objWMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")
    For $objUSBDevice in $colUSBDevices
        MsgBox(0,"USB Description",$objUSBDevice.Description)
    Next
    MsgBox(0,"USB Devices",$strDeviceName)
Next

PS: added the USB device descriptions script.

regards,

ptrex

Edited by ptrex

Share this post


Link to post
Share on other sites

@UglyBob

Good job !!

You did quit some investigation on this matter.

When you have some code running please post it in this thread, so others can benifit of it as well.

Good to see you get inspired by this !! :)

; [url="http://www.microsoft.com/technet/scriptcenter/resources/qanda/mar05/hey0315.mspx"]http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx[/url]

$strComputer = "."

$objWMIService = ObjGet("winmgmts:\\" & $strComputer & "\root\cimv2")
$colDevices = $objWMIService.ExecQuery ("Select * From Win32_USBControllerDevice")

For $objDevice in $colDevices
    $strDeviceName = $objDevice.Dependent
    $strQuotes = Chr(34)
    $strDeviceName = StringReplace($strDeviceName, $strQuotes, "")
    $arrDeviceNames = StringSplit($strDeviceName, "=")
    $strDeviceName = $arrDeviceNames[2]
    $colUSBDevices = $objWMIService.ExecQuery ("Select * From Win32_PnPEntity Where DeviceID = '" & $strDeviceName & "'")
    For $objUSBDevice in $colUSBDevices
        MsgBox(0,"USB Description",$objUSBDevice.Description)
    Next
    MsgBox(0,"USB Devices",$strDeviceName)
Next

PS: added the USB device descriptions script.

regards,

ptrex

Sorry for my noob question, is this mean i have to combine this script with the first post to create the USB insert detection (monitoring) script?

Share this post


Link to post
Share on other sites

thanks for the au3 version of the USB list ptrex.

Right, here's my script so far. As mentioned previously this amalgamates a couple scripts and functions together (with the odd tweak here and there to suit). Apologies for any incorrect command useage you may find, I'm still learning.

; ====================================================================================================

======================================
; Created by UglyBob - 03/08/2007
; Thanks to:
;           Yoan Roblet (Arcker) (AutoIT member) - For the code (functions) which disconnect the detected USB device from the workstation
;           ptrex (AutoIT member) - For the initial USB detection code)
;           Johny Clelland (AutoIT member) - For the initial AD code to query group membership

; Reference Material -
;                       http://support.microsoft.com/kb/165721
;                       Microsoft Script Guy USB Monitor - http://www.microsoft.com/technet/scriptcen...06/hey0213.mspx
;                       WMI queries -  http://msdn2.microsoft.com/en-us/library/aa394173.aspx
;                       Microsoft Script Guy ID USB Devices - http://www.microsoft.com/technet/scriptcen...05/hey0315.mspx

; Version Control
; ---------------
; Updated - 06/08/2007 - Added filters to the initial SELECT query for USB devices that also create floppy & CD-ROM drives
; Updated - 07/08/2007 - Added filters to the win32_logicaldisk query to ignore already disconnected USB devices
; ====================================================================================================

======================================

#include <A3LWinApi.au3>
#include <Constants.au3>

; ------------------------------------------------------------------------------------------------------------
; Variables
$AllowUser = False
$objWMIService = ObjGet("winmgmts:\\.\root\cimv2")
$Offline = False
$OpenVolume = ""    
$szVolumeFormat = "\\\\.\\%s"
$szRootFormat = "%s\\"
$szErrorFormat = "Error %d: %s\n"
$USB_Allow_Group = "USB storage Users"

$colEvents = $objWMIService.ExecNotificationQuery _
    ("Select * From __InstanceOperationEvent Within 5 Where " _
        & "TargetInstance isa 'Win32_PnPEntity' and  " _
        & "(TargetInstance.Description = 'USB FloppyDisk Drive' or " _
        & "TargetInstance.Description = 'CD-ROM Drive' or " _
        & "TargetInstance.Description = 'Disk Drive')" )
    ; Additional filter = TargetInstance.Description = 'Generic Volume'

;------------------------------------------
;Arbitrary variables
Global Const $INVALID_HANDLE_VALUE = 0

;------------------------------------------
;DeviceIoControl Contants
Global Const $FSCTL_LOCK_VOLUME = int(0x090018)
Global Const $FSCTL_DISMOUNT_VOLUME = int(0x00090020)
Global Const $IOCTL_STORAGE_EJECT_MEDIA  = int(0x002D4808)
Global Const $IOCTL_STORAGE_MEDIA_REMOVAL = int(0x002D4804)

;------------------------------------------
;Retry Constants
Global Const $LOCK_TIMEOUT = 10000    ; 10 Seconds
Global Const $LOCK_RETRIES = 3

;------------------------------------------
; AD LDAP variables
Dim $objConnection, $oUsr, $objRootDSE
$objConnection = ObjCreate("ADODB.Connection") ; Create COM object to AD
$objConnection.Provider = "ADsDSOObject"
$objConnection.Open ("Active Directory Provider") ; Open connection to AD
$objRootDSE = ObjGet("LDAP://RootDSE")
; If there is no response from LDAP then the script will treat the computer running the script as 'offline'.
; Ideal when a laptop is not connected to the network.
If @Error then 
    $Offline = True
Else
    ConsoleWrite ( "Domain = " & $objRootDSE.Get ("defaultNamingContext") & @CRLF )
    ConsoleWrite ( "Offline = " & $Offline & @CRLF )
    $strDNSDomain = $objRootDSE.Get ("defaultNamingContext") ;Retrieve the current AD domain name (DN)
EndIf
; ------------------------------------------------------------------------------------------------------------



While 1
    $objEvent = $colEvents.NextEvent
    Select
    Case $objEvent.Path_.Class()="__InstanceCreationEvent"
        ConsoleWrite ( "Detected Device = " & $objEvent.TargetInstance.DeviceID & " - " & $objEvent.TargetInstance.Description & @CRLF )
        $Event = $objWMIService.ExecQuery("Select * From Win32_LogicalDisk Where (DriveType = 2 and MediaType != 5 and (FileSystem = 'FAT' or FileSystem = 'FAT32'))" )
        For $objItem in $Event
            $OpenVolume = $objItem.DeviceID
            ConsoleWrite ( $objItem.DeviceID & " - " & $objItem.VolumeName & " - " & $objItem.FileSystem & @CRLF )
            If $Offline = False Then
                If memberof($AllowUser) = False Then
                EjectVolume($OpenVolume)
                MsgBox (16, "USB Drive Detected", "Drive " & $OpenVolume & " has been added to your PC." & @CRLF & @CRLF & "You are not authorised to use such portable media." & @CRLF & @CRLF & "Please contact the ICT dept. for further assistance.")
                EndIf
            Else
                MsgBox (64, "USB Drive Notification", "Drive " & $OpenVolume & " has been added to your PC.")
            EndIf
        Next
        $OpenVolume = ""
        
; The 'case' statement below is no longer required for this particular script but is useful for reporting successful USB disconnections
;Case $objEvent.Path_.Class()="__InstanceDeletionEvent"
;   MsgBox (64, "USB Drive", "Drive " & $OpenVolume & " has been Removed.")
    
    EndSelect
WEnd



; ---------------------------------
;
;          FUNCTIONS
;
; ---------------------------------
Func ReportError($szMsg)
    ConsoleWrite(StringFormat($szErrorFormat, _API_GetLastErrorMessage (), $szMsg) & @CRLF)
    Exit
EndFunc  ;==>ReportError
Func OpenVolume($cDriveLetter)
   ;HANDLE hVolume
   ;UINT uDriveType
   ;TCHAR szVolumeName[8]
   ;TCHAR szRootName[5]
   ;DWORD dwAccessFlags
    $szRootName = StringFormat($szRootFormat, $cDriveLetter)
    $uDriveType = DriveGetType($szRootName);
    ConsoleWrite($szRootName & @tab & $uDriveType & @crlf)
    Switch $uDriveType
        Case "Removable"
            $dwAccessFlags = 6
        Case "CDROM"
            $dwAccessFlags = 2
        Case Else
            ConsoleWrite("Cannot eject.  Drive type is incorrect." & @CRLF)
            Return $INVALID_HANDLE_VALUE
    EndSwitch
    $szVolumeName = StringFormat($szVolumeFormat, $cDriveLetter)
   ;$szVolumeName = $szVolumeFormat & $cDriveLetter
    ConsoleWrite($szVolumeName & @crlf )
    $hVolume = _API_CreateFile ($szVolumeName, 2,$dwAccessFlags, 6)
   
    #cs
        hVolume = CreateFile(   szVolumeName,
        dwAccessFlags,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL );
    #ce
    If ($hVolume == $INVALID_HANDLE_VALUE) Then ReportError("CreateFile");
    Return $hVolume;
EndFunc  ;==>OpenVolume

Func CloseVolume($hVolume)
    Return _API_CloseHandle ($hVolume);
EndFunc  ;==>CloseVolume

Func LockVolume($hVolume)
    Local $dwBytesReturned
    Local $dwSleepAmount
    Local $nTryCount
    local $iRead
    $dwSleepAmount = $LOCK_TIMEOUT / $LOCK_RETRIES;
   ; Do this in a loop until a timeout period has expired
    For $nTryCount = 0 To $nTryCount < $LOCK_RETRIES
        If _Device_Control($hVolume, $FSCTL_LOCK_VOLUME, $iRead) Then
            Return True
        Else
            Sleep($dwSleepAmount);
        EndIf
    Next
    Return False;
EndFunc  ;==>LockVolume

Func DismountVolume($hVolume)
    ConsoleWrite("Dismount " & $hVolume & @crlf)
    Local $dwBytesReturned, $iRead
    local $aResult = _Device_Control($hVolume, $FSCTL_DISMOUNT_VOLUME, $iRead)
   ;msgbox(0,"",$aResult)
    Return $aResult
   ;Return $dwBytesReturned
EndFunc  ;==>DismountVolume

Func PreventRemovalOfVolume($hVolume, $fPreventRemoval)
    Local $dwBytesReturned
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
   
    $PMRBUFFER = DllStructCreate("bool PreventMediaRemoval")
   
    DllStructSetData($PMRBUFFER,"PreventMediaRemoval",$fPreventRemoval)
   
    $lpBytesReturned    = DllStructCreate("int Read")
    $pRead   = DllStructGetPtr($lpBytesReturned, "Read")
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hVolume,"uint",$IOCTL_STORAGE_MEDIA_REMOVAL,"ptr",DllStructGetPtr($PMRBUFFER),"uint",DllStructGetSize($PMRBUFFER), _
    "ptr",$lpOutBuffer,"uint",$nOutBufferSize,"ptr",$pRead,"ptr",$lpOverlapped)
    if $aResult = 0 then msgbox(0,"",_API_GetLastErrorMessage())
    Return $aResult <> 0
   
    ;& PMRBuffer, sizeof (PREVENT_MEDIA_REMOVAL),
   ;NULL, 0,
   ; & dwBytesReturned,
   ;NULL);
EndFunc  ;==>PreventRemovalOfVolume

Func AutoEjectVolume($hVolume)
    Local $aResult, $iRead;
    $aResult = _Device_Control($hVolume, $IOCTL_STORAGE_EJECT_MEDIA, $iRead)
    Return $aResult
EndFunc  ;==>AutoEjectVolume

Func EjectVolume($cDriveLetter)
    Local $hVolume;
    Local $fRemoveSafely = False;
    Local $fAutoEject = False;
   ; Open the volume.
    $hVolume = OpenVolume($cDriveLetter);
    If $hVolume == $INVALID_HANDLE_VALUE Then Return False
   ; Lock and dismount the volume.
    If LockVolume($hVolume) And DismountVolume($hVolume) Then
        $fRemoveSafely = True;
        ConsoleWrite("Volume Locked and Dismounted, trying to eject " & @crlf)
       ; Set prevent removal to false and eject the volume.
        If PreventRemovalOfVolume($hVolume, False) And AutoEjectVolume($hVolume) Then
            $fAutoEject = True;
        EndIf
    Else
        ConsoleWrite("Volume can't be locked or dismounted, please close possible opened files" & @crlf)
    EndIf
   
   ; Close the volume so other processes can use the drive.
    If CloseVolume($hVolume) = False Then
        Return False;
    EndIf
   
    If $fAutoEject Then
        ConsoleWrite(StringFormat("Media in Drive %s has been ejected safely.\n", $cDriveLetter))
    Else
        If $fRemoveSafely Then
            ConsoleWrite(StringFormat("Media in Drive %s can be safely removed.\n", $cDriveLetter))
        EndIf
    EndIf
   
    Return True;
EndFunc  ;==>EjectVolume

Func _Device_Control($hDevice, $dwIoControlCode, ByRef $iRead)
    Local $aResult
    Local $lpInbuffer,$nInBufferSize,$lpOutBuffer,$nOutBufferSize,$lpOverlapped
    $tRead   = DllStructCreate("int Data")
   
    $aResult = Dllcall("kernel32.dll","int","DeviceIoControl","hwnd",$hDevice,"uint",$dwIoControlCode,"ptr",$lpInBuffer,"uint",0, _
    "ptr",$lpOutBuffer,"uint",0,"ptr",DllStructGetPtr($tRead),"ptr",$lpOverlapped)
   
    $iRead   = DllStructGetData($tRead, "Data")
   
    ConsoleWrite("Device Control " & $iRead & @CRLF)
    Return $aResult<>0
EndFunc  ;==>_Device_Control

Func Memberof($AllowUser)
    Dim $usergroups[1], $i = 1
    Local $groups

    $strQuery = "<LDAP://" & $strDNSDomain & ">;( samAccountName=" & @UserName & ");ADsPath;subtree"
    $objRecordSet = $objConnection.Execute ($strQuery) ; Retrieve the FQDN for the logged on user
    If $objRecordSet.RecordCount = 1 Then 
        $ldap_entry = $objRecordSet.fields (0).value
        $oUsr = ObjGet($ldap_entry) ; Retrieve the COM Object for the logged on user
        $groups = $oUsr.groups ; Get the list of group objects from the user
        For $groupname In $groups
            ReDim $usergroups[UBound($usergroups) + 1]
            $usergroups[0] += 1 ; Increment the count of groups
            $usergroups[$i] = StringTrimLeft($groupname.name, 3)
            If $usergroups[$i] = $USB_Allow_Group Then
                $AllowUser = True
                Return $AllowUser
                ConsoleWrite ( "Allow = " & $AllowUser & @CRLF )
                ExitLoop
            EndIf
        $i += 1
        Next
    EndIf
    ConsoleWrite ( "Allow = " & $AllowUser & @CRLF )
EndFunc  ;==>memberof

The reason why I have the filter:

(DriveType = 2 and MediaType != 5 and (FileSystem = 'FAT' or FileSystem = 'FAT32')) when checking the drives is to filter the floppy disk drive and to ignore a USB device that has already been disconnected by the script but the drive is still physically attached to the PC. There may be a slightly better WMI field to query, but so far this works, you may want to add 'NTFS' should you wish to disconnect any such devices too.

I did spot a simpler script somewhere on this forum regarding the listing of a user's groups, but the AD function works so hey why change it. :)


"My God, you're looking hideously ugly today, Ugly Bob."

Share this post


Link to post
Share on other sites

Incredible, incredible!

I still can't believe what's possible with AutoIt (and the proper knowledge of Windows, of course)

Just to give a little bit back of what I got from AutoIt and this forum:

I had to integrate the check for removable volumes into a message event loop which controls an AutoIt GUI. After a little bit of research and some experiments I found the following solution (presented as a skeleton - you may add your own code where necessary)

; **** add a COM error handler (see below) ****

global $ErrorHandler = ObjEvent("AutoIt.Error","handleCOMError")

func handleCOMError ()
  if ($ErrorHandler.number = -2147352567) then        ; i.e. if timeout occurred
    sleep(100)                             ; just wait a moment (then try again)
    return                                                 ; continue processing
  endif

  with $ErrorHandler
    ConsoleWriteError("COMError.number         = " & string(.number)         & @LF)
    ConsoleWriteError("COMError.windescription = " & string(.windescription) & @LF)
    ConsoleWriteError("COMError.source         = " & string(.source)         & @LF)
    ConsoleWriteError("COMError.description    = " & string(.description)    & @LF)
    ConsoleWriteError("COMError.helpfile       = " & string(.helpfile)       & @LF)
    ConsoleWriteError("COMError.helpcontext    = " & string(.helpcontext)    & @LF)
    ConsoleWriteError("COMError.lastdllerror   = " & string(.lastdllerror)   & @LF)
    ConsoleWriteError("COMError.scriptline     = " & string(.scriptline)     & @LF)
  endwith

  exit                                   ; abort program in case of a real error
endfunc

; **** set-up the WMIService object and register a query ****

; ... <= create WMIService and ExecNotificationQuery as required

; **** now continously check for WMI "events" ****

while true
  $objEvent = $colEvents.NextEvent(1)           ; do not wait longer than 1 msec
  if ($objEvent <> 0) then                         ; did we get a *real* result?

;   ... <= process the WMI "event" as required

  endif
wend

The basic "trick" to provide a "timeout" (given in milliseconds) when calling ".NextEvent" and to catch the "timeout" (which is an error from the WMIService' point of view)

Hope this is of any help!

Kind regards,

Andreas Rozek

Share this post


Link to post
Share on other sites

#19 ·  Posted (edited)

This is giving me some ideas to improve my concept as posted before in here:

#366233

But the big problem I find in using COM is that the script can break easily if the error processing doesn't predict all the situations.

The posted script by UgglyBob looks interesting, but offline mode does not work and crashes easilly if you disconnect the network - if a user knows that, it will crash the script and he can then use the USB storage device. With my initial script, if it crashes at least he might be protected... It's a nice idea to use USB events to trigger some checks and avoid traffic to the domain controllers I guess. :)

Oh by the way, how would you implement such script? As a service? As normal user I guess it won't have permissions to work right...

Edited by BullGates

[topic="51913"]Restrict USB Storage usage to group membership[/topic] * [topic="48699"]Using nircmd library[/topic] * Some admin notes

Share this post


Link to post
Share on other sites

well, it was (and still is) of course work in progress. One of the other fundamental flaws in the script is the fact that you can plug the USB device prior to script actually running (such as booting up). This would not be picked up by '__InstanceCreationEvent '.

I'm working on an improved script. I've ditched the above WMI query, and instead am using Win32_DiskDrive as the initial check, which will query every 5 seconds for any USB drives (regardless of whether they have been plugged in before the script has started).

As for the AD issue, well this all depends on how you want to control USB devices. My main thought is to prevent users connecting USB devices allowing them to copy data from network servers or try to use software stored on said devices. That subject has many other issues and ways of circumvention, I guess you gotta start somewhere....

so...

1) Do you block ALL USB drives?

2) Do you allow authorised domain/local users to plug in USB devices?

If so, do you query AD or local workstation groups?

3) Do you allow offline connectivity when laptops are not connected to the network?

So far, my latest version is working (it doesn't fall over, or hang when offline). The script now dismounts drives unless it can confirm that the logged on user is a member of a specific AD group. As for how to run the script, that's still up for debate, but I think a service may be the option (I guess this all depends on the environment and situations that the script will be used).

More testing to do.... :)


"My God, you're looking hideously ugly today, Ugly Bob."

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0