0

So I have about wrapped up my holiday break personal project.

I have a form that refreshes on a set interval(which with this last problem solved will start creating a config file)

Before I added the on_tick function and on load function that allowed for the functionality I wanted, the program ran fine if not the results I wanted. When I mean ran fine I mean if I clicked close("X" button in top right) or wanted to move the window I could

After I added the fixes for refresh The Form window is now unresponsive or will take forever to register a "close" command

########################################################################
#Purpose to have a UI running at a 30 second intervel to update on 
#network and machine performance metrics 
########################################################################
function OnApplicationLoad {
    return $true 
}
function OnApplicationExit {
    $script:ExitCode = 0 
}
function Get-ComputerStats {
    process {

        $avg = Get-WmiObject win32_processor | 
                    Measure-Object -property LoadPercentage -Average | 
                    Foreach {$_.Average}
        $mem = Get-WmiObject win32_operatingsystem |
                    Foreach {"{0:N2}" -f ((($_.TotalVisibleMemorySize - $_.FreePhysicalMemory)*100)/ $_.TotalVisibleMemorySize)}
        $free = Get-WmiObject Win32_Volume -Filter "DriveLetter = 'C:'" |
                    Foreach {"{0:N2}" -f (($_.FreeSpace / $_.Capacity)*100)}
        [pscustomobject] [ordered] @{ 
            ComputerName = $env:computername
            AverageCpu = $avg
            MemoryUsage = $mem
            PercentFree = $free
        }
    }
}
function GenerateForm {
    [void][reflection.assembly]::Load("System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
    [void][reflection.assembly]::Load("System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
    [void][reflection.assembly]::Load("mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
    [void][reflection.assembly]::Load("System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")
    [System.Windows.Forms.Application]::EnableVisualStyles()
    $form = New-Object System.Windows.Forms.Form
    $button = New-Object System.Windows.Forms.Button
    $outputBox = New-Object System.Windows.Forms.RichTextBox
    $InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
    $timer = New-Object System.Windows.Forms.Timer
    $timer.Interval = 30000
    $form.ForeColor = "#25c420"
    $form.BackColor = "#000000"

    #tick function - code that actually gets the metrics all other code is for the silly gui
    Function Timer_Tick(){
            $date  = Get-Date -Format "HH:mm:ss"
            $form.Text = "Network and Health Monitor ($date)"
            $outputBox.ForeColor = "#25c420"
            $outputBox.BackColor = "#000000"
            $outputBox.Text += "`n"
            $pySpeedDir = "C:\Users\CentralTerminal\AppData\Local\Programs\Python\Python36\Scripts\pyspeedtest.exe"
            $speed = & $pySpeedDir
            $table = Get-ComputerStats | Select-Object ComputerName,AverageCpu,MemoryUsage,PercentFree | Out-String
            #$outputBox.Text += get-date
            $outputBox.Text += "$date`n"
            $outputBox.Text += "CPU and Memory Utilization`n"
            $outputBox.Text += $table
            $outputBox.Text += "`r`n"
            $outputBox.Text += "Network Test in Progress...`n"
            $outputBox.Text += $speed[0]+ "`n" + $speed[1] + "`n" + $speed[2] + "`n" + $speed[3]
            $outputBox.Text += "`r`n"
            $outputBox.Select()
            $outputBox.SelectionStart = $outputBox.Text.Length
            $outputBox.ScrollToCaret()
            $outputBox.Refresh()
    }

    Function Form_Load{
        #$form.Text = "Timer started"
        Timer_Tick
        $timer.Start()
    }


    $form_StateCorrection_Load={
        $form.WindowState = $InitialFormWindowState
    }


    $form.Controls.Add($outputBox)
    $form.Text = "Network and Machine Load"
    $form.Name = "GUM"
    $form.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation 
    $form.ClientSize = New-Object System.Drawing.Size(800,400)
    $form.BackgroundImageLayout = "None"
    $form.add_Load({Form_Load})
    $timer.Add_Tick({Timer_Tick})


    $outputBox.Name = "outputBox"
    $outputBox.Text = ""
    $outputBox.DataBindings.DefaultDataSourceUpdateMode = [System.Windows.Forms.DataSourceUpdateMode]::OnValidation 
    $outputBox.Location = New-Object System.Drawing.Point(5,35)
    $outputBox.Size = New-Object System.Drawing.Size(785,320) 
    $outputBox.font = "lucida console"
    $outputBox.TabIndex = 0

    $InitialFormWindowState = $form.WindowState
    $form.add_Load($form_StateCorrection_Load)
    return $form.ShowDialog()
} 

if(OnApplicationLoad -eq $true){
    GenerateForm | Out-Null
    OnApplicationExit
}

My problem is that I have no exceptions being thrown. I am going to add a try catch to this system as well but there are no error messages or anything that is technically breaking for me to start my investigation. If you also just know where to start debugging that would be helpful too as I am trying to get better at Production Support in general

Thanks for reading

Craig
  • 173
  • 4
  • 15
  • 1
    Probably the best around this is to create a separate worker/thread with either [Start-Job](https://learn.microsoft.com/powershell/module/microsoft.powershell.core/start-job?view=powershell-5.1) or a [RunSpace](https://stackoverflow.com/questions/7414187/powershell-job-event-action-with-form-not-executed/40808521#40808521) which has a `SessionStateProxy` to interchange your `Get-ComputerStats`. – iRon Nov 25 '17 at 19:08
  • hrm.. this seems like a good idea. I will try that and update with results. Thanks for the feedback – Craig Nov 25 '17 at 22:31

0 Answers0