Powershell, Regular Expressions And You!

“^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$”

Pretty scary, isn’t it? While most of you will never have to build something this long and complex, it still is a nice idea to learn how to use Regular Expressions in your scripts when you need to look for patterns in the contents of a log file, enforce a specific pattern for something like a phone number or login name.  Whatever the case may be, Regular Expressions can save you a lot of time in either of these situations.  The only problem is…Where do you begin?  Hopefully the my posts on this subject will give an idea on where this can take you.  Please understand that I am no expert on this subject and this is by no means an advanced take on the topic.  My only goal is to get you started on using Regular Expressions and showing some potential “Real World Examples” that will hopefully help you out.

By the way, the expression shown at the beginning is used to verify IPv4 addresses.

Let’s just start off with something more simple, such as a phone number. For instance, you want to enforce in your script to build user accounts in Active Directory that the phone numbers need to match the following: “555-5555”. Seems simple enough, right? Looking at this number, we see three things that we need to enforce:

  1. Prior to the “-” we need exactly 3 digits
  2. We need to make sure that after the 3 digits, there is a “-” before the next set of digits.
  3. Lastly, after the “-” we need exactly 4 digits

How we would do that is setting the Regular Expression as such: “^\d{3}-\d{4}$”

Lets break this down to understand what each part in this plays.

  1. First, we encase the expression in quotes “” so it knows to where the expression begins and ends.
  2. The “^” (carrot) tells the expression that the beginning part of the string to be matched must match the beginning of the expression. In this case, the beginning must match 3 digits.
  3. Next is the “\d” which is used to match a digit, usually something like “\d[0-9]” or “\d{2}”
  4. The “{3} after the digit tells the expression that it must be 3 digits in length, no more and no less.
  5. The “-” tells the expression that there must be a dash after the first 3 digits and before the following 4 digits:
  6. Again, we have the “\d{4}” which tells us that there must be exactly 4 digits after the “-“.
  7. Lastly, we have the “$” which tells us that it must end with the 4 digits, otherwise it will be considered invalid.

Let’s put this into a more “Real World Example”. Lets assume this piece of code is in a script to build an Active Directory account:

[regex]$phone = “^\d{3}-\d{4}$”

