Top.Mail.Ru
Ответы
Аватар пользователя
1 год назад
от
Изменено

Помогите разобраться с гибридной химерой CMD/PowerShell

Почему ЭТО работает

1234567891011121314151617181920212223
 <# : 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 должен выполнить все, что в скобках...

1234567891011121314151617181920212223
 <# : 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`.