Powershell 的总 n00b。我决定开始学习 Powershell,因为我在工作中执行了一些标准流程,我希望自动化/简化这些流程。我熟悉其他脚本/编程语言,例如 Python 和 Bash,但不是很熟练。我试图简化的过程是在同一个表中获取 AD 中的基本用户信息(ADuser SamAccountName、UserPrincipalName 和 ADcomputer Name)。我试图通过与用户登录名匹配的计算机描述来获取计算机名称,并将所有信息输出到一个整洁的表格中。
在工作中,我们使用 TeamViewer 远程访问我们的用户系统。我更喜欢使用用户计算机名进行远程访问,而不是他们的 ID,因为我厌倦了解释 TeamViewer 不是 MS Teams 以及在哪里可以找到 ID。无论如何,要查找电脑名称,我需要首先在 AD 中获取用户登录名,然后通过计算机描述搜索计算机。我们有大约 25 个组织单位,其中都有大约 100 名用户和计算机。因此手动遍历每个 OU 来查找它是不可能的。当我每天需要与用户通电话并倾听他们遇到的问题时执行 60 次时,这变得非常乏味。
我们的新用户的登录名是“firstlastname”。年长员工的登录名均以相同的开头,但以姓名首字母“公司名首字母”结尾。我正在尝试编写一个脚本,当运行时提示用户输入真实姓名,无论登录名如何,然后让它吐出所有相关信息。如果它输出具有相似名称的多个用户信息(例如“Sarah”或“John”),那就没问题。只要它能把信息组织得井井有条,我和我的团队就会很高兴。我已经尝试了大约一个月,但未能掌握某些 cmdlet 实际工作原理和最佳实践的一些概念。
任何意见都值得赞赏,但请放轻松,因为我还不太了解 Powershell 的高级概念,而且我知道我编写了垃圾代码。我正在努力变得更好。
我尝试了很多不同的事情,我需要写一本 10 章的书。然而,我最接近得到它的是创建一个新对象。当脚本运行时,它会获取所有正确的信息,但将每条信息放在每个对象成员下,但不分开。所有这些都被捣碎成一根长绳。不知道如何准确解释。但这是迄今为止的整个脚本。我假设我需要在某个地方使用 ForEach 但不确定如何正确执行此操作。我认为我不需要保留对象创建部分,以便将其删除,但我将其放在这里供所有人查看它的外观。也许 if 语句不是正确的方法,我不确定。
$Name = Read-Host -Prompt " "
$UserAccount = Get-ADUser -Filter "Name -like '*$Name*'"
if($UserAccount.SamAccountName -like "companyname-initials*") {
$UserCpu = Get-ADComputer -Filter "Description -like 'companyname-initials*'"
} else {
$UserCpu = Get-ADComputer -Filter "Description -like '*$Name*'"
}
$Output = [pscustomobject]@{
Email = $UserAccount.UserPrincipalName
Login = $UserAccount.SamAccountName
PCName = $UserCpu.Name
}
$Output | Select-Object Email,Login,PCName
如果有什么需要更好的解释,请告诉我。
谢谢!
当脚本运行时,它会获取所有正确的信息,但将每条信息放在每个对象成员下,但不分开。全部捣碎成一根长绳。
从字里行间看出,我认为您无意中使用了名为“成员访问枚举”的功能。
# set up some test data
$users = @(
[pscustomobject] @{
"firstname" = "vic";
"lastname" = "reeves"
},
[pscustomobject] @{
"firstname" = "bob";
"lastname" = "mortimer"
}
);
# build the result object
$output = [pscustomobject] @{
"firstname" = $users.firstname
"lastname" = $users.lastname
"pcname" = "..."
}
# display the result
$output | format-table
这显示以下输出:
firstname lastname pcname
--------- -------- ------
{vic, bob} {reeves, mortimer} {..., ...}
因为
$users
是一个包含多个值的
array,所以
$users.firstname
正在做的是使用成员访问枚举来构建 firstname
数组中对象的 $users
属性的数组 - 结果等价于 @("vic, "bob")
,与 $users.lastname
相同,给出 @("reeves", "mortimer")
。当这些值呈现到屏幕上时,它们将按上述方式序列化。解决方案
要修复此问题,您需要迭代
$users
$output = @()
foreach( $user in $users )
{
[pscustomobject] @{
"firstname" = $user.firstname;
"lastname" = $user.lastname
"pcname" = "..."
}
}
# display the result
$output | format-table
firstname lastname pcname
--------- -------- ------
vic reeves ...
bob mortimer ...
在您的情况下,根本原因是
$UserAccount = Get-ADUser -Filter "Name -like '*$Name*'"
返回多个
帐户,因此您需要迭代它们:
$Name = Read-Host -Prompt " "
# might contain multiple accounts
$UserAccounts = Get-ADUser -Filter "Name -like '*$Name*'"
# loop over each account adding it to the $output array
$output = @()
foreach( $UserAccount in $UserAccounts )
{
if($UserAccount.SamAccountName -like "companyname-initials*") {
$UserCpu = Get-ADComputer -Filter "Description -like 'companyname-initials*'"
} else {
$UserCpu = Get-ADComputer -Filter "Description -like '*$Name*'"
}
$Output += [pscustomobject]@{
Email = $UserAccount.UserPrincipalName
Login = $UserAccount.SamAccountName
PCName = $UserCpu.Name
}
}
# show the results
$Output | Format-Table
您现在应该每行获得一个帐户...
在上面为简单起见,我使用了一种称为加法赋值运算符
的东西 -
+=
行中的 $Output += [pscustomobject]@{ ... }
- 简单来说,这会将一个项目附加到
$Output
数组,但是它如果您正在处理非常大的数据集,则可能会出现性能问题 - 对于这个答案来说,这很好,并且对于小型数据集来说它也可以正常工作,但是如果您看到您的代码在处理大量结果时开始运行缓慢,那么这是第一个看的地方...管道 为了避免“加法分配”运算符的性能问题,您可以使用管道重写示例以收集每个用户帐户的所有结果:
# loop over each account adding it to the $output array
$output = $users | foreach-object
{
if($_.SamAccountName -like "companyname-initials*") {
$UserCpu = Get-ADComputer -Filter "Description -like 'companyname-initials*'"
} else {
$UserCpu = Get-ADComputer -Filter "Description -like '*$Name*'"
}
# this implicitly returns the values to the pipeline to be
# collected into the $output variable as an array
[pscustomobject]@{
Email = $_.UserPrincipalName
Login = $_.SamAccountName
PCName = $UserCpu.Name
}
}
这应该会产生与之前的解决方法相同的结果,但不会遇到相同的性能问题...