使用Where-Object后使用Get-Random创建一个空值表达式

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了使用Where-Object后使用Get-Random创建一个空值表达式相关的知识,希望对你有一定的参考价值。

我正在尝试创建一个包含数字,字母(大写和小写)和符号混合的10个字符的密码。

下面是我在函数中使用的脚本:

Function Get-TempPassword {

$TempPassword = $null

$ascii = $NULL;For ($a = 33;$a –le 126;$a++) {$ascii +=, ([char][byte]$a | Where-Object {$_ -notin "'",'`','|','_',"`;",'"',','})}

Do {$TempPassword += $ascii | Get-Random; $loop++}

Until ($loop -eq 11)

return $TempPassword

}

如果我删除以下部分:

| Where-Object {$ _ -notin“'”,'`','|','_',“;”,'“',','}

密码的创建工作正常,尽管包括我不想包含的符号。

使用Where-Object函数会使Get-Random函数仅使用数组中的前5个字符,因此我不会获得任何案例类型,数字或任何其他符号的字母。

我发现如果我使用$ascii[26](数组中的第25个字符),我得到一个空值,但我认为这将允许使用这个字符的任何字符,或者根本不使用,不仅仅是第一个第25个角色恰好是一个; (ascii值59)。我尝试将符号添加到Where-Object排除项中,并将其从数组中删除,但第25个字符仍显示为空值。

我对每个字符的ascii值[int[]][char[]]执行了反向查找;符号会出现,它返回值58和60,让我相信它是值59,但是此时的符号应该被排除在外。

在'where-object'排除列表中添加字符应该是从数组中删除它们,看起来如果运行$ascii.Count显示49个字符,无论我是否在Where-Object排除列表中添加或删除字符。

我在网上寻找信息似乎找不到任何信息,虽然它可能是我正在使用的搜索词,因为它有点复杂的情况,没有多少报道。

任何帮助表示赞赏。

答案

我没有写这个,我不记得我在哪里得到它但我已经将其构建到任何脚本中以创建随机安全的Windows密码,您可以指定param [int]$PasswordLength返回的密码长度(我已经设置了它到10)。

function New-SWRandomPassword {
    [CmdletBinding(DefaultParameterSetName='FixedLength',ConfirmImpact='None')]
    [OutputType([String])]
    Param
    (
        # Specifies minimum password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='RandomLength')]
        [ValidateScript({$_ -gt 0})]
        [Alias('Min')] 
        [int]$MinPasswordLength = 8,

        # Specifies maximum password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='RandomLength')]
        [ValidateScript({
                if($_ -ge $MinPasswordLength){$true}
                else{Throw 'Max value cannot be lesser than min value.'}})]
        [Alias('Max')]
        [int]$MaxPasswordLength = 11,

        # Specifies a fixed password length
        [Parameter(Mandatory=$false,
                   ParameterSetName='FixedLength')]
        [ValidateRange(1,2147483647)]
        [int]$PasswordLength = 10,

        # Specifies an array of strings containing charactergroups from which the password will be generated.
        # At least one char from each group (string) will be used.
        [String[]]$InputStrings = @('abcdefghijkmnpqrstuvwxyz', 'ABCEFGHJKLMNPQRSTUVWXYZ', '23456789', '!"#%&'),

        # Specifies a string containing a character group from which the first character in the password will be generated.
        # Useful for systems which requires first char in password to be alphabetic.
        [String] $FirstChar,

        # Specifies number of passwords to generate.
        [ValidateRange(1,2147483647)]
        [int]$Count = 1
    )
    Begin {
        Function Get-Seed{
            # Generate a seed for randomization
            $RandomBytes = New-Object -TypeName 'System.Byte[]' 4
            $Random = New-Object -TypeName 'System.Security.Cryptography.RNGCryptoServiceProvider'
            $Random.GetBytes($RandomBytes)
            [BitConverter]::ToUInt32($RandomBytes, 0)
        }
    }
    Process {
        For($iteration = 1;$iteration -le $Count; $iteration++){
            $Password = @{}
            # Create char arrays containing groups of possible chars
            [char[][]]$CharGroups = $InputStrings

            # Create char array containing all chars
            $AllChars = $CharGroups | ForEach-Object {[Char[]]$_}

            # Set password length
            if($PSCmdlet.ParameterSetName -eq 'RandomLength')
            {
                if($MinPasswordLength -eq $MaxPasswordLength) {
                    # If password length is set, use set length
                    $PasswordLength = $MinPasswordLength
                }
                else {
                    # Otherwise randomize password length
                    $PasswordLength = ((Get-Seed) % ($MaxPasswordLength + 1 - $MinPasswordLength)) + $MinPasswordLength
                }
            }

            # If FirstChar is defined, randomize first char in password from that string.
            if($PSBoundParameters.ContainsKey('FirstChar')){
                $Password.Add(0,$FirstChar[((Get-Seed) % $FirstChar.Length)])
            }
            # Randomize one char from each group
            Foreach($Group in $CharGroups) {
                if($Password.Count -lt $PasswordLength) {
                    $Index = Get-Seed
                    While ($Password.ContainsKey($Index)){
                        $Index = Get-Seed                        
                    }
                    $Password.Add($Index,$Group[((Get-Seed) % $Group.Count)])
                }
            }

            # Fill out with chars from $AllChars
            for($i=$Password.Count;$i -lt $PasswordLength;$i++) {
                $Index = Get-Seed
                While ($Password.ContainsKey($Index)){
                    $Index = Get-Seed                        
                }
                $Password.Add($Index,$AllChars[((Get-Seed) % $AllChars.Count)])
            }
            Return $(-join ($Password.GetEnumerator() | Sort-Object -Property Name | Select-Object -ExpandProperty Value))
        }
    }
}

New-SWRandomPassword

编辑:::

https://gallery.technet.microsoft.com/scriptcenter/Generate-a-random-and-5c879ed5

脚本可以在这里找到。

另一答案

短版(对我而言最好的方法):

$possible=36..38 + 40..43 + 45..58 + 60..94 + 97..123 + 125..126 + 33
(get-random -count 10 -input $possible | % {[char]$_}) -join ''
另一答案

使用以下脚本似乎完全符合我的要求。

我从此行的+ =后删除了逗号(,):

$ascii = $NULL;For ($a = 33;$a –le 126;$a++) {$ascii +=, ([char][byte]$a | Where-Object {$_ -notin "'",'`','|','_',";",'"',','})}

在将数组添加到:$ascii = @()之前,我创建了一个空白数组

完整的代码块如下:

Function Get-TempPassword {

    $TempPassword = $null

    $ascii = @()
    For ($a = 33;$a –le 126; $a++) { $ascii += ([char][byte]$a | Where-Object { $_ -notin "'",'`','|','_',";",'"',',' }) }

    Do {$TempPassword += $ascii | Get-Random; $loop++}

    Until ($loop -eq 11)

    return $TempPassword
}
另一答案

递归方法:

Function random-password ($length = 10)
{

$Assembly = Add-Type -AssemblyName System.Web
$password = [System.Web.Security.Membership]::GeneratePassword($length, 2)

$desablechar = "[``'|_;,`"]"

  if ($password -match $desablechar )
  {
    random-password $length
  }
  else
  {
    $password
  }
}

