2016-07-27 3 views
1

У меня есть код ниже, над которым я работал, и у меня есть проблема, я не могу заставить его отправить сообщение переменной на компьютер, если я выберу переменную, которая работает, но это не то, что я пытался с этим сделать.Переменная не отправляется на удаленный сеанс

Function Send-PopupMessage { 
    #Requires -Version 2.0 
    [CmdletBinding()] 
    Param(
     [Parameter(Mandatory = $true)] 
     [String]$ComputerName, 
     [Parameter(Mandatory = $true)] 
     [String]$Message 
    ) 

    Invoke-Command -ComputerName $ComputerName -Scriptblock { 
     $CmdMessage = "msg.exe * $Message" 
     Write-Host $CmdMessage 
     $CmdMessage | Invoke-Expression 
    } 
} 

Это не то же самое, как question linked, потому что я нахожусь в сеансе к другому компьютеру с помощью PSWA, так что я не в состоянии начать новую сессию этого. Кроме того, даже когда я изменил код, чтобы больше походить на один в «Дубликат» вопрос я все еще получаю те же результаты, что CMD отправляется на другой компьютер

MSG.EXE * «» вместо от msg.exe * 'Тестовое сообщение'

+0

Вкратце: используйте '$ using: Message', чтобы ссылаться на _local_ определение' $ Message'. – mklement0

ответ

1

Блоки сценариев PowerShell по умолчанию не являются лексическими закрытиями. Сценарий, переданный Invoke-Command, не сохраняет текущее значение параметра $Message при запуске на другом компьютере.

Когда блок запускается в удаленном сеансе, он использует текущее значение $Message в этом сеансе. Поскольку эта переменная, скорее всего, $null, сообщение опускается из вашей команды.

Используйте синтаксис $using:variabledescribed in this question, чтобы получить значение $Message.

Invoke-Command -ComputerName $ComputerName -Scriptblock { 
    $CmdMessage = "msg.exe * $using:Message" 
    Write-Host $CmdMessage 
    $CmdMessage | Invoke-Expression 
} 

$using:variable Синтаксис работает только при вызове блока на удаленном компьютере. Если вам нужно захватить переменные в скриптблоке для локального выполнения, вместо этого вызовите GetNewClosure() в ScriptBlock.

$Message = "Hey there." 
$closure = { 
    $CmdMessage = "msg.exe * $Message" 
    Write-Host $CmdMessage 
    $CmdMessage | Invoke-Expression 
}.GetNewClosure() 

$Message = $null 
Invoke-Command -Scriptblock $closure 
+0

Хотя ваши объяснения верны, я не думаю, что ваше решение работает: предполагая, что ваш локальный компьютер настроен для удаленного доступа, сравните следующие команды (только последний работает): '$ foo = 'bar'; icm -computername. {$ foo} 'против' $ foo = 'bar'; icm -computername. {$ foo} .GetNewClosure() 'vs.' $ foo = 'bar'; icm -computername. {$ using: foo} ' – mklement0

+0

AFAIK, для удаленного вызова' Invoke-Command' игнорируется любой модуль, к которому прикреплен ScriptBlock', поэтому 'GetNewClosure()' бесполезно здесь. – PetSerAl

+1

Отредактировал ответ, чтобы включить синтаксис '$ using: var', хотя я согласен, что, вероятно, делает это обманом. Спасибо @ mklement0 –

Смежные вопросы