简体   繁体   中英

Powershell balloonTip: singleton variable and code block with Start-Job?

I have a need to use Balloon Tips in two different ways. 1: In my main code as a warning that a configuration issue is not addressed properly. 2: In a separate job process that monitors an environment variable for a message to display. The reason being the vagaries of how Autodesk Revit processes it's Journal files. Anyway...

Given that I am doing the exact same thing in two places, it makes sense to have a function, and given that I need to pass the function to the Job it makes sense to use a code block. However, I also want each new message to replace the last, not wait for a fade. So I need to use $balloonTip.Dispose . However, this only works when there is only one Global $balloonTip, basically a Singleton. But it needs to be mutable, so neither $balloonTip as a constant nor a Closure for the code block makes sense to me. In this example I just reference the variable from the parent scope, but I wonder if there is a better approach. Especially with regards to a Job. Or does a job by definition create a totally different scope with no chance of shared variables, and I should just implement this same scenario, but within the job. Functionally that will work as a balloonTip driven by the job will never show up if the error bt is shown. Indeed the job never gets created. But that's specific to this implementation, and I imagine a situation where I might want to truly have a single $balloonTip, potential even driven by two different Jobs.

Add-Type -assemblyName:System.Windows.Forms
$balloonTip = New-Object System.Windows.Forms.NotifyIcon


    $messageArguments = @{
        icon = [System.Drawing.Icon]::ExtractAssociatedIcon($(Get-Process -id:$pid | Select-Object -expandProperty:Path))
        btIcon = 'Info'
        btTitle = 'Test'
        btText = "$env:userName $(Get-Date)"
    }


    $sendMessage = {
        param (
            [System.Drawing.Icon]$icon,
            [String]$btIcon,
            [String]$btTitle,
            [String]$btText
        )

        $balloonTip.Dispose

        $balloonTip.Icon = $icon
        $balloonTip.balloonTipIcon = $btIcon
        $balloonTip.balloonTipTitle = $btTitle
        $balloonTip.balloonTipText = $btText

        $balloonTip.visible = $true 
        $balloonTip.showBalloonTip(0)
    }

    $a=0
    do {
        & $sendMessage @messageArguments
        Start-Sleep -s:3
    } While (++$a -le 5)

And to not only answer PetSerAl's question, but expand on my own, I have this bit of code that I would have thought would work, with the $balloonTip variable in the job scope. But it seems not to work. And the issue is probably in the passed code block, so i have revised the title to reflect the expanded question.

$sendMessage = {
    param (
        [System.Drawing.Icon]$icon,
        [String]$btIcon,
        [String]$btTitle,
        [String]$btText
    )

    $balloonTip.Icon = $icon
    $balloonTip.balloonTipIcon = $btIcon
    $balloonTip.balloonTipTitle = $btTitle
    $balloonTip.balloonTipText = $btText

    $balloonTip.visible = $true 
    $balloonTip.showBalloonTip(0)
}


function Start-MessageJob {
    [CmdletBinding()]   
    param (  
        [Int]$id,
        [ScriptBlock]$sendMessage
    )

    Start-Job -name:Messages -argumentList:@($id, $sendMessage) -scriptBlock {
        param (  
            [Int]$id,
            [ScriptBlock]$sendMessage
        )

        Add-Type -assemblyName:System.Windows.Forms  

        if ($balloonTip) {
            $balloonTip.Dispose
        } else {
            $balloonTip = New-Object System.Windows.Forms.NotifyIcon
        }

        $messageArguments = @{
            icon = [System.Drawing.Icon]::ExtractAssociatedIcon($(Get-Process -id:$id | Select-Object -expandProperty:Path))
            btIcon = 'Info'
            btTitle = 'Test'
            btText = $null
        }


        do {
            $messageArguments.btText = "$env:userName $(Get-Date)"
            & $sendMessage @messageArguments
            Start-Sleep -s:5

        } while (Get-Process -id:$id -errorAction:silentlyContinue)
    } > $null
}


Start-MessageJob -id:$pid -sendMessage:$sendMessage

I write this code to display popUp

function Show-BalloonTip {
    [CmdletBinding(SupportsShouldProcess = $true)]
    param
    (
        [Parameter(Mandatory=$true)]
            $Title,
        [Parameter(Mandatory=$true)]
            $Text,
        [ValidateSet('None', 'Info', 'Warning', 'Error')]
            $Icon = 'Info',
            $Timeout = 10000
    )
    remove-Job -Name BalloonTip -State Completed -ea 0
    Start-Job -name BalloonTip -ScriptBlock {
    param ($Title, $Text, $Icon, $Timeout)
        Add-Type -AssemblyName System.Windows.Forms

        $balloon = New-Object System.Windows.Forms.NotifyIcon

        switch($icon){
            Warning {
                $balloon.Icon = [System.Drawing.SystemIcons]::Warning
                Write-Host "$([char]7)" # beep sound
            }
            Error {
                $balloon.Icon = [System.Drawing.SystemIcons]::Error
                Write-Host "$([char]7)" # beep sound
            }
            default {
                #Define the icon for the system tray
                $balloon.Icon = [System.Drawing.SystemIcons]::Information
            }
        }
        #Type of balloon icon
        $balloon.BalloonTipIcon = $Icon

        #Display title of balloon window
        $balloon.BalloonTipTitle = $Title
        #Notification message
        $balloon.BalloonTipText = $Text
        #Make balloon tip visible when called
        $balloon.Visible = $True
        #Call the balloon notification
        $balloon.ShowBalloonTip($Timeout)
        Start-Sleep -Milliseconds $Timeout
        $balloon.Dispose()
    } -ArgumentList @($Title, $Text, $Icon, $Timeout)
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM