Skip to content

Instantly share code, notes, and snippets.

@ctigeek
Created March 23, 2016 14:44
Show Gist options
  • Star 35 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ctigeek/bd637eeaeeb71c5b17f4 to your computer and use it in GitHub Desktop.
Save ctigeek/bd637eeaeeb71c5b17f4 to your computer and use it in GitHub Desktop.
Powershell sleep function, with progress bar.
function Start-Sleep($seconds) {
$doneDT = (Get-Date).AddSeconds($seconds)
while($doneDT -gt (Get-Date)) {
$secondsLeft = $doneDT.Subtract((Get-Date)).TotalSeconds
$percent = ($seconds - $secondsLeft) / $seconds * 100
Write-Progress -Activity "Sleeping" -Status "Sleeping..." -SecondsRemaining $secondsLeft -PercentComplete $percent
[System.Threading.Thread]::Sleep(500)
}
Write-Progress -Activity "Sleeping" -Status "Sleeping..." -SecondsRemaining 0 -Completed
}
@evoelker
Copy link

evoelker commented Oct 3, 2017

This was just what I was looking for. Made some changes so I could still use Start-Sleep and to give wait time in minutes and seconds.

@J-Coc
Copy link

J-Coc commented Nov 29, 2018

I'm trying to use your function and get it to display in a GUI Form. The code above works just fine to display the progress bar while in ISE, but when I run my whole code it only shows in the Console. I'm wanting to have it actually pop open a GUI window within the boundary of my main form and display the bar, any thoughts how I could do that? I'm still working on my Poweshell GUI App like getting the $ChosenItem property text to display in label13 and a few more enhancements. Thank you for your help on this, here is my code below:

