Powershell GUI Issues - powershell

I know the code I have isn't quite correct in terms of the loop, at the ,moment, once I click the start button, thew window freezes and the form/buttons do not respond to any input, which I know is due to the infinite do while loop. This is my first Powershell GUI script and I have tried to find answers but so far unsuccessful.
I want the code to keep running in the form but allow the form to be movable and the stop button t close the GUI/script.
Here is an example of the code:
Set-ExecutionPolicy unrestricted
Add-Type -assembly System.Windows.Forms
#Form + Properties
$main_form = New-Object System.Windows.Forms.Form
$main_form.TopMost = $True
$main_form.Text ='Techs'
$main_form.Width = 300
$main_form.Height = 450
$main_form.AutoSize = $true
#Textbox1 + Properties
$TextBox1 = New-Object system.Windows.Forms.TextBox
$TextBox1.BackColor = "Black"
$TextBox1.multiline = $true
$TextBox1.width = 295
$TextBox1.height = 195
$TextBox1.location = New-Object System.Drawing.Point(05,30)
$TextBox1.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($Textbox1)
#Textbox2 + Properties
$TextBox2 = New-Object system.Windows.Forms.TextBox
$TextBox2.BackColor = "Black"
$TextBox2.multiline = $true
$TextBox2.width = 295
$TextBox2.height = 195
$TextBox2.location = New-Object System.Drawing.Point(05,225)
$TextBox2.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($Textbox2)
#Start Button + Properties
$buttonStart = New-Object system.Windows.Forms.Button
$buttonStart.text = "Start"
$buttonStart.Size = '80,20'
$buttonStart.location = '05, 05'
$buttonStart.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($buttonStart)
#Stop Button + Properties
$buttonStop = New-Object system.Windows.Forms.Button
$buttonStop.text = "Stop"
$buttonStop.Size = '80,20'
$buttonStop.location = '90, 05'
$buttonStop.Font = 'Microsoft Sans Serif,10'
$main_form.Controls.Add($buttonStop)
cls
$x=1
$TechArray = "1","2","3","4","5","6","7","8","9","10"
$url = "https://website/api/v3/techs/"
$tech_key = #{ 'authtoken' = '12345678-12AB-12AB-1111-1111'}
$buttonStart.Add_Click({
Do {
$TextBox1.Text=""
$TextBox2.Text=""
foreach ($Tech in $TechArray) {
$response = Invoke-RestMethod -Uri $url$Tech -Method get -Headers $tech_Key
if ($response.tech.is_online -eq "1")
{
$TextBox1.ForeColor = "Green"
$TextBox1.AppendText("`n`n Online - " + $response.tech.login_name + "`n`n")
}
else
{
$TextBox2.ForeColor = "Red"
$TextBox2.AppendText("`n`n Offline - " + $response.tech.login_name + "`n`n")
}
}
Start-Sleep -Seconds 5
}
while ($x -ne 0)
})
$main_form.ShowDialog()

