4

Hope some brave will help me !

I’m working from a few days now on a Powershell tool that display a dashboard on the screen corner to give some network “real-time” diagnostics of the computer. This dashboard can be minimized in the notification area.

First, I created a function that get the diagnostics and display the status on the form. I tried to refresh data with a timer (See: Real Time Data With Powershell GUI).

The problem was that my function took too much time to be executed and it froze the interface. So buttons on the form were no more usable… (See: Mouse event don't work after first timer Tick ).

Now, I try to use background jobs. My idea is to launch a job in a loop mode and get his status on a timer interval.

First, the Job couldn’t call a function declared in my main script (line 361). I know that I can use global and/or don’t use a function but write the code directly on the ScriptBlock but… even with this, I don’t know how to let the job turning in a loop and get his status by interval (line 368)…

You can see that I’m not really experimented in PowerShell and GUI… It’s been a while since I have developed and it was in another language…

Thank you in advance for your kind help

If you want to run it, I’ve uploaded the images folder here: https://omerta.is/2A1L

Here is my code below

 ####################################### FUNCTIONS   ########################################

#Get diagnostics status
function GetStatus
{

    #Create a return table
    [hashtable]$Return = @{}

    ###Test LAN adapter###
    $EthernetAdapter = (Get-WMIObject Win32_NetworkAdapter | Select Name, NetConnectionStatus | Where Name -like "*Gigabit*")

    If ($EthernetAdapter -ne $null)
    {
        If ($EthernetAdapter.NetConnectionStatus -eq 2)
            {$Return.LANOnStatus = $True}
        else
            {$Return.LANOnStatus = $False}
    }
    else
    {
        $Return.LANOnStatus = $False
    }



    ###Test Wi-Fi adapter###
    $WiFiAdapter = (Get-WMIObject Win32_NetworkAdapter | Select Name, NetConnectionStatus | Where Name -like "*Wireless*")

    If ($WiFiAdapter -ne $null)
    {
        If ($WiFiAdapter.NetConnectionStatus -eq 2)
            {$Return.WiFiOnStatus = $True}
        else
            {$Return.WiFiOnStatus = $False}
    }
    else
    {
        $Return.WiFiOnStatus = $False
    }



    ###Test Network (Default Gateway Reachable)###
    $DefaultGateway = (Get-WmiObject -Class Win32_IP4RouteTable | where { $_.destination -eq '0.0.0.0' -and $_.mask -eq '0.0.0.0'} | Sort-Object metric1 | select nexthop, metric1, interfaceindex).nexthop

    If ($DefaultGateway -ne $null)
    {
        If (Test-Connection -ComputerName $DefaultGateway -Count 1 -TTL 4 -Quiet)
            {$Return.NetworkStatus = $True}
        else
            {$Return.NetworkStatus = $False}
    }   
    else 
    {
        $Return.NetworkStatus = $False
    }          


    #Test Internet connection
    $GoogleWebSite = "www.google.com"

    Try
        {$Return.GoogleStatus = Test-Connection -ComputerName $GoogleWebSite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.GoogleStatus = $False}


    ###DontReplyToo###
    $DontReplyTooWebSite = "mdm.pictet.com"

    Try
        {$Return.DontReplyTooStatus = Test-Connection -ComputerName $DontReplyTooWebSite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.DontReplyTooStatus = $False}


    ###DONT REPLY###
    $DontReplyWebsite = "www.idontreply.com"

    Try
        {$Return.DontReplyStatus = Test-Connection -ComputerName $DontReplyWebsite -Count 1 -TTL 64 -Quiet}
    Catch
        {$Return.DontReplyStatus = $False}       


    #Return the table
    Return $Return

}


########################################### EVENTS ###########################################


#Manual Synchronization
function ManualSync
{
    Sync-Content

}


#Open Browser from dashboard
function Open-Browser
{
    &($BrowserExe)      
}


#Open a help message on click on help icon
function Open-Help($HelpText)
{

    [System.Windows.Forms.MessageBox]::Show($HelpText,"Hotlines",0,32)
}


#Close Dashboard form on click on minimize icon
function Minimize-Dashboard
{

    #Close Dashboard on click minimize
    $Form.WindowState = "Minimize"
    $Form.Visible = $False
    $objNotifyIcon.Visible = $True 

    #!!!!! TO CHECK !!!!!
    Wait-Event -Timeout 15 -SourceIdentifier NotifyIcon_Event
    Remove-Event -SourceIdentifier NotifyIcon_Event

}


#Open Dashboard form on double click on agent icon in notification area
function OpenDashboard
{

    #Open Dashboard on double-click
    $Form.Visible = $True
    $Form.WindowState = "Normal"

}

######################################### ASSEMBLIES #########################################


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


######################################### VAR & CONST ########################################

#Screen placement
$Screen = [system.windows.forms.screen]::PrimaryScreen
$FormPos = $Screen.Bounds.Width - 160

#Dashboard Timer
$Timer = New-Object 'System.Windows.Forms.Timer'
$Timer.Interval = 3000

#Home directory of the program
$HomeDir = Split-Path $script:MyInvocation.MyCommand.Path

#Dashboard Images
$Background = [system.drawing.image]::FromFile("$HomeDir\img\interface.png")
$GreenLight = [system.drawing.image]::FromFile("$HomeDir\img\greenlight.png")
$RedLight = [system.drawing.image]::FromFile("$HomeDir\img\redlight.png")
$SyncImg = [system.drawing.image]::FromFile("$HomeDir\img\sync.png")
$BrowserImg = [system.drawing.image]::FromFile("$HomeDir\img\browser.png")
$HelpImg = [system.drawing.image]::FromFile("$HomeDir\img\help.png")
$MinimizeImg = [system.drawing.image]::FromFile("$HomeDir\img\minimize.png")

#Agent Images
$IconStd = New-Object system.drawing.icon ("$HomeDir\img\icon.ico")
$IconFocus = New-Object system.drawing.icon ("$HomeDir\img\icon_focus.ico")

#Log files
$LogLastSync = ("$HomeDir\Logs\LastSync.log")
$LogSyncAgent = ("$HomeDir\Logs\SyncAgentError.log")

#Browser Module
$BrowserExe = "$HomeDir\bin\Browser.exe"

#Free File Sync Module
$SyncAgentExe = "$HomeDir\bin\SyncAgent.exe"
$SyncJob = "$HomeDir\bin\SyncSettings.xml"

#Strings
$HelpText = "Hotline: 432423432423423"


########################################### FORMS ###########################################


#Dashboard Windows Forms
$Form = New-Object System.Windows.Forms.Form
$Font = New-Object System.Drawing.Font("Arial Unicode MS",10,[System.Drawing.FontStyle]::Bold)
$Lb_LANOn = New-Object System.Windows.Forms.Label
$Lb_WiFiOn = New-Object System.Windows.Forms.Label
$Lb_Network = New-Object System.Windows.Forms.Label
$Lb_Google = New-Object System.Windows.Forms.Label
$Lb_DontReplyToo = New-Object System.Windows.Forms.Label
$Lb_DontReply = New-Object System.Windows.Forms.Label
$Pb_LANOn = New-Object System.Windows.Forms.PictureBox
$Pb_WiFiOn = New-Object System.Windows.Forms.PictureBox
$Pb_Network = New-Object System.Windows.Forms.PictureBox
$Pb_Google = New-Object System.Windows.Forms.PictureBox
$Pb_DontReplyToo = New-Object System.Windows.Forms.PictureBox
$Pb_DontReply = New-Object System.Windows.Forms.PictureBox
$Pb_Sync = New-Object System.Windows.Forms.PictureBox
$Pb_Browser = New-Object System.Windows.Forms.PictureBox
$Pb_Help = New-Object System.Windows.Forms.PictureBox
$Pb_Minimize = New-Object System.Windows.Forms.PictureBox

#Agent Windows Form
$objNotifyIcon = New-Object System.Windows.Forms.NotifyIcon
$objNotifyIcon.Add_Click({OpenDashboard})
Register-ObjectEvent $objNotifyIcon Click NotifyIcon_Event


#Dashboard Interface Generation
$Form.Size = '150, 220'
$Form.FormBorderStyle = 'None'
$Form.Name = "Form"
$Form.StartPosition = 'Manual'
$Form.Location = $FormPos.ToString()+', 10'
$Form.Text = "Dashboard"
$Form.Font = $Font
$Form.BackgroundImage = $Background
$Form.BackgroundImageLayout = "None"
$Form.TransparencyKey = "White"
$Form.BackColor = "White"
#$Form.Opacity = '.85'

$Form.Controls.Add($Lb_LANOn)
$Lb_LANOn.Location = '10, 30'
$Lb_LANOn.Size = '75, 20'
$Lb_LANOn.Text = "LAN On"
$Lb_LANOn.ForeColor = 'Gray'
$Lb_LANOn.BackColor = "Transparent"

$Form.Controls.Add($Lb_WiFiOn)
$Lb_WiFiOn.Location = '10, 55'
$Lb_WiFiOn.Size = '75, 20'
$Lb_WiFiOn.Text = "Wi-Fi On"
$Lb_WiFiOn.ForeColor = 'Gray'
$Lb_WiFiOn.BackColor = "Transparent"

$Form.Controls.Add($Lb_Network)
$Lb_Network.Location = '10, 80'
$Lb_Network.Size = '75, 20'
$Lb_Network.Text = "Network"
$Lb_Network.ForeColor = 'Gray'
$Lb_Network.BackColor = "Transparent"

$Form.Controls.Add($Lb_Google)
$Lb_Google.Location = '10, 105'
$Lb_Google.Size = '75, 20'
$Lb_Google.Text = "Google"
$Lb_Google.ForeColor = 'Gray'
$Lb_Google.BackColor = "Transparent"

$Form.Controls.Add($Lb_DontReplyToo)
$Lb_DontReplyToo.Location = '10, 130'
$Lb_DontReplyToo.Size = '75, 20'
$Lb_DontReplyToo.Text = "DontReplyToo"
$Lb_DontReplyToo.ForeColor = 'Gray'
$Lb_DontReplyToo.BackColor = "Transparent"

$Form.Controls.Add($Lb_DontReply)
$Lb_DontReply.Location = '10, 155'
$Lb_DontReply.Size = '75, 20'
$Lb_DontReply.Text = "Dont Reply"
$Lb_DontReply.ForeColor = 'Gray'
$Lb_DontReply.BackColor = "Transparent"

$Form.Controls.Add($Pb_LANOn)
$Pb_LANOn.Location = '115, 33'
$Pb_LANOn.Size = '15, 15'
$Pb_LANOn.Image = $RedLight
$Pb_LANOn.BackColor = "Transparent"

$Form.Controls.Add($Pb_WiFiOn)
$Pb_WiFiOn.Location = '115, 58'
$Pb_WiFiOn.Size = '15, 15'
$Pb_WiFiOn.Image = $RedLight
$Pb_WiFiOn.BackColor = "Transparent"

$Form.Controls.Add($Pb_Network)
$Pb_Network.Location = '115, 83'
$Pb_Network.Size = '15, 15'
$Pb_Network.Image = $RedLight
$Pb_Network.BackColor = "Transparent"

$Form.Controls.Add($Pb_Google)
$Pb_Google.Location = '115, 108'
$Pb_Google.Size = '15, 15'
$Pb_Google.Image = $RedLight
$Pb_Google.BackColor = "Transparent"

$Form.Controls.Add($Pb_DontReplyToo)
$Pb_DontReplyToo.Location = '115, 133'
$Pb_DontReplyToo.Size = '15, 15'
$Pb_DontReplyToo.Image = $RedLight
$Pb_DontReplyToo.BackColor = "Transparent"

$Form.Controls.Add($Pb_DontReply)
$Pb_DontReply.Location = '115, 158'
$Pb_DontReply.Size = '15, 15'
$Pb_DontReply.Image = $RedLight
$Pb_DontReply.BackColor = "Transparent"

#Toolbar

$Form.Controls.Add($Pb_Sync)
$Pb_Sync.Location = '20, 195'
$Pb_Sync.Size = '20, 20'
$Pb_Sync.Image = $SyncImg
$Pb_Sync.BackColor = "Transparent"
$Pb_Sync.Add_Click({Sync-Content})

$Form.Controls.Add($Pb_Browser)
$Pb_Browser.Location = '51, 195'
$Pb_Browser.Size = '20, 20'
$Pb_Browser.Image = $BrowserImg
$Pb_Browser.BackColor = "Transparent"
$Pb_Browser.Add_Click({Open-Browser})

$Form.Controls.Add($Pb_Help)
$Pb_Help.Location = '82, 195'
$Pb_Help.Size = '20, 20'
$Pb_Help.Image = $HelpImg
$Pb_Help.BackColor = "Transparent"
$Pb_Help.Add_Click({Open-Help($HelpText)})

$Form.Controls.Add($Pb_Minimize)
$Pb_Minimize.Location = '113, 195'
$Pb_Minimize.Size = '20, 20'
$Pb_Minimize.Image = $MinimizeImg
$Pb_Minimize.BackColor = "Transparent"
$Pb_Minimize.Add_Click({Minimize-Dashboard})

   ########## MAIN

#Status Init
#$Status = GetStatus 

#Create the Status Background Job 
Start-Job -Name "jobGetStatus" -ScriptBlock {$Status = GetStatus} #function not recognized by Background Job

#Wait for job result
While (Get-Job -Name "jobGetStatus" | where { $_.State -eq "Running" })
    {Start-Sleep 1}

#Get Status on Timer Tick
$Timer.Add_Tick({Get-Job -Name "jobGetStatus" | Receive-Job}) #job not updated

#Display new status on tick
$Timer.Add_Tick({
                        #LAN
                        If ($Status.LANOnStatus -eq $True)
                            {$Pb_LANOn.Image = $GreenLight}
                        else
                            {$Pb_LANOn.Image = $RedLight}

                        #WIFI
                        If ($Status.WiFiOnStatus -eq $True)
                            {$Pb_WiFiOn.Image = $GreenLight}
                        else
                            {$Pb_WiFiOn.Image = $RedLight}

                        #NETWORK
                        If ($Status.NetworkStatus -eq $True)
                            {$Pb_Network.Image = $GreenLight}
                        else
                            {$Pb_Network.Image = $RedLight}

                        #GOOGLE
                        If ($Status.GoogleStatus -eq $True)
                            {$Pb_Google.Image = $GreenLight}
                        else
                            {$Pb_Google.Image = $RedLight}

                        #DontReplyToo
                        If ($Status.DontReplyTooStatus -eq $True)
                            {$Pb_DontReplyToo.Image = $GreenLight}
                        else
                            {$Pb_DontReplyToo.Image = $RedLight}            

                        #BING
                        If ($Status.DontReplyStatus -eq $True)
                            {$Pb_DontReply.Image = $GreenLight}
                        else
                            {$Pb_DontReply.Image = $RedLight}         

})

#Start Timer
$Timer.Enabled = $True

#Agent Init
$objNotifyIcon.Icon = $IconStd
$objNotifyIcon.Text = "Dashboard"
$objNotifyIcon.Visible = $True 

#Show Interface
$Form.ShowDialog() 

  ############## END
Community
  • 1
  • 1
Nick32342
  • 93
  • 1
  • 7

1 Answers1

1

Nice little utility.

I removed all references to the Job, and added the code from the job into the Tick itself:

$Timer.Add_Tick({
   $Status = GetStatus
   #LAN
   If ($Status.LANOnStatus -eq $True)
      {$Pb_LANOn.Image = $GreenLight}
   else
      {$Pb_LANOn.Image = $RedLight}
   ...
})

Since you mentioned the function took too much time, I also increased the Tick interval from 3 to 10 seconds. This seems to work fine on my PC.

xXhRQ8sD2L7Z
  • 1,686
  • 1
  • 14
  • 16