.png)
Я пытаюсь запустить скрипт PowerShell ниже, чтобы определить тип интерфейса USB или SCSI, подключенного к компьютеру. Скрипт работает отлично, если я не использую операторы IF
и-Or
if(($diskdrive = (gwmi win32_diskdrive | ?{$_.interfacetype -eq 'USB'})) -Or ($diskdrive =(gwmi win32_diskdrive | ?{$_.interfacetype -eq 'SCSI'}))){
$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}
setx OSDUSBDrive $letters /M
Write-Output $diskdrive, $letters}
Start-Sleep -s 5
if (-not ("Win32.NativeMethods" -as [Type]))
{
# import sendmessagetimeout from win32
Add-Type -Namespace Win32 -Name NativeMethods -MemberDefinition @"
[DllImport("user32.dll", SetLastError = true, CharSet = CharSet.Auto)]
public static extern IntPtr SendMessageTimeout(
IntPtr hWnd, uint Msg, UIntPtr wParam, string lParam,
uint fuFlags, uint uTimeout, out UIntPtr lpdwResult);
"@
}
$HWND_BROADCAST = [IntPtr] 0xffff;
$WM_SETTINGCHANGE = 0x1a;
$result = [UIntPtr]::Zero
# notify all windows of environment block change
[Win32.Nativemethods]::SendMessageTimeout($HWND_BROADCAST, $WM_SETTINGCHANGE, [UIntPtr]::Zero, "Environment", 2, 5000, [ref] $result);
Start-Sleep -s 5
ОШИБКА: Неверный синтаксис. Параметр по умолчанию не допускается более '2' раз(а). C:\temp\AddOSDUSBDrive_NEW.ps1:10 : 1 + setx OSDUSBDrive $letters /M + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (Ошибка: Синтаксис...более 2 раз:String) [], RemoteException + FullyQualifiedErrorId : NativeCommandError Введите "SETX /?", чтобы показать синтаксис.
Есть идеи?
решение1
Использоватьsetx OSDUSBDrive "$letters" /M
ПрименяемыйSETX.exe
синтаксисшаблон
SETX [/s Computer [Credentials]] Variable Value [/m] ↑↑↑↑↑
может быть неправильным, если $letters
содержит большебуквынапример F:
, G:
,H:
setx OSDUSBDrive $letters /M
# ↑↑↑↑↑↑↑↑ this evaluates to
setx OSDUSBDrive F: G: H: /M
# ↑↑ ↑↑ ↑↑ three space-separated values (WRONG)
Скорректировано (см.Синтаксис: экранированные символы, разделители и кавычки):
setx OSDUSBDrive "$letters" /M
# ↑↑↑↑↑↑↑↑↑↑ this evaluates to
setx OSDUSBDrive "F: G: H:" /M
# ↑↑↑↑↑↑↑↑ one string value (quotes = escape characters)
Более того, я бы скорректировал первый пункт IF
следующим образом:
if ( $diskdrive = ( Get-WmiObject win32_diskdrive |
Where-Object { $_.interfacetype -in ('USB','SCSI') } ) ) {
Объяснение: -or
оператор означает логическое ИЛИ:TRUE
когда либот.е. если первый операнд равен TRUE
, то другие операнды никогда не оцениваются.
Например, запустите
Remove-Variable a, b -ErrorAction SilentlyContinue
if ( ($a = 1) -or ($b = 3) ) { Write-host "a=$a b=$b" }
Переменная «$b» не может быть извлечена, поскольку она не была установлена.
if ( ($a = $null) -or ($b = 3) ) { Write-host "a=$a b=$b" }
а= б=3
решение2
На самом деле я добавил это, как вы и предложили:
если ( $diskdrive = ( Get-WmiObject win32_diskdrive | Where-Object { $_.interfacetype -in ('USB','SCSI') } ) ) {
Скрипт работает нормально, когда я запускаю его вручную, однако при его вызове из SCCM возникает следующая ошибка
Необходимо указать выражение значения справа от оператора «-». TaskSequencePSHost 06.03.2018 16:36:37 0 (0x0000) В D:\SMS\PKG\SE1001B5\AddOSDUSBDrive_NEW.ps1:2 символ:42 + Where-Object { $_.interfacetype - <<<< в ('USB','SCSI') } ) ){ TaskSequencePSHost 06.03.2018 16:36:37 0 (0x0000) ParserError: (:) [], ParseException TaskSequencePSHost 06.03.2018 16:36:37 0 (0x0000) TSHOST: Скрипт завершен с кодом возврата 0 TaskSequencePSHost 06.03.2018 16:36:37 0 (0x0000)