Link to home
Start Free TrialLog in
Avatar of Leo Torres
Leo TorresFlag for United States of America

asked on

Powershell GUI need button actions to work

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


User generated imageUser generated image
Avatar of Qlemo
Qlemo
Flag of Germany image

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.
Avatar of Leo Torres

ASKER

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.
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.
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.

User generated image
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

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.
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.
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

Format table produced this result
User generated image

Join with tab produced this code
User generated imageHere 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
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.
ASKER CERTIFIED SOLUTION
Avatar of Qlemo
Qlemo
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thank you!