Solved

Powershell GUI need button actions to work

Posted on 2014-10-21
11
546 Views
Last Modified: 2014-11-16
I thought this was going to be simple. In concept it does not seems too hard. I have some template code that has been Provided to run a GUI.

I do know that this command does give me the data I need
Get-WmiObject Win32_Service -ComputerName $Targetserver  | where{ ($_.StartMode -eq "Auto" -or $_.StartMode -eq "Disabled")-and $_.State -ne "Running" } | Select name, StartMode | Format-Table

But I cant translate it into the form as the checklistbox ($TargetServices) to be processed


GUI objective: Query $TargetServer variable and display services in CheckListBox with name and State. When the QueryServer button is pressed.
Here is the code
function OnApplicationLoad {
	#Note: This function is not called in Projects
	#Note: This function runs before the form is created
	#Note: To get the script directory in the Packager use: Split-Path $hostinvocation.MyCommand.path
	#Note: To get the console output in the Packager (Windows Mode) use: $ConsoleOutput (Type: System.Collections.ArrayList)
	#Important: Form controls cannot be accessed in this function
	#TODO: Add modules and custom code to validate the application load
	
	return $true #return true for success or false for failure
}


function OnApplicationExit {
	#Note: This function is not called in Projects
	#Note: This function runs after the form is closed
	#TODO: Add custom code to clean up and unload modules when the application exits
	
	$script:ExitCode = 0 #Set the exit code for the Packager
}

$FormEvent_Load={
	#TODO: Initialize Form Controls here
	
}

#region Control Helper Functions
function Load-ListBox 
{
<#
	.SYNOPSIS
		This functions helps you load items into a ListBox or CheckedListBox.

	.DESCRIPTION
		Use this function to dynamically load items into the ListBox control.

	.PARAMETER  ListBox
		The ListBox control you want to add items to.

	.PARAMETER  Items
		The object or objects you wish to load into the ListBox's Items collection.

	.PARAMETER  DisplayMember
		Indicates the property to display for the items in this control.
	
	.PARAMETER  Append
		Adds the item(s) to the ListBox without clearing the Items collection.
	
	.EXAMPLE
		Load-ListBox $ListBox1 "Red", "White", "Blue"
	
	.EXAMPLE
		Load-ListBox $listBox1 "Red" -Append
		Load-ListBox $listBox1 "White" -Append
		Load-ListBox $listBox1 "Blue" -Append
	
	.EXAMPLE
		Load-ListBox $listBox1 (Get-Process) "ProcessName"
#>
	
	
	Param (
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		[System.Windows.Forms.ListBox]$ListBox,
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		$Items,
	    [Parameter(Mandatory=$false)]
		[string]$DisplayMember,
		[switch]$Append
	)
	
	if(-not $Append)
	{
		$listBox.Items.Clear()	
	}
	
	if($Items -is [System.Windows.Forms.ListBox+ObjectCollection])
	{
		$listBox.Items.AddRange($Items)
	}
	elseif ($Items -is [Array])
	{
		$listBox.BeginUpdate()
		foreach($obj in $Items)
		{
			$listBox.Items.Add($obj)
		}
		$listBox.EndUpdate()
	}
	else
	{
		$listBox.Items.Add($Items)	
	}

	$listBox.DisplayMember = $DisplayMember	
}
#endregion

$buttonQueryServer_Click={
	#TODO: Place custom script here
	
	Load-ListBox $listBox (Get-WmiObject Win32_Service -ComputerName "Spiderman" | where{ ($_.StartMode -eq "Auto" -or $_.StartMode -eq "Disabled") -and $_.State -ne "Running" } | Select name, StartMode ) "ServiceNames"
	
}

Open in new window


This is the error when Ran
>> Running (CheckBoxList.psf) Script...
>> Building (CheckBoxList.psf) ...
>> Platform: V4 64Bit (STA)
ERROR: Load-ListBox : Cannot validate argument on parameter 'ListBox'. The argument is null. Provide a valid value for the argument, and then try running the command
ERROR: again.
CheckBoxList.psf (105): ERROR: At Line: 105 char: 15
ERROR: +         Load-ListBox $listBox (Get-WmiObject Win32_Service -ComputerName "Spiderman" | ...
ERROR: +                      ~~~~~~~~
ERROR:     + CategoryInfo          : InvalidData: (:) [Load-ListBox], ParameterBindingValidationException
ERROR:     + FullyQualifiedErrorId : ParameterArgumentValidationError,Load-ListBox
ERROR:

>> Execution time: 00:00:18
>> Script Ended

Open in new window


GUIProperties
0
Comment
Question by:Leo Torres
  • 6
  • 5
11 Comments
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
Your $listbox var seems not be populated with the ListBox GUI code.

BTW, I recommend to use Get-Service instead of using WMI. And you probably want to include some type of formatting, as the list box will contain just service name and state separated by a single space.
0
 
LVL 8

Author Comment

by:Leo Torres
Comment Utility
I guess I don't have the command in the right place with in the code. I know the command works and it returns data I just need to pass the dataset to the CheckboxList which is my struggle.

As for the Get-Service sure I can use that as long as I can bring back all service that are not running whether its on "Automatic" or "Disabled". And I also forgot in the code but I also need to list Service that are in a Starting State.
0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
Re "Pass the dataset to the Checkboxlist": that is definitely an issue, as the list receives a bunch of strings, and cannot handle the underlying objects, so you need to do the formatting pre-display and the parsing after submitting choices. Don't underestimate that parts.

Re "Starting State", you already get those. Everything different from "Running" will we pass thru.

A slightly improved way to ask for the services using WMI is:
Get-WmiObject Win32_Service -ComputerName $TargetServer | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | Select name, StartMode, State

Open in new window

Note that I've also added the State info, which gets important for "Starting", maybe hinting that there is an issue with that service.

Please ignore my note about Get-Service - it does not reveal the start mode, so is not suited for your needs here.
0
 
LVL 8

Author Comment

by:Leo Torres
Comment Utility
Thanks for the code. Sorry about delay. Code now works great! Except for one minor detail you are returning an array of items. I need to have columns for each item.

10-29-2014-7-48-47-AM.png
function Load-ListBox 
{
	Param (
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		[System.Windows.Forms.ListBox]$ListBox,
		[ValidateNotNull()]
		[Parameter(Mandatory=$true)]
		$Items,
	    [Parameter(Mandatory=$false)]
		[string]$DisplayMember,
		[switch]$Append
	)
	
	if(-not $Append)
	{
		$listBox.Items.Clear()	
	}
	
	if($Items -is [System.Windows.Forms.ListBox+ObjectCollection])
	{
		$listBox.Items.AddRange($Items)
	}
	elseif ($Items -is [Array])
	{
		$listBox.BeginUpdate()
		foreach($obj in $Items)
		{
			$listBox.Items.Add($obj)
		}
		$listBox.EndUpdate()
	}
	else
	{
		$listBox.Items.Add($Items)	
	}

	$listBox.DisplayMember = $DisplayMember	
}
#endregion
$Output = New-Object System.Windows.Forms.TextBox
$buttonGetServices_Click={
	#TODO: Place custom script here
	New-Variable -Name Servername -Value ($tb_ServerName.Text) -Scope: global -ErrorAction: SilentlyContinue
	
	#$Services = (Get-Service -ComputerName $Servername.Text | Where-Object { $_.Status -eq "stopped" -or $_.Status -eq "Starting" }).DisplayName
	#-and $_.Name -like "*IBM*"
	$Services = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | Select name, StartMode, State
	
	
	$Chk_list_box.Items.Clear()
	$Chk_list_box.Visible = $True
	$Output.Visible = $False
	
	FOREACH ($Service in $Services)
	{
		$Chk_list_box.Items.Add("$Service") | Out-Null
	}
	
	
}

Open in new window

0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
That is what I stated in http:#a40394901: You need to do some formatting first. This is completely up to you how to do. But remember, what you stuff in you will get back! You are using a simple listbox, only able to display a line of string.
You can try if appending | format-table -auto  to the Get-WMIObject line supplies you with something suitable - but that depends on the font used, and how you want to proceed with the selected (= checked) data.
0
Highfive + Dolby Voice = No More Audio Complaints!

Poor audio quality is one of the top reasons people don’t use video conferencing. Get the crispest, clearest audio powered by Dolby Voice in every meeting. Highfive and Dolby Voice deliver the best video conferencing and audio experience for every meeting and every room.

 
LVL 8

Author Comment

by:Leo Torres
Comment Utility
So what should I be adding to get desired result. Format-table? will translate to GUI? If so how and where should I declare it.
0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
Try if this in line 48 works for you;
$objServices = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | select Select name, StartMode, State
$Services = $objServices | Format-Table -auto

Open in new window

The result after pressing the "StartServices" button will be the complete string, which will be needed to match against $Services to find out the current index in $objServices, to get the real service name.
Another way is to display a tab or comma seperated (unaligned) list, and parse out the first element of the result, like with
$Services = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' }  | % { ($_.name, StartMode, State) -join "`t") }

Open in new window

0
 
LVL 8

Author Comment

by:Leo Torres
Comment Utility
Format table produced this result
first code

Join with tab produced this code
join CodeHere is a working version you can run on your PC.  Now from selected Items I must start select items. if Disabled Set to Automatic and start. If service is in starting State. Stop it and start it again
#------------------------------------------------------------------------
# Source File Information (DO NOT MODIFY)
# Source ID: 7c0daeca-b0d3-4607-9de3-217431ac5002
# Source File: C:\Users\LeandroT\Documents\SAPIEN\PowerShell Studio 2014\Files\StartServices2.psf
#------------------------------------------------------------------------
#region File Recovery Data (DO NOT MODIFY)
<#RecoveryData:
tA0AAB+LCAAAAAAABAC9V11v2jAUfZ+0/2DlOQKSED4kiNRm7TSNbtVg3d6Qk1yoh2NXttOS/fo5
H7S0gZJ0BSEhB1/73HPPvQcY/YCQ34NIP2GFkV5IwtnYsA3v4weERt8FWRKG6SWh8A3H4E0VFmoK
4p6EIO3WnVyM2pWg4mjwB0KFVHoHY2OaSgVx6xdhEX+QrUsu4uLdRLu2THRTZtJtdbKXifyEqkTA
mEGiBKYmuk4CSsKvkM74Ctg46PexG7o9a+h0oTMYGojpVMbGQt9nGSi8JTQSOs7wOVOCU1kw1Ile
C34HQqXlAZ8SYGpK/oLh9fpdE/Vtd9TeBO05lNE2vBzrYOwM1srwMp7V0It7jV3GTTiOyjvn2XrU
znc3oYfrO8EB0KMXmGYoWUeAeK3M1TpMeIiVTsHwHMdE1qBSjX1l3kKscaZQ0um4JrKdGvEzHHxh
Eaz1mTrRuZi1k8nCzyhZatJXJIoo+FrRHSf1UOXy1hc7u/mcr48ud0E1W/+P2t1+bbWfABuK3Wkk
tv0OGpwnSnF2dAmCHOYzPPrwW5XoWraWoupu+6SoANdWxHKHjcev6qT7xq9ZRj8l3BCZYDpVKYVz
HK58TrkwvJlIdvbYtinrb4dwtaMS83zjhUU3biD/FsIVRBMiTzLL/u1qTjXWPODrZj2UZYKVImx5
wXBAIdpfvb3dZ2eub9U3gu1sazdez9JW4LrDRp1XdY5nUj5/OJMSYl1ukJvY8pPUK+W7wgwvIdaN
0TpLFI9z/k8yOnVldKxg4QzcHo6cXhccPbePSC+RYxlyQUnwDs3yCkrB7xQY7z4ChxGzH8SnARL4
QQ/SW7A6zsJd9BeWFbkd7ODDWL9jehpOROgB4SLd+ONJ2PlcwEnolay0SWhqR+D2+Fi4yqi9/S/N
+wc8jhYCtA0AAA==#>
#endregion

<#
    .NOTES
    --------------------------------------------------------------------------------
     Code generated by:  SAPIEN Technologies, Inc., PowerShell Studio 2014 v4.1.74
     Generated on:       11/7/2014 1:40 AM
     Generated by:       LeandroT
     Organization:       Ultimate
    --------------------------------------------------------------------------------
    .DESCRIPTION
        GUI script generated by PowerShell Studio 2014
#>
#----------------------------------------------
#region Application Functions
#----------------------------------------------

function OnApplicationLoad {
	#Note: This function is not called in Projects
	#Note: This function runs before the form is created
	#Note: To get the script directory in the Packager use: Split-Path $hostinvocation.MyCommand.path
	#Note: To get the console output in the Packager (Windows Mode) use: $ConsoleOutput (Type: System.Collections.ArrayList)
	#Important: Form controls cannot be accessed in this function
	#TODO: Add modules and custom code to validate the application load
	
	return $true #return true for success or false for failure
}

function OnApplicationExit {
	#Note: This function is not called in Projects
	#Note: This function runs after the form is closed
	#TODO: Add custom code to clean up and unload modules when the application exits
	
	$script:ExitCode = 0 #Set the exit code for the Packager
}

#endregion Application Functions

#----------------------------------------------
# Generated Form Function
#----------------------------------------------
function Call-StartServices2_psf {

	#----------------------------------------------
	#region Import the Assemblies
	#----------------------------------------------
	[void][reflection.assembly]::Load('mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System.Data, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
	[void][reflection.assembly]::Load('System.Xml, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System.DirectoryServices, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
	[void][reflection.assembly]::Load('System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089')
	[void][reflection.assembly]::Load('System.ServiceProcess, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a')
	#endregion Import Assemblies

	#----------------------------------------------
	#region Generated Form Objects
	#----------------------------------------------
	[System.Windows.Forms.Application]::EnableVisualStyles()
	$form1 = New-Object 'System.Windows.Forms.Form'
	$labelServer = New-Object 'System.Windows.Forms.Label'
	$Servername = New-Object 'System.Windows.Forms.TextBox'
	$buttonGetServices = New-Object 'System.Windows.Forms.Button'
	$Chk_list_box = New-Object 'System.Windows.Forms.CheckedListBox'
	$InitialFormWindowState = New-Object 'System.Windows.Forms.FormWindowState'
	#endregion Generated Form Objects

	#----------------------------------------------
	# User Generated Script
	#----------------------------------------------
	
	
	function OnApplicationLoad {
		#Note: This function is not called in Projects
		#Note: This function runs before the form is created
		#Note: To get the script directory in the Packager use: Split-Path $hostinvocation.MyCommand.path
		#Note: To get the console output in the Packager (Windows Mode) use: $ConsoleOutput (Type: System.Collections.ArrayList)
		#Important: Form controls cannot be accessed in this function
		#TODO: Add modules and custom code to validate the application load
		
		return $true #return true for success or false for failure
	}
	
	
	function OnApplicationExit {
		#Note: This function is not called in Projects
		#Note: This function runs after the form is closed
		#TODO: Add custom code to clean up and unload modules when the application exits
		
		$script:ExitCode = 0 #Set the exit code for the Packager
	}
	
	$form1_Load={
		#TODO: Initialize Form Controls here
		
	}
	
	#region Control Helper Functions
	function Load-ListBox
	{
		Param (
			[ValidateNotNull()]
			[Parameter(Mandatory = $true)]
			[System.Windows.Forms.ListBox]$ListBox,
			[ValidateNotNull()]
			[Parameter(Mandatory = $true)]
			$Items,
			[Parameter(Mandatory = $false)]
			[string]$DisplayMember,
			[switch]$Append
		)
		
		if (-not $Append)
		{
			$listBox.Items.Clear()
		}
		
		if ($Items -is [System.Windows.Forms.ListBox+ObjectCollection])
		{
			$listBox.Items.AddRange($Items)
		}
		elseif ($Items -is [Array])
		{
			$listBox.BeginUpdate()
			foreach ($obj in $Items)
			{
				$listBox.Items.Add($obj)
			}
			$listBox.EndUpdate()
		}
		else
		{
			$listBox.Items.Add($Items)
		}
		
		$listBox.DisplayMember = $DisplayMember
	}
	#endregion
	$Output = New-Object System.Windows.Forms.TextBox
	$buttonGetServices_Click = {
		#TODO: Place custom script here
		New-Variable -Name Servername -Value ($tb_ServerName.Text) -Scope: global -ErrorAction: SilentlyContinue
		
		#$Services = (Get-Service -ComputerName $Servername.Text | Where-Object { $_.Status -eq "stopped" -or $_.Status -eq "Starting" }).DisplayName
		#-and $_.Name -like "*IBM*"
		#$Services   = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | Select name, StartMode, State
		#$objServices = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | select  name, StartMode, State
		#$Services = $objServices | Format-Table -auto
		
	$Services = Get-WmiObject Win32_Service -ComputerName $Servername.Text | where{ 'Auto', 'Disabled' -contains $_.StartMode -and $_.State -ne 'Running' } | % { ($_.name, $_.DisplayName, $_.StartMode, $_.State) -join "`t`t" } 
	
		
		
		
		$Chk_list_box.Items.Clear()
		$Chk_list_box.Visible = $True
		$Output.Visible = $False
		
		FOREACH ($Service in $Services)
		{
			$Chk_list_box.Items.Add("$Service") | Out-Null
		}
		
		
	}
	#endregion
	
	# --End User Generated Script--
	#----------------------------------------------
	#region Generated Events
	#----------------------------------------------
	
	$Form_StateCorrection_Load=
	{
		#Correct the initial state of the form to prevent the .Net maximized form issue
		$form1.WindowState = $InitialFormWindowState
	}
	
	$Form_Cleanup_FormClosed=
	{
		#Remove all event handlers from the controls
		try
		{
			$buttonGetServices.remove_Click($buttonGetServices_Click)
			$form1.remove_Load($form1_Load)
			$form1.remove_Load($Form_StateCorrection_Load)
			$form1.remove_FormClosed($Form_Cleanup_FormClosed)
		}
		catch [Exception]
		{ }
	}
	#endregion Generated Events

	#----------------------------------------------
	#region Generated Form Code
	#----------------------------------------------
	$form1.SuspendLayout()
	#
	# form1
	#
	$form1.Controls.Add($labelServer)
	$form1.Controls.Add($Servername)
	$form1.Controls.Add($buttonGetServices)
	$form1.Controls.Add($Chk_list_box)
	$form1.ClientSize = '674, 725'
	$form1.Name = "form1"
	$form1.Text = "Form"
	$form1.add_Load($form1_Load)
	#
	# labelServer
	#
	$labelServer.Location = '33, 18'
	$labelServer.Name = "labelServer"
	$labelServer.Size = '305, 23'
	$labelServer.TabIndex = 3
	$labelServer.Text = "Server"
	$labelServer.TextAlign = 'MiddleCenter'
	#
	# Servername
	#
	$Servername.Location = '33, 47'
	$Servername.Name = "Servername"
	$Servername.Size = '305, 20'
	$Servername.TabIndex = 2
	#
	# buttonGetServices
	#
	$buttonGetServices.Location = '412, 45'
	$buttonGetServices.Name = "buttonGetServices"
	$buttonGetServices.Size = '159, 23'
	$buttonGetServices.TabIndex = 1
	$buttonGetServices.Text = "GetServices"
	$buttonGetServices.UseVisualStyleBackColor = $True
	$buttonGetServices.add_Click($buttonGetServices_Click)
	#
	# Chk_list_box
	#
	$Chk_list_box.FormattingEnabled = $True
	$Chk_list_box.Location = '23, 117'
	$Chk_list_box.Name = "Chk_list_box"
	$Chk_list_box.Size = '615, 559'
	$Chk_list_box.TabIndex = 0
	$form1.ResumeLayout()
	#endregion Generated Form Code

	#----------------------------------------------

	#Save the initial state of the form
	$InitialFormWindowState = $form1.WindowState
	#Init the OnLoad event to correct the initial state of the form
	$form1.add_Load($Form_StateCorrection_Load)
	#Clean up the control events
	$form1.add_FormClosed($Form_Cleanup_FormClosed)
	#Show the Form
	return $form1.ShowDialog()

} #End Function

#Call OnApplicationLoad to initialize
if((OnApplicationLoad) -eq $true)
{
	#Call the form
	Call-StartServices2_psf | Out-Null
	#Perform cleanup
	OnApplicationExit
}

Open in new window

11-7-2014-1-40-04-AM.jpg
0
 
LVL 68

Expert Comment

by:Qlemo
Comment Utility
The code is missing the "Start Services" button, so I cannot try. And after trying to add the button my PowerGUI crashed :(.
But I expect you need to go thru $Chk_list_box content to check for checked entries, then reparse each line with something like ($curLine is the listbox entry as string):
$service = $curLine | convertFrom-CSV -del "`t" -header Name, StartMode, State

Open in new window

$service than contains the same properties as what you stuffed into the listbox.

How to do remote controll of services is a different topic.
0
 
LVL 68

Accepted Solution

by:
Qlemo earned 500 total points
Comment Utility
BTW, I'm pretty sure you should be able to use a different dialog element than CheckedListBox for this purpose, something which is able to display a table ...
A different approach is to not use a form, but ask the user on call e.g. by read-host for a server name, then use out-gridview to display and select entries. As that  retains objects, it is much easier to handle.
0
 
LVL 8

Author Closing Comment

by:Leo Torres
Comment Utility
Thank you!
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

Synchronize a new Active Directory domain with an existing Office 365 tenant
Create and license users in Office 365 in bulk based on a CSV file. A step-by-step guide with PowerShell script examples.
The viewer will learn how to create and use a small PHP class to apply a watermark to an image. This video shows the viewer the setup for the PHP watermark as well as important coding language. Continue to Part 2 to learn the core code used in creat…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

772 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now