`

Load Assemblies

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
$net = New-Object -ComObject Wscript.Network

Display progress bar

<# #>
Function Start-Sleep($seconds)
{
$doneDT = (Get-Date).AddSeconds($seconds)
while($doneDT -gt (Get-Date))
{
$secondsLeft = $doneDT.Subtract((Get-Date)).TotalSeconds
$percent = ($seconds - $secondsLeft) / $seconds * 100
Write-Progress -Activity "Pausing" -Status "Pausing..." -SecondsRemaining $secondsLeft -PercentComplete $percent
[System.Threading.Thread]::Sleep(500)
}
Write-Progress -Activity "Pausing" -Status "Pausing..." -SecondsRemaining 0 -Completed
}

Display the Main Screen

Function Display-MainScreen
{
$Form.Controls.Add($ListBox1)
$Form.Controls.Add($Button1)
$Form.Controls.Add($Button2)
$Form.Controls.Add($Label2)
}

---------- Button Click Actions ------

Define Return Button Click Function

Function Return-MainScreen
{
$Form.Controls.Remove($Label)
$Form.Controls.Remove($Label3)
$Form.Controls.Remove($Label4)
$Form.Controls.Remove($Label5)
$Form.Controls.Remove($Label6)
$Form.Controls.Remove($Label7)
$Form.Controls.Remove($Label8)
$Form.Controls.Remove($Label9)
$Form.Controls.Remove($Label10)
$Form.Controls.Remove($Label11)
$Form.Controls.Remove($Label12)
$Form.Controls.Remove($Label13)
$Form.Controls.Remove($Label9)
$Form.Controls.Remove($Button3)
$Form.Controls.Remove($Button4)
#$Form.Controls.Remove($Button5)
#$Form.Controls.Remove($Button6)

$Form.Refresh()
Display-MainScreen
}

Define OK Button Click Function

Function Display-UserInfo($ChosenItem)
{

Clear the window

$Form.Controls.Remove($ListBox1)
$Form.Controls.Remove($Label2)
$Form.Controls.Remove($Button1)
$Form.Controls.Remove($Button2)
#$Form.Controls.Remove($Button5)
#$Form.Controls.Remove($Button6)
$Form.Refresh()

Create Output

Add-Type -AssemblyName System.Windows.Forms

Get user Information

$Selecteduser = Get-ADUser -Identity $ChosenItem -Properties Name,SID,description,sAMAccountName,title,canonicalname
$Global:Name = $Selecteduser.Name
$Sam = $Selecteduser.sAMAccountName
$desc = $Selecteduser.description
$sid = $Selecteduser.sid
$Title = $Selecteduser.title
$OU = $Selecteduser.canonicalname
#$output = $sam

Create text

$Label.Text = 'Display Name: ' + $Name
$Label4.Text = 'AD Sam Name: ' + $Sam
$Label5.Text = 'Description: ' + $desc
$Label6.Text = 'Job Title: ' + $title
$Label7.Text = 'SID: ' + $sid
$Label8.Text = 'OU: ' + $OU

$Label9.Text = ''
$Label10.Text =''
$Label11.Text =''
$Label12.Text =''
$Label13.Text =''

Display Screen Contents

$Form.Controls.Add($Label)
$Form.Controls.Add($Label3)
$Form.Controls.Add($Label4)
$Form.Controls.Add($Label5)
$Form.Controls.Add($Label6)
$Form.Controls.Add($Label7)
$Form.Controls.Add($Label8)
$Form.Controls.Add($Label9)
$Form.Controls.Add($Label10)
$Form.Controls.Add($Label11)
$Form.Controls.Add($Label12)
$Form.Controls.Add($Label13)
$Form.Controls.Add($Button3)
$Form.Controls.Add($Button4)
#If ($State -eq 'Off')
#{
#$Form.Controls.Add($Button5)
#}
#If ($State -EQ 'Running')
#{
#$Form.Controls.Add($Button6)
#}
}

------ Define All GUI Objects-------

Define Label - This is a text box object that will display user data

$Label = New-Object System.Windows.Forms.Label
$Label.AutoSize = $False
$Label.Location = new-object System.Drawing.Size(50,30)
$Label.Size = New-Object System.Drawing.Size(320,20)
$Label.ForeColor = "Black"
$label.BackColor = 'White'

Define Label2 - The Please Make a Selection Text

$Label2 = New-Object System.Windows.Forms.Label
$Label2.AutoSize = $True
$Label2.Location = new-object System.Drawing.Size(20,50)
$Label2.ForeColor = "DarkBlue"
$Label2.Text = "Please select an AD User to Term."

Define Label3 - The This is Your Selected AD User Text

$Label3 = New-Object System.Windows.Forms.Label
$Label3.AutoSize = $True
$Label3.Location = new-object System.Drawing.Size(50,10)
$Label3.ForeColor = "DarkBlue"
$Label3.Text = "Your selected AD User:"

Define Label4 - The This is the User label

$Label4 = New-Object System.Windows.Forms.Label
$Label4.AutoSize = $False
$Label4.Location = new-object System.Drawing.Size(50,50)
$Label4.Size = New-Object System.Drawing.Size(320,20)
$Label4.ForeColor = "Black"
$Label4.BackColor = 'White'

Define Label5 - The This is the description label

$Label5 = New-Object System.Windows.Forms.Label
$Label5.AutoSize = $False
$Label5.Location = new-object System.Drawing.Size(50,70)
$Label5.Size = New-Object System.Drawing.Size(320,20)
$Label5.ForeColor = "Black"
$Label5.BackColor = "White"

Define Label6 - The This is the SID label

$Label6 = New-Object System.Windows.Forms.Label
$Label6.AutoSize = $False
$Label6.Location = new-object System.Drawing.Size(50,90)
$Label6.Size = New-Object System.Drawing.Size(320,20)
$Label6.ForeColor = "Black"
$Label6.BackColor = 'White'

Define Label7 - The This is the Job Title label

$Label7 = New-Object System.Windows.Forms.Label
$Label7.AutoSize = $False
$Label7.Location = new-object System.Drawing.Size(50,110)
$Label7.Size = New-Object System.Drawing.Size(320,20)
$Label7.ForeColor = "Black"
$Label7.BackColor = 'White'

Define Label8 - The This is the ou label

$Label8 = New-Object System.Windows.Forms.Label
$Label8.AutoSize = $False
$Label8.Location = new-object System.Drawing.Size(50,130)
$Label8.Size = New-Object System.Drawing.Size(320,20)
$Label8.ForeColor = "Black"
$Label8.BackColor = 'White'

Define Label9 - This is the Disabled user text

$Label9 = New-Object System.Windows.Forms.Label
$Label9.Location = New-Object System.Drawing.Size(50,200)
$Label9.Size = New-Object System.Drawing.Size(320,20)
$Label9.ForeColor = "Black"
$Label9.BackColor = 'White'

Define Label10 - This is the AD Group changes text

$Label10 = New-Object System.Windows.Forms.Label
$Label10.Location = New-Object System.Drawing.Size(50,220)
$Label10.Size = New-Object System.Drawing.Size(320,20)
$Label10.ForeColor = "Black"
$Label10.BackColor = 'White'

Define Label11 - This is the AD password changes text

$Label11 = New-Object System.Windows.Forms.Label
$Label11.Location = New-Object System.Drawing.Size(50,240)
$Label11.Size = New-Object System.Drawing.Size(320,20)
$Label11.ForeColor = "Black"
$Label11.BackColor = 'White'

Define Label12 - This is the AD OU changes text

$Label12 = New-Object System.Windows.Forms.Label
$Label12.Location = New-Object System.Drawing.Size(50,260)
$Label12.Size = New-Object System.Drawing.Size(320,20)
$Label12.ForeColor = "Black"
$Label12.BackColor = 'White'

Define Label13 - This is the Termed text

$Label13 = New-Object System.Windows.Forms.Label
$Label13.Location = New-Object System.Drawing.Size(50,280)
$Label13.Size = New-Object System.Drawing.Size(320,50)
$Label13.ForeColor = "Black"
$Label13.BackColor = 'White'

Define List Box - This will display the Users that can be selected

$ListBox1 = New-Object System.Windows.Forms.ListBox
$ListBox1.Location = New-Object System.Drawing.Size(20,80)
$ListBox1.Size = New-Object System.Drawing.Size(260,20)
$ListBox1.Height = 80

This code populates the list box with User names

$ADusers = Get-ADUser -filter {(Enabled -eq $True)} -Searchscope 2 -Properties Name,SID,description,sAMAccountName,title,canonicalname | Sort-Object -Property sAMAccountName
ForEach ($name in $ADusers)
{
[void] $ListBox1.Items.Add($name.sAMAccountName)
}

Define Button 1 - This is the selection screen's OK button

$Button1 = new-object System.Windows.Forms.Button
$Button1.Location = new-object System.Drawing.Size(20,170)
$Button1.Size = new-object System.Drawing.Size(70,30)
$Button1.BackColor ="LightGray"
$Button1.Text = "OK"
$Button1.Add_Click({$ChosenItem=$ListBox1.SelectedItem;Display-UserInfo $ChosenItem})

Define Button 2 - This is the selection screen's Cancel button

$Button2 = New-Object System.Windows.Forms.Button
$Button2.Location = New-Object System.Drawing.Size(120,170)
$Button2.Size = New-Object System.Drawing.Size(70,30)
$Button2.BackColor ="LightGray"
$Button2.Text = "Cancel"
$Button2.Add_Click({$Form.Close()})

Define Button 3 - This is the Return to Main Screen button

$Button3 = New-Object System.Windows.Forms.Button
$Button3.Location = New-Object System.Drawing.Size(50,160)
$Button3.Size = New-Object System.Drawing.Size(150,30)
$Button3.BackColor ="LightGray"
$Button3.Text = "Return to Main Screen"
$Button3.Add_Click({Return-MainScreen})

Define Button 4 - This button Runs the script to term selected user

$Button4 = New-Object System.Windows.Forms.Button
$Button4.Location = New-Object System.Drawing.Size(220,160)
$Button4.Size = New-Object System.Drawing.Size(150,30)
$Button4.BackColor ="LightGray"
$Button4.Text = "Term Selected User"
$Button4.Add_Click({

$newLine = [System.Environment]::NewLine

$WPFsamBox = $Selecteduser

#Set-ADUser -Identity $WPFsamBox -Enabled 0

$Label9.Text = 'Pausing for 10 seconds for User to be disabled'
$Form.Refresh()

Start-Sleep 2
#Displays in ISE when run, but not from GUI

$Label10.Text = 'Pausing for 10 seconds for AD Group Changes'
$Form.Refresh()

Start-Sleep 2
#Displays in ISE when run, but not from GUI

$Label11.Text ="Pausing for 10 seconds for AD Password Changes"
$Form.Refresh()

Start-Sleep 2
#Displays in ISE when run, but not from GUI

$Label12.Text ="Waiting for user to be moved to Pending Deletion OU"
$Form.Refresh()

Start-Sleep 2
#Displays in ISE when run, but not from GUI

$Label13.Text ="$WPFsamBox has been terminated"

})

-------- This is the end of the object definition section ------

-----Draw the empty form----

$Form = New-Object System.Windows.Forms.Form
$Form.width = 525
$Form.height = 380
$Form.BackColor = "lightblue"
$Form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::Fixed3D
$Form.Text = "Disable Users"
$Form.maximumsize = New-Object System.Drawing.Size(525,380)
$Form.startposition = "centerscreen"
$Form.KeyPreview = $True

$Form.Add_KeyDown({if ($_.KeyCode -eq "Escape")
{$Form.Close()}})

----Populate the form----

Display-MainScreen
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog()`

