Подтвердить что ты не робот

Использование Windows Forms Заблокирует сеанс PowerShell ISE через несколько минут после завершения script

У меня здесь интересная проблема. Я создаю календарь для использования, когда мы создаем учетные записи. Он отлично работает и все еще продолжается, но я заметил, что когда я запускаю script в PowerShell ISE, через несколько минут он блокируется (я могу редактировать и сохранять код за несколько минут до этого). В журнале событий ничего нет. Я получаю диалоговое окно, в котором говорится, что powershell не реагирует. Использование памяти также кажется нормальным. Я не знаю, что происходит.

Это происходит независимо от того, как я запускаю PowerShell ISE (Запуск от имени администратора, Запуск от имени другой учетной записи и обычный ISE). Я запускаю Windows 8.1.

Сотрудник предположил, что это модель квартиры, поэтому я пробовал STA и MTA, но проблема возникает в любом случае. Это не происходит, когда один и тот же код запускается с хоста консоли.

[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

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 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 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()

}
}
4b9b3361

Ответ 1

Я использовал combobox.items.add:

$configCombo.Items.Add($wks)

и я посмотрел, как сохранить ключи от печати на консоли - и изменил добавление на:

[void]$configCombo.Items.Add($wks)

С тех пор я добавил пустоту - я запускал ее в ISE, и она не видела с тех пор.

Ответ 2

Ошибка MTA/STA

Не используйте

$form.showDialog()

Используйте

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

вместо

и он отлично работает каждый раз

Другой способ - поместить его в другой поток:

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

Предоставить переменные из вызывающего script:

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

до BeginInvoke используйте variablenname без $...

Ответ 3

Это длинный снимок, но проблема может заключаться в том, что powershell не закрывает объект $objForm правильно, оставив его в памяти, в то время как ISE ждет ввода после завершения script. Если вы проверяете свой диспетчер задач, остается ли форма в фоновом режиме? Вы также можете попробовать добавить "Remove-Variable objForm" (нет $) после dispose() и посмотреть, помогает ли это.

Дополнительная информация: https://technet.microsoft.com/en-us/library/ff730962.aspx

Как я уже сказал, это длинный выстрел.

Ответ 4

Иди в эту проблему. Обычно это происходит, когда я блокирую рабочую станцию ​​и возвращаюсь. После того, как я купил и googleing, я нашел это https://support.microsoft.com/en-us/help/943139/windows-forms-application-freezes-when-system-settings-are-changed-or, что похоже на проблему.

Вопрос

Приложение не будет отвечать, и поток пользовательского интерфейса будет зависать в Вызов вызова при обработке уведомления OnUserPreferenceChanged

Причина

Это происходит, если элемент управления создается на потоке, который не работает сообщения и поток пользовательского интерфейса получает сообщение WM_SETTINGCHANGE.

Разрешение

Приложения никогда не должны оставлять объекты управления в потоках без насос активных сообщений. Если элементы управления не могут быть созданы в основном пользовательском интерфейсе потоки, они должны быть созданы на выделенном вторичном потоке пользовательского интерфейса и Убираются, как только они больше не нужны.