random-password
另一答案

尝试像这样的东西:

Function random-password ($length = 10)
{
  $possible=36..38 + 40..43 + 45..58 + 60..94 + 97..123 + 125..126  + 33

  $password = get-random -count $length -input $possible |
            % -begin { $aa = $null } -process {$aa += [char]$_} -end {$aa}

  return $password
}

random-password
另一答案

我已经纠正了我的其他命题,但我提出了另一种方法:)

Function random-password2 ($length = 10)
{

$Assembly = Add-Type -AssemblyName System.Web
$password = [System.Web.Security.Membership]::GeneratePassword(50, 2)

$possible=36..38 + 40..43 + 45..58 + 60..94 + 97..123 + 125..126 + 33    
$newchar=[char](get-random -count 1 -input $possible)
$password=$password -replace "[`'|_;,]",  $newchar
$password.Substring(0, $length)


}

random-password2

以上是关于使用Where-Object后使用Get-Random创建一个空值表达式的主要内容,如果未能解决你的问题,请参考以下文章

Where-Object 多个条件不起作用

如何使用 Where-Object/Wildcards 匹配多个字符串?

如何像 IN 语句一样使用 Powershell Where-Object

混合 Where-Object/ForEach-Object 语法

Powershell where-object 返回码

支持词法范围的 ScriptBlock 参数(例如 Where-Object)