Embedding Powershell in to Windows Forms

I'm writing a small GUI based (windows form) powershell tool for my team and my own use based on things that we repetitively do every day (like check if a service is running, start/stop/restart, check for amt of memory, cpu spikes, check for win updates, if C drv is really full etc).
So basically I have a form with a bunch of buttons with some logic (check if they have entered the right hostname, or if the service exists or not, displays/starts/stops services from multiple machines etc). I'm trying to display at least the output of these cmdlets in a textbox or richtextbox or datagridview, but can't seem to figure out how or which to use...
For example get-service (either all or one particular service or wild-card) should be shown in the richtextbox, right now i'm just using popup windows and out-gridview.

Even better (i understand this must be very hard, I saw PowerShellTunnel) will be to be able to embed Powershell window inside a win form, is that even possible? Basically capture console screen and display it...
Any useful/alternate ideas or suggestions, examples, links, anything at all on this topic will help me move forward with this project....thanks for your help in advance..
emkaydAsked:
Who is Participating?
 
Brent ChallisConnect With a Mentor Principal: ITCommented:
As PowerShell is based on the .NET Framework you can use it to work with .NET functionality in exactly the same way that you can use languages such as C#, VB.NET or the myriad of other languages.  I too use PrimalForms for some GUI based utilities that I have.  While it is possible to export the work as straight PowerShell script in a PS1 file, I have chosen to package it into an EXE file from PrimalForms.  I have also written manual code to create a Windows Form based application (see example below which reads a file and populates listboxes on the forms).

Re you questions:
1. The best way to get this information is probably to create a DataGridView on a form and populate it.  The code I used to do this in a PrimalForms project is listed at the beginning of the attached code.

2. As all the controls are the windows controls you can create a TextBox and set the password character property to provide a login form.  There is an explaination of how to create a credential object using a name and password that is supplied here: http://blogs.technet.com/b/gary/archive/2009/07/23/creating-a-ps-credential-from-a-clear-text-password-in-powershell.aspx

3. If you want to be able to trap errors occurring as the code executes you need to use a try/catch block.  e.g.

try
          {
             $wc = new-object System.Net.WebClient
             $wc.DownloadFile("http://www.contoso.com/MyDoc.doc")
          }
          catch [System.Net.WebException],[System.IO.IOException]
          {
              "Unable to download MyDoc.doc from http://www.contoso.com."
          }
          catch
          {
              "An error occurred that could not be resolved."
          }
This will let you write code to process any information that you want to keep/log.


#Code to populate a DataGridView

	$details = (Get-WmiObject -class win32_service | 
             Select DisplayName, Name, State, Status, StartMode | Sort-Object Displayname  )
	$array = New-Object System.Collections.ArrayList
	$array.AddRange($details)
	$datagridviewResults.DataSource = $array

# Demonstration code to create a .NET Windows Form, populate it with controls and use it
# to read and process a file.

# Load the .NET Assemblies
[void][System.Reflection.Assembly]::LoadWithPartialName("System.windows.forms")
[void][reflection.assembly]::LoadWithPartialName("System.Drawing")

function LoadCSV(){
	# Clear any items that may exist in the lists.
	$count = $form.Controls["lstNames"].Items.Count - 1
	for ($i = $count;$i -ge 0;$i--)
	{
		$form.Controls["lstNames"].Items.RemoveAt($i)
		$form.Controls["lstEmails"].Items.RemoveAt($i)
		$form.Controls["lstphones"].Items.RemoveAt($i)
	}

	[System.Windows.Forms.OpenFileDialog]$ofd = New-Object System.Windows.Forms.OpenFileDialog
	$ofd.ShowHelp = $True
	$ofd.Filter = "CSV Files (*.csv)|*.csv|All Files (*.*)|*.*"
	if ($ofd.ShowDialog() -eq "OK")
    {
     	$details = Import-Csv -Path $ofd.FileName
        foreach ($line in $details)
        {
			$form.Controls["lstNames"].Items.Add($line.Name)
			$form.Controls["lstEmails"].Items.Add($line.Email)
			$form.Controls["lstphones"].Items.Add($line.Phone)
		}
	}
}

function ProcessDetails()
{
    Clear-Host
	for ($i = 0;$i -lt $form.Controls["lstNames"].Items.Count;++$i)
	{
		Write-Host $form.Controls["lstNames"].Items[$i] " - " $form.Controls["lstEmails"].Items[$i] " - " $form.Controls["lstphones"].Items[$i]
	}
}

