Solved

Powershell GUI need button actions to work

Posted on 2014-10-21
11
583 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 69

Expert Comment

by:Qlemo
ID: 40394499
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
ID: 40394567
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 69

Expert Comment

by:Qlemo
ID: 40394901
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
3 Use Cases for Connected Systems

Our Dev teams are like yours. They’re continually cranking out code for new features/bugs fixes, testing, deploying, testing some more, responding to production monitoring events and more. It’s complex. So, we thought you’d like to see what’s working for us.

 
LVL 8

Author Comment

by:Leo Torres
ID: 40410446
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 69

Expert Comment

by:Qlemo
ID: 40410496
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
 
LVL 8

Author Comment

by:Leo Torres
ID: 40423087
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 69

Expert Comment

by:Qlemo
ID: 40423454
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
ID: 40427814
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 69

Expert Comment

by:Qlemo
ID: 40429142
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 69

Accepted Solution

by:
Qlemo earned 500 total points
ID: 40429147
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
ID: 40446647
Thank you!
0

Featured Post

Netscaler Common Configuration How To guides

If you use NetScaler you will want to see these guides. The NetScaler How To Guides show administrators how to get NetScaler up and configured by providing instructions for common scenarios and some not so common ones.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This script can help you clean up your user profile database by comparing profiles to Active Directory users in a particular OU, and removing the profiles that don't match.
The following article is intended as a guide to using PowerShell as a more versatile and reliable form of application detection in SCCM.
Learn the basics of strings in Python: declaration, operations, indices, and slicing. Strings are declared with quotations; for example: s = "string": Strings are immutable.: Strings may be concatenated or multiplied using the addition and multiplic…
The viewer will learn the basics of jQuery, including how to invoke it on a web page. Reference your jQuery libraries: (CODE) Include your new external js/jQuery file: (CODE) Write your first lines of code to setup your site for jQuery.: (CODE)

773 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