我正在尝试创建用户创建脚本,以作为一种自学更多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"
答案 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)