1 (изменено: Poltergeyst, 2014-11-23 19:10:53)

Тема: HTA: Отслеживание USB накопителя

Без гарантий. Используете на свой страх и риск.

Скрипт предназначен для слежения за подключением/отключением Flash USB накопителя и основан на интерфейсе WMI. События подключения, останова и физического извлечения накопителя, подтверждаются соответствующими сообщениями. Желательно запускать скрипт при включенном и опознанном накопителе, либо при программно остановленном и удаленном из USB разъема компьютера.

Lang. HTA + VBScript
OC WinXP

usbwatch.hta


<HTML>
<TITLE>USB Watch</TITLE>
<HEAD>
<META HTTP-EQUIV=Content-Type content='text/html;charset=windows-1251'>
<HTA:APPLICATION
CAPTION='YES'
CONTEXTMENU='NO'
INNERBORDER='NO'        
NAVIGABLE='NO'        
SELECTION='NO'        
SHOWINTASKBAR='YES'    
SINGLEINSTANCE='YES'    
SYSMENU='YES'
WINDOWSTATE='normal' 
/>

<STYLE type=text/css>
BODY {cursor: hand; background-color: #c0c0c0;}

INPUT.headbtn     {
            position: absolute;
            left: 10px; 
            width: 150px; 
            height: 20px; 
            border: 1px;
            border-style: outset;
            background-color: #c0c0c0;
            font-family: MS Sans Serif; 
            font-size: 11px;
            font-weight: bold;
            cursor: hand; 
            
        }

</STYLE>
</HEAD>

<BODY SCROLL="NO">

    <!--------------------------------------------------------------------------------->
    <OBJECT ID="ObjSink" 
        STYLE="position:absolute;top:0;left:0;width:0;height:0"
        CLASSID="CLSID:75718C9A-F029-11D1-A1AC-00C04FB6C223">
    </OBJECT>
    
    <INPUT TYPE=BUTTON ID='btn1' 
            class='headbtn' 
            VALUE='Извлечь' style='top: 10px;'
            onclick='UnplugDialog()'>
    <P>
    <INPUT TYPE=BUTTON ID='btn2'
            class='headbtn' 
            VALUE='Выход' style='top: 40px;'
            onclick='window.close();'>
    <!--------------------------------------------------------------------------------->
    <SCRIPT LANGUAGE="VBScript">

        Public StateFlag
        Public sPrevDrivesStr
        Public objService, objProc

        Set objService = GetObject("winmgmts:root\cimv2")
        Set objProc = objService.Get("Win32_Process")
        
        lW = window.screen.width
        lH = window.screen.height
            window.moveTo lW - 180, 0
            window.resizeTo 180, 100
        
        StateFlag = False
        GetDriveLetter False    'Определение первоначального состояния съемных накопителей

        '/Выполнить запрос асинхронного отслеживания WMI/
        '---------------------------------------------------------------------------
        objService.ExecNotificationQueryAsync ObjSink, _
        "SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA ""Win32_USBControllerDevice"""
        
        '/Получение буквы съемного Flash USB диска/
        '---------------------------------------------------------------------------
        Function GetDriveLetter(flg)
            
            Dim sDrivesStr
            Dim sDev
            Dim sCur1, sCur2
            Dim a,b

            On Error Resume Next

            '/Перебор букв дисков/
            '---------------------------------------------------------------------------------
            sDrivesStr = ""
            Set objRemovableDrives = objService.ExecQuery("SELECT * FROM Win32_LogicalDisk WHERE DriveType = 2")
            
            For Each objDrive In objRemovableDrives
                sDrivesStr = sDrivesStr & CStr(objDrive.DeviceId)
            Next

            '/Выяснение буквы добавленного или удаленного диска/
            '-------------------------------------------------------------------
            If flg = True Then

                a = (Len(sDrivesStr) > Len(sPrevDrivesStr)) 'Добавление устройства
                b = (Len(sDrivesStr) < Len(sPrevDrivesStr)) 'Извлечение устройства
                sCur1 = sDrivesStr
                sCur2 = sPrevDrivesStr

                For Each objDrive In objRemovableDrives

                    sDev = CStr(objDrive.DeviceId)
                    
                    '/Добавление устройства/
                    If a Then
                        If (InStr(sDrivesStr,sDev)<>0) And Not (InStr(sPrevDrivesStr,sDev)<>0) Then GetDriveLetter = sDev: Exit For
                    End If
                    
                    '/Извлечение устройства/
                    If b Then
                        sCur1 = Replace(sCur1, sDev, "")
                        sCur2 = Replace(sCur2, sDev, "")
                    End If

                Next    
                If b Then
                    If Len(sCur1) < Len(sCur2) Then GetDriveLetter = sCur2
                End If
            End If
            '-------------------------------------------------------------------
            sPrevDrivesStr = sDrivesStr
            If Err.Number <> 0 Then GetDriveLetter = ""
            Err.Clear
        
        End Function

        '/Обработка событий вставки-извлечения/
        '---------------------------------------------------------------------------
        Sub ObjSink_OnObjectReady(objWbemObject, objContext)    'Подключение
            
            Dim sEventType, sDepend
            Dim a,b,c

             sEventType = CStr(objWbemObject.Path_.Class)
            sDepend = CStr(objWbemObject.TargetInstance.Dependent)

            '/Условия/
            '-------------------------------------------------------------------
            a = (InStr(1, sEventType, "CreationEvent") <> 0)
            b = (InStr(1, sEventType, "DeletionEvent") <> 0)
            c = (InStr(1, sDepend, "USBSTOR") <> 0)
            
            '-------------------------------------------------------------------
            If a And c Then
                StateFlag = False
                MsgBox "Подключен USB накопитель. [" & GetDriveLetter(True) & "]", vbInformation Or vbSystemModal, "Reply"
                
            End If
            
            If b Then

                If StateFlag Then
                    StateFlag = False
                    If InStr(sDepend,"VID")<>0 Then    MsgBox "USB устройство отстыковано аппаратно.", vbInformation Or vbSystemModal, "Reply"
                End If
    
                If c Then
                    StateFlag = True
                    MsgBox "USB накопитель отключен программно или небезопасно отстыкован. [" & GetDriveLetter(True) & "]", vbInformation Or vbSystemModal, "Reply"
                End If
                    
                
            End If
        End Sub
        
        '/Вызов диалога безопасного извлечения устройства/
        '---------------------------------------------------------------------------
        Sub UnplugDialog()

            On Error Resume Next
            objProc.Create "rundll32.exe shell32,Control_RunDLL hotplug.dll", null, null, pID

        End Sub
        '---------------------------------------------------------------------------
        Function window_onunload()

            ObjSink.Cancel()
            Set objService = Nothing
            Set objProc = Nothing

        End Function

        '---------------------------------------------------------------------------
        Function window_onload()
        
        End Function

    </SCRIPT>
    <!--------------------------------------------------------------------------------->
</BODY>
</HTML>

2

Re: HTA: Отслеживание USB накопителя

Пока разбирался с VBS (моя вечная проблема) сваял приблуду (в Линуксе такое видел):

<html>
<head>
  <hta:application applicationName="USBDL-Zs" showInTaskbar="no" singleInstance="yes" />
  <script type="text/jscript" language="JScript">moveTo(-10000,-10000);</script>
</head>
<body><object id="os" classid="CLSID:75718C9A-F029-11D1-A1AC-00C04FB6C223"></object></body>
<script type="text/jscript" language="JScript">
  var
   c=[],    // массив существующих линков
   d,        // массив USB накопителей
   f=new ActiveXObject('Scripting.FileSystemObject'),
   s=new ActiveXObject('WScript.Shell'),
   t=f.getFolder(s.specialFolders.item(10)),
   o;        // WMI

  try{o=GetObject('winmgmts:root\\cimv2');}
  catch(e){alert('Не удалось соединиться с WMI');window.close();}
  o.execNotificationQueryAsync(os,
   'SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA '+
   '"Win32_USBControllerDevice"'
  );
  fc();

  function fa(e){                // создаём ярлык
    var u=t.path+'\\USB диск '+e+'.lnk';
    with(s.createShortcut(u)){
      targetPath=e+':';
      save();
    }c.push(u);
  }
  function fb(){                // удаляем линки
    if(!c.length)with(new Enumerator(t.files)){
      while(!atEnd()){                // читаем линки
        if(/USB\sдиск\s\w\.lnk/.test(item().name))c.push(item().path);
        moveNext();
      }
    }
    for(var i=0;i<c.length;i++)if(f.fileExists(c[i]))f.deleteFile(f.getFile(c[i]),true);
    c=[];
  }
  function fc(){                // перечитываем диски
    fb();                    // удаляем линки
    d=[];
    with(new Enumerator(f.drives)){        // читаем диски
      while(!atEnd()){
        if(item().driveType==1)d.push(item().driveLetter);
        moveNext();
      }
    }for(var i=0;i<d.length;i++)fa(d[i]);    // создаём линки
  }
</script>
<script type="text/javascript" language="javascript" for="os" event="onobjectready()">
  fc();
</script>
</html>

Предполагается, что этот .hta стартует вместе с системой и с ней же завершается, поэтому прибить его можно только из Диспетчера задач. Кодировка 1251 (на всякий случай).
Poltergeyst, спасибо за пример.