使用 Windows 窗体在脚本终止后几分钟锁定 PowerShell ISE [英] Using Windows Forms Locks up PowerShell ISE minutes after script has terminated

查看:40
本文介绍了使用 Windows 窗体在脚本终止后几分钟锁定 PowerShell ISE的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个有趣的问题.我正在创建一个日历选择器,供我们创建帐户时使用.它工作正常并且仍在进行中,但我注意到当我在 powershell ISE 中运行脚本时,几分钟后它会锁定(我可以在此之前编辑和保存代码几分钟).事件日志中没有任何内容.我收到一个对话框,说 powershell 没有响应.内存使用似乎也很正常.我不知道发生了什么.

I have an interesting issue here. I'm creating a calendar picker for use when we create accounts. It works fine and is still in progress but I have noticed that when I run the script in powershell ISE, after a few minutes it locks up (I am able to edit and save the code for a few minutes prior to that). There is nothing in the event log. I get a dialog box saying that powershell is non responsive. Memory usage seems normal as well. I do not know what is happening.

无论我如何运行 Powershell ISE(以管理员身份运行、以另一个帐户运行和正常 ISE)都会发生这种情况,我正在运行 Windows 8.1.

This occurs no matter how I run Powershell ISE (Run as Administrator, Run as another account, and normal ISE) I am running windows 8.1.

一位同事建议它可能是公寓模型,所以我尝试了 STA 和 MTA,但无论哪种方式都会出现问题.从控制台主机运行相同的代码时不会发生这种情况.

A coworker suggested it may be the apartment model, so I've tried STA and MTA, but the problem occurs either way. It does not happen when the same code is run from the console host.

[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

$objForm = New-Object Windows.Forms.Form 

$objForm.Text = "Select a Date" 
$objForm.Size = New-Object Drawing.Size @(490,250)
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True

$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Enter") 
        {
            $script:dtmDate=$objCalendar.SelectionStart
            $objForm.Close()
        }
    })

$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Escape") 
        {
            $objForm.Close()
        }
    })

$objCalendar = New-Object System.Windows.Forms.MonthCalendar 
$objCalendar.Text = "Start"
$objCalendar.ShowTodayCircle = $False
$objCalendar.MaxSelectionCount = 1
$objForm.Controls.Add($objCalendar) 

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})  
[void] $objForm.ShowDialog() 

if ($dtmDate)
    {
        Write-Host "Date selected: $dtmDate"
    }

$objForm.Dispose()

<小时>

回应@The Unique Paul Smith


In Response to @The Unique Paul Smith

function Find-CalenderDateTest {
[CmdletBinding()]
param(
    [Parameter(
        Mandatory=$false
    )]
    [ValidateSet('long','short','powerpoint')]
    [ValidateNotNullOrEmpty()]
    [string]
    $DateFormat

)

Begin{
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") 

$objForm = New-Object Windows.Forms.Form 

$objForm.Text = "Select a Date" 
$objForm.Size = New-Object Drawing.Size @(243,250) 
$objForm.StartPosition = "CenterScreen"

$objForm.KeyPreview = $True

$dtmDate = $null

$objForm.Add_KeyDown( {
    if ($_.KeyCode -eq "Enter") 
        {
            $dtmDate=$objCalendar.SelectionStart
            $objForm.Close()
        }
    })


$objForm.Add_KeyDown({
    if ($_.KeyCode -eq "Escape") 
        {
            $objForm.Close()
        }
    })

#region   OK Button
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(20,175)
$OKButton.Size = New-Object System.Drawing.Size(75,23)
$OKButton.Text = "OK"

# Got rid of the Click event for OK Button, and instead just assigned its DialogResult property to OK.
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::OK

$objForm.Controls.Add($OKButton)

# Setting the form's AcceptButton property causes it to automatically intercept the Enter keystroke and
# treat it as clicking the OK button (without having to write your own KeyDown events).
$objForm.AcceptButton = $OKButton
#endregion 

#region Cancel Button
$CancelButton = New-Object System.Windows.Forms.Button
$CancelButton.Location = New-Object System.Drawing.Size(80,175)
$CancelButton.Size = New-Object System.Drawing.Size(75,23)
$CancelButton.Text = "Cancel"

# Got rid of the Click event for Cancel Button, and instead just assigned its DialogResult property to Cancel.
$CancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel

$objForm.Controls.Add($CancelButton)

# Setting the form's CancelButton property causes it to automatically intercept the Escape keystroke and
# treat it as clicking the OK button (without having to write your own KeyDown events).
$objForm.CancelButton = $CancelButton
#endregion 

$objCalendar = New-Object System.Windows.Forms.MonthCalendar 
$objCalendar.ShowTodayCircle = $False
$objCalendar.MaxSelectionCount = 1
$objForm.Controls.Add($objCalendar) 

$objForm.Topmost = $True

$objForm.Add_Shown({$objForm.Activate()})  

$Results = $objForm.ShowDialog()
}

Process{}

End{
if ($Results -eq "OK")
    {
    $objCalendar.SelectionStart
    }

$objForm.Dispose()

}
}

推荐答案

错误是 MTA/STA

The error is MTA/STA

不要使用

$form.showDialog()

使用

[system.windows.forms.application]::run($form)

代替

而且每次都很好

另一种方法是把它放在另一个线程中:

Another way is to put it in another thread:

$code
{
  //form code here
  $form.showDialog()
}
$newThread = [Powershell]::Create()
$newThread.AddScript($code)
$handle = $newThread.BeginInvoke() 

从调用脚本中提供变量:

Provide variables from the calling script:

$newThread.Runspace.SessionStateProxy.SetVariable("variablenname",value)

BeginInvoke 之前使用 variablenname 不带 $...

before the BeginInvoke use variablenname without $...

这篇关于使用 Windows 窗体在脚本终止后几分钟锁定 PowerShell ISE的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