function BuildForm()
{
	#Create the form
	$form = new-object Windows.Forms.form
	$form.Size = new-object System.Drawing.Size @(800,300)   
	$form.text = "Demo Form created with PowerShell"  
	
	#Create the buttons
	$btnLoadCSV = New-Object System.Windows.Forms.Button 
	$btnLoadCSV.Width=100
	$btnLoadCSV.Location = New-Object System.Drawing.Size(350, 10)
	$btnLoadCSV.Text = "Load CSV File"
	
	$btnProcessCSV = New-Object System.Windows.Forms.Button 
	$btnProcessCSV.Width = 100
	$btnProcessCSV.Text = "Process CSV Data"
	$btnProcessCSV.Location = New-Object System.Drawing.Size(350, 35)
	
	#Create the list boxes and their assosciated labels.
	#Names
	$lblNames = New-Object System.Windows.Forms.Label
	$lblNames.Text = "Names"
	$lblNames.Location = New-Object System.Drawing.Size(50, 75)
	
	$lstNames = New-Object System.Windows.Forms.ListBox
	$lstNames.Name = "lstNames"
	$lstNames.Width = 200
	$lstNames.Height = 100
	$lstNames.Location = New-Object System.Drawing.Size(50, 100)
	
	#Email addresses
	$lblEmails = New-Object System.Windows.Forms.Label
	$lblEmails.Text = "Email Addresses"
	$lblEmails.Location = New-Object System.Drawing.Size(300, 75)
	
	$lstEmails = New-Object System.Windows.Forms.ListBox
	$lstEmails.Name = "lstEmails"
	$lstEmails.Width = 200
	$lstEmails.Height = 100
	$lstEmails.Location = New-Object System.Drawing.Size(300, 100)
	
	#Phone numbers
	$lblPhones = New-Object System.Windows.Forms.Label
	$lblPhones.Text = "Phone Numbers"
	$lblPhones.Location = New-Object System.Drawing.Size(550, 75)
	
	$lstPhones = New-Object System.Windows.Forms.ListBox
	$lstPhones.Name = "lstPhones"
	$lstPhones.Width = 200
	$lstPhones.Height = 100
	$lstPhones.Location = New-Object System.Drawing.Size(550, 100)
	
	#Add the controls to the form
	$form.Controls.Add($btnLoadCSV)
	$form.Controls.Add($btnProcessCSV)
	$form.Controls.Add($lstNames)
	$form.Controls.Add($lstEmails)
	$form.Controls.Add($lstPhones)
	$form.Controls.Add($lblNames)
	$form.Controls.Add($lblEmails)
	$form.Controls.Add($lblPhones)
	
	$btnLoadCSV.add_click({LoadCSV})
	$btnProcessCSV.add_click({ProcessDetails})
	return $form
}

$form = BuildForm;
$form.ShowDialog();

Open in new window

0
 
emkaydAuthor Commented:
Thanks for the reply, but I don't understand how that thread is relevant to what I have asked for...
0
Improved Protection from Phishing Attacks

WatchGuard DNSWatch reduces malware infections by detecting and blocking malicious DNS requests, improving your ability to protect employees from phishing attacks. Learn more about our newest service included in Total Security Suite today!

 
Kamaraj SubramanianApplication Support AnalystCommented:
are you creating a form ( using vb.net ? )

how you are creating form ?
0
 
emkaydAuthor Commented:
I'm using Primal Forms to generate my GUI code, but before i realized there was a free community version of Primal Forms i did write the code without any 'visual' guide. But to answer your question, no i don't believe that is VB.NET code.
It is Powershell code which has ability to call .NET libraries to create GUI.
0
 
emkaydAuthor Commented:
Ok, since nobody has really answered my question, I think I might have asked it in a very confusing way. Let me attempt to make it a little clear -
I was hoping to get some insight/help/suggestion on the following -

1. How to format the result of this (with a title based on computernames) to show in a richtexbox or datagridview in a windows form (this is inside a 'for' loop)---> Get-WmiObject -class win32_service -computername $x[$y] -credential $cred | Select DisplayName, Name, State, Status, StartMode | Sort-Object Displayname |

2. Is it possible to have a username and password (not visible) Textboxes in the form and use those values from there everytime i use $cred? Right now $cred = Get-Credential, it's popping a challenge window. I have ask for credentials a lot of times because our environment is such, we have multiple domains and can't use one domain or service account for all.

3. A way to capture some of the errors that show up in the console right now, for instance, if the credentials entered doesn't have admin rights or if the user entered the wrong password etc.

Please let me know if you have any questions or need screenshots of what i have current to understand better. Thank you very much in advance.
0
 
emkaydAuthor Commented:
Really? Nobody can even attempt at answering some of the questions I have?
0
 
emkaydAuthor Commented:
Does anyone have any ideas about question no. 2 (to get admin credentials via win forms, basically type once and leave it there and all button clicks will get their $credential from those 2 Textboxes, instead of getting prompted every time)? I have figured out Q#1.
0
 
R3C0NCommented:
EMKAYD,

I was creating a form in Powershell using PrimalForms and am also a member of EE and came across your post. Here are some things I came across.

Advanced Cred Function for storing passwords with Powershell on disk, Posted 5 days ago...

http://poshcode.org/3532

This link is more of MS general explanation of storing Cred usernames and passwwords to disk.

http://technet.microsoft.com/en-us/magazine/ff714574.aspx

-R3c0n
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.