Solved

Powershell GUI need button actions to work

Posted on 2014-10-21
11
603 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
Is Your AD Toolbox Looking More Like a Toybox?

Managing Active Directory can get complicated.  Often, the native tools for managing AD are just not up to the task.  The largest Active Directory installations in the world have relied on one tool to manage their day-to-day administration tasks: Hyena. Start your trial today.

 
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

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

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

"Migrate" an SMTP relay receive connector to a new server using info from an old server.
The Nano Server Image Builder helps you create a custom Nano Server image and bootable USB media with the aid of a graphical interface. Based on the inputs you provide, it generates images for deployment and creates reusable PowerShell scripts that …
Learn the basics of while and for loops in Python.  while loops are used for testing while, or until, a condition is met: The structure of a while loop is as follows:     while <condition>:         do something         repeate: The break statement m…
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…

840 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