Need help gui background-job double-hop issue and script freezing - powershell

I'm having an issue with double hopping scriptblock for background job that either does nothing or freezes the script. Explenation below.
The idea for the script is to get a list of files (very large count, ~200k) and then process them in three individual ways (get hashcodes and get true duplicates, compare filenames and get pseudo duplicates, get zero length files). At this moment I'm working on hashes. The result of $job1 is a string (array?) that cannot be piped to get-filehash. This results in $job2 looping through each string in order to get hashes. As background-jobs work on scriptblocks and foreach loop has scriptblock component a double hop is created. I've worked around that by using invoke-command combined with [scriptblock]::Create() method inside job scriptblock. That unfortunately freezes the form. My question to you is as follows. How do I force $job1 result to be of system.io.fileinfo type OR how do I unfreeze script while Invoke-command is in progress?
Add-Type -AssemblyName System.Windows.Forms
add-type -AssemblyName system.drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
$path = "C:\"
$window = New-Object system.Windows.Forms.Form
$window.Size = New-Object system.Drawing.Size #(400,400)
$window.StartPosition = "CenterScreen"
$window.Font = New-Object System.Drawing.Font("Calibri",11,[System.Drawing.FontStyle]::Bold)
$window.Text = "STARTING UP"
$ProgressBar1 = New-Object System.Windows.Forms.ProgressBar
$ProgressBar1.Location = New-Object System.Drawing.Point(10, 10)
$ProgressBar1.Size = New-Object System.Drawing.Size(365, 20)
$ProgressBar1.Style = "Marquee"
$ProgressBar1.MarqueeAnimationSpeed = 20
$ProgressBar1.UseWaitCursor = $true
$ProgressBar1.Visible = $false
$button = New-Object System.Windows.Forms.Button
$button.size = New-Object system.drawing.size #(50,50)
$button.Location = New-Object System.Drawing.Point(20, 70)
$button.Text = "TEST"
$window.Controls.add($button)
$label = New-Object System.Windows.Forms.Label
$label.Size = New-Object System.Drawing.Size #(100, 50)
$label.Location = New-Object System.Drawing.Point (80, 70)
$label.BorderStyle = 'Fixed3D'
$label.ForeColor = 'green'
$label.TextAlign = 'middlecenter'
$window.Controls.Add($label)
$timer = New-Object System.Windows.Forms.Timer
$timer.Interval = 1000
$timer.add_Tick({$script:time2 =((get-date)-$script:time1).ToString("hh\:mm\:ss")
$label2.text = $script:time2
})
$button.add_Click(
{$1 = Get-Date
$Script:time1 = Get-Date
$timer.start()
$ProgressBar1.BringToFront()
$ProgressBar1.Show()
$this.Enabled = $false
$job = Start-Job -ScriptBlock {
Get-ChildItem -File -recurse $HOME -ErrorAction SilentlyContinue|select -ExpandProperty FullName
}
while($job.State -eq 'Running') {
[System.Windows.Forms.Application]::DoEvents()
}
$script:asd = $job | Receive-Job #-AutoRemoveJob -Wait
$ProgressBar1.Hide()
$this.Enabled = $true
$2 = ((get-date) - $1).ToString("hh\:mm\:ss")
$label.text = $2
$timer.stop()
}
)
$button2 = New-Object System.Windows.Forms.Button
$button2.Size = New-Object System.Drawing.Size #(50, 50)
$button2.Location = New-Object System.Drawing.Point (200, 70)
$button2.Text = 'Exit'
$window.Controls.Add($button2)
$button2.add_Click({$window.Close()})
$button3 = new-object System.Windows.Forms.Button
$button3.Size = New-Object System.Drawing.Size #(50, 50)
$button3.Location = New-Object System.Drawing.Point (20, 200)
$button3.Text = "Start"
$window.Controls.Add($button3)
$button3.add_Click({
$sb = foreach ($qwe in $Script:asd){Get-FileHash $qwe -Algorithm MD5|select -ExpandProperty Hash -OutVariable +Script:tester}
$ProgressBar2.BringToFront()
$ProgressBar2.Show()
$this.Enabled = $false
$job2 = start-job -Name 'asd' -scriptblock {
param($sb)
$sb = [scriptblock]::Create($sb)
Invoke-command -ScriptBlock $sb
}
while($job2.State -eq 'Running') {
[System.Windows.Forms.Application]::DoEvents()
}
Write-Host $Script:tester
$ProgressBar2.Hide()
$this.Enabled = $true
})
$label2 = New-Object System.Windows.Forms.Label
$label2.size = New-Object System.Drawing.Size #(100, 50)
$label2.Location = New-Object System.Drawing.Point (80, 200)
$label2.BorderStyle = 'Fixed3D'
$label2.ForeColor = 'green'
$label2.TextAlign = 'middlecenter'
$window.Controls.Add($label2)
$ProgressBar2 = New-Object System.Windows.Forms.ProgressBar
$ProgressBar2.Location = New-Object System.Drawing.Point(10, 330)
$ProgressBar2.Size = New-Object System.Drawing.Size(365, 20)
$ProgressBar2.Style = "Marquee"
$ProgressBar2.MarqueeAnimationSpeed = 20
$ProgressBar2.UseWaitCursor = $true
$ProgressBar2.Visible = $false
$window.Controls.Add($ProgressBar2)
$groupbox = New-Object System.Windows.Forms.GroupBox
$groupbox.size = New-Object system.drawing.size #(377, 365)
$groupbox.Location = New-Object System.Drawing.point (4, -5)
$window.Controls.Add($groupbox)
$window.Controls.Add($ProgressBar1)
$window.ShowDialog()|out-null

