# encoding: ascii
# api: powershell
# title: Get-NewPassword
# description: Password gerneration function originally posted on PoshCode.org by Sean Kearney.  Without any arguments, Get-NewPassword generates an 8 character password with upper, lower, and numeric characters.  It can accept 2 options, the first is password length (up to 94 chars) and the other is complexity (1 to 4).  I had to modify the code so that it wouldn’t create repeating characters.  The code may be ugly, but it’s because I am a network admin and not a programmer.  I hope it helps someone.
# version: 1.0
# type: script
# author: johnwcannon at gmail dot com
# license: CC0
# x-poshcode-id: 2237
# x-archived: 2010-09-22T05:09:25
#
#
#/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\
#
# Script Name: Get-NewPassword.ps1
#       Title: Random Password Generator
#     Version: 1.0
#      Author: johnwcannon at gmail dot com
#        Date: September 16th, 2010
#
# Description: Password gerneration function based upon code
#              originally posted on PoshCode.org by Sean Kearney
#              
#		Usage: Without any arguments, Get-NewPassword
#			   generates an 8 character password with
#			   upper, lower, and numeric characters.
#			   It can accept 2 options, the first is
#			   password length (up to 94) and the other
#			   is complexity (1 to 4). The complexity
#			   Levels are:
#			   1 - Lowercase characters only
#			   2 - Lower and Uppercase characters
#			   3 - Upper, Lower and Numeric (default)
#			   4 - Upper, Lower, Numeric, and Special chars
#			   *Passwords generated do NOT reuse characters
#			    and attempt to avoid creating repeating series
#			    of characters, like abc or 123
#/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\/\

function global:Get-NewPassword([int]$PasswordLength, [int]$Complexity) {

#Perform some (very) basic input sanitation on the variables (possibly) getting passed
if ($PasswordLength -ne 0)
	{
	if ($PasswordLength -gt 94)
		{
		Write-Host "That's a long password you requested!  There aren't enough unique characters to make a password that long."
		Return
		}
	if ($PasswordLength -lt 1)
		{
		Write-Host $PasswordLength
		Write-Host "You have entered an invalid password length."
		Return
		}
	}
if ($Complexity -ne 0)
	{
	if (($Complexity -lt 1) -or ($Complexity -gt 4))
		{
		Write-Host "You entered an invalid complexity value!"
		Return
		}
	}
# Password length can be from 1 to 94, but defaults to 8 if no value is passed
If ($PasswordLength -eq 0)
	{
	$PasswordLength=8
	}
#Set a default complexity level to 3 if one is not specified
If ($Complexity -eq 0) { $Complexity=3 }

if (($Complexity -eq 3) -and ($PasswordLength -gt 62))
	{
	Write-Host "You have requested a password that has more characters than the `ncomplexity you chose.  Try a complexity of 4 next time"
	Return
	}
if (($Complexity -eq 2) -and ($PasswordLength -gt 52))
	{
	Write-Host "You have requested a password that has more characters than the `ncomplexity you chose.  Try a complexity of 3 or 4 next time"
	Return
	}
if (($Complexity -eq 1) -and ($PasswordLength -gt 26))
	{
	Write-Host "You have requested a password that has more characters than the `ncomplexity you chose.  Try a complexity of 2, 3 or 4 next time"
	Return
	}

# Declare arrays holding the decimal equivalents of the ascii characters
$uppercasedec = 65..90
$lowercasedec = 97..122
$numeraldec = 48..57
#There are 4 ranges of special characters
$specialchardec = 33..47
$specialchardec1 = 58..64
$specialchardec2 = 91..96
$specialchardec3 = 123..126


# Complexity can be from 1 - 4 with the results being
# 1 - Pure lowercase Ascii
# 2 - Mix Uppercase and Lowercase Ascii
# 3 - Ascii Upper/Lower with Numbers
# 4 - Ascii Upper/Lower with Numbers and Special Characters

#Build an array of the complexity specified
if($Complexity -eq 1)
	{
	$passchars += $lowercasedec
	}
if($Complexity -eq 2)
	{
	$passchars += $lowercasedec + $uppercasedec
	}
if($Complexity -eq 3)
	{
	$passchars += $lowercasedec + $uppercasedec + $numeraldec
	}
if($Complexity -eq 4)
	{
	$passchars += $lowercasedec + $uppercasedec + $numeraldec + `
	$specialchardec + $specialchardec1 + $specialchardec2 + $specialchardec3 
	}
	

#Here is the loop that generates a character until the requested
#password length is reached
Foreach ($counter in 1..$PasswordLength)
	{
	$lastchar = $null
	#We pluck out a random character from the character set chosen
	$tempchar = ($passchars | Get-Random)
	
	#We asign a last character chosen variable to prevent repeating patterns like abc or 123
	$lastchar = $tempchar

	#If statement to check if character is adjacent to last character used
	#and checks to make sure that there aren't only two characters left in
	#the set that might create an infinite loop if they are actually adjacent
	If (($lastchar -eq ($tempchar + 1)) -or ($lastchar -eq ($tempchar - 1)) -and ($passchars.count -gt 2))
		{
		#Let's pluck out a new random character since the last one was adjacent
		$tempchar = ($passchars | Get-Random)
		
		#Reset the $lastchar variable so it can be tested again
		$lastchar = $tempchar
		}
	#Now that we have verified that the character isn't adjacent to
	#the last character we pulled, we need to remove it from the array
	$passchars = ($passchars | Where-Object {$_ -ne $tempchar})
	
	#Now we build the password and convert the decimal to ASCII
	$NewPassword=$NewPassword+[char]($tempchar)
	}

# When we are done, we return the completed password 
# back to the calling party
Return $NewPassword

}
