Раскрытие переменных в аргументах в PowerShell

Вопрос или проблема

Расширение переменных в аргументах в PowerShell

Я пытаюсь написать скрипт PowerShell, который копирует временный каталог на локальном ПК, копирует файлы и папки с сервера во временный каталог и в конце выполняет установщик с аргументами.

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

function Install-AutoCAD_2024 {
    # Определение переменных 
    $temp_dir="C:\deploy_temp"
    $application_name="AutoCAD 2024"
    $source_path = "\\server\software\Autodesk\2024\AutoCAD_2024\"
    $destination_path="$temp_dir\$application_name"
    $installer_path="$destination_path\image\Installer.exe"

    # Проверка существования каталога 
    If (!(Test-Path $destination_path) -and (Test-Path $temp_dir)) {
        Write-Host "Создание временного каталога для '$application_name...'" 
        New-Item -Path "$temp_dir\$application_name" -ItemType Directory -Force
        } else { 
            Write-Host "Копирование файлов. Пожалуйста, подождите..."
            Copy-Item -Path "$source_path" -Destination "$destination_path" -Recurse
            Write-Host "Установка '$application_name'..."
            Start-Process -FilePath "$installer_path" -NoNewWindow -Wait -ArgumentList "-i deploy --offline_mode -q -o ""$destination_path\image\Collection.xml"" --installer_version "1.40.0.2""
        }
}

Однако, если я расширю переменные под командлетом Start-Process до полных строк, то могу установить приложение без проблем.

function Install-AutoCAD_2024 {
    # Определение переменных 
    $temp_dir="C:\deploy_temp"
    $application_name="AutoCAD 2024"
    $source_path = "\\server\software\Autodesk\2024\AutoCAD_2024\"
    $destination_path="$temp_dir\$application_name"
    $installer_path="$destination_path\image\Installer.exe"

    # Проверка существования каталога 
    If (!(Test-Path $destination_path) -and (Test-Path $temp_dir)) {
        Write-Host "Создание временного каталога для '$application_name...'" 
        New-Item -Path "$temp_dir\$application_name" -ItemType Directory -Force
        } else { 
            Write-Host "Копирование файлов. Пожалуйста, подождите..."
            Copy-Item -Path "$source_path" -Destination "$destination_path" -Recurse
            Write-Host "Установка '$application_name'..."
            Start-Process -FilePath 'C:\deploy_temp\AutoCAD 2024\image\Installer.exe' -NoNewWindow -Wait -ArgumentList "-i deploy --offline_mode -q -o 'C:\deploy_temp\AutoCAD 2024\image\Collection.xml' --installer_version '1.40.0.2'"
        }
}

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

Ответ или решение

Расширение переменных в аргументах PowerShell

Теория

PowerShell — это мощная оболочка и язык сценариев, который используется для автоматизации управленческих задач в Windows и других операционных системах. Одной из его ключевых возможностей является работа с переменными, которая позволяет динамически управлять командами и их параметрами. Однако, как и в любом языке программирования, при работе с переменными в PowerShell могут возникать определенные трудности, особенно когда дело касается передачи переменных в аргументы командлетов, таких как Start-Process.

Проблемы с расширением переменных могут возникнуть по ряду причин:

  1. Кавычки: PowerShell различает двойные кавычки (") и одинарные кавычки (‘). Переменные обрабатываются внутри двойных кавычек, но рассматриваются как текст внутри одинарных кавычек. Это означает, что использование кавычек неправильно может привести к тому, что переменные не будут заменены их значениями.

  2. Экранирование: Символы, такие как кавычки внутри самой строки, могут требовать экранирования. Обычно это достигается удвоением кавычек или использованием обратной косой черты.

  3. Синтаксическая структура: Некорректная структура команд или аргументов, где переменная должна быть расширена, также может привести к ошибкам.

Пример

В рассматриваемом вами коде вы столкнулись с проблемой передачи переменных в командлете Start-Process. Попробуем более детально рассмотреть две версии функции и выявить причины, почему одна из них работает, а другая — нет.

Ваш код с переменными:

Start-Process -FilePath "$installer_path" -NoNewWindow -Wait -ArgumentList "-i deploy --offline_mode -q -o ""$destination_path\image\Collection.xml"" --installer_version ""1.40.0.2"""

Код с полными строками:

Start-Process -FilePath 'C:\deploy_temp\AutoCAD 2024\image\Installer.exe' -NoNewWindow -Wait -ArgumentList "-i deploy --offline_mode -q -o 'C:\deploy_temp\AutoCAD 2024\image\Collection.xml' --installer_version '1.40.0.2'"

Вы заметили, что код с расширенными строками работает корректно, тогда как код с переменными вызывает ошибку. Основная причина, вероятно, кроется в том, как PowerShell интерпретирует кавычки и расширяет переменные в строках.

Применение

Для корректного расширения переменных в PowerShell необходимо правильно использовать кавычки и экранирование. Ниже приведен усовершенствованный пример функции, которая должна работать корректно:

function Install-AutoCAD_2024 {
    # Определение переменных 
    $temp_dir = "C:\deploy_temp"
    $application_name = "AutoCAD 2024"
    $source_path = "\\server\software\Autodesk\2024\AutoCAD_2024\"
    $destination_path = "$temp_dir\$application_name"
    $installer_path = "$destination_path\image\Installer.exe"

    # Проверка существования директории 
    If (!(Test-Path $destination_path) -and (Test-Path $temp_dir)) {
        Write-Host "Создание временной директории для '$application_name...'" 
        New-Item -Path "$temp_dir\$application_name" -ItemType Directory -Force
    } else { 
        Write-Host "Копирование файлов. Пожалуйста, подождите..."
        Copy-Item -Path "$source_path" -Destination "$destination_path" -Recurse
        Write-Host "Установка '$application_name'..."
        $args = @("-i", "deploy", "--offline_mode", "-q", "-o", "$destination_path\image\Collection.xml", "--installer_version", "1.40.0.2")
        Start-Process -FilePath $installer_path -NoNewWindow -Wait -ArgumentList $args
    }
}

Объяснение изменений:

  1. Массив аргументов: Вместо того чтобы конструировать строку с аргументами, мы создаем массив $args, где каждый аргумент является отдельным элементом. Это упрощает обработку и снимает необходимость в экранировании кавычек.

  2. Использование переменных: В ArgumentList теперь передается массив $args, который PowerShell понимает как список отдельных аргументов, что исключает ошибки, связанные с кавычками.

Такой подход делает ваш код более ясным и защищенным от ошибок при расширении переменных. Убедитесь, что переменные действительно содержат ожидаемые пути, прежде чем вызывать командлет Start-Process. Для этого можно дополнительно использовать Write-Output для отладки скрипта.

При использовании PowerShell важно понимать тонкости работы с кавычками и аргументами командлетов, что поможет избежать распространенных ошибок и сделать код более устойчивым.

Оцените материал
Добавить комментарий

Капча загружается...