Помогите разобраться с гибридной химерой CMD/PowerShell
Почему ЭТО работает
<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
echo You chose %%~I
::set "chose=%%~I"
::echo %chose%
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
А это - НЕТ, и вообще на все что бы не подставил, кроме первого echo ему плевать. А по идее do должен выполнить все, что в скобках...
<# : chooser.bat
:: launches a File... Open sort of file chooser and outputs choice(s) to the console
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
::echo You chose %%~I
set "chose=%%~I"
echo %chose%
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows.Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
:: внутри for замени на rem
не спрашивай почему. В ответе выше этой строки нет, так что ии тут ни при делах
Проблема здесь в том, что в коде PowerShell/Batch команды выполняются асинхронно, и их результаты не всегда доступны немедленно. Давайте рассмотрим почему второй вариант не работает как ожидается:
```batch
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
set "chose=%%~I"
echo !chose! REM На этом шаге переменная chose еще не имеет значения, потому что код PowerShell еще не выполнился полностью.
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows .Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
```
После выполнения команды `powershell`, пока код PowerShell еще выполняется, обработка батч-скрипта продолжится дальше, и оператор `echo %chose%` будет выполнен до того, как переменная `chose` получит значение. Чтобы обойти эту проблему, вам нужно использовать восклицательные знаки `!` вместо процентов `%` для переменной `chose`, чтобы обеспечить доступ к актуальному значению переменной внутри цикла.
Вот исправленный вариант:
```batch
@echo off
setlocal enabledelayedexpansion
for /f "delims=" %%I in ('powershell -noprofile "iex (${%~f0} | out-string)"') do (
set "chose=%%~I"
echo !chose!
)
goto :EOF
: end Batch portion / begin PowerShell hybrid chimera #>
Add-Type -AssemblyName System.Windows .Forms
$f = new-object Windows.Forms.OpenFileDialog
$f.InitialDirectory = pwd
$f.Filter = "Text Files (*.txt)|*.txt|All Files (*.*)|*.*"
$f.ShowHelp = $true
$f.Multiselect = $true
[void]$f.ShowDialog()
if ($f.Multiselect) { $f.FileNames } else { $f.FileName }
```
Теперь переменная `chose` будет выводиться с правильным значением, которое она получила в цикле `for`.