Using Get-Random -Count

Hello,

I looked around at examples of generating ‘random’ passwords with PS, and while I could probably copy-paste something, a lot of it seems long-winded and I wanted to try it myself. I came up with this, which offers the control and requirements I am after…

Function Password () {

    $pass = $null
    $lower = ([char[]]([char]'a'..[char]'z'))
    $upper = ([char[]]([char]'A'..[char]'Z'))
    $special = ([char[]]([char]'!')) + ([char[]]([char]'@') + ([char[]]([char]'$')))
    $num = (0..9)

    $pass += $lower | Get-Random #-Count 2
    $pass += $upper | Get-Random #-Count 2
    $pass += $special | Get-Random #-Count 2
    $pass += $num | Get-Random #-Count 2

    $pass | Sort-Object {Get-Random}

}

$newPass = Password

The issue is that when I comment in ‘-Count 2’, it will output to Int32. Otherwise it is System.String.

The result using ‘-Count 2’ does not append the same. How can I grab 2 of each character and still sort them randomly in the end?

Thank you!

Well, you’re appending a string together, so that’s what you get. Sort-Object can’t “sort” a single string.

I wonder if you started by declaring

$pass = @()

Meaning, $pass is an array of characters. You’d then be adding items to an array - well, a collection, technically - and Sort-Object can operate on that. You’d probably have to run the final result through Out-String to turn it into a single string.

Try wrapping this in a function:

-join (33..126 | foreach-object {[char]$_} | Get-Random -Count 10)

Hope it helps.

Thank you for your suggestion! This doesn’t guarantee that I will always get a number, upper, lower or special character,etc.

It is very probable that I would, but not for sure? That is why I was trying it as my function above shows.

Hi Don, again, thank you for this great community and all of your efforts here.

I am not sure if this is exactly what you meant, but I do have all of the characters in an array (I checked, GetType(), and $pass[0…7], etc), and I have that piped to Sort-Object {Get-Random}, and it is what I need it to be…

$pass = $null

    $lower = ([char[]]([char]'a'..[char]'z'))
    $upper = ([char[]]([char]'A'..[char]'Z'))
    $special = ([char[]]([char]'!')) + ([char[]]([char]'@') + ([char[]]([char]'$')))
    $num = (0..9)

    
    $pass = @(

    $lower | Get-Random -Count 2
    $upper | Get-Random -Count 2
    $special | Get-Random -Count 2
    $num | Get-Random -Count 2
    
    )

    #$pass.GetType()

    #$pass[0..7]

    $password = $pass | Sort-Object {Get-Random} | Out-String

The result is still printing a column of characters and not a row. I take it that I have not managed to do this correctly.

Result:

S
7
c
!
4
K
w
$

Update

This ‘format’ is how $lower, $upper, etc are being returned.

This is a simplified version to achieve, what you want to do:

function Get-Password{
    $pass =@(
        [char[]](65..91 | Get-Random -Count 2)
        [char[]](97..123 | Get-Random -Count 2) 
        '!','@','$' | Get-Random -Count 2
        0..9 | Get-Random -Count 2
    ) | sort {Get-Random} 
    $pass -join ''
}

Hello,

I got this going with your example. Slightly modified…

-join ((65..90)+(97..122)+(48..57)+(33,35,36)  | foreach-object {[char]$_} | Get-Random -Count 8)

Thank you!

Nice!
Glad it helped you.

Hi Dirk,
Nice example. The only draw back I see there is you don’t get repeating characters which eliminates some of the complexity, and would be necessary if, for example, they wanted 5 special characters from the list of 3 possibilities.

There is one aspect that I’m not understanding how it works. I can see that it obviously does work, but I would like to understand why.

 | sort {Get-Random}

What is this doing? How does Sort-Object interact with the Curly Braces and Get-Random here? I can’t find any documentation on it.

Slight modification to your code so you can get repeat characters in each category

function Get-Password{
    $pass =@(
        1..2 | % {[char[]](65..91 | Get-Random)}
        1..2 | % {[char[]](97..123 | Get-Random)}
        1..5 | % {'!','@','$' | Get-Random}
        1..2 | % {0..9 | Get-Random}
    ) | sort {Get-Random} 
    $pass -join ''
}

Hi Curtis,
good thinking.
The way this works is, that the result of the expression within the scriptblock is used to rank the indiviual elements of the collection. Since Get-Random is used, it results in a random order. This makes Sort-Object really powerful.
I’ve written a blog post (Sort data using a custom list in PowerShell). Here are some more examples on how this can be used:

#Descending (not the best way of doing it)
1..5 | sort { -$_ } 
"--"
#Even after odd
1..5 | sort { $_ % 2 } 
#numberwords
"--"
$numberWords="three","one","two","four"
$numberWords=$numberWords*10
$customList="one","two","three","four"
$numberWords | sort { $customList.IndexOf($_) }

Ok, I think I get it, since get-random generates a random large number for each object that is piped in, the result is the list being sorted numerically by the number randomly generated by get-random. This is intriguing. I’m gonna have to play with it a little more. Thanks for sharing the knowledge.