你好伙伴Stackoverflowers:)
我正在寻找在Windows Server 2012(Foundation)上为USB驱动器分配固定的Driveletter的方法。
情景: 我的一个小客户为他的服务器备份提供了2个USB驱动器,每天都要进行交换以进行异地备份。目前,如果存在不匹配,他们会手动重新分配Driveletters。
我已经有了实现这一目标的计划,但是在实施之前想要征求意见,因为我不确定这是否是最好的解决方案。
我会按照以下方式进行:
所以问题是:
是否有可能将固定的驱动器分配给一组USB设备,而无需在每次连接设备时运行脚本?
如果没有更好的方法来检测何时连接设备并触发任务?
当然我做了一些研究,但只找到了Windows7或Server2008的解决方案。我宁愿在没有第三方工具的情况下解决这个问题。
提前感谢您对此主题的任何见解
关心保罗
答案 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()
}