For anyone interested. The answer was piping $job results to set-variable - $job|Wait-job|Receive-Job|Set-Variable -Name JOB_RESULT -Scope Script.
Then using $using: scope in $job2 scriptblock - $job2 = start-job -scriptblock { $using:JOB_RESULT|Get-FileHash -Algorithm MD5}

Related

How to remove checked margin in tray icon context menu

I've created this little script running in tray. I've noticed that contex menu text is not placed completely to the left. After a little investigation I found out that it is because there is a space left for .checked state indicator. I found out that it can be removed by .showcheckedmargin property of ContextMenuStrip but have no idea how to implement that.
Please advise.
add-type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'PresentationFramework'
$2 = "BASE64 CODE"
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($2)
$bitmap.EndInit()
$bitmap.Freeze()
$image = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($bitmap.StreamSource)
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app = New-Object System.Windows.Forms.NotifyIcon
$app.Text = ""
$app.Icon = $icon
$app.Visible = $true
$Zenek = New-Object System.Windows.Forms.MenuItem
$Zenek.Text = "Zenek"
$NetExt = New-Object System.Windows.Forms.MenuItem
$NetExt.Text = "NetExt"
$Busy = New-Object System.Windows.Forms.MenuItem
$Busy.Text = "BUSY"
$Time = New-Object System.Windows.Forms.MenuItem
$Time.Text = "Time"
$Exit = New-object System.Windows.Forms.MenuItem
$Exit.Text = "Exit"
$context = New-Object System.Windows.Forms.ContextMenu
$app.ContextMenu = $context
$app.ContextMenu.MenuItems.AddRange(#($Zenek, $NetExt, $Busy, $Time, $Exit))
$keepAwakeScript = {
while (1) {
$wsh = New-Object -ComObject WScript.Shell
$wsh.SendKeys('+{F15}')
Start-Sleep -seconds 59
}
}
Start-Job -ScriptBlock $keepAwakeScript -Name "keepAwake"|out-null
$Zenek.Add_Click({Set-Clipboard -Value "SOME TEXT"})
$NetExt.Add_Click({Set-Clipboard -Value "SOME OTHER TEXT"})
$Busy.Add_Click({
$running = Get-Job|?{$_.Name -like 'KAPS'}
$icon = new-object System.Drawing.Icon("MY PRIVATE LOCATION\red.ico")
$app.Icon = $icon
if($running -eq $null){
Start-Job -Name KAPS -ScriptBlock{
while ($true){
$shell = New-Object -ComObject WScript.Shell
$shell.SendKeys('{CAPSLOCK}')
Start-Sleep 1
}
}
}else{
Stop-Job KAPS
Remove-Job KAPS
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app.Icon = $icon
}
})
$Time.Add_Click({
$main = New-Object System.Windows.Forms.Form
$main.ClientSize = '200,200'
$main.MinimizeBox = $false
$main.MaximizeBox = $false
$label = New-Object System.Windows.Forms.Label
$label.Size = '190,30'
$label.Location = '10,10'
$label.Text = 'Ile minut?'
$font = New-Object System.Drawing.Font("Arial", 23)
$label.Font = $font
$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Size = '50,100'
$textbox.Location = '10,70'
$button = New-Object System.Windows.Forms.Button
$button.Size = '50,50'
$button.Location = '10,120'
$button.Text = 'GO'
$button.Add_Click({
$timer.Start()
$textbox.Visible =$false
$button.Visible = $false
$label.Visible = $false
$script:1 = New-TimeSpan -minutes ([int]$textbox.Text)
$label2.Visible = $true
$label2.Text = $1.ToString("mm\:ss")
})
$timer = New-Object System.Windows.Forms.Timer
$timer.Enabled = $false
$timer.Interval = '1000'
$second = New-TimeSpan -Seconds 1
$timer.Add_Tick({
$script:1 = $1.Subtract($second)
$label2.Text = $1.ToString("mm\:ss")
if($script:1.TotalSeconds -le 0){$timer.Stop(); $timer.Dispose(); [System.Windows.Forms.Application]::SetSuspendState("Hibernate", $true, $false); $main.Close(); $main.Dispose()}
})
$label2 = New-Object System.Windows.Forms.Label
$label2.Size = '190,30'
$label2.Location = '10,10'
$label2.Text = $1
$font = New-Object System.Drawing.Font("Arial", 23)
$label2.Font = $font
$label2.Visible = $false
$main.Controls.Add($textbox)
$main.Controls.Add($button)
$main.Controls.Add($label)
$main.Controls.Add($label2)
$main.ShowDialog()
})
$Exit.Add_Click({
$app.Visible = $false
Stop-Job -Name "keepAwake"
$appContext.ExitThread()
Stop-Process -Id $PID
})
$appContext = New-Object System.Windows.Forms.ApplicationContext
[void][System.Windows.Forms.Application]::Run($appContext)
For anyone with the same problem. I've managed to figure it out.
Another post from SO allowed me to do so.
I had to replace .ContextMenu with .ContextMenuStrip for the Menu itself,
replace .MenuItem with .ToolStripMenuItem, add .ShowImageMargin to ContextMenuStrip variable, then finall add items via .Items.AddRange(#()).
Before
After
In the end the code looks like this and works as intended.
add-type -AssemblyName 'System.Windows.Forms'
Add-Type -AssemblyName 'System.Drawing'
Add-Type -AssemblyName 'PresentationFramework'
$2 =
"BASE 64 CODE"
$bitmap = New-Object System.Windows.Media.Imaging.BitmapImage
$bitmap.BeginInit()
$bitmap.StreamSource = [System.IO.MemoryStream][System.Convert]::FromBase64String($2)
$bitmap.EndInit()
$bitmap.Freeze()
$image = [System.Drawing.Bitmap][System.Drawing.Image]::FromStream($bitmap.StreamSource)
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app = New-Object System.Windows.Forms.NotifyIcon
$app.Text = ""
$app.Icon = $icon
$app.Visible = $true
$Zenek = New-Object System.Windows.Forms.ToolStripMenuItem
$Zenek.Text = "Zenek"
$Zenek.Checked = $true
$NetExt = New-Object System.Windows.Forms.ToolStripMenuItem
$NetExt.Text = "NetExt"
$Busy = New-Object System.Windows.Forms.ToolStripMenuItem
$Busy.Text = "BUSY"
$Time = New-Object System.Windows.Forms.ToolStripMenuItem
$Time.Text = "Time"
$Exit = New-object System.Windows.Forms.ToolStripMenuItem
$Exit.Text = "Exit"
$sep = New-Object System.Windows.Forms.ToolStripSeparator
$context = New-Object System.Windows.Forms.ContextMenuStrip
$context.ShowImageMargin = $false
$context.Items.AddRange(#($Zenek, $NetExt, $Busy, $Time, $sep, $Exit))
$app.ContextMenuStrip = $context
$keepAwakeScript = {
while (1) {
$wsh = New-Object -ComObject WScript.Shell
$wsh.SendKeys('+{F15}')
Start-Sleep -seconds 59
}
}
Start-Job -ScriptBlock $keepAwakeScript -Name "keepAwake"|out-null
$Zenek.Add_Click({Set-Clipboard -Value "SOME TEXT"})
$NetExt.Add_Click({Set-Clipboard -Value "SOME OTHER TEXT"})
$Busy.Add_Click({
$running = Get-Job|?{$_.Name -like 'KAPS'}
$icon = new-object System.Drawing.Icon("MY PRIVATE LOCATION\red.ico")
$app.Icon = $icon
if($running -eq $null){
Start-Job -Name KAPS -ScriptBlock{
while ($true){
$shell = New-Object -ComObject WScript.Shell
$shell.SendKeys('{CAPSLOCK}')
Start-Sleep 1
}
}
}else{
Stop-Job KAPS
Remove-Job KAPS
$icon = [System.Drawing.Icon]::FromHandle($image.GetHicon())
$app.Icon = $icon
}
})
$Time.Add_Click({
$main = New-Object System.Windows.Forms.Form
$main.ClientSize = '200,200'
$main.MinimizeBox = $false
$main.MaximizeBox = $false
$label = New-Object System.Windows.Forms.Label
$label.Size = '190,30'
$label.Location = '10,10'
$label.Text = 'Ile minut?'
$font = New-Object System.Drawing.Font("Arial", 23)
$label.Font = $font
$textbox = New-Object System.Windows.Forms.TextBox
$textbox.Size = '50,100'
$textbox.Location = '10,70'
$button = New-Object System.Windows.Forms.Button
$button.Size = '50,50'
$button.Location = '10,120'
$button.Text = 'GO'
$button.Add_Click({
$timer.Start()
$textbox.Visible =$false
$button.Visible = $false
$label.Visible = $false
$script:1 = New-TimeSpan -minutes ([int]$textbox.Text)
$label2.Visible = $true
$label2.Text = $1.ToString("mm\:ss")
})
$timer = New-Object System.Windows.Forms.Timer
$timer.Enabled = $false
$timer.Interval = '1000'
$second = New-TimeSpan -Seconds 1
$timer.Add_Tick({
$script:1 = $1.Subtract($second)
$label2.Text = $1.ToString("mm\:ss")
if($script:1.TotalSeconds -le 0){$timer.Stop(); $timer.Dispose(); [System.Windows.Forms.Application]::SetSuspendState("Hibernate", $true, $false); $main.Close(); $main.Dispose()}
})
$label2 = New-Object System.Windows.Forms.Label
$label2.Size = '190,30'
$label2.Location = '10,10'
$label2.Text = $1
$font = New-Object System.Drawing.Font("Arial", 23)
$label2.Font = $font
$label2.Visible = $false
$main.Controls.Add($textbox)
$main.Controls.Add($button)
$main.Controls.Add($label)
$main.Controls.Add($label2)
$main.ShowDialog()
})
$Exit.Add_Click({
$app.Visible = $false
Stop-Job -Name "keepAwake"
$appContext.ExitThread()
#Stop-Process -Id $PID
})
$appContext = New-Object System.Windows.Forms.ApplicationContext
[void][System.Windows.Forms.Application]::Run($appContext)

powershell gui creating local users

i need some help with my powershell gui. i want to create a gui for creating local useraccounts with some parameters provided in the checkbox i need to click. the gui is running but i need some help for the code lines for the checkboxes. what do i need to add that the code is running fone when i click the checkboxes? for example if i just click checkbox 1 i get an error the username is to long even i name the testaccount "testuser"
$PSDefaultParameterValues['*:Encoding'] = 'ascii'
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
#create form
$form = New-Object System.Windows.Forms.Form
$form.Width = 500
$form.Height = 400
$form.MaximizeBox = $false
$form.TopMost = $true
$objLabel = New-Object System.Windows.Forms.label
$objLabel.Location = New-Object System.Drawing.Size(10,20)
$objLabel.Size = New-Object System.Drawing.Size(130,15)
$objLabel.BackColor = "Transparent"
$objLabel.ForeColor = "Black"
$objLabel.Text = "name"
$Form.Controls.Add($objLabel)
#textbox with choosen user name
$txtBox = New-Object System.Windows.Forms.TextBox
$txtBox.Location = New-Object System.Drawing.Point (180, 20)
$txtBox.Size = New-Object System.Drawing.Size(280,100)
$form.Controls.Add($txtBox)
$objLabel2 = New-Object System.Windows.Forms.label
$objLabel2.Location = New-Object System.Drawing.Size(10,50)
$objLabel2.Size = New-Object System.Drawing.Size(130,15)
$objLabel2.BackColor = "Transparent"
$objLabel2.ForeColor = "Black"
$objLabel2.Text = "password"
$Form.Controls.Add($objLabel2)
#textbox with choosen password
$txtBox2 = New-Object System.Windows.Forms.TextBox
$txtBox2.Location = New-Object System.Drawing.Point (180, 50)
$txtBox2.Size = New-Object System.Drawing.Size(280,100)
$form.Controls.Add($txtBox2)
#create checkbox1
$checkBox = New-Object System.Windows.Forms.CheckBox
$checkBox.Location = New-Object System.Drawing.Point (10, 100)
$checkBox.Size = New-Object System.Drawing.Size(350,30)
$checkBox.Text = "PasswordNeverExpires"
$form.Controls.Add($checkBox)
#create checkbox2
$checkBox2 = New-Object System.Windows.Forms.CheckBox
$checkBox2.Location = New-Object System.Drawing.Point (10, 150)
$checkBox2.Size = New-Object System.Drawing.Size(350,30)
$checkBox2.Text = "UserMayChangePassword"
$form.Controls.Add($checkBox2)
#create checkbox2
$checkBox3 = New-Object System.Windows.Forms.CheckBox
$checkBox3.Location = New-Object System.Drawing.Point (10, 200)
$checkBox3.Size = New-Object System.Drawing.Size(350,30)
$checkBox3.Text = "AccountNeverExpires"
$form.Controls.Add($checkBox3)
#create user button
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(10,250)
$Button.Size = New-Object System.Drawing.Size(150,50)
$Button.Text = "create user"
$Button.Add_Click({
if(($checkBox.Checked -eq $false) -and ($checkBox2.Checked -eq $false) -and ($checkBox3.Checked -eq $false)) {
[System.Windows.Forms.Messagebox]::Show("No CheckBox checked")
}
#checkbox1 action
if ($checkBox.Checked -eq $true) {
$adminName = $txtBox
$securePassword = $txtBox2
$newUser = New-LocalUser -Name $adminName -Password $securePassword -Description $adminName -FullName $adminName #-ErrorAction Stop
$newUser | Set-LocalUser <#-PasswordNeverExpires $true#> -UserMayChangePassword $false <#-AccountNeverExpires#> #-ErrorAction Stop
Add-LocalGroupMember -Group "Administrators" -Member $adminName #-ErrorAction Stop
if(-not $?) {[System.Windows.Forms.MessageBox]::Show( "no success",'','OK',"Error")}
else {[System.Windows.Forms.MessageBox]::Show( "success",'','OK',"Information")}
}
#checkbox2 action
if ($checkBox2.Checked -eq $true) {
if(-not $?) {[System.Windows.Forms.MessageBox]::Show( "no success",'','OK',"Error")}
else {[System.Windows.Forms.MessageBox]::Show( "success",'','OK',"Information")}
}
#checkbox3 action
if ($checkBox3.Checked -eq $true) {
if(-not $?) {[System.Windows.Forms.MessageBox]::Show( "no success",'','OK',"Error")}
else {[System.Windows.Forms.MessageBox]::Show( "success",'','OK',"Information")}
}
})
$form.Controls.Add($Button2)
#end
[void]$form.ShowDialog()

Add an existing Progressbar into an GUI

I have writen an simple GUI for my command to display. When i press a button my script searches for matches in a Log File and while doing that it displays a Progressbar, but it only displays it in the ISE Window not in the GUI itself. How can i Display it in the GUI.
I found New-Object System.Windows.Forms.ProgressBar when searching for a way.
But in the examples i only found how they do new Bars not add existings that only exist inside of a Button.
This is my Script
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
#Dropdown/Serverauswahl
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$form = New-Object System.Windows.Forms.Form
$form.Text = 'Select a Computer'
$form.Size = New-Object System.Drawing.Size(600,400)
$form.StartPosition = 'CenterScreen'
$okButton = New-Object System.Windows.Forms.Button
$okButton.Location = New-Object System.Drawing.Point(150,240)
$okButton.Size = New-Object System.Drawing.Size(150,46)
$okButton.Text = 'OK'
$okButton.DialogResult = [System.Windows.Forms.DialogResult]::OK
$form.AcceptButton = $okButton
$form.Controls.Add($okButton)
$cancelButton = New-Object System.Windows.Forms.Button
$cancelButton.Location = New-Object System.Drawing.Point(300,240)
$cancelButton.Size = New-Object System.Drawing.Size(150,46)
$cancelButton.Text = 'Cancel'
$cancelButton.DialogResult = [System.Windows.Forms.DialogResult]::Cancel
$form.CancelButton = $cancelButton
$form.Controls.Add($cancelButton)
$label = New-Object System.Windows.Forms.Label
$label.Location = New-Object System.Drawing.Point(10,20)
$label.Size = New-Object System.Drawing.Size(560,40)
$label.Text = 'Please select a Server:'
$form.Controls.Add($label)
$listBox = New-Object System.Windows.Forms.ListBox
$listBox.Location = New-Object System.Drawing.Point(20,80)
$listBox.Size = New-Object System.Drawing.Size(540,40)
$listBox.Font = "courier New, 13"
$listBox.Height =150
[void] $listBox.Items.Add('LNS5')
[void] $listBox.Items.Add('LNS10')
[void] $listBox.Items.Add('LNS13')
[void] $listBox.Items.Add('LNS14')
[void] $listBox.Items.Add('LNS62')
$form.Controls.Add($listBox)
$form.Topmost = $true
$result = $form.ShowDialog()
if ($result -eq [System.Windows.Forms.DialogResult]::OK)
{
$x = $listBox.SelectedItem
$path = "C:\temp\SMTPFilter\${x}filter.txt"
}
#zweites Fenster
$objForm = New-Object System.Windows.Forms.Form
$objForm.StartPosition = "CenterScreen"
$objForm.Size = New-Object System.Drawing.Size(1200,800)
$objForm.Text = "Test GUI"
$form = New-Object System.Windows.Forms.Form
$form.Size = New-Object System.Drawing.Size(900,600)
$dataGridView = New-Object System.Windows.Forms.DataGridView
$dataGridView.Size=New-Object System.Drawing.Size(800,400)
#Filtern
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(30,112)
$OKButton.Size = New-Object System.Drawing.Size(300,92)
$OKButton.Text = "Filtern"
$OKButton.Name = "Filter"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::None
$OKButton.Add_Click({$i= 0
$length = (Get-Content $path).Length
$global:result = Get-Content $path | ForEach-Object {
if($_ -match '(\d{2}\.\d{2}\.\d{4} \d{2}:\d{2}:\d{2}).*\(((?:\d{1,3}\.){3}\d{1,3})\) disconnected\.?\s+(\d+) message\[s\]'){
[PsCustomObject]#{
IP = $matches[2]
Messages = [int]$matches[3]
Date = [datetime]::ParseExact($matches[1], 'dd.MM.yyyy HH:mm:ss', $null)
}}
$i++
if($i % 1000 -eq 0){
Write-Progress -activity "Searching for matches" -status "Scanned: $i of $($length)" -percentComplete (($i / $length) * 100)
}}
Write-Progress -activity "Searching for matches" -status "Scanned: $i of $($length)" -percentComplete (($i / $length) * 100)
#Messages Counted
$global:cumulative = $result | Group-Object -Property IP | ForEach-Object {
try {
$dns = [System.Net.Dns]::GetHostEntry($_.Name).HostName
}
catch {
$dns = 'Not available'
}
[PsCustomObject]#{
IP = $_.Name
Messages = ($_.Group | Measure-Object -Property Messages -Sum).Sum
DNSName = $dns
Date = ($_.Group | Sort-Object Date)[-1].Date
}
}})
$objForm.Controls.Add($OKButton)
#Ergebnis Anzeigen
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(30,214)
$OKButton.Size = New-Object System.Drawing.Size(300,92)
$OKButton.Text = "Ergebnis anzeigen"
$OKButton.Name = "Egebnis Button"
$OKButton.DialogResult = [System.Windows.Forms.DialogResult]::None
$OKButton.Add_Click({$objTextBox1 = New-Object System.Windows.Forms.TextBox
$objTextBox1.Multiline = $True;
$objTextBox1.Location = New-Object System.Drawing.Size(360,10)
$objTextBox1.Size = New-Object System.Drawing.Size(800,600)
$objTextBox1.Text = $cumulative | Out-String
$objTextBox1.Font = "courier New, 13"
$objTextBox1.Scrollbars = "Vertical"
$objForm.Controls.Add($objTextBox1)
#outgridview
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(30,316)
$OKButton.Size = New-Object System.Drawing.Size(300,92)
$OKButton.Text = "Ergebnis in GridView"
$OKButton.Name = "GridView"
$OKButton.DialogResult = "OK"
$OKButton.Add_Click({$cumulative | Out-GridView})
$objForm.Controls.Add($OKButton)
#Export CSV
$OKButton = New-Object System.Windows.Forms.Button
$OKButton.Location = New-Object System.Drawing.Size(30,418)
$OKButton.Size = New-Object System.Drawing.Size(300,92)
$OKButton.Text = "Export CSV (in C:/temp)"
$OKButton.Name = "CSV"
$OKButton.DialogResult = "OK"
$OKButton.Add_Click({$cumulative | Export-Csv -Path 'C:\temp\SMTPresult.Csv'})
$objForm.Controls.Add($OKButton) })
$objForm.Controls.Add($OKButton)
[void] $objForm.ShowDialog()
There is a ProgressBar control available which you can use:
System.Windows.Forms.ProgressBar
See https://mcpmag.com/articles/2014/02/18/progress-bar-to-a-graphical-status-box.aspx for an example
There is also a way of displaying a progressbar inside the taskbar button but you need to deploy a dll from the Microsoft WindowsAPICodePack so that it's available to the person running the script. If you're interested I'll dig out the details

ComboBox.SelectedItem is null

I populated a combobox with AD SamAccountName items. When selecting one of the items, one can push a button in order to retrieve information from that account. However, when clicking the button I receive the below error:
Cannot validate argument on parameter 'Identity'. The argument is null. Provide a valid value for the argument, and then try running the command again.
The command the error refers to is:
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
The crucial part of the code is:
$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$ComboBox.Width = 300
$ComboBox.Location = New-Object -TypeName System.Drawing.Point(250, 25)
$Users = Get-ADUser -Filter * | Where-Object {$_.SamAccountName -match '^adminA'}
ForEach ($User in $Users){
$ComboBox.Items.Add($User.SamAccountName)
}
$ComboBox.SelectedIndex = 1
$MainWindow.Controls.Add($ComboBox)
$Button_Check_TEST = New-Object -TypeName System.Windows.Forms.Button
$Button_Check_TEST.Location = New-Object -TypeName System.Drawing.Size(350, 150)
$Button_Check_TEST.Size = New-Object -TypeName System.Drawing.Size(150, 50)
$Button_Check_TEST.Text = 'Check'
$MainWindow.Controls.Add($Button_Check_TEST)
$Button_Check_TEST.Add_Click({
Try{
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
}
Catch{
Write-Verbose -Verbose $_.Exception.Message
}
})
The problem is, that I need two layers. Basically, there should be a menu with four different options, one of them is 'User'. When clicking on 'User' the ComboBox and the 'Click'-Button shall appear.
Using the code above without the 'User'-Button works fine.
Question: Why does the ComboBox.SelectedItem not work when I use a button to 'create' the ComboBox?
The complete code is below:
$font = New-Object -TypeName System.Drawing.Font("Times New Roman", 18, [System.Drawing.FontStyle]::Bold)
$MainWindow = New-Object -TypeName System.Windows.Forms.Form
$MainWindow.Text = 'PIM v10 Administrator Window'
$MainWindow.Width = 600
$MainWindow.Height = 555
$MainWindow.AutoSize = $true
$Button_User = New-Object -TypeName System.Windows.Forms.Button
$Button_User.Location = New-Object -TypeName System.Drawing.Size(25, 25)
$Button_User.Size = New-Object -TypeName System.Drawing.Size(200, 75)
$Button_User.Text = 'User'
$Button_User.Font = $font
$MainWindow.Controls.Add($Button_User)
$Button_User.Add_Click({
$Label_User = New-Object -TypeName System.Windows.Forms.Label
$Label_User.Text = 'Given Name:'
$Label_User.Location = New-Object -TypeName System.Drawing.Point(250, 50)
$Label_User.AutoSize = $true
$MainWindow.Controls.Add($Label_User)
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$Label_User_ItemContent.Text = ''
$Label_User_ItemContent.Location = New-Object -TypeName System.Drawing.Point(250, 100)
$MainWindow.Controls.Add($Label_User_ItemContent)
$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$ComboBox.Width = 300
$ComboBox.Location = New-Object -TypeName System.Drawing.Point(250, 25)
$Users = Get-ADUser -Filter * | Where-Object {$_.SamAccountName -match '^adminA'}
ForEach ($User in $Users){
$ComboBox.Items.Add($User.SamAccountName)
}
$ComboBox.SelectedIndex = 1
$MainWindow.Controls.Add($ComboBox)
$Button_Check_TEST = New-Object -TypeName System.Windows.Forms.Button
$Button_Check_TEST.Location = New-Object -TypeName System.Drawing.Size(350, 150)
$Button_Check_TEST.Size = New-Object -TypeName System.Drawing.Size(150, 50)
$Button_Check_TEST.Text = 'Check'
$MainWindow.Controls.Add($Button_Check_TEST)
$Button_Check_TEST.Add_Click({
Try{
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
}
Catch{
Write-Verbose -Verbose $_.Exception.Message
}
})
if (-not ($ComboBox.SelectedItem -eq $null)){
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
}
else {
Write-Host -Object "Object is null"
}
})
$MainWindow.ShowDialog()
So whats happening is you are creating variables in the wrong scope
$Button_User.Add_Click({
$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$MainWindow.Controls.Add($ComboBox)
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$Button_Check_TEST.Add_Click({
$Label_User_ItemContent.Text = (Get-ADUser -Identity
$ComboBox.SelectedItem).SamAccountName
)}
})
Since you are creating the Combo and the Lable inside a Add_click action. Those Values only exist when the action is taken and in the $MainWindows.Controls. The items are then cleared from memory
When you run the next action $Button_Check_TEST.Add_Click() since the variables are cleared then $ComboBox and $Label_User_ItemContent equal nothing.
A fix would be to place them outside the $Button_User.Add_Click() event
$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$Button_User.Add_Click({
$MainWindow.Controls.Add($ComboBox)
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$Button_Check_TEST.Add_Click({
$Label_User_ItemContent.Text = (Get-ADUser -Identity
$ComboBox.SelectedItem).SamAccountName
)}
})
Here is the whole script in working condition now
$font = New-Object -TypeName System.Drawing.Font("Times New Roman", 18, [System.Drawing.FontStyle]::Bold)
$MainWindow = New-Object -TypeName System.Windows.Forms.Form
$MainWindow.Text = 'PIM v10 Administrator Window'
$MainWindow.Width = 600
$MainWindow.Height = 555
$MainWindow.AutoSize = $true
$Button_User = New-Object -TypeName System.Windows.Forms.Button
$Button_User.Location = New-Object -TypeName System.Drawing.Size(25, 25)
$Button_User.Size = New-Object -TypeName System.Drawing.Size(200, 75)
$Button_User.Text = 'User'
$Button_User.Font = $font
$MainWindow.Controls.Add($Button_User)
$ComboBox = New-Object -TypeName System.Windows.Forms.ComboBox
$Label_User_ItemContent = New-Object -TypeName System.Windows.Forms.Label
$Button_User.Add_Click({
$Label_User = New-Object -TypeName System.Windows.Forms.Label
$Label_User.Text = 'Given Name:'
$Label_User.Location = New-Object -TypeName System.Drawing.Point(250, 50)
$Label_User.AutoSize = $true
$MainWindow.Controls.Add($Label_User)
$Label_User_ItemContent.Text = ''
$Label_User_ItemContent.Location = New-Object -TypeName System.Drawing.Point(250, 100)
$MainWindow.Controls.Add($Label_User_ItemContent)
$ComboBox.Width = 300
$ComboBox.Location = New-Object -TypeName System.Drawing.Point(250, 25)
$Users = Get-ADUser -Filter * | Where-Object {$_.SamAccountName -match '^adminA'}
$MainWindow.Controls.Add($ComboBox)
ForEach ($User in $Users){
$ComboBox.Items.Add($User.SamAccountName)
}
$MainWindow.Controls.Add($ComboBox)
$ComboBox.SelectedIndex = 0
$Button_Check_TEST = New-Object -TypeName System.Windows.Forms.Button
$Button_Check_TEST.Location = New-Object -TypeName System.Drawing.Size(350, 150)
$Button_Check_TEST.Size = New-Object -TypeName System.Drawing.Size(150, 50)
$Button_Check_TEST.Text = 'Check'
$MainWindow.Controls.Add($Button_Check_TEST)
$Button_Check_TEST.Add_Click({
Try{
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
}
Catch{
Write-Verbose -Verbose $_.Exception.Message
}
})
if (-not ($ComboBox.SelectedItem -eq $null)){
$Label_User_ItemContent.Text = (Get-ADUser -Identity $ComboBox.SelectedItem).SamAccountName
}
else {
Write-Host -Object "Object is null"
}
})
$MainWindow.ShowDialog()

Build Checkbox list programmatically using powershell

I am trying to populate checkbox from value return in $domain = Get-MsolDomain which return domains available then generate the checkbox based on the value return and excluding the value from #mail. Thank you
Here is the code that i have so far:
$snapin = Get-PSSnapin | Where-Object {$_.Name -eq 'Microsoft.SharePoint.Powershell'}
if ($snapin -eq $null)
{
Write-Host -foregroundcolor Green "Loading SharePoint PowerShell Snapin"
Add-PSSnapin "Microsoft.SharePoint.Powershell"
}
Import-Module MSOnline
$credentials = Get-Credential
Connect-MsolService -Credential $credentials
$unlicensedUsersBatch500 = Get-MsolUser -UnlicensedUsersOnly -MaxResults 500
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(600,700)
$Form.text ="Office 365 Licence Activation"
############################################## Start group boxes
$groupBox = New-Object System.Windows.Forms.GroupBox
$groupBox.Location = New-Object System.Drawing.Size(240,20)
$groupBox.size = New-Object System.Drawing.Size(200,100)
$groupBox.text = "Availabe Office 365 Domains:"
$Form.Controls.Add($groupBox)
$Checkboxes += New-Object System.Windows.Forms.CheckBox
$Checkboxes.Location = New-Object System.Drawing.Size(10,20)
$domain = Get-MsolDomain
foreach ($a in $domain)
{
for ($i=1;$i -lt 6; $i++)
{
$Checkboxes.Text = $a.Name
}
}
$groupBox.Controls.Add($Checkboxes)
I would do it as follows. Note that I created and populated $domain for the sake of testing, so you will need to replace that with your call to Get-MsolDomain.
Small plus, the size of the groupbox will grow automatically, based on the number of elements in $domain.
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$Form = New-Object System.Windows.Forms.Form
$Form.Size = New-Object System.Drawing.Size(600,700)
$Form.text ="Office 365 Licence Activation"
############################################## Start group boxes
$groupBox = New-Object System.Windows.Forms.GroupBox
$groupBox.Location = New-Object System.Drawing.Size(240,20)
$groupBox.text = "Availabe Office 365 Domains:"
$Form.Controls.Add($groupBox)
$Checkboxes += New-Object System.Windows.Forms.CheckBox
$Checkboxes.Location = New-Object System.Drawing.Size(10,20)
#$domain = Get-MsolDomain
$domain = #()
$domain += #{"Name"="domain1"}
$domain += #{"Name"="domain2"}
$domain += #{"Name"="domain3"}
$Checkboxes = #()
$y = 20
foreach ($a in $domain)
{
$Checkbox = New-Object System.Windows.Forms.CheckBox
$Checkbox.Text = $a.Name
$Checkbox.Location = New-Object System.Drawing.Size(10,$y)
$y += 30
$groupBox.Controls.Add($Checkbox)
$Checkboxes += $Checkbox
}
$groupBox.size = New-Object System.Drawing.Size(200,(40*$checkboxes.Count))
$form.ShowDialog()| Out-Null