Как мне передавать переменные с помощью командлета Invoke-Command?

#windows #amazon-web-services #powershell

#powershell #переменные #invoke-command

Вопрос:

Мне нужно получать журналы событий с некоторых серверов, и я не хочу читать учетные данные для каждого найденного сервера.

Я пытался передать свои переменные с помощью параметра ArgumentList, но у меня ничего не получается.

Это мой код:

 $User = Read-Host -Prompt "Enter Username"
$Password = Read-Host -Prompt "Enter Password" -AsSecureString
$BSTR = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
$UnsecurePassword = [System.Runtime.InteropServices.Marshal]::PtrToStringAuto($BSTR)

Get-ADComputer -Filter "OperatingSystem -Like '*Server*'" | Sort-Object Name |
ForEach-Object{
    if($_.Name -like '*2008*'){
        Invoke-Command -ComputerName $_.Name -ArgumentList $User, $UnsecurePassword -ScriptBlock {  
            net use P: \Serverdir1dir2 /persistent:no /user:$User $UnsecurePassword
            Get-EventLog -LogName System -After (Get-Date).AddHours(-12) -EntryType Error, Warning | format-list | 
            out-file P:EventLog_$env:COMPUTERNAME.log
            net use P: /delete /yes
        }
    }
}
  

Как я могу использовать переменные в скриптовом блоке Invoke-Command?

Ответ №1:

В качестве альтернативы вы можете использовать область $Using: видимости. Смотрите Пример 5 по этой ссылке.

Пример:

 $servicesToSearchFor = "*"
Invoke-Command -ComputerName $computer -Credential (Get-Credential) -ScriptBlock { Get-Service $Using:servicesToSearchFor }
  

При $Using: этом вам не нужны -ArgumentList параметр и param блок в scriptblock.

Комментарии:

1. Это работает намного лучше, чем param и тому подобное! Спасибо!

Ответ №2:

Либо вы объявляете параметры в начале вашего скриптового блока:

    {  
        param($user,$unsecurepassword)
        net use P: \Serverdir1dir2 /persistent:no /user:$User $UnsecurePassword
        Get-EventLog -LogName System -After (Get-Date).AddHours(-12) -EntryType Error, Warning | format-list | 
        out-file P:EventLog_$env:COMPUTERNAME.log
        net use P: /delete /yes
    }
  

Или вы получаете доступ к своим аргументам с помощью $args переменной:

 #first passed parameter
$args[0]
#second passed parameter
$args[1]
....
  

Документация: MSDN

Комментарии:

1. Просто убедитесь, что ваши переменные в param() совпадают с теми, которые вы передаете через -ArgumentList . Я узнал это на собственном опыте, когда мой $computer продолжал отображаться как мой идентификатор пользователя, lol

Ответ №3:

При использовании ScriptBlock with Invoke-Command предполагается, что все переменные внутри ScriptBlock определены в удаленном сеансе при его подключении, поэтому он недоступен в вашем текущем блоке скрипта как обычная форма использования переменных!

Если вам нужно использовать переменную, заполненную внутри вашего скрипта на удаленной стороне, вам следует использовать Using модификатор области видимости для идентификации этой локальной переменной в среде удаленного управления.

Смотрите Пример 9 на: https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/invoke-command?view=powershell-7.3

измените свой код следующим образом:

 ...
    ForEach-Object{
    if($_.Name -like '*2008*'){
        Invoke-Command -ComputerName $_.Name -ArgumentList $User, $UnsecurePassword -ScriptBlock {  
            net use P: \Serverdir1dir2 /persistent:no /user:$Using:User $Using:UnsecurePassword
            Get-EventLog -LogName System -After (Get-Date).AddHours(-12) -EntryType Error, Warning | format-list | 
            out-file P:EventLog_$env:COMPUTERNAME.log
            net use P: /delete /yes
        }
    }