2

我在使用一些 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。我想我会在 Code.ps1 中调用 GUI.ps1,获取我需要的用户输入到变量中。然后获取这些变量并将它们从 GUI.ps1 传递给 Code.ps1(我需要该信息才能在此处运行任何东西)。

然后,一旦我在 Code.ps1 中获得了这些值,就运行我正在做的所有其他事情..?

但是现在如果我的用户出于某种原因决定只点击取消按钮......

(老实说,可能不会发生很多事情,我更想让这个功能为学习而工作。他们可能会不小心运行脚本,不知何故..)

...它只会关闭 GUI,但 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.
}

谢谢您的帮助

4

1 回答 1

2

PowerShell 完全按照它的设计目的去做。PowerShell 是一个脚本环境,可以启动多个单独的程序,不像 C# 程序使用可以终止的单个线程运行。

从 PowerShell 启动的每个进程都在它们自己的进程中单独启动。没有一个命令可以结束所有进程。相反,您必须掌握您打开的所有进程,然后关闭每个进程。

$MainForm.Close()

将关闭 GUI。它不会关闭其他任何东西。

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。

- 编辑 - -

回复您的评论:

好的。如果我理解你,请忽略我上面所说的。您基本上希望 GUI 显示,提供运行脚本的其余部分并退出(不继续并运行脚本的其余部分)或继续并运行脚本的其余部分的选项。

您遇到的问题是 PowerShell 如何加载脚本。首先它创建表单,创建按钮,然后创建事件处理程序来处理按钮单击,并显示表单。然后它继续运行脚本的其余部分。因为您正在使用 Windows 窗体创建 GUI,所以它是非阻塞的,即它不会停止执行脚本以等待您的输入,然后再继续。阻塞命令的一个示例是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.

如果你想用 GUI 来处理它,比如 windows 窗体,那么最简单的方法是将你的代码分成两部分。

第一部分 (GUI.ps1) 是您的 GUI。它所做的只是显示提示,然后脚本完成。(请记住,GUI 已创建,并在脚本执行完毕后继续运行)

第二部分(Code.ps1)是您希望它执行的代码。

在 GUI 代码中,您有 2 个按钮和 2 个处理程序,您有“运行”按钮和“取消”按钮。

您的“运行”按钮代码将是:

$handler_RunButton_Click={
      #Run Code script
      . .\Code.ps1
}

您的“取消”按钮与您当前拥有的代码相同:

$handler_cancelButton_Click={
      $MainForm.Close()
}
于 2014-03-18T18:20:45.610 回答