How to close a winform with powershell? - winforms

I have created a winform:
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
function more {
$MoreTools = New-Object system.Windows.Forms.Form
$MoreTools.ClientSize = New-Object System.Drawing.Point(903,473)
$MoreTools.text = "$title002"
$MoreTools.TopMost = $false
$MoreTools.icon = "ressources\pictures\ico.ico"
$MoreTools.StartPosition = 'CenterScreen'
$ButtonB = New-Object system.Windows.Forms.Button
$ButtonB.text = "$button007"
$ButtonB.width = 128
$ButtonB.height = 25
$ButtonB.location = New-Object System.Drawing.Point(387,350)
$ButtonB.Font = New-Object System.Drawing.Font('Segoe UI',10)
$MoreTools.controls.AddRange(#($ButtonB))
$ButtonB.Add_Enter({
$MoreTools.Close
})
[void]$MoreTools.ShowDialog()
}
more
exit
When I use exit or $MoreTools.Close it doesn't want to close.
So, how to close the form or where is the error?
Thanks
JJB

Use add_Click() method rather than Add_Enter() on a button; moreover, .Close does not mean .Close():
$ButtonB.Add_Click({
$MoreTools.Close();
$MoreTools.Dispose(); # facultative
})

Related

PowerShell and Windows Forms Tooltip custom colour

I'm trying to customise a simple tooltip with a black background (and black border if possible) and white text. I have the following code, but at the moment it's flakey, sometimes works, other times doesn't.
Can somebody please advise how to make this more reliable? Thanks.
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Windows.Forms.Application]::EnableVisualStyles()
Add-Type -AssemblyName System.Drawing
#create form
$form = New-Object System.Windows.Forms.Form
$shutdownBtn = New-Object System.Windows.Forms.Button
$shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
$shutdownBtn.Text = "Shut down"
$form.Controls.Add($shutdownBtn)
$tooltip2 = New-Object System.Windows.Forms.ToolTip
$tooltip2.SetToolTip($shutdownBtn, "Shut down.")
$tooltip2.OwnerDraw = $true
$tooltip2.Add_Draw($tooltip2_Draw)
$tooltip2_Draw=[System.Windows.Forms.DrawToolTipEventHandler]{
$fontstyle = New-Object System.Drawing.Font("Segoe UI", 9, [System.Drawing.FontStyle]::Normal)
$format = [System.Drawing.StringFormat]::GenericTypographic
$myBrush1 = new-object Drawing.SolidBrush White
$_.Graphics.DrawString($_.ToolTipText, $fontstyle, $myBrush1, $_.Bounds.X, $_.Bounds.Y, $format)
$myBrush2 = new-object Drawing.SolidBrush Black
$_.Graphics.FillRectangle($myBrush2, $_.Bounds)
$_.DrawBackground()
$_.DrawBorder()
$_.DrawText()
}
$form_cleanup =
{
$tooltip2.Remove_Draw($tooltip2_Draw)
$form.remove_FormClosed($form_cleanup)
}
$form.add_FormClosed($form_cleanup)
[void]$form.ShowDialog()
$form.Dispose()
I'll answer my own question:
There were a couple of glaring errors from a tired mind. Firstly:
$tooltip2.Add_Draw($tooltip2_Draw)
should have been called after I declared
$tooltip2_Draw
Secondly, I needed to call
FillRectangle
before i called
DrawString
And finally, since I set OwnerDraw = $true I didn't need to call:
$_.DrawBackground()
$_.DrawBorder()
$_.DrawText()
So here is the solution:
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[System.Windows.Forms.Application]::EnableVisualStyles()
Add-Type -AssemblyName System.Drawing
#create form
$form = New-Object System.Windows.Forms.Form
$shutdownBtn = New-Object System.Windows.Forms.Button
$shutdownBtn.Size = New-Object System.Drawing.Size(200, 40)
$shutdownBtn.Text = "Shut down"
$form.Controls.Add($shutdownBtn)
$tooltip2 = New-Object System.Windows.Forms.ToolTip
$tooltip2.SetToolTip($shutdownBtn, "Shut down now.")
$tooltip2.OwnerDraw = $true
$tooltip2_Draw=[System.Windows.Forms.DrawToolTipEventHandler]{
$fontstyle = new-object System.Drawing.Font('Microsoft Sans Serif', 16, [System.Drawing.FontStyle]::Regular)
$format = [System.Drawing.StringFormat]::GenericTypographic
$format.LineAlignment = [System.Drawing.StringAlignment]::Center;
$format.Alignment = [System.Drawing.StringAlignment]::Center;
$whiteBrush = new-object Drawing.SolidBrush White
$blackBrush = new-object Drawing.SolidBrush Black
$_.Graphics.FillRectangle($blackBrush, $_.Bounds)
$_.Graphics.DrawString($_.ToolTipText, $fontstyle, $whiteBrush, ($_.Bounds.X + ($_.Bounds.Width/2)), ($_.Bounds.Y + ($_.Bounds.Height/2)), $format)
}
$tooltip2.Add_Draw($tooltip2_Draw)
$form_cleanup =
{
$tooltip2.Remove_Draw($tooltip2_Draw)
$form.remove_FormClosed($form_cleanup)
}
$form.add_FormClosed($form_cleanup)
[void]$form.ShowDialog()
$form.Dispose()

