我在使用某些PS GUI功能时遇到问题。
我试过很多东西,到处都找(所有链接都是紫色的!(。
我的表单上有一个取消按钮,现在当用户单击取消按钮时,它指向这个处理程序,我的表单将关闭。
$handler_cancelButton_Click={
$MainForm.Close()
}
然而,一旦表单关闭,我的所有其他脚本都会尝试继续运行(FTP、运行Excel、发送电子邮件等(,并给我带来错误。
我尝试了很多不同的方法,我只运行了Exit
命令,它会关闭我的窗体,抛出错误,并关闭我的整个IDE(PowerGUI(。
现在我也尝试过这样的东西:
[environment]::exit(0)
[System.Windows.Forms.Application]::Exit($null)
两者都将执行仅调用Exit
所要执行的操作。关闭我的窗体,然后使用PowerGUI。
我希望发生的情况是,当用户按下cancel时,我的窗体关闭,脚本的其余部分停止或终止。
编辑
现在,我有了一个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.
}
感谢的帮助
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个处理程序,您有"Run"按钮和"Cancel"按钮。
您的"运行"按钮代码为:
$handler_RunButton_Click={
#Run Code script
. .Code.ps1
}
您的"取消"按钮与您当前的代码相同:
$handler_cancelButton_Click={
$MainForm.Close()
}