1

タイマー オブジェクトとメッセージ ボックスをいじっていて、レンガの壁にぶつかりました。

再利用可能な関数を使用してタイマー オブジェクトとポップアップを管理しようとしています。

私はこれらの機能のほとんどを単独で、そして小さな部分で最初にテストしました。すべてが機能したので、すべてをつなぎ合わせることにしました。

一緒に、それはうまくいかないようだったので、機能を基本に分解しました:

# functionfile
function Show-MsgBox {
  Write.Host "debugFUNC2"
  #usage:
  #Show-MsgBox -Prompt "This is the prompt" -Title "This Is The Title" -Icon Critical -BoxType YesNo -DefaultButton 1

  [CmdletBinding()]
  param(
    [Parameter(Position=0, Mandatory=$true)] [string]$Prompt,
    [Parameter(Position=1, Mandatory=$false)] [string]$Title ="",
    [Parameter(Position=2, Mandatory=$false)] [string]$Icon ="Information",
    [Parameter(Position=3, Mandatory=$false)] [string]$BoxType ="OkOnly",
    [Parameter(Position=4, Mandatory=$false)] [int]$DefaultButton = 1
  )
  [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic")
  switch ($Icon) {
    "Question" {$vb_icon = [microsoft.visualbasic.msgboxstyle]::Question }
    "Critical" {$vb_icon = [microsoft.visualbasic.msgboxstyle]::Critical}
    "Exclamation" {$vb_icon = [microsoft.visualbasic.msgboxstyle]::Exclamation}
    "Information" {$vb_icon = [microsoft.visualbasic.msgboxstyle]::Information}
  }
  switch ($BoxType) {
    "OKOnly" {$vb_box = [microsoft.visualbasic.msgboxstyle]::OKOnly}
    "OKCancel" {$vb_box = [microsoft.visualbasic.msgboxstyle]::OkCancel}
    "AbortRetryIgnore" {$vb_box = [microsoft.visualbasic.msgboxstyle]::AbortRetryIgnore}
    "YesNoCancel" {$vb_box = [microsoft.visualbasic.msgboxstyle]::YesNoCancel}
    "YesNo" {$vb_box = [microsoft.visualbasic.msgboxstyle]::YesNo}
    "RetryCancel" {$vb_box = [microsoft.visualbasic.msgboxstyle]::RetryCancel}
  }
  switch ($Defaultbutton) {
    1 {$vb_defaultbutton = [microsoft.visualbasic.msgboxstyle]::DefaultButton1}
    2 {$vb_defaultbutton = [microsoft.visualbasic.msgboxstyle]::DefaultButton2}
    3 {$vb_defaultbutton = [microsoft.visualbasic.msgboxstyle]::DefaultButton3}
  }
  $popuptype = $vb_icon -bor $vb_box -bor $vb_defaultbutton 
  $ans = [Microsoft.VisualBasic.Interaction]::MsgBox($prompt,$popuptype,$title)
  return $ans
} #end function

function mafunc {
  Write-Host "debugFUNC1"
  $timer.start()
  $timer
  return 0
}

# calling file

$timer = New-Object System.Timers.Timer
#$timer.interval = 1800000
$timer.interval = 30000
$timer.Enabled = $true
$timer.AutoReset = $False
$scriptsleep = 0
$timer.stop()

$ThirtyAction = {
  Write-Host "action"
  Write-Host "action2"
  if ((Show-MsgBox -Prompt "prompt" -Title "title" -Icon Critical -BoxType YesNo -DefaultButton 1) -eq "No") {
    Write-Host "debugNO"
  } else {
    Write-Host "debugYES"
    $timer
    $timer.stop()
    Show-MsgBox -Prompt "prompt" -Title "title" # standard promt = OKonly button
    $timer.interval=30000
    $timer.start()
    $timer
    Write-Host "timer start"
  }
}

Register-ObjectEvent -InputObject $timer -EventName Elapsed -SourceIdentifier ThirtySecTimer -Action $ThirtyAction

myfunc

経過アクション中に「ハング」し続けるため、スクリプトを実行できません ( $Thirtyaction)。PowerShell コンソールに最後に表示されるのは、actionaction2です。したがって、問題はボックス関数内にあると考えましたが、次のとおりです。

  • ISE でスクリプトを呼び出すと、期待どおりに実行されます
  • 最初に functionfile を実行してからファイルを実行すると、(first/YesNo) msg​​Box で再び停止/ハングします。
  • コンソールに msgBox 関数を手動で入力してからファイルを開始すると、msgBoxes が表示されますが、elseステートメント内のコードが正しく実行されません ((2 回目/OK のみ)msgBox が表示された後に停止します)。

これが理にかなっている方法は考えられず、デバッグ/スイッチアップ/ダムダウンなどに多くの時間を費やしました.

edit1: 新鮮な日ともう少し情報。

関数を windows.Forms に変更しましたが、うまくいきませんでした。次に、すべての関数とスクリプトの一部のスレッド ID を出力し、ほら:

Main script
6
1176

myfunc
6
1176

Elapsedaction ($Thirtyaction)
11
4236

Timerevent$actionが発生したときにトリガーされる は、新しい PowerShell 実行空間で実行されるため、以前に定義された変数や関数にアクセスできなくなります。

これを修正する方法や回避する方法はわかりませんが、少なくとも何が問題なのかはわかっています。どんなアイデアでも大歓迎です。すでに答えてくれて、正しい方向へのヒントをくれた ppl に感謝します!

解決策と回避策を含むEdit2

$Thirtyactionスクリプトブロック内からタイマー属性を制御する方法の質問に対する回答が見つかった場合は、別のユーザーに感謝します。

リンク

スクリプトブロックで関数ファイルをドットソーシングするだけで、MsgBox 関数を使用できます。

変数に対する私の回避策は、3 つの環境変数を使用することでした。これは賢明でもベストプラクティスでもないと確信していますが、私の特別なケースでは問題にならず、うまくいきます。

例として、ここに私の現在の$Thirtyactionスクリプトブロックがあります:

 $ThirtyAction={
    . .\testfunction.ps1
    $Sender.stop()
    Write-Host "action"
    Write-Host "action2"
    if ((($ans=(Show-new-MsgBox -Prompt "Prompt" -Title "Title" -Icon "Warning" -BoxType "YesNo")) -eq "No") -or !($Env:Sessionsleepstate -eq 0)) {
        Write-Host $Env:Sessionsleepstate
        $Env:Sessionsleepstate = 3
        if ($Env:Sessionsleepstate -eq 1) {
            Show-new-MsgBox -Prompt "Prompt" -Title "Title"
        }
        Show-new-MsgBox -Prompt "Prompt" -Title "Title"
        Write-Host "killfunction placeholder"
    }
    else{
    $Sender.stop()
    Show-new-MsgBox -Prompt "Prompt" -Title "Title"
    $Sender.interval=300000
    $Env:Sessionsleepstate = 1
    $Sender.start()
    Write-Host "timer start"
    }
    }
4

1 に答える 1