Do {
Write-host -ForegroundColor Cyan “Please Enter a Phone Number that matches the following: 555-5555”
$number = Read-Host
If (!($number -match $phone)) {
Write-Host -ForegroundColor Red “Phone Number: $($number) is in incorrect format! `nPlease try again!”
}
}
Until ($number -match $phone)
Write-Host -ForegroundColor Green “Phone Number: $($number) is in proper format”

Using this code, you can see when running the script that the user cannot continue on with the build until they put in an acceptable phone number.

As you can see, only a phone number with the correct format is acceptable.

This ends my first part in a multi-part series on using Regular Expressions with Powershell.  Next time I will dive into using letters and ranges of numbers and letters for validating content.

Posted in powershell | Tagged , , | 5 Comments

Retrieve computer status with IP Address

Here is a simple script that I posted both in the Powershell forums and on the technet script repository.  Basically all it does is take either a provided computername or reads from a host list and proceeds to “ping” each computer to test for connectivity and if reachable, also grabs the IP address of the machine and adds to an array.  Machines that are not reachable are added to the list but without the IP address.


<#
.SYNOPSIS
Tests computer for connection and lists status with IP address.
.DESCRIPTION
Tests computer for connection and lists status with IP address.
.PARAMETER server
Name of server to test connection to.
.PARAMETER file
Name of host file to test connection to.
.PARAMETER credential
Allows the use of alternate credentials, if required.
.NOTES
Name: Get-ComputerIP.ps1
Author: Boe Prox
DateCreated: 05Aug2010

.LINK
http://
.EXAMPLE
Get-ComputerIP

#>
[cmdletbinding(
SupportsShouldProcess = $True,
DefaultParameterSetName = ‘computer’,
ConfirmImpact = ‘low’
)]
param(
[Parameter(
Mandatory = $False,
ParameterSetName = ‘computer’,
ValueFromPipeline = $True)]
[string]$computer,
[Parameter(
Mandatory = $False,
ParameterSetName = ‘file’)]
[string]$file,
[Parameter(
Mandatory = $False,
ParameterSetName = ”)]
[switch]$credential
)
If ($file) {
$computers = Get-Content $file
}
Else {
$computers = $computer
}
If ($credential) {
$cred = Get-Credential
}
$report = @()
ForEach ($computer in $Computers) {
Try {
$tempreport = New-Object PSObject
If ($credential) {
$IP = ((Test-Connection -ea stop -Count 1 -comp $computer -credential $cred).IPV4Address).IPAddresstoString
}
Else {
$IP = ((Test-Connection -ea stop -Count 1 -comp $computer).IPV4Address).IPAddresstoString
}
$tempreport | Add-Member NoteProperty Computer $computer
$tempreport | Add-Member NoteProperty Status “Up”
$tempreport | Add-Member NoteProperty IP $ip
$report += $tempreport
}
Catch {
$tempreport = New-Object PSObject
$tempreport | Add-Member NoteProperty Computer $computer
$tempreport | Add-Member NoteProperty Status “Down”
}
}
$report


Posted in powershell, scripts | Tagged , , | 2 Comments

Password Generator

During my time as a help desk/service center rep, we had a tool which would generate a password via a form and button and then was able to print out the form to give to each customer to take with them so they would not forget their password.  During my time there I was given the task to update the password requirements and wording on the form.  Visual Studio was the tool that I used to make this happen. Now during that time, I had to locate the source files and grab a temporary license to use Visual Studio to make the modifications to the code in order to make the changes required. Now approximately 4 years after the last time I worked on the vb code, I was asked again to perform some work on it in my new position.

Long story short, I spent a little bit of time working with Visual Studio 2005 and was able to get it working only on my machine, but it would not work on anyone elses machine.  I decided there that Powershell would be the way to go.

The easiest way to build the front end form was using Primal Forms Community Edition to build it out.  Once I had the form looking exactly like the original form, I was then able to export the code without much effort to a .ps1 file which I could then finish coding the rest of the tool.

I then used Powershells own ISE editor to finish adding the required code to finish out the tool.

The first piece I wanted to work on was the Password generation function that would create a randomly generated password using some specified parameters in the code.  For this instance, I wanted to have a minimum amount of 14 characters and have at least 3 characters for Upper, Lower, numerical and symbols.

Function Create-Password {
#How many characters in the password
[int]$passwordlength = 14

##Make sure that number of characters below are not greater than $passwordlength!!

#Minimum Upper Case characters in password
[int]$min_upper = 3

#Minimum Lower Case characters in password
[int]$min_lower = 3

#Minimum Numerical characters in password
[int]$min_number = 3

#Minimum Symbol/Puncutation characters in password
[int]$min_symbol = 3

#Misc password characters in password
[int]$min_misc = ($passwordlength – ($min_upper + $min_lower + $min_number + $min_symbol))

#Characters for the password
$upper = @(“A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,”P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”)
$lower = @(“a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,”p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”)
$number = @(1,2,3,4,5,6,7,8,9,0)
$symbol = @(“!”,”@”,”#”,”%”,”&”,”(“,”)”,”`””,”.”,”<“,”>”,”+”,”=”,”-“,”_”)
$combine = $upper + $lower + $number + $symbol

$password = @()

#Start adding upper case into password
1..$min_upper | % {$password += Get-Random $upper}
#Add lower case into password
1..$min_lower | % {$password += Get-Random $lower}
#Add numbers into password
1..$min_number | % {$password += Get-Random $number}

#Add symbols into password
1..$min_symbol | % {$password += Get-Random $symbol}

#Fill out the rest of the password length
1..$min_misc | % {$password += Get-Random $combine}

#Randomize password
Get-Random $password -count $passwordlength | % {[string]$randompassword += $_}
Return $randompassword
}

I can then call this function when the Generate Password button is pressed and the Password text is then modified from NOTVALID1 to whatever the randomly generated password is.  During the time the password is also copied to clipboard via the following lines of code:

[Windows.Forms.Clipboard]::SetText($password)

With this, the help desk work can then paste the password into the account reset dialog in active directory.

Another feature that I fought with for a week or so was trying to emulate the printing of the windows form that I created with the password that can be given to the user. During my research I found ways to print the entire screen, print a set area of the screen, but nothing that would print the active window or the actual windows form.  VB has the capability of doing this, but powershell, with Windows.Forms namespace does not. After some searching, I was able to find some C# code that does this, but using the handle of a window.  I am by no means a C# programmer and I was able to locate the window form handle but could not effectively replicate the form printing.
Doing some further research I was able to find a piece of code that would allow me to grab the active window:

GetForegroundWindow()
[DllImport(“user32.dll”)]
public static extern IntPtr GetForegroundWindow();

Here is the complete C# code:

using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
namespace ScreenShotDemo
{
/// <summary>
/// Provides functions to capture the entire screen, or a particular window, and save it to a file.
/// </summary>
public class ScreenCapture
{
/// <summary>
/// Creates an Image object containing a screen shot the active window
/// </summary>
/// <returns></returns>
public Image CaptureActiveWindow()
{
return CaptureWindow( User32.GetForegroundWindow() );
}
/// <summary>
/// Creates an Image object containing a screen shot of the entire desktop
/// </summary>
/// <returns></returns>
public Image CaptureScreen()
{
return CaptureWindow( User32.GetDesktopWindow() );
}
/// <summary>
/// Creates an Image object containing a screen shot of a specific window
/// </summary>
/// <param name=”handle”>The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
/// <returns></returns>
private Image CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle,ref windowRect);
int width = windowRect.right – windowRect.left;
int height = windowRect.bottom – windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest,hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle,hdcSrc);
// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
/// <summary>
/// Captures a screen shot of the active window, and saves it to a file
/// </summary>
/// <param name=”filename”></param>
/// <param name=”format”></param>
public void CaptureActiveWindowToFile(string filename, ImageFormat format)
{
Image img = CaptureActiveWindow();
img.Save(filename,format);
}
/// <summary>
/// Captures a screen shot of the entire desktop, and saves it to a file
/// </summary>
/// <param name=”filename”></param>
/// <param name=”format”></param>
public void CaptureScreenToFile(string filename, ImageFormat format)
{
Image img = CaptureScreen();
img.Save(filename,format);
}

/// <summary>
/// Helper class containing Gdi32 API functions
/// </summary>
private class GDI32
{

public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
[DllImport(“gdi32.dll”)]
public static extern bool BitBlt(IntPtr hObject,int nXDest,int nYDest,
int nWidth,int nHeight,IntPtr hObjectSource,
int nXSrc,int nYSrc,int dwRop);
[DllImport(“gdi32.dll”)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC,int nWidth,
int nHeight);
[DllImport(“gdi32.dll”)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport(“gdi32.dll”)]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport(“gdi32.dll”)]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport(“gdi32.dll”)]
public static extern IntPtr SelectObject(IntPtr hDC,IntPtr hObject);
}

/// <summary>
/// Helper class containing User32 API functions
/// </summary>
private class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport(“user32.dll”)]
public static extern IntPtr GetDesktopWindow();
[DllImport(“user32.dll”)]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport(“user32.dll”)]
public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDC);
[DllImport(“user32.dll”)]
public static extern IntPtr GetWindowRect(IntPtr hWnd,ref RECT rect);
[DllImport(“user32.dll”)]
public static extern IntPtr GetForegroundWindow();
}
}
}

Using a piece of code given to me by super Powershell writer MOW, I was able to grab the captured image in its raw format and print it out to the default printer:

$pd = New-Object System.Drawing.Printing.PrintDocument
$pd.Add_PrintPage({$_.Graphics.DrawImage(([System.Drawing.Image]$img), 0, 0)})
$pd.Print()

To avoid having the border included in the print screen, I removed the border for the duration of the screen capture and print job. I also gave the form 1 second to make the change and refresh before performing the screen capture, otherwise the password would not show up correctly on the print-out as shown:

This quite a fun challenge as I am not into building a GUI using Powershell.  But the challenge of making it completely like the old tool and still keeping all of the features of the old tool to include printing of the form made this a great learning experience for me and also taught me more on using C# code to make the script do more things such as capturing the active window.

I have this script uploaded to the following sites:
PoshCode.org
Microsoft Technet Script Repository

Here is the complete code:

Function Create-Password {
#How many characters in the password
[int]$passwordlength = 14

##Make sure that number of characters below are not greater than $passwordlength!!

#Minimum Upper Case characters in password
[int]$min_upper = 3

#Minimum Lower Case characters in password
[int]$min_lower = 3

#Minimum Numerical characters in password
[int]$min_number = 3

#Minimum Symbol/Puncutation characters in password
[int]$min_symbol = 3

#Misc password characters in password
[int]$min_misc = ($passwordlength – ($min_upper + $min_lower + $min_number + $min_symbol))

#Characters for the password
$upper = @(“A”,”B”,”C”,”D”,”E”,”F”,”G”,”H”,”I”,”J”,”K”,”L”,”M”,”N”,”O”,”P”,”Q”,”R”,”S”,”T”,”U”,”V”,”W”,”X”,”Y”,”Z”)
$lower = @(“a”,”b”,”c”,”d”,”e”,”f”,”g”,”h”,”i”,”j”,”k”,”l”,”m”,”n”,”o”,”p”,”q”,”r”,”s”,”t”,”u”,”v”,”w”,”x”,”y”,”z”)
$number = @(1,2,3,4,5,6,7,8,9,0)
$symbol = @(“!”,”@”,”#”,”%”,”&”,”(“,”)”,”`””,”.”,”<“,”>”,”+”,”=”,”-“,”_”)
$combine = $upper + $lower + $number + $symbol

$password = @()

#Start adding upper case into password
1..$min_upper | % {$password += Get-Random $upper}
#Add lower case into password
1..$min_lower | % {$password += Get-Random $lower}
#Add numbers into password
1..$min_number | % {$password += Get-Random $number}

#Add symbols into password
1..$min_symbol | % {$password += Get-Random $symbol}

#Fill out the rest of the password length
1..$min_misc | % {$password += Get-Random $combine}

#Randomize password
Get-Random $password -count $passwordlength | % {[string]$randompassword += $_}
Return $randompassword
}
#Generated Form Function
function GenerateForm {

#region Import the Assemblies
[reflection.assembly]::loadwithpartialname(“System.Windows.Forms”) | Out-Null
[reflection.assembly]::loadwithpartialname(“System.Drawing”) | Out-Null
#endregion

#Show popup if not running in -STA mode
If (((get-host).RunSpace).ApartmentState -ne “STA”) {
[System.Windows.Forms.MessageBox]::Show(“You are not running Powershell in (Single Threaded Apartment) STA mode! Please restart powershell in STA mode (powershell.exe -STA)”,”Warning”) | Out-Null
Break
}

#region Generated Form Objects
$form1 = New-Object System.Windows.Forms.Form
$textBox1 = New-Object System.Windows.Forms.TextBox
$lbl_summary = New-Object System.Windows.Forms.Label
$lbl_passwordlabel = New-Object System.Windows.Forms.Label
$btn_generate = New-Object System.Windows.Forms.Button
$chk_printreport = New-Object System.Windows.Forms.CheckBox
$lbl_bottomheader = New-Object System.Windows.Forms.Label
$lbl_topheader = New-Object System.Windows.Forms.Label
$InitialFormWindowState = New-Object System.Windows.Forms.FormWindowState
#endregion Generated Form Objects

#———————————————-
#Generated Event Script Blocks
#———————————————-
#Provide Custom Code for events specified in PrimalForms.
$btn_generate_OnClick= {
#Saving password to variable
$password = Create-Password

#Displaying password to screen
$textBox1.Text = $password
Start-Sleep -Seconds 1

If ($($chk_printreport.Checked) -eq $True) {
#Define Printer – Uses Default printer

$code = @’
using System;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;
namespace ScreenShotDemo
{
/// <summary>
/// Provides functions to capture the entire screen, or a particular window, and save it to a file.
/// </summary>
public class ScreenCapture
{
/// <summary>
/// Creates an Image object containing a screen shot of the entire desktop
/// </summary>
/// <returns></returns>
public Image CaptureScreen()
{
return CaptureWindow( User32.GetForegroundWindow() );
}
/// <summary>
/// Creates an Image object containing a screen shot of a specific window
/// </summary>
/// <param name=”handle”>The handle to the window. (In windows forms, this is obtained by the Handle property)</param>
/// <returns></returns>
public Image CaptureWindow(IntPtr handle)
{
// get te hDC of the target window
IntPtr hdcSrc = User32.GetWindowDC(handle);
// get the size
User32.RECT windowRect = new User32.RECT();
User32.GetWindowRect(handle,ref windowRect);
int width = windowRect.right – windowRect.left;
int height = windowRect.bottom – windowRect.top;
// create a device context we can copy to
IntPtr hdcDest = GDI32.CreateCompatibleDC(hdcSrc);
// create a bitmap we can copy it to,
// using GetDeviceCaps to get the width/height
IntPtr hBitmap = GDI32.CreateCompatibleBitmap(hdcSrc,width,height);
// select the bitmap object
IntPtr hOld = GDI32.SelectObject(hdcDest,hBitmap);
// bitblt over
GDI32.BitBlt(hdcDest,0,0,width,height,hdcSrc,0,0,GDI32.SRCCOPY);
// restore selection
GDI32.SelectObject(hdcDest,hOld);
// clean up
GDI32.DeleteDC(hdcDest);
User32.ReleaseDC(handle,hdcSrc);
// get a .NET image object for it
Image img = Image.FromHbitmap(hBitmap);
// free up the Bitmap object
GDI32.DeleteObject(hBitmap);
return img;
}
/// <summary>
/// Captures a screen shot of a specific window, and saves it to a file
/// </summary>
/// <param name=”handle”></param>
/// <param name=”filename”></param>
/// <param name=”format”></param>
public void CaptureWindowToFile(IntPtr handle, string filename, ImageFormat format)
{
Image img = CaptureWindow(handle);
img.Save(filename,format);
}
/// <summary>
/// Captures a screen shot of the entire desktop, and saves it to a file
/// </summary>
/// <param name=”filename”></param>
/// <param name=”format”></param>
public void CaptureScreenToFile(string filename, ImageFormat format)
{
Image img = CaptureScreen();
img.Save(filename,format);
}

/// <summary>
/// Helper class containing Gdi32 API functions
/// </summary>
private class GDI32
{

public const int SRCCOPY = 0x00CC0020; // BitBlt dwRop parameter
[DllImport(“gdi32.dll”)]
public static extern bool BitBlt(IntPtr hObject,int nXDest,int nYDest,
int nWidth,int nHeight,IntPtr hObjectSource,
int nXSrc,int nYSrc,int dwRop);
[DllImport(“gdi32.dll”)]
public static extern IntPtr CreateCompatibleBitmap(IntPtr hDC,int nWidth,
int nHeight);
[DllImport(“gdi32.dll”)]
public static extern IntPtr CreateCompatibleDC(IntPtr hDC);
[DllImport(“gdi32.dll”)]
public static extern bool DeleteDC(IntPtr hDC);
[DllImport(“gdi32.dll”)]
public static extern bool DeleteObject(IntPtr hObject);
[DllImport(“gdi32.dll”)]
public static extern IntPtr SelectObject(IntPtr hDC,IntPtr hObject);
}

/// <summary>
/// Helper class containing User32 API functions
/// </summary>
private class User32
{
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
[DllImport(“user32.dll”)]
public static extern IntPtr GetDesktopWindow();
[DllImport(“user32.dll”)]
public static extern IntPtr GetWindowDC(IntPtr hWnd);
[DllImport(“user32.dll”)]
public static extern IntPtr ReleaseDC(IntPtr hWnd,IntPtr hDC);
[DllImport(“user32.dll”)]
public static extern IntPtr GetWindowRect(IntPtr hWnd,ref RECT rect);
[DllImport(“user32.dll”)]
public static extern IntPtr GetForegroundWindow();
}
}
}
‘@

add-type $code -ReferencedAssemblies ‘System.Windows.Forms’,’System.Drawing’

#Print Form
$form1.FormBorderStyle = 0
$form1.Activate()
$fph = New-Object ScreenShotDemo.ScreenCapture
$img = $fph.CaptureScreen()
$pd = New-Object System.Drawing.Printing.PrintDocument
$pd.Add_PrintPage({$_.Graphics.DrawImage(([System.Drawing.Image]$img), 0, 0)})
$pd.Print()

$form1.FormBorderStyle = 5
}
#Pasting password to clipboard
#This will only work if Powershell is running in Single Threaded Apartment (STA): powershell.exe -sta or run from ISE
#You can check by running the following command: ((get-host).RunSpace).ApartmentState
[Windows.Forms.Clipboard]::SetText($password)

}

$handler_form1_Load=
{
$form1.TopMost = $True
$form1.Activate()

}

$OnLoadForm_StateCorrection=
{#Correct the initial state of the form to prevent the .Net maximized form issue
$form1.WindowState = $InitialFormWindowState
}

#———————————————-
#region Generated Form Code
$form1.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,9.75,1,3,0)
$form1.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
$form1.Text = “Password Generator”
$form1.AllowDrop = $True
$form1.Name = “form1”
$form1.DataBindings.DefaultDataSourceUpdateMode = 0
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 685
$System_Drawing_Size.Height = 496
$form1.ClientSize = $System_Drawing_Size
$form1.FormBorderStyle = 5
$form1.add_Load($handler_form1_Load)

$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 227
$System_Drawing_Size.Height = 19
$textBox1.Size = $System_Drawing_Size
$textBox1.DataBindings.DefaultDataSourceUpdateMode = 0
$textBox1.ReadOnly = $True
$textBox1.BorderStyle = 0
$textBox1.Text = “NOTVALID1”
$textBox1.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,12,1,3,0)
$textBox1.Name = “textBox1”
$textBox1.BackColor = [System.Drawing.Color]::FromArgb(255,255,255,255)
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 304
$System_Drawing_Point.Y = 268
$textBox1.Location = $System_Drawing_Point
$textBox1.TabIndex = 7
$textBox1.add_TextChanged($handler_textBox1_TextChanged)

