检测在Windows PowerShell脚本中挂载虚拟(TrueCrypt)卷

6
我正在使用以下的Windows PowerShell脚本来检测特定的卷是否已挂载,以便我可以运行一个脚本,将文件从我的计算机移动到设备上(我对PowerShell脚本不太了解,这是我在网上找到的)。
#Requires -version 2.0
Register-WmiEvent -Class win32_VolumeChangeEvent -SourceIdentifier volumeChange
write-host (get-date -format s) "     Beginning script..."
do{
  $newEvent = Wait-Event -SourceIdentifier volumeChange
  $eventType = $newEvent.SourceEventArgs.NewEvent.EventType
  $eventTypeName = switch($eventType)
    {
    1 {"Configuration changed"}
    2 {"Device arrival"}
    3 {"Device removal"}
    4 {"docking"}
    }
  write-host (get-date -format s) "     Event detected = " $eventTypeName
  if ($eventType -eq 2)
  {
    $driveLetter = $newEvent.SourceEventArgs.NewEvent.DriveName
    $driveLabel = ([wmi]"Win32_LogicalDisk='$driveLetter'").VolumeName
    write-host (get-date -format s) "     Drive name = " $driveLetter
    write-host (get-date -format s) "     Drive label = " $driveLabel
    # Execute process if drive matches specified condition(s)
    if ($driveLetter -eq 'G:' -and $driveLabel -eq 'My Book')
    {
        write-host (get-date -format s) "     Starting task in 5 seconds..."
     start-sleep -seconds 5
        start-process "F:\copy_backups.bat"
    }
  }
  Remove-Event -SourceIdentifier volumeChange
} while (1-eq1) #Loop until next event
Unregister-Event -SourceIdentifier volumeChange

G是一个物理外置硬盘,F是G中的TrueCrypt容器。当脚本检测到正确的设备已经挂载为G时,它会等待5秒钟以便TrueCrypt有足够的时间来挂载F,并且然后运行在F上找到的脚本。似乎只有在连接/断开物理驱动器(至少是脚本接收事件的唯一时间)时才会生成卷更改事件,因为保持G连接并挂载/卸载F不会触发脚本。
我希望能够在没有任何其他更改的情况下检测到TrueCrypt容器何时被挂载。在某种程度上,这一定是可能的,因为Windows资源管理器在容器挂载或卸载时更新其驱动器显示。我阅读了关于win32_VolumeChangeEvent的内容,但是我无法找到与虚拟驱动器相关的任何信息。感谢您的帮助。
2个回答

1
我很惊讶这篇文章已经发布了一年但是没有答案!对于任何访问者:

Register_WMIEvent 对我完全不起作用。相反,我采用了另一种方法来监视驱动器事件。不幸的是,该脚本并不是万无一失的,因为它在添加任何新驱动器时都会执行一个操作。随意添加更多条件。

我猜测,Register_WMIEvent 监视 win32_VolumeChangeEvent 仅当物理驱动器更改时,根据卷管理器条目。

以下是允许你执行任何操作的脚本。(提示:可能将您的TC容器挂载到高字母,并制作一个仅限于这些字母的函数,以便在连接低字母驱动器(如U盘)时脚本不会触发)

$DrivesCount = (gwmi -Query "Select * from Win32_LogicalDisk").Count
$Drives = (gwmi -Query "Select * from Win32_LogicalDisk")

while(1) {
Start-Sleep -Seconds 5
    $DrivesCountNew = (gwmi -Query "Select * from Win32_LogicalDisk").Count
        if ($DrivesCount -ne $DrivesCountNew) 
          {
          $DrivesNew = (gwmi -Query "Select * from Win32_LogicalDisk")
          $DriveLetter = Compare-Object -ReferenceObject $Drives -DifferenceObject $DrivesNew | Select -ExpandProperty InputObject | Select -ExpandProperty DeviceId
          if (!($DriveLetter -eq $null)) { 
          Write-host "New drive mounted $DriveLetter"

          ##Place for you to do something with your drive
          }
          $DrivesCount = (gwmi -Query "Select * from Win32_LogicalDisk").Count 
          }
         }

关于脚本的快速评论: $DrivesCount 获取驱动器列表的初始值,$Drives 将它们全部列出到变量中。然后,无限循环开始,在其中每5秒计算是否挂载了新驱动器($DrivesCountNew)。如果没有注册任何更改,则不执行任何操作(值相同)。但是,如果出现新驱动器,则通过比较差异来检查 $DriveLetter 变量,并返回驱动器的唯一字母(使用 ExpandProperty 函数几次)。
随后,对 $DriveLetter 进行检查,因为如果移除驱动器,脚本将触发(我们不希望在此处发生任何操作)。当然,脚本之后将执行任何脚本块,因此最好通过添加某些条件来限制执行(例如:if ($DriveLetter -eq "Z:") { }
成功执行结束时,它再次覆盖 $DrivesCount 变量(以防止旧变量仍保留位置而导致脚本重复执行操作)。
很抱歉您没有及时得到回复,但我希望有人能够发现这个脚本很有用。(至少我学到了更多关于WMI对象的知识)。

0

Koliat发布的脚本非常好用,它能够正常工作,但是其中有两个错误,我已经修复了。 新的无bug(希望如此)脚本应该长这样:

$DrivesCount = (gwmi -Query "Select * from Win32_LogicalDisk").Count
$Drives = (gwmi -Query "Select * from Win32_LogicalDisk")

while(1) {
    Start-Sleep -Seconds 5
    $DrivesCountNew = (gwmi -Query "Select * from Win32_LogicalDisk").Count
    if ($DrivesCount -ne $DrivesCountNew) {
        $DrivesNew = (gwmi -Query "Select * from Win32_LogicalDisk")
        $DriveLetter = Compare-Object -ReferenceObject $Drives -DifferenceObject $DrivesNew | Select -ExpandProperty InputObject | Select -ExpandProperty DeviceId

        if (!($DriveLetter -eq $null)) { 

            $match = $DrivesNew -match $DriveLetter

            if ([string]::IsNullOrEmpty($match)) {
                write-host "Drive $DriveLetter REMOVED"
            } else {
                Write-host "Drive $DriveLetter MOUNTED"
                ##Place for you to do something with your drive
                if ($DriveLetter -eq "M:") {
                    write-host " Starting task in 3 seconds..."
                    start-sleep -seconds 3
                    #start-process "anything"
                }
            }    
        }
        $DrivesCount = $DrivesCountNew
        $Drives = $DrivesNew
    }
}

你好,欢迎来到SO。如果您能清楚地解释这两个错误会更好。通常情况下,添加某种评论或解释而不仅仅是提供代码会更好。因此,请[编辑]您的答案并尝试描述它的作用和方式。谢谢! - Fabio says Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接