为什么从任务栏关闭时,PowerShell脚本会卡住?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了为什么从任务栏关闭时,PowerShell脚本会卡住?相关的知识,希望对你有一定的参考价值。
我正在尝试编写一个小脚本,通过它我可以将文件中的关键字更改为我在文本框中键入的内容。我制作了一个包含文件的目录副本,并将它们使用唯一的目录名称复制到名为temp
的映射中。它还会启动一个文件。关闭脚本或按Cancel
时,关闭启动的程序,并再次删除文件。
一切正常,但是每当我通过Windows任务栏关闭表单,并且想再次启动脚本时,即使最小化,表单也不会显示,而PowerShell控制台也会显示,即使完全最小化,也无法编辑任何内容。我可以用Ctrl + C将其关闭,但是下次启动脚本时,它将再次卡住。
这是我编写的第一个脚本,不确定如何解决此问题。
如果停止进程时有一种方法可以删除该唯一随机目录中的文件,那就更好了。例如,如果我关闭通过脚本打开的文件settings.txt
,则删除所有文件。
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Windows.Forms.Application]::EnableVisualStyles()
# Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)
# makes form
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(200,180)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(10,70)
$okButton.Size = New-Object System.Drawing.Size(160,20)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(10,100)
$cancelButton.Size = New-Object System.Drawing.Size(160,20)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(170,20)
$label.Text = 'Please enter the Server name:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(160,20)
$form.Controls.Add($textBox)
$form.Topmost = $true
$form.Add_Shown({$textBox.Select()})
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$server = $textBox.Text
$server
$folder = [System.IO.Path]::GetRandomFileName()
Copy-Item -Path C:powershellmain -Destination c:powershell emp –Recurse
Rename-Item -Path "C:powershell empmain" -NewName $folder
(Get-Content -Path "C:powershell emp$foldersettings.txt" -raw) -replace '<SERVERNAME>',"$server" | Set-Content "C:powershell emp$foldersettings.txt"
$app = (Start-Process "C:powershell emp$foldersettings.txt" -passthru).ID
$form.Size = New-Object System.Drawing.Size(250,100)
$form.StartPosition = 'CenterScreen'
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(200,20)
$label.Text = "Click 'cancel' to close Server $server"
$cancelButton.Location = New-Object System.Drawing.Point(10,40)
$cancelButton.Size = New-Object System.Drawing.Size(180,20)
$cancelButton.Text = 'Cancel'
$result = $form.ShowDialog()
if($result -eq [System.Windows.Forms.DialogResult]::cancel)
{
Stop-Process $app
Remove-Item –path "C:powershell emp$folder" –recurse
}
}
答案
重新启动计算机以清除内存泄漏,然后测试此代码。
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Windows.Forms.Application]::EnableVisualStyles()
# The reason that your form does not open sometime is caused by a memory leak. The code below should resolve the issue.
# If you add to the GUI them add that control below. If a variable does not have a .dispose() then .NET will clean it up.
# These are Events and will fire when the window closes.
# These will fix the memory leak issue.
$Form.Add_FormClosing({
$form.Dispose()
$okButton.Dispose()
$cancelButton.Dispose()
$label.Dispose()
$textBox.Dispose()
})
$Form2.Add_FormClosing({
$form2.Dispose()
$label2.Dispose()
$cancelButton2.Dispose()
})
# Hide PowerShell Console
Add-Type -Name Window -Namespace Console -MemberDefinition '
[DllImport("Kernel32.dll")]
public static extern IntPtr GetConsoleWindow();
[DllImport("user32.dll")]
public static extern bool ShowWindow(IntPtr hWnd, Int32 nCmdShow);
'
$consolePtr = [Console.Window]::GetConsoleWindow()
[Console.Window]::ShowWindow($consolePtr, 0)
# makes form
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Data Entry Form'
$form.Size = New-Object System.Drawing.Size(200,180)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(10,70)
$okButton.Size = New-Object System.Drawing.Size(160,20)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(10,100)
$cancelButton.Size = New-Object System.Drawing.Size(160,20)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(170,20)
$label.Text = 'Please enter the Server name:'
$form.Controls.Add($label)
$textBox = New-Object System.Windows.Forms.TextBox
$textBox.Location = New-Object System.Drawing.Point(10,40)
$textBox.Size = New-Object System.Drawing.Size(160,20)
$form.Controls.Add($textBox)
$form.Topmost = $true
# Is this line needed
#$form.Add_Shown({$textBox.Select()}) # this sometimes will not let me type in the textbox
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$server = $textBox.Text
$server
$folder = [System.IO.Path]::GetRandomFileName()
Copy-Item -Path C:powershellmain -Destination c:powershell emp –Recurse
Rename-Item -Path "C:powershell empmain" -NewName $folder
(Get-Content -Path "C:powershell emp$foldersettings.txt" -raw) -replace '<SERVERNAME>',"$server" | Set-Content "C:powershell emp$foldersettings.txt"
$app = (Start-Process "C:powershell emp$foldersettings.txt" -passthru).ID
# This is winform. They work on comobjects and you not reuse the variable name because it will not
# free up memory resource when the are reused. I rename your variables to get around this issue.
$form2 = New-Object System.Windows.Forms.Form
$form2.Size = New-Object System.Drawing.Size(350,250)
$form2.StartPosition = 'CenterScreen'
$label2 = New-Object System.Windows.Forms.Label
$label2.Location = New-Object System.Drawing.Point(10,20)
$label2.Size = New-Object System.Drawing.Size(350,20)
$label2.Text = "Click 'cancel' to close Server $server"
$form2.Controls.Add($label2)
$cancelButton2 = New-Object System.Windows.Forms.Button
$cancelButton2.Location = New-Object System.Drawing.Point(10,80)
$cancelButton2.Size = New-Object System.Drawing.Size(180,40)
$cancelButton2.Text = 'Cancel'
$form2.CancelButton = $cancelButton2
$form2.Controls.Add($cancelButton2)
$result = $form2.ShowDialog()
if($result -eq [System.Windows.Forms.DialogResult]::cancel)
{
Stop-Process $app
Remove-Item –path "C:powershell emp$folder" –recurse
}
}
以上是关于为什么从任务栏关闭时,PowerShell脚本会卡住?的主要内容,如果未能解决你的问题,请参考以下文章
Chocolatey 和 powershell:从任务栏和文件关联中固定和取消固定程序