Using Get-Random -Count

Welcome Forums General PowerShell Q&A Using Get-Random -Count

This topic contains 10 replies, has 5 voices, and was last updated by

 
Participant
1 year, 3 months ago.

  • Author
    Posts
  • #73502

    Participant
    Points: 0
    Rank: Member

    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!

  • #73505

    Keymaster
    Points: 1
    Rank: Member

    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.

    • #73519

      Participant
      Points: 0
      Rank: Member

      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.

  • #73510

    Participant
    Points: 0
    Rank: Member

    Try wrapping this in a function:

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

    Hope it helps.

    • #73513

      Participant
      Points: 0
      Rank: Member

      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.

    • #73576

      Participant
      Points: 0
      Rank: Member

      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!

    • #73589

      Participant
      Points: 0
      Rank: Member

      Nice!
      Glad it helped you.

  • #73523

    Participant
    Points: 0
    Rank: Member

    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 ''
    }
    
    
    • #73601

      Participant
      Points: 0
      Rank: Member

      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 ''
      }
    • #73610

      Participant
      Points: 0
      Rank: Member

      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($_) }
      
  • #73613

    Participant
    Points: 0
    Rank: Member

    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.

The topic ‘Using Get-Random -Count’ is closed to new replies.