You need to separate the fetching of the web call from your UI thread.
This means you need to create a separate thread to execute this as a background task.
In Powershell (Core) 7+ there is this cmdLet: Start-ThreadJob, but there is also a port of this in Powershell 5.1, which you can download from:
https://www.powershellgallery.com/packages/ThreadJob/2.0.3
As a sample proof of concept instead of this, which blocks the UI thread:
$buttonStart.Add_Click({
Write-Host "Hi"
Start-Sleep -Seconds 5
}
Try this one and you'll see that the window does not freeze anymore:
$buttonStart.Add_Click({
Start-ThreadJob -StreamingHost $Host -ScriptBlock {
Write-Host "Hi"
Start-Sleep -Seconds 5
}
})

Related

How can I uninstall Hotfix remotely with Powershell

This what I have so far it brings up a Syntax screen for wusa. I have confirmed that the Trim is working. If I leave out the remote computer name is works on the local computer. I will be adding this to a much larger script just trying to get this working before trying to add it.
<#
.NAME
Template
#>
$comp = "Remote Pc Name Goes Here"
$str = $Hotfix_TextBox.Text. Trim("K","B")
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = New-Object System.Drawing.Point(400,400)
$Form.text = "Form"
$Form.TopMost = $false
$gethotfix = New-Object system.Windows.Forms.Button
$gethotfix.text = "Get Hotfixes"
$gethotfix.width = 120
$gethotfix.height = 30
$gethotfix.location = New-Object System.Drawing.Point(100,81)
$gethotfix.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$removehotfix = New-Object system.Windows.Forms.Button
$removehotfix.text = "Remove Hotfix"
$removehotfix.width = 120
$removehotfix.height = 30
$removehotfix.location = New-Object System.Drawing.Point(100,120)
$removehotfix.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
$Hotfix_TextBox = New-Object system.Windows.Forms.TextBox
$Hotfix_TextBox.Text = ""
$Hotfix_TextBox.multiline = $false
$Hotfix_TextBox.width = 174
$Hotfix_TextBox.height = 20
$Hotfix_TextBox.location = New-Object System.Drawing.Point(12,235)
$Hotfix_TextBox.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
<#
$Trimmed_TextBox = New-Object system.Windows.Forms.TextBox
#$Trimmed_TextBox.Text = "$str"
$Trimmed_TextBox.multiline = $false
$Trimmed_TextBox.width = 174
$Trimmed_TextBox.height = 20
$Trimmed_TextBox.location = New-Object System.Drawing.Point(12,265)
$Trimmed_TextBox.Font = New-Object System.Drawing.Font('Microsoft Sans Serif',10)
#>
$Form.controls.AddRange(#($gethotfix,$removehotfix,$Hotfix_TextBox))
$gethotfix.Add_Click({ GetHotfix })
$removehotfix.Add_Click({ RemoveHotfix })
#region Logic
function GetHotfix {$Hotfix_TextBox.Text = Get-Hotfix -Computername $comp |
Select-Object -ExpandProperty 'HotFixID'|
Out-GridView -Title 'Installed Hotfixes' -PassThru }
#$Hotfix_TextBox.Text. Trim("K","B")
#$Hotfix_TextBox.Text = "$str"
function RemoveHotfix{
#$Trimmed_TextBox.Text = "$str"
$comp = "dus-xtdfed9r386"
#Uninstall-HotFix -ComputerName $comp
wusa -computername /$comp | /uninstall | /kb:$str
}
#endregion
[void]$Form.ShowDialog()
This turned out to be a fiasco. Even when I could get it to work there are many KBs that cannot be removed, as well as we had policies that would not allow us to remove many others. Just not worth the effort. Perhaps someone with less strengent policies in place can do something with this. Have Fun.

powershell progressbar in groupbox GUI

I'm working on a script but for some reason my ProgressBar won't appear in my groupbox.
I tried a lot of different things (like making the groupbox trensparent) but nothing really work.
Here is my code 'simplified' with just the problematic parts.
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
$Form = New-Object System.Windows.Forms.Form
$Form.ClientSize = ‘345,160’
$Form.Text = " bug progressbar "
$Form.StartPosition = "CenterScreen"
#Functions
Function BDDchoice(){
$BDD = $args[0]
$Label2.Text = "it takes a few seconds"
$ProgressBarcheck = New-Object System.Windows.Forms.ProgressBar
$ProgressBarcheck.Location = New-Object System.Drawing.Point(230,49)
$ProgressBarcheck.Size = New-Object System.Drawing.Size(98, 23)
$ProgressBarcheck.Style = "Marquee"
$ProgressBarcheck.MarqueeAnimationSpeed = 20
$ButtonNEXT1.Hide()
$Form.Controls.Add($ProgressBarcheck);
$job1 ={
sleep 10
$bdd_min = $args[0]
echo $bdd_min
}
Start-Job -ScriptBlock $job1 -ArgumentList $BDD -Name bdd
do { [System.Windows.Forms.Application]::DoEvents() } until ((Get-Job -Name bdd).State -eq "Completed")
Wait-Job -Name bdd
$resultat = Receive-Job -Name bdd -Keep
Get-Job | Remove-Job -Force
$TextBoxBDD.text = $resultat
$ProgressBarcheck.Hide()
$ButtonNEXT1.Visible = $true
$Label2.Text = "BDD:"
}
#variables
$BDDXS = #('SCHEM1','SCHEM2','SCHEM3','SCHEM4')
$BDD1 = 'BDD1'
$BDD2 = 'BDD2'
$BDD3 = 'BDD3'
$BDD4 = 'BDD4'
$BDD = $null
#groupbox
$GroupBoxCREATE = New-Object System.Windows.Forms.GroupBox
$GroupBoxCREATE.Location = New-Object System.Drawing.Point(10,5)
$GroupBoxCREATE.Width = 325
$GroupBoxCREATE.Height = 150
$GroupBoxCREATE.Text = " Create "
#combobox ZONE
$comboBoxTRIG = New-Object System.Windows.Forms.ComboBox
$comboBoxTRIG.Location = New-Object System.Drawing.Point(25, 50)
$comboBoxTRIG.Size = New-Object System.Drawing.Size(200, 200)
foreach($BDDX in $BDDXS)
{
$comboBoxTRIG.Items.add($BDDX)
}
$comboBoxTRIG.Text = "REGION"
$comboBoxTRIG.AutoCompleteMode = "SuggestAppend"
$comboBoxTRIG.AutoCompleteSource = "ListItems"
$comboBoxTRIG.SelectedIndex ="0"
#butons
$ButtonNEXT1 = New-Object System.Windows.Forms.Button
$ButtonNEXT1.Location = New-Object System.Drawing.Point(230,49)
$ButtonNEXT1.Size = New-Object System.Drawing.Size(98, 23)
$ButtonNEXT1.Text = "OK"
$ButtonNEXT1.add_Click({
$zone = $comboBoxTRIG.SelectedItem.ToString()
if ($zone -like "SCHEM1"){
$BDD = $BDD1
}
if ($zone -like "SCHEM2") {
$BDD = $BDD2
}
if ($zone -like "SCHEM3") {
$BDD = $BDD3
}
if ($zone -like "SCHEM4") {
$BDD = $BDD4
}
BDDchoice($BDD)
})
#labels
$Label1 = New-Object System.Windows.Forms.Label
$Label1.Location = New-Object System.Drawing.Point(25,25)
$Label1.Text = "REGION :"
$Label2 = New-Object System.Windows.Forms.Label
$Label2.Location = New-Object System.Drawing.Point(25,80)
$label2.Width = 200
$Label2.Text = "BDD :"
#textbox
$TextBoxBDD = New-Object System.Windows.Forms.TextBox
$TextBoxBDD.Location = New-Object System.Drawing.Point(25,100)
$TextBoxBDD.Width = 200
$TextBoxBDD.ReadOnly = $true
$TextBoxBDD.Text = ""
$TextboxBDD.BackColor = "white"
#list form's butons/lists/combobox
$Form.Controls.AddRange(#($TextBoxBDD))
$Form.controls.AddRange(#($Label1,$Label2))
$Form.controls.AddRange(#($ButtonNEXT1))
$Form.controls.AddRange(#($comboBoxTRIG))
$Form.controls.AddRange(#($GroupBoxCREATE))
$Form.ShowDialog()
i'm interested in any idea.
My coworkers could not find anything but I must admit we are far from expert (i'm still learning and so are they).
$Form.Controls.Add($ProgressBarcheck);
It looks like you're adding Progress Bar to your form, NOT the groupbox. Add progress bar to groupbox then add groupbox to form.
$GroupBoxCREATE.Controls.Add($ProgressBarcheck);
$Form.Controls.Add($GroupBoxCREATE);

Issue to create a dynamic Powershell Form, showing output data from the running the script

I have a question about a Powershell Form script that I can't quite get to work yet.
The code below does give the output I expect, but I can't manage to display the Form as it was during the initialization of 'establishing the connection'. The point is that we only want to start a program when there is connectivity with the router and the end user should also be able to see it that way, not just the end result.
Can anyone point me in the right direction to make the form dynamically show what's happening at the time when the script is running?
Ow, and also the 'Retry' ([System.Windows.Forms.DialogResult]::Retry)function does not do anything as expected... :(
#---------------------------------------------------------[Initialisations]--------------------------------------------------------
# Init PowerShell Gui
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#---------------------------------------------------------[Form]--------------------------------------------------------
[System.Windows.Forms.Application]::EnableVisualStyles()
$LocalRCForm = New-Object system.Windows.Forms.Form
$LocalRCForm.ClientSize = '480,300'
$LocalRCForm.text = "Status router connection"
$LocalRCForm.BackColor = "#F9F9F9"
$LocalRCForm.StartPosition = "CenterScreen"
$LocalRCForm.TopMost = $true
$LocalRCForm.SuspendLayout()
$Titel = New-Object system.Windows.Forms.Label
$Titel.text = "Status router connection"
$Titel.AutoSize = $true
$Titel.width = 25
$Titel.height = 10
$Titel.location = New-Object System.Drawing.Point(20,20)
$Titel.Font = 'Microsoft Sans Serif,14,style=Bold'
$Description = New-Object system.Windows.Forms.Label
$Description.text = "To start Security Desk, wait for an established connection"
$Description.AutoSize = $false
$Description.width = 450
$Description.height = 50
$Description.location = New-Object System.Drawing.Point(20,60)
$Description.Font = 'Microsoft Sans Serif,10'
$RCStatus = New-Object system.Windows.Forms.Label
$RCStatus.text = "Status:"
$RCStatus.AutoSize = $true
$RCStatus.width = 25
$RCStatus.height = 10
$RCStatus.location = New-Object System.Drawing.Point(20,115)
$RCStatus.Font = 'Microsoft Sans Serif,10,style=Bold'
$RCFound = New-Object system.Windows.Forms.Label
$RCFound.text = "Connecting to router..."
$RCFound.AutoSize = $true
$RCFound.width = 25
$RCFound.height = 10
$RCFound.location = New-Object System.Drawing.Point(100,115)
$RCFound.Font = 'Microsoft Sans Serif,10'
$RCDetails = New-Object system.Windows.Forms.Label
$RCDetails.text = "Router succesfully connected"
$RCDetails.AutoSize = $true
$RCDetails.width = 25
$RCDetails.height = 10
$RCDetails.location = New-Object System.Drawing.Point(20,150)
$RCDetails.Font = 'Microsoft Sans Serif,10,style=Bold'
$RCTestConnection = New-Object system.Windows.Forms.Label
$RCTestConnection.text = "Checking connection"
$RCTestConnection.AutoSize =
$RCTestConnection.width = 25
$RCTestConnection.height = 10
$RCTestConnection.location = New-Object System.Drawing.Point(100,115)
$RCTestConnection.Font = 'Microsoft Sans Serif,10'
$AddRCBtn = New-Object system.Windows.Forms.Button
$AddRCBtn.BackColor = "#ff7b00"
$AddRCBtn.text = "Ok"
$AddRCBtn.width = 150
$AddRCBtn.height = 30
$AddRCBtn.location = New-Object System.Drawing.Point(300,250)
$AddRCBtn.Font = 'Microsoft Sans Serif,10'
$AddRCBtn.ForeColor = "#000"
$AddRCBtn.DialogResult = [System.Windows.Forms.DialogResult]::Yes
$CloseBtn = New-Object system.Windows.Forms.Button
$CloseBtn.BackColor = "#ffffff"
$CloseBtn.text = "Close"
$CloseBtn.width = 90
$CloseBtn.height = 30
$CloseBtn.location = New-Object System.Drawing.Point(300,250)
$CloseBtn.Font = 'Microsoft Sans Serif,10'
$CloseBtn.ForeColor = "#000"
$CloseBtn.DialogResult = [System.Windows.Forms.DialogResult]::Retry
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$testConnection))
#-----------------------------------------------------------[Functions]------------------------------------------------------------
function AddRC {
$RCFound.ForeColor = "#000000"
$RCFound.Text = 'Connected to Router'
}
#---------------------------------------------------------[Script]--------------------------------------------------------
# Check if router is online
$routerIp = '1.1.1.1'
$testConnection = Test-Connection $routerIp
If ($testConnection) {
$RCFound.text = "Router Ready"
$RCFound.ForeColor = "#7ed321"
$AddRCBtn.text = "Run the program"
$CloseBtn.Visible = $false
$RCDetails.Visible = $true
}else{
$RCFound.text = "Router not found"
$RCFound.ForeColor = "#D0021B"
$CloseBtn.text = "Close"
$AddRCBtn.Visible = $false
$RCDetails.Visible = $false
}
$AddRCBtn.Add_Click({ AddRC })
$LocalRCForm.Add_Shown({$testConnection.Enabled = $true; $testConnection.Start()})
return $LocalRCForm.ShowDialog()
There is too much to say about your script so let's focus on your main issue:
Your script will only show the form once the connection is tested, so the form will never display the various steps.
To achieve your goal, you should put your main code in a function and run it once the form is displayed.
function funTestConnection {
$testConnection = Test-Connection $routerIp
If($testConnection) {
$RCFound.text = "Router Ready"
$RCFound.ForeColor = "#7ed321"
$AddRCBtn.text = "Run the program"
$CloseBtn.Visible = $false
$RCDetails.Visible = $true
} else {
$RCFound.text = "Router not found"
$RCFound.ForeColor = "#D0021B"
$CloseBtn.text = "Close"
$AddRCBtn.Visible = $false
$RCDetails.Visible = $false
}
}
Also, you are trying to add a control in your form that is not a control ($testConnection). I suppose you wanted to add $RCTestConnection instead (and don't forget to take care of it's position).
# Change this line:
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$testConnection))
# To this line:
$LocalRCForm.controls.AddRange(#($Titel,$Description,$RCStatus,$RCFound,$RCType,$AddRCBtn,$CloseBtn,$RCDetails,$routerIp,$RCTestConnection))
Again, you use the variable $testConnection but it neither have a property enabled or a method Start(). So this line makes no sense and after having put your main code in a function, it should be replaced as follow:
# Replace this line that has no meaning
$LocalRCForm.Add_Shown({$testConnection.Enabled = $true; $testConnection.Start()})
# By this line
$LocalRCForm.Add_Shown({funTestConnection})
About retrying if not connected, [System.Windows.Forms.DialogResult]::Retry is not a function, it's a constant value so you can't expect it to do anything.
For it to be taken into account, you should use it in a way or the other.
One example would be like this:
# This code
do { $returnDialog = $LocalRCForm.ShowDialog() }
while($returnDialog -eq [System.Windows.Forms.DialogResult]::Retry)
# instead of this line
return $LocalRCForm.ShowDialog()
Finally, your function AddRC has no real impact as the form is closed when it's called (just a remark).
With all that said, you will have a functional script but it needs quite some adjustments related to what messages and information are displayed during the process (button names, labels, etc.) but at least it should do what you're expecting.

PowerShell form not displaying when screen is locked

I'm using a PowerShell form to prompt users to close down Adobe Reader so it can be upgraded. It's executed via SCCM, so runs in the System context. It works if the user is logged on and the session is active, but if the screen is locked, the form does not display when I unlock the screen, although the script is running.
I originally used $Form.ShowDialog() to display it but saw some other posts that said it wasn't reliable, so I switched to [void][System.Windows.Forms.Application]::Run($Form) but it still doesn't work. Can anyone help me fix this please?
Below is the trimmed-down script with only the code relevant to rendering the form.
Add-Type -AssemblyName System.Windows.Forms, System.Drawing
$Font = New-Object System.Drawing.Font('Segoe UI Light',14,[System.Drawing.FontStyle]::Regular)
$FontBold = New-Object System.Drawing.Font('Segoe UI',13,[System.Drawing.FontStyle]::Bold)
Function EndForm
{
$Timer.Stop();
$Timer.Dispose();
$Label.Dispose();
$CountdownLabel.Dispose();
$ProgressBar.Dispose();
$OKButton.Dispose();
$Form.Close();
$Form.Dispose();
}
$OnOKClick =
{
$MsgBoxInput = [System.Windows.Forms.MessageBox]::Show("Are you sure you want to close and uninstall Adobe Reader now?","Confirm Adobe Reader Removal","YesNo","Warning")
If ($MsgBoxInput -eq "Yes") {EndForm}
}
$Script:Countdown = 3600
$OKToolTip = "Click OK to close and uninstall Adobe Reader now"
$CountdownSubtitle = "Adobe Reader will close and uninstall in"
$Label = New-Object System.Windows.Forms.Label
$Label.AutoSize = $False
$Label.Height = 120
$Label.Width = 630
$Label.Font = $Font
$Label.BackColor = "White"
$Label.ForeColor = "#4D4C5C"
$Label.Location = New-Object System.Drawing.Size(52,180)
$Label.Text = "Your computer will soon be upgraded to newer versions of Windows 10 and Office 365. In order to succeed, the upgrade process requires that Adobe Reader be closed and uninstalled first. It will not be available for use again until after the upgrade has completed."
$CountdownLabel = New-Object System.Windows.Forms.Label
$CountdownLabel.AutoSize = $False
$CountdownLabel.Height = 40
$CountdownLabel.Width = 530
$CountdownLabel.Font = $Font
$CountdownLabel.BackColor = "White"
$CountdownLabel.ForeColor = "#4D4C5C"
$CountdownLabel.Location = New-Object System.Drawing.Size(120,380)
$ProgressBar = New-Object System.Windows.Forms.ProgressBar
$ProgressBar.Location = New-Object System.Drawing.Size(52,340)
$ProgressBar.Size = New-Object System.Drawing.Size(635,35)
$ProgressBar.Style = "Continuous"
$ProgressBar.Maximum = $Script:Countdown
$ProgressBar.Minimum = 0
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Name = "OK_Button"
$OKButton.Size = New-Object System.Drawing.Size(80,40)
$OKButton.Location = New-Object System.Drawing.Size(330,450)
$OKButton.UseVisualStyleBackColor = $True
$OKButton.Text = "OK"
$OKButton.DataBindings.DefaultDataSourceUpdateMode = 0
$OKButton.Add_Click($OnOKClick)
$ToolTip = New-Object System.Windows.Forms.ToolTip
$ToolTip.IsBalloon = $False
$ToolTip.InitialDelay = 100
$ToolTip.ReshowDelay = 200
$ToolTip.SetToolTip($OKButton,$OKToolTip)
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Contoso LLC"
$Form.Font = $Font
$Form.Width = 770
$Form.Height = 580
$Form.MinimizeBox = $False
$Form.MaximizeBox = $False
$Form.ControlBox = $False
$Form.ShowIcon = $False
$Form.WindowState = "Normal"
$Form.FormBorderStyle = "Fixed3D"
$Form.ShowInTaskbar = $True
$Form.StartPosition = "CenterScreen"
$Form.Topmost = $True
$Form.Controls.Add($ProgressBar)
$Form.Controls.Add($Label)
$Form.Controls.Add($CountdownLabel)
$Form.Controls.Add($OKButton)
$Timer = New-Object System.Windows.Forms.Timer
$Timer.Interval = 1000
$Timer.Add_Tick(
{
If ($Script:Countdown -eq 0) {EndForm}
$ProgressBar.Value = $Script:Countdown
$TimeRemain = New-Timespan -Seconds $Script:Countdown
$HrsRemain = $TimeRemain.Hours
$MinsRemain = $TimeRemain.Minutes
$SecsRemain = $TimeRemain.Seconds
If ($HrsRemain -ge 2) {$HrsText = "$HrsRemain hours"}
If ($HrsRemain -eq 1) {$HrsText = "$HrsRemain hour"}
If ($MinsRemain -ge 2) {$MinsText = "$MinsRemain minutes"}
If ($MinsRemain -eq 1) {$MinsText = "$MinsRemain minute"}
If ($SecsRemain -ge 2) {$SecsText = "$SecsRemain seconds"}
If ($SecsRemain -eq 1) {$SecsText = "$SecsRemain second"}
$CountdownLabel.Text = "$CountdownSubtitle $HrsText $MinsText $SecsText"
If ($HrsRemain -ge 1 -And $MinsRemain -eq 0) {$CountdownLabel.Text = "$CountdownSubtitle $HrsText $SecsText"}
If ($HrsRemain -eq 0) {$CountdownLabel.Text = "$CountdownSubtitle $MinsText $SecsText"}
If ($HrsRemain -eq 0 -And $MinsRemain -eq 0) {$CountdownLabel.Text = "$CountdownSubtitle $SecsText"}
$Script:Countdown--
})
$Timer.Start()
[void][System.Windows.Forms.Application]::Run($Form)
I have decided to 'work around' this issue by detecting for the presence of the logonui process, which means the screen is locked. In that case, I will just close Adobe Reader anyway.

Powershell Forms refresh GUI

The script is a simple administration tool to indicate the status of three windows services and to toggle them.
Everything works fine but I don't get it done to implement the refreshment of the GUI.
I want to show up the related status in labels and to hide the non-clickable buttons. I was playing around so far with a timer, but the GUI still doesn't refresh..
#variables
$ums = get-service "UMS Server"
$mySQL = get-service "mySQL56"
$maria = get-service "MariaDB_10.1.21"
function OnApplicationLoad {
return $true
}
function OnApplicationExit {
$script:ExitCode = 0
}
function generateForm {
Add-Type -AssemblyName System.Windows.Forms
$UMSDatabaseadministration = New-Object system.Windows.Forms.Form
$UMSDatabaseadministration.Text = "UMS Database administration"
$UMSDatabaseadministration.TopMost = $true
$UMSDatabaseadministration.Width = 614
$UMSDatabaseadministration.Height = 316
$UMSDatabaseadministration.StartPosition = "CenterScreen"
$timer = New-Object System.Windows.Forms.Timer #$UMSDatabaseadministration
$timer.Interval = 1000 # once per second
$timer.Add_Tick({ $UMSDatabaseadministration.Refresh() })
#button 1 start UMS
$button11 = New-Object system.windows.Forms.Button
$button11.Text = "start"
$button11.Width = 60
$button11.Height = 30
if ($ums.Status -eq "Running"){
$button11.visible = $false
}
$button11.Add_Click({
$ums.start()
})
$button11.location = new-object system.drawing.point(303,38)
$button11.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button11)
#button 2 stop UMS
$button15 = New-Object system.windows.Forms.Button
$button15.Text = "stop"
$button15.Width = 60
$button15.Height = 30
if ($ums.Status -eq "Stopped"){
$button15.visible = $false
}
$button15.Add_Click({$ums.stop()})
$button15.location = new-object system.drawing.point(409,39)
$button15.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button15)
#button 3 start mySQL
$button12 = New-Object system.windows.Forms.Button
$button12.Text = "start"
$button12.Width = 60
$button12.Height = 30
if ($maria.Status -eq "Running" -Or $mySQL.Status -eq "Running"){
$button12.visible = $false
}
$button12.Add_Click({$mySQL.start()})
$button12.location = new-object system.drawing.point(303,98)
$button12.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button12)
#button 4 stop mySQL
$button14 = New-Object system.windows.Forms.Button
$button14.Text = "stop"
$button14.Width = 60
$button14.Height = 30
if ($mySQL.Status -eq "Stopped"){
$button14.visible = $false
}
$button14.Add_Click({$mySQL.stop()})
$button14.location = new-object system.drawing.point(410,99)
$button14.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button14)
#button 5 start mariaDB
$button13 = New-Object system.windows.Forms.Button
$button13.Text = "start"
$button13.Width = 60
$button13.Height = 30
if ($mySQL.Status -eq "Running" -Or $maria.Status -eq "Running"){
$button13.visible = $false
}
$button13.Add_Click({$maria.start()})
$button13.location = new-object system.drawing.point(302,147)
$button13.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button13)
#button 6 stop mariaDB
$button16 = New-Object system.windows.Forms.Button
$button16.Text = "stop"
$button16.Width = 60
$button16.Height = 30
if ($maria.Status -eq "Stopped"){
$button16.visible = $false
}
$button16.Add_Click({$maria.stop()})
$button16.location = new-object system.drawing.point(410,148)
$button16.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button16)
$button17 = New-Object system.windows.Forms.Button
$button17.Text = "shut down UMS Server and toggle DB`'s"
$button17.Add_Click({
#variables
$ums = get-service "UMS Server"
$mySQL = get-service "mySQL56"
$maria = get-service "MariaDB_10.1.21"
if ($ums.Status -eq "Running") {$ums.stop()}
if ($mySQL.Status -eq "Running") {$mySQL.stop(); $maria.start()}
if ($maria.Status -eq "Running") {$maria.stop(); $mySQL.start()}
})
$button17.Width = 166
$button17.Height = 42
$button17.location = new-object system.drawing.point(303,209)
$button17.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($button17)
$label18 = New-Object system.windows.Forms.Label
$label18.Text = "UMS Server is:"
$label18.AutoSize = $true
$label18.Width = 25
$label18.Height = 10
$label18.location = new-object system.drawing.point(33,38)
$label18.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label18)
$label19 = New-Object system.windows.Forms.Label
$label19.Text = "mySQL is:"
$label19.AutoSize = $true
$label19.Width = 25
$label19.Height = 10
$label19.location = new-object system.drawing.point(33,95)
$label19.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label19)
$label20 = New-Object system.windows.Forms.Label
$label20.Text = "mariaDB is:"
$label20.AutoSize = $true
$label20.Width = 25
$label20.Height = 10
$label20.location = new-object system.drawing.point(34,146)
$label20.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label20)
#status UMS red
$label24 = New-Object system.windows.Forms.Label
$label24.Text = $ums.status
$label24.AutoSize = $true
$label24.ForeColor = "#fe0004"
$label24.Width = 25
$label24.Height = 10
if ($ums.status -eq "Running"){
$label24.visible = $false
}
$label24.location = new-object system.drawing.point(152,37)
$label24.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label24)
#status UMS green
$label25 = New-Object system.windows.Forms.Label
$label25.Text = $ums.status
$label25.AutoSize = $true
$label25.ForeColor = "#149600"
$label25.Width = 25
$label25.Height = 10
if ($ums.status -eq "Stopped"){
$label25.visible = $false
}
$label25.location = new-object system.drawing.point(153,40)
$label25.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label25)
#status mySQL red
$label26 = New-Object system.windows.Forms.Label
$label26.Text = $mySQL.status
$label26.AutoSize = $true
$label26.ForeColor = "#ff0004"
$label26.Width = 25
$label26.Height = 10
if ($mySQL.status -eq "Running"){
$label26.visible = $false
}
$label26.location = new-object system.drawing.point(152,94)
$label26.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label26)
#status mySQL green
$label27 = New-Object system.windows.Forms.Label
$label27.Text = $mySQL.status
$label27.AutoSize = $true
$label27.ForeColor = "#149600"
$label27.Width = 25
$label27.Height = 10
if ($mySQL.status -eq "Stopped"){
$label27.visible = $false
}
$label27.location = new-object system.drawing.point(152,96)
$label27.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label27)
#status mariaDB red
$label28 = New-Object system.windows.Forms.Label
$label28.Text = $maria.status
$label28.AutoSize = $true
$label28.ForeColor = "#ff0004"
$label28.Width = 25
$label28.Height = 10
if ($maria.status -eq "Running"){
$label28.visible = $false
}
$label28.location = new-object system.drawing.point(151,145)
$label28.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label28)
#status mariaDB green
$label29 = New-Object system.windows.Forms.Label
$label29.Text = $maria.status
$label29.AutoSize = $true
$label29.ForeColor = "#149600"
$label29.Width = 25
$label29.Height = 10
if ($maria.status -eq "Stopped"){
$label29.visible = $false
}
$label29.location = new-object system.drawing.point(151,145)
$label29.Font = "Microsoft Sans Serif,10"
$UMSDatabaseadministration.controls.Add($label29)
[void]
$UMSDatabaseadministration.ShowDialog()
$UMSDatabaseadministration.Dispose()
}
if(OnApplicationLoad -eq $true)
{
GenerateForm | Out-Null
$timer.Start()
OnApplicationExit
}
First I must say that your code needs a lot of TLC. You shouldn't label your buttons or labels 1-20. Makes the code look messy and 15 days down the line you will have no idea what the code says. At lines 2-4 and 128-130 you define your variables twice.
What I have done now is create this Service GUI that will not just help you out, but anyone looking to do the same kind of task. You simple add the services you want into the Param function.
First we see if you are an Administrator, because not everyone is.
Add-Type -AssemblyName System.Windows.Forms
function Test-Admin {
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
}
if ((Test-Admin) -eq $false) {
if ($elevated)
{
# tried to elevate, did not work, aborting
}
else {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
}
exit
}
We create a central location to have the parameters.
Note that you see that I use the $Global: You can read about that here:
https://msdn.microsoft.com/en-us/powershell/reference/3.0/microsoft.powershell.core/about/about_scopes
Function Param{
$Global:Option1 = get-service "Hamachi2Svc"
$Global:Option2 = get-service "NitroUpdateService"
$Global:Option3 = get-service "TeamViewer"
$Global:Option1Txt=$Global:Option1.Displayname
$Global:Option2Txt=$Global:Option2.Displayname
$Global:Option3Txt=$Global:Option3.Displayname
}
Now we create the Form
Function ServiceAdminForm {
$Form.Close()
$Form.Dispose()
Test-Admin
MakeForm
}
Now we define the functions that our buttons will use.
Function Option1 {
if ($Global:Option1.Status -eq "Running"){ Stop-Service $Global:Option1
}
else {Start-Service $Global:Option1}
}
Function Option2 {
if ($Global:Option2.Status -eq "Running"){ Stop-Service $Global:Option2
}
else {Start-Service $Global:Option2}
}
Function Option3 {
if ($Global:Option3.Status -eq "Running"){ Stop-Service $Global:Option3
}
else {Start-Service $Global:Option3}
}
Function Toggle {
if ($Global:Option1.Status -eq "Running") {$Global:Option1.stop()}
if ($Global:Option2.Status -eq "Running") {$Global:Option2.stop(); $Global:Option3.start()}
if ($Global:Option3.Status -eq "Running") {$Global:Option3.stop(); $Global:Option2.start()}
}
Now we make the layout of the GUI
Calling the parameters and the button functions.
Function MakeForm {
Param
$script:Form = New-Object system.Windows.Forms.Form
$Form.Text = "Service Administration"
$Font = New-Object System.Drawing.Font("Times New Roman",12,[System.Drawing.FontStyle]::Bold)
$Form.Font = $Font
#Label for Option1
$Global:Option1lbl = New-Object system.windows.Forms.Label
$Global:Option1lbl.Text = $Global:Option1.Status
$Global:Option1lbl.AutoSize = $true
$Global:Option1lbl.Width = 25
$Global:Option1lbl.Height = 10
$Global:Option1lbl.location = new-object system.drawing.point(5,90)
#Label for Option2
$Global:Option2lbl = New-Object system.windows.Forms.Label
$Global:Option2lbl.Text = $Global:Option2.Status
$Global:Option2lbl.AutoSize = $true
$Global:Option2lbl.Width = 25
$Global:Option2lbl.Height = 10
$Global:Option2lbl.location = new-object system.drawing.point(5,150)
#Label for Option3
$Global:Option3lbl = New-Object system.windows.Forms.Label
$Global:Option3lbl.Text = $Global:Option3.Status
$Global:Option3lbl.AutoSize = $true
$Global:Option3lbl.Width = 25
$Global:Option3lbl.Height = 10
$Global:Option3lbl.location = new-object system.drawing.point(5,210)
#Refresh/Reload
$Reloadbtn = New-Object System.Windows.Forms.Button
$Reloadbtn.Location = New-Object System.Drawing.Size(5,10)
$Reloadbtn.AutoSize = $true
$Reloadbtn.Text = "Reload"
$Reloadbtn.Add_Click({ServiceAdminForm})
#Toggle
$Togglebtn = New-Object System.Windows.Forms.Button
$Togglebtn.Location = New-Object System.Drawing.Size(80,10)
$Togglebtn.AutoSize = $true
$Togglebtn.Text = "Toggle"
$Togglebtn.Add_Click({Toggle})
#Button Option1
$Global:Option1btn = New-Object System.Windows.Forms.Button
$Global:Option1btn.Location = New-Object System.Drawing.Size(5,60)
$Global:Option1btn.AutoSize = $true
$Global:Option1btn.Text = "$Global:Option1Txt"
$Global:Option1btn.Add_Click({Option1})
#Button Option2
$Global:Option2btn = New-Object System.Windows.Forms.Button
$Global:Option2btn.Location = New-Object System.Drawing.Size(5,120)
$Global:Option2btn.AutoSize = $true
$Global:Option2btn.Text = "$Global:Option2Txt"
$Global:Option2btn.Add_Click({Option2})
#Button Option3
$Global:Option3btn = New-Object System.Windows.Forms.Button
$Global:Option3btn.Location = New-Object System.Drawing.Size(5,180)
$Global:Option3btn.AutoSize = $true
$Global:Option3btn.Text = "$Global:Option3Txt"
$Global:Option3btn.Add_Click({Option3})
#Form Controls
$Form.Controls.Add($Global:Option1lbl)
$Form.Controls.Add($Global:Option2lbl)
$Form.Controls.Add($Global:Option3lbl)
$Form.Controls.Add($Reloadbtn)
$Form.Controls.Add($Togglebtn)
$Form.Controls.Add($Global:Option1btn)
$Form.Controls.Add($Global:Option2btn)
$Form.Controls.Add($Global:Option3btn)
$Form.ShowDialog()
}
MakeForm
Maybe someone has a better way to refresh, but reloading the form does the job.