$form1.Controls.Add($textBox1)

$lbl_summary.TabIndex = 6
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 619
$System_Drawing_Size.Height = 156
$lbl_summary.Size = $System_Drawing_Size
$lbl_summary.Text = “Ensure your password contains at least 3 special characters, 3 numbers, 3 uppercase and 3 lowercase letters for a total of at least 14 characters long. You will be unable to change this password for the next 24 hours.”
$lbl_summary.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,12,1,3,0)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 41
$System_Drawing_Point.Y = 85
$lbl_summary.Location = $System_Drawing_Point
$lbl_summary.DataBindings.DefaultDataSourceUpdateMode = 0
$lbl_summary.Name = “lbl_summary”

$form1.Controls.Add($lbl_summary)

$lbl_passwordlabel.TabIndex = 4
$lbl_passwordlabel.TextAlign = 64
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 111
$System_Drawing_Size.Height = 47
$lbl_passwordlabel.Size = $System_Drawing_Size
$lbl_passwordlabel.Text = “Password:”
$lbl_passwordlabel.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,12,1,3,0)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 184
$System_Drawing_Point.Y = 254
$lbl_passwordlabel.Location = $System_Drawing_Point
$lbl_passwordlabel.DataBindings.DefaultDataSourceUpdateMode = 0
$lbl_passwordlabel.Name = “lbl_passwordlabel”

