Using Get-Random -Count

Tagged: ,

This topic contains 10 replies, has 5 voices, and was last updated by Profile photo of Curtis Smith Curtis Smith 1 month ago.

  • Author
    Posts
  • #73502
    Profile photo of Creed Cordonier
    Creed Cordonier
    Participant

    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
    Profile photo of Don Jones
    Don Jones
    Keymaster

    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
      Profile photo of Creed Cordonier
      Creed Cordonier
      Participant

      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
    Profile photo of Ben Camareno
    Ben Camareno
    Participant

    Try wrapping this in a function:

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

    Hope it helps.

    • #73513
      Profile photo of Creed Cordonier
      Creed Cordonier
      Participant

      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
      Profile photo of Creed Cordonier
      Creed Cordonier
      Participant

      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
      Profile photo of Ben Camareno
      Ben Camareno
      Participant

      Nice!
      Glad it helped you.

  • #73523
    Profile photo of Dirk
    Dirk
    Participant

    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
      Profile photo of Curtis Smith
      Curtis Smith
      Participant

      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
      Profile photo of Dirk
      Dirk
      Participant

      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
    Profile photo of Curtis Smith
    Curtis Smith
    Participant

    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.

You must be logged in to reply to this topic.