@bakins929
Copy link

This is great, thanks!

@jcefoli
Copy link

jcefoli commented Jan 6, 2022

Is there a way to fix the progress bar showing at 100% for a few seconds when the loop starts before correcting itself?

@ctigeek
Copy link
Author

ctigeek commented Jan 7, 2022

@jcefoli I just tested it and I'm not seeing that behavior. Are you using it in newer powershell core? I've only tested it in legacy powershell.

@jcefoli
Copy link

jcefoli commented Jan 7, 2022

I tested this a bit and I see what is happening. It's not very apparent if the countdown is short, but I had a 1 hour countdown, and for a while, it was completely filled in, then after some time, jumped back down and started slowly incrementing.

In the Write-Progress commandlet, the -PercentComplete parameter will display the progress bar fully highlighted if its value is 0 or a decimal less than 1. Once it hits 1, it will calculate the filled in area properly.

I tricked it by doing this:

if ($percent -lt 1) {$progressBarPercent = 1 } else { $progressBarPercent = $percent }
 Write-Progress -Activity "Sleeping" -Status "Sleeping..." -SecondsRemaining $secondsLeft -PercentComplete $progressBarPercent 

@petvo78
Copy link

petvo78 commented Jan 31, 2022

Great stuff. Thanks.

@recycleleash
Copy link

awesome!! thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment