I am fiddling with the timer object and message boxes and hit a brick wall.
I am trying to manage the timer object and popups through reusable functions.
I tested most of these functions on their own and in small parts first. Since everything worked, I decided to string everything together.
Together, it did not seem to work, so i broke down functionality to the basics:
# 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
I still cannot run the script as it keeps "hanging" during the Elapsed action ($Thirtyaction
). The last thing it shows in the PowerShell console is: action
and action2
. So I figured the problem lies within the box function, but:
- if I call the script with ISE, it will run as expected
- if I first execute the functionfile and then the file, it will again stop/hang at the (first/YesNo) msgBox
- if I manually enter the msgBox function into the console and then start the file, it will show msgBoxes, but does not execute the code in the
else
statement correctly (stops after the (second/OKonly)msgBox has been shown)
I can't think of any way this makes sense and I've spent a lot of time trying to debug/switch it up/dumb it down etc.
edit1: A fresh day and a bit of more Information.
I changed the function to windows.Forms but had no luck. I then proceded to print out thread IDs for all functions and parts of the script and voila:
Main script
6
1176
myfunc
6
1176
Elapsedaction ($Thirtyaction)
11
4236
The $action
that triggers when the Timerevent fires, is run in a new PowerShell Runspace and therefore has no more acces to Variables and functions that have been defined before.
I'm not sure how to fix this or work around it, but at least i know what's the problem. Any Ideas are welcome and thanks to the ppl that already answered and gave me a hint in the right direction!
Edit2 with solution and workaround:
thanks to another user if found an answer to the question of how to controll the timer attributes from within the $Thirtyaction
scriptblock:
I can use the MsgBox function by simply dotsourcing the functionfile in the scriptblock
my workaround for variables was to use three environement variables. I'm pretty sure this is neither smart nor best practice, but shouldn't be an issue in my special case and it works.
as an example here is my current $Thirtyaction
scriptblock:
$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"
}
}