Unable to process powershell function with content from windows form

function CalendarShare {
Add-MailboxFolderPermission -Identity ${FromUser.Text} -AccessRights Editor -User ${ToUser.Text}
}
When the program is running, it works until it processes the share calendar button. It states that it
cannot bind the argument parameter identity because it is null.
I have no idea what can cause this
Full code:
Add-Type -AssemblyNAme System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
#Declare Functions
function login {
$LiveCred = Get-Credential
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic -AllowRedirection
Import-PSSession $Session
$btnlogin.Visible = $False
}
function quitprogram {
$Form.Close()
Exit-PSSession []
}
function CalendarShare {
Add-MailboxFolderPermission -Identity ${FromUser.Text} -AccessRights Editor -User ${ToUser.Text}
}
#Creates base form
$Form = New-Object system.Windows.Forms.Form
$Form.ClientSize = '400,400'
$Form.Text = 'Powershell GUI'
$Form.TopMost = $False
#Creates Login button
$btnlogin = New-Object System.windows.Forms.button
$btnlogin.text = 'Login'
$btnlogin.width = 80
$btnlogin.height = 40
$btnlogin.location = New-Object System.Drawing.Point(150,5)
#Add_Click defines what to do on click
$btnlogin.Add_Click( {
login #function previously defined. Line 6
})
#Creates label for From user
$FromUserLabel = New-Object system.Windows.Forms.Label
$FromUserLabel.text = 'Share Calendar From User'
$FromUserLabel.AutoSize = $true
$FromUserLabel.width = 25
$FromUserLabel.height = 10
$FromUserLabel.location = New-Object System.Drawing.Point(130,100) #Define where it appears on the map
#Create first input. From User
$FromUser = New-Object system.Windows.Forms.TextBox
$FromUser.multiline = $False
$FromUser.width - 200
$FromUser.height = 20
$FromUser.location = New-Object System.Drawing.Point(135,125)
#Create label for To user
$ToUserLabel = New-Object system.Windows.Forms.Label
$ToUserLabel.text = 'Share Calendar To User'
$ToUserLabel.AutoSize = $True
$ToUserLabel.width = 25
$ToUserLabel.height = 10
$ToUserLabel.location = New-Object System.Drawing.Point(135,175)
#Create second input. To User
$ToUser = New-Object system.Windows.Forms.TextBox
$ToUser.multiline = $False
$ToUser.width - 200
$ToUser.height = 20
$ToUser.location = New-Object System.Drawing.Point(135,200)
#Create Share Button Calendar
$btnsharecalendar = New-Object System.windows.Forms.button
$btnsharecalendar.text = 'Share Calendar'
$btnsharecalendar.width = 165
$btnsharecalendar.height = 30
$btnsharecalendar.location = New-Object System.Drawing.Point(105,275)
#Define Add_Click below
$btnsharecalendar.Add_Click({
CalendarShare
})
#Create button to close program
$btnquit = New-Object System.windows.Forms.button
$btnquit.text = 'Quit'
$btnquit.width = 80
$btnquit.height = 40
$btnquit.location = New-Object System.Drawing.Point(150,325)
#Add_Click defines what to do on click
$btnquit.Add_Click( {
quitprogram #function previously defined. Line 12
})
#Allows form to work
$Form.Controls.AddRange(#($btnlogin,$FromUserLabel,$FromUser,$ToUserLabel,$ToUser,$btnsharecalendar,$btnquit))
$Form.ShowDialog()
Note: This is assuming that both $FromUser and $ToUser are textboxes
You aren't using your variable correctly for the identity parameter, should be:
function CalendarShare {
Add-MailboxFolderPermission -Identity $FromUser.Text -AccessRights Editor -User $ToUser.Text}
}

Get returned variable from add_Click event (PowerShell)

