Кнопка отмены PowerShell Stop Script
У меня проблемы с некоторыми функциями PS GUI.
Я попробовал немало вещей и искал повсюду (ВСЕ ССЫЛКИ ФИОЛЕТОВЫЕ!).
У меня есть кнопка отмены в моей форме, прямо сейчас, когда пользователь нажимает кнопку отмены, он указывает на этот обработчик, и моя форма закрывается.
$handler_cancelButton_Click={
$MainForm.Close()
}
Однако, как только форма закрывается, все остальные части моего сценария пытаются продолжить работу (FTP, запуск Excel, отправка электронных писем и т. Д.) И выдают мне ошибки.
Я пробовал много разных вещей, я пробежал только Exit
команда, которая закрывает мою форму, выдает ошибку и закрывает всю мою IDE (PowerGUI).
Теперь я также попробовал такие вещи:
[environment]::exit(0)
[System.Windows.Forms.Application]::Exit($null)
Оба будут делать именно то, что звонят просто Exit
Сделаю. Закройте мою форму и PowerGUI.
Я хочу, чтобы пользователь нажимал "Отмена", моя форма закрывалась, а остальная часть моего сценария останавливалась или заканчивалась.
РЕДАКТИРОВАТЬ
Теперь у меня есть GUI.ps1 и Code.ps1. Я думаю, что я бы вызвал GUI.ps1 внутри Code.ps1, чтобы получить пользовательский ввод, который мне нужен, в переменные. Затем возьмите эти переменные и передайте их из GUI.ps1 в Code.ps1 (эта информация мне нужна для того, чтобы что-то здесь запустить).
Затем, когда у меня есть эти значения в Code.ps1, запустите все остальное, что я делаю..?
Но теперь, если мой пользователь решил только нажать кнопку отмены по какой-то причине...
(Скорее всего, ничего особенного не произойдет, я больше хочу, чтобы эта функциональность работала ради обучения. Они могут случайно запустить скрипт, как-то..)
... он просто закроет графический интерфейс, но не будет ли работать остальная часть Code.ps1?
Или теперь я мог бы сказать что-то подобное в моем скрипте Code.ps1:
if($someGUIValue -eq $null -and $someOtherGUIValues - eq $null){
Exit #would I be able to run this now the way I think it would?
}
else{
#yes, run the script..
}
** НАЙТИ ОТВЕТ
РЕДАКТИРОВАТЬ..
Я создал флаг. Перед началом любого из моих сценариев я объявил переменную примерно так:
$terminateScript = $false
В моем обработчике событий я добавил это
$handler_cancelButton_Click={
$terminateScript = $true
$MainForm.Close()
return $terminateScript
}
Как только они нажмут кнопку отмены, она установит $terminateScript = $true
, Так что теперь, когда я вызываю все свои функции, у меня есть что-то вроде этого:
$username, $password, $someOtherValue, $anotherVaklue, $terminateScript = MainForm
if($terminateScript -eq $false){
SomeFunction
AnotherFunction
}
else{
Exit #this now works here, and cancels my script, without closing my IDE.
}
Спасибо за помощь
1 ответ
PowerShell делает именно то, для чего он предназначен. PowerShell - это среда сценариев, которая запускает несколько отдельных программ, а не программу на C#, работающую с одним потоком, который можно прервать.
Каждый процесс, который вы запускаете из PowerShell, запускается отдельно в своем собственном процессе. Нет единой команды для завершения всех процессов. Вместо этого вы должны следить за всеми процессами, которые вы открываете, и закрывать каждый из них.
$MainForm.Close()
Закрыт графический интерфейс. Больше ничего не закрывает.
Exit
Будет завершен весь запрос PowerShell. Если вы запустили такой исполняемый файл, как Excel, он все равно будет открыт в своем собственном процессе.
Если вы запускаете что-то вроде Excel, вы должны использовать дескриптор, чтобы закрыть его:
#create Excel object
$Excel = New-Object -comobject Excel.Application
#.... do stuff...
#Close Excel
$Excel.quit()
[Runtime.Interopservices.Marshal]::ReleaseComObject($excel) # Release COM
Remove-Variable excel # Remove the Variable
И точно так же, если вы запускаете процесс, как блокнот, используя Start-Process
, вы можете использовать -Passthru
параметр, чтобы получить дескриптор, чтобы вы могли его закрыть:
#Run process
$Handle = Start-Process notepad.exe -PassThru
#.... do stuff...
#End process
$Handle | Stop-Process
Итак, если вы хотите, чтобы ваш скрипт "выходил", вы должны отслеживать все, что вы открываете, и закрывать их, останавливать другие ваши скрипты, завершать все процессы, которые были созданы... и, наконец, закрывать ваш GUI.
--Редактировать---
Отвечая на ваш комментарий:
Хорошо. Если я вас понимаю, игнорируйте то, что я сказал выше. По сути, вы хотите, чтобы графический интерфейс отображался, предлагали либо запустить остальную часть сценария, и выйти (без продолжения и запуска оставшейся части сценария), либо продолжить и запустить оставшуюся часть сценария.
Проблема в том, как PowerShell загружает скрипт. Сначала он создает форму, создает кнопку, а затем создает обработчик событий для обработки нажатия кнопки и отображает форму. Затем он продолжает выполнение остальной части вашего сценария. Поскольку вы создаете графический интерфейс с помощью Windows Forms, он неблокируемый, то есть он не останавливает выполнение скрипта, ожидая ввода, прежде чем продолжить. Примером команды блокировки является Read-Host
команда:
$Response = Read-Host -Prompt "Do I continue (y/n)?"
... Который остановит выполнение текущего скрипта, подскажет, хотите ли вы продолжить. а потом продолжай. Затем вы затем используете простой оператор if, чтобы определить, следует ли продолжить и запустить оставшуюся часть сценария:
if($Response -eq "y")
{
#Run rest of script
}
#else the script ends and you do nothing.
Если вы хотите обрабатывать его с помощью графического интерфейса, такого как формы Windows, тогда самый простой способ - разделить ваш код на две части.
Первая часть (GUI.ps1) - это ваш графический интерфейс. Все, что он делает, это отображает приглашение, а затем скрипт завершает работу. (Помните, что графический интерфейс создан и продолжает работать после завершения выполнения скрипта)
Вторая часть (Code.ps1) - это ваш код, который вы хотите выполнить.
В коде GUI у вас есть 2 кнопки и 2 обработчика, у вас есть кнопка "Выполнить" и кнопка "Отмена".
Ваш код кнопки "Выполнить" будет:
$handler_RunButton_Click={
#Run Code script
. .\Code.ps1
}
Ваша кнопка "Отмена" имеет тот же код, что и сейчас:
$handler_cancelButton_Click={
$MainForm.Close()
}