$form1.Controls.Add($lbl_passwordlabel)

$btn_generate.TabIndex = 3
$btn_generate.Name = “btn_generate”
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 104
$System_Drawing_Size.Height = 39
$btn_generate.Size = $System_Drawing_Size
$btn_generate.UseVisualStyleBackColor = $True

$btn_generate.Text = “Generate”
$btn_generate.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,8.25,1,3,0)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 304
$System_Drawing_Point.Y = 364
$btn_generate.Location = $System_Drawing_Point
$btn_generate.DataBindings.DefaultDataSourceUpdateMode = 0
$btn_generate.add_Click($btn_generate_OnClick)

$form1.Controls.Add($btn_generate)

$chk_printreport.UseVisualStyleBackColor = $True
$chk_printreport.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,9,1,3,0)
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 104
$System_Drawing_Size.Height = 24
$chk_printreport.Size = $System_Drawing_Size
$chk_printreport.TabIndex = 2
$chk_printreport.Text = “Print Report”
$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 304
$System_Drawing_Point.Y = 323
$chk_printreport.Location = $System_Drawing_Point
$chk_printreport.DataBindings.DefaultDataSourceUpdateMode = 0
$chk_printreport.Name = “chk_printreport”
$chk_printreport.checked = $True

$form1.Controls.Add($chk_printreport)

