Функция пути Powershell не работает для ps1, вызываемая из ps1

1-й PS1:

#$dll = 'C:\Some\Path\To\dll'

$dll = $PSScriptRoot+'\dll'
Write-Host $dll -foreground Green
 
$code = @"
Some code that works
"@

Add-Type -TypeDefinition $code -Language CSharp -ReferencedAssemblies $dll
[System.Reflection.Assembly]::LoadFrom($dll)

[HelloWorld.Program]::Main()

2-й PS1:

$job = Start-Job -FilePath "Myps1.ps1" -Name "aaa"

$dll = $PSScriptRoot+'\Mydll.dll'
Write-Host $dll -foreground Yellow

Start-Sleep 5

$JobStatus = $job.State
Write-Host $job.State -foreground Yellow

if ($JobStatus -like "Running")
    {
        Write-Host "Gresit" -foreground Red
    }
else 
    {
        Write-Host "Corect" -foreground Green
    }

Звоню на первый пс1 со 2-го пс1. Проблема возникает потому, что при вызове первого пс1 со 2-го, если я использую

$dll = 'C:\Some\Path\To\dll'

тогда программа работает. Но если я использую

$dll = $PSScriptRoot+'\dll'

тогда программа ничего не делает.

Излишне говорить, что если я вызову первый ps1, он будет работать с обеими версиями пути dll.

Каково значение $PSScriptRoot во втором скрипте (используйте write-host “script root = ‘$PSScriptRoot’”, чтобы узнать) и какое оно должно быть, по вашему мнению?

mclayton 20.06.2024 10:30

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

Anne Marie 20.06.2024 10:46

Можете ли вы показать буквальные значения $PSScriptRoot — текущие и ожидаемые? Помните, что люди, читающие ваш вопрос, не видят ваш экран, поэтому вам необходимо предоставить в своем вопросе конкретные технические подробности. даже если они кажутся вам очевидными

mclayton 20.06.2024 12:07

C:\Users\Admin\Documents\PowerShell Scripts

Anne Marie 20.06.2024 12:54

это значение $PSScriptRoot и значение ожидаемого пути.

Anne Marie 20.06.2024 12:54

В каждом отдельном случае $PSScriptRoot ведет себя очень хорошо.

Anne Marie 20.06.2024 12:55

Я знаю, что он работает правильно, потому что когда я запускаю первый скрипт сам по себе, он работает, но когда я запускаю его из второго сценария, он ничего не делает. Код С# ничего не делает :(

Anne Marie 20.06.2024 12:58

Вы имеете в виду, что значение $PSScriptRoot всегда правильное? Даже когда вы вызываете его из второго скрипта?

Ocaso Protal 20.06.2024 14:09

@OcasoProtal - я подозреваю, что $PSScriptRoot внутри сценария 1 равен $null или не определен при вызове его из Start-Job в сценарии 2, а ОП предоставляет неоднозначные факты - Start-Job запускает файл как блок сценария, а не сценарий, а блоки сценариев не $PSScriptRoot определены ...

mclayton 20.06.2024 14:52

спасибо, это очень помогло мне понять мою проблему. таким образом, обходным путем можно было бы отправить параметры в функцию, но это кажется таким трудным, особенно внутри Start-Job

Anne Marie 20.06.2024 15:57

Окасо Протал, да, я вот что имею в виду.

Anne Marie 20.06.2024 16:04
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
11
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Так это твоя проблема...

$job = Start-Job -FilePath "Myps1.ps1" -Name "aaa"

Если вы посмотрите документацию по параметру -FilePathStart-Job, там написано:

-FilePath

При использовании этого параметра PowerShell преобразует содержимое указанного файла сценария в блок сценария и запускает блок сценария в качестве фонового задания.

Итак, ваш код эквивалентен:

$src = Get-Content "Myps1.ps1"
$sb  = [scriptblock]::Create($src)
$job = Start-Job -ScriptBlock $sb -Name "aaa"

А если мы запустим почти идентичный пример с возможностью вырезания и вставки:

$src = @"
write-host "root = '$PSScriptRoot'"
"@
$sb = [scriptblock]::Create($src)
$job = Start-Job -ScriptBlock $sb -Name "aaa"

Wait-Job $job
Receive-Job $job

Мы видим следующий вывод:

root = ''

Это связано с тем, что $PSScriptRoot не определяется при запуске внутри ScriptBlock, а только при запуске как скрипт:

$PSScriptBlock

Содержит полный путь к родительскому каталогу исполняемого сценария.

В PowerShell 2.0 эта переменная действительна только в модулях сценариев (.psm1). Начиная с PowerShell 3.0, он действует во всех сценариях.

ScriptBlock — это объект в памяти, поэтому у него нет «родительского каталога», а создание ScriptBlock из содержимого файла не сохраняет путь к файлу в ScriptBlock, поэтому $PSScriptRoot не определен в обоих случаях.

Этот ответ дает более подробную информацию:

https://stackoverflow.com/a/72026978/3156906

Предлагаемый обходной путь — сделать вызов Start-Job простой оболочкой вокруг оператора вызова для вызова вашего сценария, поскольку тогда ваш сценарий выполняется как сценарий (а не блок сценария) и имеет доступ к автоматической переменной $PSScriptBlock. :

$sb = { & ".\first.ps1" }
$job = Start-Job -ScriptBlock $sb -Name "aaa"

$result = Wait-Job $job
Receive-Job $job

Таким образом, файл сценария запускается как сценарий, а не как блок сценария, и в результате ему доступна автоматическая переменная $PSScriptRoot, что приводит к следующему выводу:

C:\src\so\root\dll

большое спасибо. Теперь я намного лучше понимаю свою проблему <3

Anne Marie 20.06.2024 16:03

НП. не стесняйтесь отмечать как ответ, если это решит вашу проблему.

mclayton 20.06.2024 16:19

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