Get-WmiObject не обрабатывает переменную, поскольку она напечатана - PullRequest
0 голосов
/ 26 ноября 2018

Я пытаюсь получить список всех компьютеров и вошел в систему пользователя для каждого компьютера.

Я получаю список компьютеров, и когда я запрашиваю каждую возвращенную строку, я могу получить зарегистрированного пользователя.

Однако, когда я использую переменную имени компьютера, чтобы получить всех пользователей - я получаю сообщение об ошибке, говорящее, что моя переменная неизвестна.Я попытался преобразовать имя компьютера в строку, но это не помогло.

Кстати, та же самая ошибка возникает, когда я набираю неправильное имя компьютера, поэтому это как-то связано с типомпеременная #item, когда я печатаю переменную, она правильная, но не может использоваться внутри цикла.

$obj = Get-ADComputer -Filter 'Name -like "L*"' -Properties * | Select -ExpandProperty Name
foreach ( $item in $obj ) { 
    $itemString = $item.ToString()
    $user = Get-WmiObject –ComputerName $itemString –Class Win32_ComputerSystem | Select-Object UserName | select -expandproperty UserName -first 1
    $user = $user.SubString(8)
    write-output "Computer: $itemString Username: $user" 

}
Get-WmiObject : The RPC server is unavailable. (Exception from HRESULT: 0x800706BA)
At N:\Foreach.ps1:4 char:13
+     $user = Get-WmiObject –ComputerName $itemString –Class Win32_Comp ...
+             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [Get-WmiObject], COMException
    + FullyQualifiedErrorId : GetWMICOMException,Microsoft.PowerShell.Commands.GetWmiObjectCommand

1 Ответ

0 голосов
/ 26 ноября 2018

Ваш симптом говорит о том, что целевой компьютер-нарушитель просто недоступен , например, из-за того, что он отключен от сети или выключен.

Ваш кодне имеет отношения к этому сценарию, но в остальном он корректен с точки зрения типов данных (хотя, учитывая, что свойство .Name имеет тип [string], и вы использовали Select-Object -ExpandProperty, $obj уже представляет собой массив строки, следовательно, $item является одной строкой в ​​цикле foreach, нет необходимости в отдельной переменной $itemString, полученной с помощью .ToString()).

Примечание: я предполагаючто значение свойства .Name достаточно для идентификации компьютера в вызове Get-WmiObject;если это не так, используйте Select-Object -ExpandProperty DNSHostName.

Как правило, обратите внимание, что параметр Get-WmiObject -ComputerName имеет тип [string[]], так что вы можете напрямую передать массив имен хостов к нему.

Однако, к сожалению, [System.Management.Automation.ErrorRecord] экземпляры, созданные Get-WmiObject, когда целевой компьютер недоступен, не содержат имя компьютера-нарушителя, поэтому использование одной команды с последующей проверкой вывода ошибок не является(хотя см. альтернативу Get-CimInstance внизу).

Имея это в виду, вот решение на основе петель PSv3 + , которое обрабатывает недоступные компьютеры изящно :

foreach ($computer in (Get-ADComputer -Filter 'Name -like "L*"' -Properties *).Name) {
  $computerInfo = Get-WmiObject -ErrorAction SilentlyContinue -ComputerName $computer -Class Win32_ComputerSystem
  if (-not $?) { # Call failed, analyze the reason.
    if ($Error[0].Exception.HResult -eq 0x800706BA) { # unavailable
      # Merely issue a *warning*. 
      # Alternatively, collect the unavailable names in an array for later use.
      Write-Warning "Computer is unavailable: $computer"
    } else { # unexpected error, pass it through
      Write-Error $Error[0]
    }
  } else { # success
    "Computer: $($computerInfo.Name) Username: $(($computerInfo.UserName -split '\\')[-1])" 
  }
}

Для сравнения Get-CimInstance - рекомендуется вместо Get-WmiObject, так как его введение в PSv3 - делает добавление информации о происхождении в записи ошибок, поэтому a одного достаточно вызова Get-CimInstance - обратите внимание, что результаты не гарантируются в том же порядке, в котором были указаны компьютеры, но вы получаете выгоду от параллельно исполнение .

# Use a single Get-CimInstance call to target all computers and
# quietly collect errors for later analysis.
$computerNames = (Get-ADComputer -Filter 'Name -like "L*"' -Properties *).Name
Get-CimInstance -ErrorAction SilentlyContinue -ErrorVariable errs `
                -ComputerName $computerNames -Class Win32_ComputerSystem |             #`
  ForEach-Object {
    "Computer: $($_.Name) Username: $(($_.UserName -split '\\')[-1])" 
  }

# Analyze the errors that occurred, if any.
$errs | ForEach-Object {
  if ($_.Exception -is [Microsoft.Management.Infrastructure.CimException] -and $_.CategoryInfo.Category -eq 'ConnectionError') {
    Write-Warning "Computer is unavailable: $($_.OriginInfo.PSComputerName)"
  } else { # unexpected error, pass it through
    Write-Error $_
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...