The goal is to get the "The Returned Variable Worked" into a variable.
I am trying to avoid the using any globals such as $Script: $Global:
Out-host is not an option. Ideally the "Generate-Form" function could return the variable.
Function Button_Click()
{
[System.Windows.Forms.MessageBox]::Show("Button Clicked")
$returnedVariable = "The Returned Variable Worked"
Return $returnedVariable
}
Function Generate-Form {
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
# Build Form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "My Form"
$Form.Size = New-Object System.Drawing.Size(200,200)
$Form.StartPosition = "CenterScreen"
$Form.Topmost = $True
# Add Button
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(35,35)
$Button.Size = New-Object System.Drawing.Size(120,23)
$Button.Text = "Show Dialog Box"
$Form.Controls.Add($Button)
#Add Button event
$OutputVariableFromGenerateForm = $Button.Add_Click({$returnedVar = Button_Click ; $Form.Close(); return $returnedVar})
# $returnedVar contains an array #("OK,"The Returned Variable Worked"),
# but it appears to be out of scope because it is in a script block.
# I only want "The Returned Variable Worked"
#Show the Form
$form.ShowDialog()| Out-Null
$OutputVariableFromGenerateForm # This is null
$returnedVar # This is null
} #End Function
Generate-Form
Use a hashtable:
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
$hash = [hashtable]::Synchronized(#{})
$hash.returnedVar = ""
Function Button_Click() {
[System.Windows.Forms.MessageBox]::Show("Button Clicked")
$returnedVariable = "The Returned Variable Worked"
Return $returnedVariable
}
Function Generate-Form {
# Build Form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "My Form"
$Form.Size = New-Object System.Drawing.Size(200,200)
$Form.StartPosition = "CenterScreen"
$Form.Topmost = $True
# Add Button
$Button = New-Object System.Windows.Forms.Button
$Button.Location = New-Object System.Drawing.Size(35,35)
$Button.Size = New-Object System.Drawing.Size(120,23)
$Button.Text = "Show Dialog Box"
$Form.Controls.Add($Button)
#Add Button event
$OutputVariableFromGenerateForm = $Button.Add_Click({$hash.returnedVar = Button_Click; [void]$form.Close(); [void]$form.Dispose(); })
# $returnedVar contains an array #("OK,"The Returned Variable Worked"),
# but it appears to be out of scope because it is in a script block.
# I only want "The Returned Variable Worked"
#Show the Form
[void]$form.ShowDialog()
$OutputVariableFromGenerateForm # This is OK
$hash.returnedVar # This is "The Returned Variable Worked"
} #End Function
Generate-Form

.NET DateTimePicker calendar not appearing in PowerShell form

I am trying to show a DateTimePicker in a WinForms form in PowerShell. When the form appears, the date can be changed, but hitting the dropdown button doesn't show the calendar. It seems like something is happening, it's just not visible.
What stupid thing am I missing here?
$form = New-Object Windows.Forms.Form
$form.Size = New-Object Drawing.Size #(400, 400)
$form.StartPosition = "CenterScreen"
$form.Text = "When do you want the snapshot to be taken?"
$form.Font = New-Object Drawing.Font("Microsoft Sans Serif",12)
$form.FormBorderStyle = [Windows.Forms.FormBorderStyle]::Fixed3D
$panel = New-Object Windows.Forms.FlowLayoutPanel
$panel.Height = 400
$panel.Width = 400
$panel.AutoScroll = $true
$panel.FlowDirection = [Windows.Forms.FlowDirection]::TopDown
$panel.WrapContents = $false
$titleText = New-Object Windows.Forms.Label
$titleText.AutoSize = $true
$titleText.Text = "When do you want the snapshot to be taken?"
$panel.Controls.Add($titleText)
$datePicker = New-Object Windows.Forms.DateTimePicker
$datePicker.ShowUpDown = $false
$datePicker.MinDate = $now
$datePicker.MaxDate = $now.AddMonths(3); #arbitrary
$datePicker.MaxSelectionCount = 1
$datePicker.Width = 350
$datePicker.Enabled = $false
$panel.Controls.Add($datePicker)
$form.Controls.Add($panel)
$drc = $form.ShowDialog()
Your code seems to work fine on my computer. I copy-pasted your code and added Add-Type to top:
Add-Type -AssemblyName System.Windows.Forms
And changed the $datePicker.Enabled:
$datePicker.Enabled = $true
When run, I can change the date/time and also the dropdown is working as expected:

Power Shell marquee progress bar not working

What I'm attempting to do is create a window using forms and add a marquee style progress bar that continuously loops while my script runs. I'm not concerned about tracking progress, it is just so the user knows that something is occurring.
Here's what I have so far:
Add-Type -AssemblyName System.Windows.Forms
$window = New-Object Windows.Forms.Form
$window.Size = New-Object Drawing.Size #(400,75)
$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
$window.Controls.Add($ProgressBar1)
$window.ShowDialog()
This draws the progress bar and the window, but I don't get the marquee animation inside the progress bar.
What am I missing?
VisualStyles must be enabled. That's why on ISE works, but doesn't on Console.
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.Application]::EnableVisualStyles()
$window = New-Object Windows.Forms.Form
$window.Size = New-Object Drawing.Size #(400,75)
$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
$window.Controls.Add($ProgressBar1)
$window.ShowDialog()

Resources