为Windows Server上的USB设备分配固定驱动器号(2012)

时间:2014-11-21 18:40:20

标签: windows powershell cmd windows-server-2012

你好伙伴Stackoverflowers:)

我正在寻找在Windows Server 2012(Foundation)上为USB驱动器分配固定的Driveletter的方法。

情景: 我的一个小客户为他的服务器备份提供了2个USB驱动器,每天都要进行交换以进行异地备份。目前,如果存在不匹配,他们会手动重新分配Driveletters。

我已经有了实现这一目标的计划,但是在实施之前想要征求意见,因为我不确定这是否是最好的解决方案。

我会按照以下方式进行:

  1. 启用DriverFramework-UserMode日志(如果未启用)
  2. 创建由EventID 2106触发的计划任务
  3. 运行powershell脚本(通过计划任务),如果DeviceID与其中一个备份驱动器匹配,则分配驱动器号
  4. 所以问题是:

    是否有可能将固定的驱动器分配给一组USB设备,而无需在每次连接设备时运行脚本?

    如果没有更好的方法来检测何时连接设备并触发任务?

    当然我做了一些研究,但只找到了Windows7或Server2008的解决方案。我宁愿在没有第三方工具的情况下解决这个问题。

    提前感谢您对此主题的任何见解

    关心保罗

2 个答案:

答案 0 :(得分:2)

我不知道这有多大帮助,但我在https://social.technet.microsoft.com/Forums/windowsserver/en-US/09c9814a-38fa-4b16-bc8f-01329882a791/powershell-wmi-get-usb-storage-devices-only发现了一个不错的帖子,其中以下代码有助于检测连接的USB设备:

$diskdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} |  %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid} 

$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}

然后您可以使用以下内容更改驱动器号(必须是管理员)

$drive.DriveLetter = "O:"
$drive.Put()

修改

好的,这是另一种尝试。以下代码(我在此处找到:http://blogs.technet.com/b/heyscriptingguy/archive/2010/04/13/hey-scripting-guy-april-13-2010.aspx)允许创建一个WMI事件,该事件将在插入USB驱动器时触发。

我已向该事件添加了一个操作,以便执行脚本块。 脚本块检查USB驱动器的字母,如果不是,例如“O:”,它将设置它。

我没有使用Wait-Job,因为只要事件存在,作业就会继续运行,我希望看到一些输出用于测试。

无论如何,这应该更接近你想要做的事情:

$scriptblock = {

    $driveLetter = "O:"
    $diskdrive = gwmi win32_diskdrive | ?{$_.interfacetype -eq "USB"}
    $letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} |  %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid} 

    $drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")} 

    if ($drive.DriveLetter -ne $driveLetter)
    {
        $drive.DriveLetter = $driveLetter
        $drive.Put()
    }
    $drive.DriveLetter
}

$job = Register-WmiEvent -Query "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_logicaldisk'" -SourceIdentifier usb -Timeout 1000 -Action $scriptblock

while ($job.State -ne 'Stopped')
{
    $job | Receive-Job
    sleep 5
}
Unregister-Event -SourceIdentifier usb -Force | Out-Null
$job | Remove-Job -force

值得注意的是: 脚本块将接收$ args以及$ event。我没有使用它们,但它们可能会帮助进一步优化脚本。

答案 1 :(得分:0)

以下是我最终可能会使用的代码:

创建一个运行脚本的永久wmi使用者:

$computer = "xxx"
$filterNS = "root\cimv2"
$wmiNS = "root\subscription"
$query = "Select * from __InstanceCreationEvent within 5 where targetinstance isa 'win32_logicaldisk'"

$filterName = "TestFilter"

$filterPath = Set-WmiInstance -Class __EventFilter `
 -ComputerName $computer -Namespace $wmiNS -Arguments `
  @{name=$filterName; EventNameSpace=$filterNS; QueryLanguage="WQL";
    Query=$query}

$consumerPath = Set-WmiInstance -Class CommandLineEventConsumer `
 -ComputerName $computer -Namespace $wmiNS `
 -Arguments @{
 name="TestConsumer"; 
 ExecutablePath= "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe";
 CommandLineTemplate = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe -executionpolicy bypass -file D:\\reassignDriveletter.ps1"
 }

Set-WmiInstance -Class __FilterToConsumerBinding -ComputerName $computer `
  -Namespace $wmiNS -arguments @{Filter=$filterPath; Consumer=$consumerPath} |
  out-null

如果驱动器的Serialnumber与其中一个Backupdrives匹配,则此脚本会更改驱动器号

$driveLetter = "Z:"

$diskdrive = gwmi win32_diskdrive | ?{($_.interfacetype -eq "USB") -and $_.serialnumber.trim() -eq "761203FA9J813S" -or $_.serialnumber.trim() -eq "761239FA9J813S"}
$letters = $diskdrive | %{gwmi -Query "ASSOCIATORS OF {Win32_DiskDrive.DeviceID=`"$($_.DeviceID.replace('\','\\'))`"} WHERE AssocClass = Win32_DiskDriveToDiskPartition"} |  %{gwmi -Query "ASSOCIATORS OF {Win32_DiskPartition.DeviceID=`"$($_.DeviceID)`"} WHERE AssocClass = Win32_LogicalDiskToPartition"} | %{$_. deviceid} 
$drive = gwmi win32_volume | ? {$letters -contains ($_.name -replace "\\")}

if ($drive.DriveLetter -ne $driveLetter)
    {
        $drive.DriveLetter = $driveLetter
        $drive.Put()
    }