Powershell Значение аргумента path равно NULL

Я разработал файл PS1, который будет отвечать за применение исправлений SQL Server на основе списка серверов. Таким образом, он прочитает текстовый файл со всеми серверами, которые мне нужно исправить и применить Patch. Я решил использовать PARAM для "Исходной папки" (где я получу список серверов и запись вывода); "Папка назначения" (где я смогу запустить патч), "Файл" (имя патча), "Экземпляр" (экземпляр SQL Server, на котором я буду запускать обновление патча). Когда я начинаю запускать команды ниже, он может читать список серверов (так, 1-й PARAM в порядке), но он возвращает ошибку ниже процесса прерывания. Чего не хватает или что я делаю не так в коде ниже?

PS: Я также хотел бы использовать Try...Catch для записи сообщения в выходной файл. Я правильно написал? Заранее спасибо!

[CmdletBinding()]
Param (
  [Parameter(Mandatory=$True,Position=0)]
  [string]$foldersource,

  [Parameter(Position=1)]
  [string]$folderdest,

  [Parameter(Position=2)]
  [string]$file,

  [Parameter(Position=3)]
  [string]$instance

)
foreach ($cluster in GC "$foldersource\Servers_List.txt")
{
    $output = "Server: $cluster Patch Installation on: $(Get-Date -format 'u')" 
try{
    Invoke-Command -ComputerName $cluster -ScriptBlock 
    {
        cd $folderdest
        .\$file /X:$folderdest
        Start-Sleep -s 10
        .\SETUP.exe /action=patch /instancename=$instance /quiet /IAcceptSQLServerLicenseTerms
    }
    -ErrorAction Stop; 
    $output += " SUCCESS"
   }
catch
   {
      $output += "Failed - $($_.exception.message)"
   }
$output | Out-File -Append $foldersource\Patch_Result_Non_SP.txt
} 

Как я запускаю команду выше: .\SQL_Server_install_non-Service_Pack_V2.ps1 "D:\Software\Patch" "D:\Software" "SQLServer2008R2-KB3045316-x64.exe" "MSSQLSERVER"

ERROR:

Cannot process argument because the value of argument "path" is null. Change the value of argument "path" to a non-null value.
+ CategoryInfo          : InvalidArgument: (:) [Set-Location],   PSArgumentNullException
+ FullyQualifiedErrorId : ArgumentNull,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName        : 

   The term '.\$file' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
+ CategoryInfo          : ObjectNotFound: (.\$file:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName        : 

The term '.\SETUP.exe' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, 
verify that the path is correct and try again.
+ CategoryInfo          : ObjectNotFound: (.\SETUP.exe:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName        : 

1 ответ

Вы должны передать свои аргументы либо через -ArgumentList или через $using конвенция к Invoke-Command Командлет. Так как вы не делаете это таким образом $folderdest, $file будет нулевым в объеме Invoke-Command scriptblock -> scriptblock определяет отдельную область видимости!

От Microsoft:

-ArgumentList

Предоставляет значения локальных переменных в команде. Переменные в команде заменяются этими значениями до запуска команды на удаленном компьютере. Введите значения в списке через запятую. Значения связаны с переменными в том порядке, в котором они перечислены. Псевдоним ArgumentList - Args.

Также ознакомьтесь с примерами из Invoke-Commandкомандлет через Get-Help Invoke-Command -Examples,

Если вам не нравится ArgumentList Решение вы также можете использовать удаленные переменные.

Кроме того, вы также должны определить абсолютный путь к вашему Setup.exe!

Итак, ваш код должен выглядеть так:

....
 Invoke-Command -ComputerName $cluster -ArgumentList $file, $folderdest, $instance -ScriptBlock 
{
    Param(
       [string] $rFile,
       [string] $rfileDest,
       [string] $rInstance
    )

    # Remove Write-Host after the script block works fine -> Write-Host is only a quick and dirty way to dump the variables content

    Write-Host $rFile
    Write-Host $rfileDest
    Write-Host $rInstance

    cd $rfileDest

    $someArgs = "/X:{0}" -f $rfileDest
    Start-Process -FilePath  $rFile -ArgumentList $someArgs -Wait -PassThru

    Start-Sleep -s 10

    $setupArgs = "action=patch /instancename={0} /quiet /IAcceptSQLServerLicenseTerms" -f $rInstance

    Start-Process -FilePath ".\Setup.exe" -ArgumentList $setupArgs -Wait -PassThru

}
....

Надеюсь, это поможет.

Другие вопросы по тегам