Вызвать пользовательскую функцию журнала внутри команды Invoke - PullRequest
1 голос
/ 22 марта 2019

Я написал специальную функцию записи-записи.Если я использую функцию Write-Log внутри Invoke, я получаю ниже сообщение об ошибке «Ошибка при удаленном выполнении: термин« Write-Log »не распознается как имя командлета, функции, файла сценария или работоспособной программы.Проверьте правильность написания имени или, если путь был указан, проверьте правильность пути и повторите попытку. "

Я использую Powershell 5.1.Я пытался использовать $ {function: Write-Log}, но это не сработало.

Function Write-Log([string]$ComputerList,$message, $level="INFO") {
    $date_stamp = Get-Date -Format s
    $log_entry = "$date_stamp - $level - $message"
    $log_file = "$tmp_dir\upgrade_powershell.log"
    Write-Verbose -Message $log_entry
    Add-Content -Path $log_file -Value $log_entry
}

Function Start-Process ($ComputerList) {    
    Return Invoke-Command -computername $Computer -ScriptBlock {
                Param($file)
                $Application = $args[0]
                $ApplicationName = $Application.Substring($Application.LastIndexOf('\')+1)
                $ApplicationFolderPath = $Application.Substring(0,$Application.LastIndexOf('\'))
                $ApplicationExt = $Application.Substring($Application.LastIndexOf('.')+1)
    Write-Log -message "Installing $file on $($env:COMPUTERNAME)"
    $p = Start-Process $file -Wait -Passthru

    $p.WaitForExit()
                $p.WaitForExit()
                if ($p.ExitCode -ne 0) {
                    Write-Log -message "Failed installing with error code $($p.ExitCode)"  -level "ERROR"
                    $Return = $($env:COMPUTERNAME)
                }
                else{
                    $Return = 0

        if ($p.ExitCode -ne 0 -and $p.ExitCode -ne 3010) {
        $log_msg = "$($error_msg): exit code $p.ExitCode"
        Write-Log  -message $log_msg -level "ERROR"
        #throw $log_msg
        return
      }
    if ($p.ExitCode-eq 3010) {
        Reboot-AndResume
        break
    }}


}
}

Ответы [ 2 ]

0 голосов
/ 22 марта 2019

Я пытался использовать ${function:Write-Log}, но это не сработало.

${function:Write-Log} использует нотацию переменной пространства имен , чтобы получить тело функции Write-Log в виде блока скрипта .

Поскольку вы используете remoting (вы передаете аргумент -ComputerName в Invoke-Command), вам придется либо передать этот блок скрипта в качестве аргумента к удаленно выполняемому блоку сценария, или, что более удобно, использует $using: scope (PSv3 +), чтобы сделать local значение переменной доступным remote .

К сожалению, $using: нельзя объединить с нотацией переменных пространства имен, как в Windows PowerShell v5.1 / PowerShell Core 6.2.0 - см. эту проблему GitHub .

Таким образом, при наличии ошибки ссылка на ваш блок сценария как ${using:function:Write-Log} не работает не напрямую, но вы можете использовать промежуточную переменную , а затем использовать ее для адаптации это отличный ответ , используя упрощенный сценарий:

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

function Write-Log { 
  param([string] $ComputerList, $message, $level="INFO")      
  # For testing simply echo the arguments
  "$ComputerList, $message, $level"
}

# Recreate the function's full source code as a string.
$funcDef = "function Write-Log { ${function:Write-Log} }"

Invoke-Command -Computer . -ScriptBlock {

  # Define the Write-Log function using Invoke-Expression
  # Note: This is a rare case where use of Invoke-Expression is
  #       justified; generally, it is to be AVOIDED - see
  #       https://blogs.msdn.microsoft.com/powershell/2011/06/03/invoke-expression-considered-harmful/
  Invoke-Expression $using:funcDef

  # Now you can call it as you would locally.
  Write-Log 'ws1 ws2' testing DEBUG

}

Выше должно возвращаться ws1 ws2, testing, DEBUG.


Конечно, если исходный код Write-Log:

  • легко доступны для вас и
  • вы не против дублировать внутри блока скрипта,

вы можете просто сделать определение функции частью удаленно выполняемого блока скрипта :

Invoke-Command -Computer . -ScriptBlock {

  # Embedded copy of Write-Log.
  function Write-Log { 
    param([string] $ComputerList, $message, $level="INFO")      
    # For testing simply echo the arguments
    "$ComputerList, $message, $level"
  }

  # Now you can call it as you would locally.
  Write-Log 'ws1 ws2' testing DEBUG

}
0 голосов
/ 22 марта 2019

попробуйте включить определение вашей пользовательской функции в блок скриптов, вроде как

invoke-command -scriptblock {
    param (
        your params
    )

    begin {
        function write-log (etc) {
            the function code
        }
    }

    process {
        your main scriptblock stuff
    }

    end {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...