Кнопка отмены 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()
}
Другие вопросы по тегам