I created a PS form with a MenuStrip and some abilities. In VS Code the first time I run it the MenuStrip works but nothing else. It’ll act the same way in a PS terminal. Only the MenuStrip works. When I run it a second time in VS Code everything works as it should, MenuStrip and the different set of abilities run as intended.
If I run that same form/app (whatever it’s called) from a PS terminal, it will run and the MenuStrip operations are doing what they are supposed to, just as when run from VS Code, but the actual tasks won’t work at all, no matter how often you start the form through the PS terminal. I’m wondering if the script has to load the assemblies into the session before those operations will work. So running in VS Code will work the second time because it’s loaded the assemblies from the first run, but each time you run it from a PS terminal it’s a different session so it can’t reference the assemblies? Similar to how .NET has to “prime” itself when starting up the first time. I don’t know if that’s accurate or not, which is why I’m here.
This is my first PS form, and I’m very sure there are many things with the code that could be better, but here’s a stripped down version and directions:
- From Within VS Code, click to run the script.
- Click on Home > Gather Information
- Click on Function > Last Boot Time
- Enter the name of the remote system you want to get the last boot time from
- click the button
Notice the first time you run the script from within VS Code it won’t work. Menu items do what they need to do, but it won’t fetch the last boot time.
When you run it a second time from within VS Code (following the same steps above) it will fetch the last boot time of the remote system and output the results.
If you run the ps1 from a PS terminal, the menu functions work, but it doesn’t matter how many times you run it the operation to get the last boot time doesn’t run.
What my end goal here is to package it up as an executable and have the whole thing run on the first load. Does anyone have a nugget of knowledge to drop on how to make this little guy work as intended?
# Load external assemblies
Add-Type -AssemblyName System.Windows.Forms
Add-Type -AssemblyName System.Drawing
[System.Windows.Forms.Application]::EnableVisualStyles()
#Get the screen resolution dimentions for dynamic main form sizing
$res = Get-CimInstance CIM_VideoController | Select CurrentHorizontalResolution, CurrentVerticalResolution
# ****************************************************
# **************Begin Menu Creation*******************
# ****************************************************
#Instantiate the menu strip object
$MS_Main = new-object System.Windows.Forms.MenuStrip
#Create Home menu items
$HomeMenu = new-object System.Windows.Forms.ToolStripMenuItem
$HomeGatherMenu = new-object System.Windows.Forms.ToolStripMenuItem
# Home menu buildout - This adds all the items to the HomeMenu menu
$HomeMenu.DropDownItems.AddRange(@($HomeGatherMenu))
$HomeMenu.Name = "HomeMenu"
$HomeMenu.Size = new-object System.Drawing.Size(35, 20)
$HomeMenu.Text = "&Home"
#Create Function menu items
$FunctionMenu = new-object System.Windows.Forms.ToolStripMenuItem
# ******* Gather Menu Items
$FunctionGLastBootMenu = new-object System.Windows.Forms.ToolStripMenuItem
# Function Menu buildout - This adds all the items to the FunctionMenu menu
$FunctionMenu.DropDownItems.AddRange(@($FunctionGLastBootMenu))
$FunctionMenu.Name = "FunctionMenu"
$FunctionMenu.Size = new-object System.Drawing.Size(75, 20)
$FunctionMenu.Text = "&Function"
# Menu Strip Main (MS_Main) setup
# This will add the Home, Function and Help/About menu items to the menu bar
$MS_Main.Items.AddRange(@($HomeMenu,$FunctionMenu))
$MS_Main.Location = new-object System.Drawing.Point(0, 0)
$MS_Main.Name = "MS_Main"
$MS_Main.Size = new-object System.Drawing.Size(354, 24)
$MS_Main.TabIndex = 0
$MS_Main.Text = "menuStrip1"
# ****************************************************
# ************** End Menu Creation *******************
# ****************************************************
# ****************************************************
# **** Begin Menu Item Creation and Implementation ***
# ****************************************************
# *********** Home Menu Item Buildout ***********
# HomeGatherMenu
$HomeGatherMenu.Name = "HomeGatherMenu"
$HomeGatherMenu.Size = new-object System.Drawing.Size(152, 22)
$HomeGatherMenu.Text = "&Gather Information"
$HomeGatherMenu.Add_Click( { OnClick_HomeGatherMenu $HomeGatherMenu $EventArgs} )
function OnClick_HomeGatherMenu($Sender,$e){
# ******** Show Gather Menu
$FunctionGLastBootMenu.Visible = $true
}
# ****** FUNCTION MENU ***********
# Populate the Function menu with the contextual functions
$FunctionGLastBootMenu.Name = "FunctionGLastBootMenu"
$FunctionGLastBootMenu.Size = New-Object System.Drawing.Size(152, 22)
$FunctionGLastBootMenu.Text = "&Last Boot Time"
$FunctionGLastBootMenu.Visible = $false
$FunctionGLastBootMenu.Add_Click({ OnClick_FunctionGLastBootMenu $FunctionGLastBootMenu $EventArgs})
# ****************************************************
# **** End Menu Item Creation and Implementation *****
# ****************************************************
# Create the main form for the app
$YAYMainForm = new-object System.Windows.Forms.form
$YAYMainForm.ClientSize = new-object System.Drawing.Size(($res.CurrentHorizontalResolution / 2), ($res.CurrentVerticalResolution / 1.75))
$YAYMainForm.Controls.Add($MS_Main)
$YAYMainForm.MainMenuStrip = $MS_Main
$YAYMainForm.BackgroundImage = $Image
$YAYMainForm.BackgroundImageLayout = "None"
$YAYMainForm.FormBorderStyle = 1
$YAYMainForm.MaximizeBox = $false
$YAYMainForm.Name = "YAYMainForm"
$YAYMainForm.BackColor = "#eeeeee"
#*******Create BTNGet (CONSTANT)*******
$BTNGet = New-Object system.Windows.Forms.Button
#$BTNGet.text = "Fetch"
$BTNGet.height=25
$BTNGet.width=75
$BTNGet.AutoSize = $true
$BTNGet.top= 73
$BTNGet.left=135
$BTNGet.BackColor = "#E6F3FF"
$BTNGet.Visible = $false
$BTNGet.add_click($BTNGetClick)
$YAYMainForm.controls.add($BTNGet)
#*******End button 1*******
#*******Status Label*****
# Placement needs to stay static
$LBLStatus = New-Object System.Windows.Forms.Label
$LBLStatus.Width = 40
$LBLStatus.Height = 20
$LBLStatus.top = 165
$LBLStatus.left = 26
$LBLStatus.visible = $true
$LBLStatus.text = "Status: "
$LBLStatus.BackColor = "#777777"
$LBLStatus.ForeColor = "#ffffff"
#*******End Status label********
#*******Status Output Label*****
# Placement needs to stay static
$LBLStatusOut = New-Object System.Windows.Forms.Label
#$LBLStatusOut.AutoSize = $true
$LBLStatusOut.Width = $res.CurrentHorizontalResolution / 2.212
$LBLStatusOut.Height = 20
$LBLStatusOut.top = 165
$LBLStatusOut.left = 67
$LBLStatusOut.visible = $true
$LBLStatusOut.BackColor = "#f6fcf5"
#*******End Status Output label********
#*******Host Name Label (CONSTANT)*****
$LBLHostName = New-Object System.Windows.Forms.Label
$LBLHostName.AutoSize = $true
$LBLHostName.top = 55
$LBLHostName.left = 26
$LBLHostName.Text = "Host Name:"
$LBLHostName.visible = $false
#*******End Host Name Label********
#*******Host Name Textbox*****
$TBHostName = New-object System.Windows.Forms.TextBox
$TBHostName.top = 75
$TBHostName.Left = 26
$TBHostName.BorderStyle = 1
$TBHostName.Visible = $false
$YAYMainForm.Controls.add($TBHostName)
#*******End Textbox 1********
# This next line adds the various labels to the form.
$YAYMainForm.Controls.AddRange(@($LBLStatusOut,$LBLHostName, $LBLStatus))
#********** Button Clicks **********
$BTNGetClick = {
$MethodSeed = $GLOBAL:BTNGetText
BTNGetRun -MethodSeed $MethodSeed
}
#********** END Buttn Clicks *******
#***********************************
#********** Button functions ***********
function BTNSeed ($ValueSeed) {
Switch ($ValueSeed){
"GLB" {$GLOBAL:BTNGetText = "Get Last Boot Time"}
} #End Switch
} #End Function
function BTNGetRun ($MethodSeed){
Switch ($MethodSeed){
"Get Last Boot Time" {
try {
$LBLStatusOut.Text = "Figuring out when this guy was last rebooted. Stay tuned..."
$GLBT = gcim -ComputerName $TBHostName.Text Win32_OperatingSystem
$TXTOutPut.text = ($TBHostName.text+" was last booted: "+$GLBT.LastBootUpTime)
$LBLStatusOut.Text = "Complete. Last boot information is below."
}
catch {
$LBLStatusOut.text = "An error occurred: see the message below."
$TXTOutPut.text = $_
}
} #END Last Boot Try/catch
}
}
#********** END Button functions ***********
#*******************************************
#*******************************************
#************* Menu functions ***************
function OnClick_FunctionGLastBootMenu{
#Set the seed for the button text value
$ValueSeed = "GLB"
#Call the function to get the BTNGET text
BTNSeed -ValueSeed $ValueSeed
#Set the BTNGet text value
$BTNGet.Text = $GLOBAL:BTNGetText
$BTNGet.Visible = $true
$TBHostName.Visible = $true
$LBLHostName.Visible = $true
}
#*********************************************
#***********END Menu Functions****************
#*********************************************
#*******Informational Output TextArea*****
$TXTOutPut = New-Object System.Windows.Forms.TextBox
$TXTOutPut.AutoSize = $true
$TXTOutPut.Height = ($res.CurrentVerticalResolution / 2.6)
$TXTOutPut.Width = ($res.CurrentHorizontalResolution / 2.11)
$TXTOutPut.multiline = $True
$TXTOutPut.scrollbars = "Vertical, Horizontal"
$TXTOutPut.Font="Lucida Console"
$TXTOutPut.wordwrap = $false
$TXTOutPut.top = 190
$TXTOutPut.left = 25
$YAYMainForm.Controls.Add($TXTOutPut)
#*******EndInformational Output TextArea********
function OnFormClosing_YAYMainForm($Sender,$e){
# $this represent sender (object)
# $_ represent e (eventarg)
# Allow closing
($_).Cancel= $False
}
$YAYMainForm.Add_FormClosing( { OnFormClosing_YAYMainForm $YAYMainForm $EventArgs} )
$YAYMainForm.Add_Shown({$YAYMainForm.Activate()})
$YAYMainForm.ShowDialog()
#Free ressources
$YAYMainForm.Dispose()