$lbl_bottomheader.TabIndex = 1
$lbl_bottomheader.ImageAlign = 512
$lbl_bottomheader.TextAlign = 32
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 662
$System_Drawing_Size.Height = 59
$lbl_bottomheader.Size = $System_Drawing_Size
$lbl_bottomheader.Text = “FOR OFFICIAL USE ONLY”
$lbl_bottomheader.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,20.25,1,3,0)
$lbl_bottomheader.ForeColor = [System.Drawing.Color]::FromKnownColor(“Green”)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 11
$System_Drawing_Point.Y = 425
$lbl_bottomheader.Location = $System_Drawing_Point
$lbl_bottomheader.DataBindings.DefaultDataSourceUpdateMode = 0
$lbl_bottomheader.Name = “lbl_bottomheader”
$lbl_bottomheader.add_Click($handler_label2_Click)

$form1.Controls.Add($lbl_bottomheader)

$lbl_topheader.TabIndex = 0
$lbl_topheader.ImageAlign = 512
$lbl_topheader.TextAlign = 32
$System_Drawing_Size = New-Object System.Drawing.Size
$System_Drawing_Size.Width = 662
$System_Drawing_Size.Height = 59
$lbl_topheader.Size = $System_Drawing_Size
$lbl_topheader.Text = “FOR OFFICIAL USE ONLY”
$lbl_topheader.Font = New-Object System.Drawing.Font(“Microsoft Sans Serif”,20.25,1,3,0)
$lbl_topheader.ForeColor = [System.Drawing.Color]::FromKnownColor(“Green”)

$System_Drawing_Point = New-Object System.Drawing.Point
$System_Drawing_Point.X = 11
$System_Drawing_Point.Y = 6
$lbl_topheader.Location = $System_Drawing_Point
$lbl_topheader.DataBindings.DefaultDataSourceUpdateMode = 0
$lbl_topheader.Name = “lbl_topheader”
$lbl_topheader.add_Click($handler_label1_Click)

$form1.Controls.Add($lbl_topheader)

#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($OnLoadForm_StateCorrection)
#Show the Form
$form1.ShowDialog()| Out-Null
} #End Function

#Call the Function
GenerateForm

Posted in powershell, scripts | Tagged , , , | 2 Comments

Embedding Passwords in a Script

While hanging around the Microsoft Technet Powershell forums, I came across a question regarding having a hard-coded password for a user account to run a query against some servers.  I many cases, this is never a good idea as if the script gets compromised, you could have a potential security incident on your hands. One solution that I have seen used is to encrypt your password in powershell using the ConvertFrom-SecureString cmdlet.

Warning!!!!
You need to run this as the account that is going to be running this script. Otherwise the embedded password in the script will not work! This is actually a smart idea.  If any account has the ability to run the script with the embedded password and it is a domain admin level account, a malicious user could write their own code into the script to run or even decrypt the password (which I will explain how later on).

To being with this, you can use the Read-Host -AsSecure cmdlet to first get the password that you want to use. In this case, my password is going to be “password”.

Now you have a password that is saved as a secure string “System.Security.SecureString”. Unfortunately, while you can use this in the current Powershell session for authenticating to a remote server, you will not be able to hardcode this as it is into the script or a text file to read from. You must then take that secure string and convert it from the secure string to a long string of characters using ConvertFrom-SecureString.

You can then copy and paste this string into your script or text file that will be used against the account that will be used to authenticate to the server.

The only account that will be able to use this is the account that created the string. If you attempt to use this with a different account, it will error out because it will not understand what to do with the string.

Now that we have encrypted the password and passed it into a text file or a script, we will now look at how to decrypt the string using both the account that created the string and an account that is trying to read the string.

First,the account that created the string:

As you can see, the password is now being shown in clear text for the world to see.

Now for an account that did not create the secure string:

As you can tell, Powershell has no idea what to do with this and cannot process the string into the password.

To summarize:
1. This is only recommended as a last resort for scripts. Hard-coding a password into a script, encrypted or not, is always a risk.
2. You must use the ConvertFrom-SecureString to put the password into a usable string to copy/paste into the script.
3. Only the account that converted the string and decrypt it and use the password for authentication.

Posted in powershell | Tagged , , | 4 Comments

Tech-Ed 2010

In case anyone was curious, I took second place in the Microsoft 2010 Scripting Games this year and won a pass to Tech-Ed 2010 in New Orleans, LA.  I had a blast during this time and learned a lot of things from it.  The link for my trip report that I sent to the Scripting Guys is at this link.

Posted in Tech-Ed | Tagged , | Leave a comment