尝试创建Powershell用户创建脚本,想要在用户名后添加数字(如果已存在)

时间:2018-11-13 18:56:58

标签: powershell

我正在尝试创建用户创建脚本,以作为一种自学更多Powershell的方式。目前,我只在创建用户名,并希望确保每个用户名都是唯一的。

用户输入用户的名称和编号后,脚本应执行以下操作。

获取名字 得到中间的首字母 获取姓氏 组合名字的首字母+中间的首字母+姓氏中的6个字符 如果用户已经存在,请添加从1开始的数字,直到用户名唯一为止。 我目前停留在第5步。如果用户名不是唯一的,它将附加一个数字。即用户Brenda T Follower的用户名为BTFollow,如果该用户名已经存在,则为BTFollow1。

但是,如果已经存在BTFollow和BTFollow1而不是使其成为BTFollow2,那么它将成为BTFollow12。

最后,虽然不是一个大问题,但我希望我的参数显示Read-Host之后的内容,但该文本不会仅显示变量名。

这是我的代码。

Param(
#Gather users first name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$FirstName = (Read-Host -Prompt 'Please input the users first name.'),

#Gather users middle initial, required input and must not be empty or null and must only be one character
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidateLength(1,1)]
[string]
$MiddleInitial = (Read-Host -Prompt 'Please input the users middle initial.'),

#Gather users last name, required input and must not be empty or null
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[string]
$LastName = (Read-Host -Prompt 'Please input the users last name.'),

#Gathers user phone extension, required input, mustn ot be empty or null, and must only user numbers
[Parameter(Mandatory=$True)]
[ValidateNotNullOrEmpty()]
[ValidatePattern("[0-9][0-9][0-9][0-9]")]
[ValidateLength(4,4)]
[String]
$PhoneExtension = (Read-Host -Prompt 'Please input the users 4 digit exension, numbers only')
)

$i = 0



#Create user name
$Username = $FirstName.Substring(0,1) + $MiddleInitial + $LastName.Substring(0,6)

#Check username does not exist, if it does add numbers

Do {
    Try {
        Get-ADUser $UserName | Out-Null
        $UserName = $Username + ++$i
        Continue
    }
    Catch {
        Break
    }
} While ($True)

Write-Host "Username is $Username"

2 个答案:

答案 0 :(得分:2)

由于您在循环中进行了反复修改 $UserName,因此您最终在每次迭代中都添加了其他号:

$UserName = $Username + ++$i

使用BTFollow作为原始值,该值在第一次迭代后为BTFollow1,然后在第二次迭代中将2附加到 that ,产生BTFollow12,依此类推。

Your own answer的工作原理(尽管-like应该用-eq代替),鉴于其吸引人的简洁性和重复名称的相对稀有性,很可能是要走的路。

>

以下解决方案提供了优化,但所需的复杂性可能不值得;至少我希望它能展示一些有趣的技术。


通过用Get-AdUser预先过滤可能的重复项,然后在本地处理候选者,可以完全避免在Get-ADUser -Filter周围进行昂贵的循环

$highestIndexSoFar =
  Get-ADUser -Filter "SamAccountName -like '$UserName*'" | 
    ForEach-Object { if ($_.SamAccountName -match '\d*$') { [int] $Matches[0] } } |
      Sort-Object -Descending | Select-Object -First 1

if ($null -eq $highestIndexSoFar) { # no duplicates -> use as-is
    $UniqueUserName = $UserName
} else { # increment the highest index to date to make the username unique
    $UniqueUserName = $UserName + (1 + $highestIndexSoFar)
}

上述解决方案的另一个优点是,它确定实际名称中的后缀数量最高,可靠地使用了迄今为止最高的 +1 后缀,而循环调用{Get-AdUser的方法使用的是不采用的第一个索引(尽管只有随着时间的推移用户被删除或序列后缀是手动创建的。

  • Get-ADUser -Filter "SamAccountName -like '$UserName*'"检索潜在重复项; -Filter语法不够复杂,不足以允许基于正则表达式的匹配,因此此预过滤只能找到共享相同前缀(可能包含误报)的所有用户名(例如{jdoet {1}},而最终仅应考虑使用数字后缀,例如jdoe

  • 然后,使用
  • 正则表达式jdoe1清除此类误报,并且实际的,可能为空的数字后缀('\d*$')反映在自动\d*变量的{{ 1}}条目。

  • 数字后缀(如果存在或为空)则强制转换为$Matches并输出。

    • 请注意,最初未索引的用户名(例如[0]将导致[int]为空字符串,将其转换为BTFollow会转换为$Matches[0],因此附加的第一个索引将是[int]
  • 0按降序对结果数字进行排序,然后1提取找到的第一个(即,最高的)后缀号(如果有)。

  • 如果根本找不到匹配项,即,如果尚未使用用户名,则无需排序,Sort-Object -Descending有效地产生Select-Object -First 1;否则,必须将Select-Object -First 1添加到最高编号以形成新的唯一用户名。

注意事项:如果其他人同时创建用户,这种方法可能仍然会失败。

答案 1 :(得分:2)

在Reddit的帮助下找到了答案。我需要替换当前的代码。

const onHeaders = require('on-headers');

onHeaders(res, function () {
    this.removeHeader('etag');
});

有效的新代码。

Do {
    Try {
        Get-ADUser $UserName | Out-Null
        $UserName = $Username + ++$i
        Continue
    }
    Catch {
        Break
    }
} While ($True)