简体   繁体   English

检查和更新 AD 用户的多个属性

[英]Check and Update multiple attributes of AD users

I am trying to do an update to Active Directory from a CSV.我正在尝试从 CSV 更新 Active Directory。 I want to check each value to see if the AD and CSV values match.我想检查每个值以查看 AD 和 CSV 值是否匹配。 If the AD value and CSV values don't match, then I want to update the AD value.如果 AD 值和 CSV 值不匹配,那么我想更新 AD 值。 finally I want to create a log of the values changed, which would eventually be exported to a CSV report.最后,我想创建一个更改值的日志,最终将其导出到 CSV 报告。

Now there is about 30 values I want to check.现在我要检查大约 30 个值。 I could do an if statement for each value, but that seems like the hard way to do it.我可以为每个值做一个 if 语句,但这似乎很难做到。

I am try to use a function, but I cant seem to get it working.我尝试使用 function,但我似乎无法让它工作。 I am getting errors like:我收到如下错误:

set-ADUser : replace
At line:94 char:9
+         set-ADUser -identity $ADUser -replace @{$ADValue = $DIAccount ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (JDoe:ADUser) [Set-ADUser], ADInvalidOperationException
    + FullyQualifiedErrorId : ActiveDirectoryServer:0,Microsoft.ActiveDirectory.Management.Commands.SetADUser

set-ADUser : The specified directory service attribute or value does not exist
Parameter name: Surname
At line:94 char:9
+         set-ADUser -identity $ADUser -replace @{$ADValue = $DIAccount ...
+         ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidArgument: (JDoe:ADUser) [Set-ADUser], ArgumentException
    + FullyQualifiedErrorId : ActiveDirectoryCmdlet:System.ArgumentException,Microsoft.ActiveDirectory.Management.Commands.SetADUser

Any suggestions would be welcome Code I am using:欢迎任何建议我正在使用的代码:

Function AD-Check ($ADValue, $ADUser, $ADAccount, $UpdateAccount)
{
    If ($ADAccount -ne $UpdateAccount)
    {
        set-ADUser -identity $ADUser -replace @{$ADValue = $UpdateAccount}
        $Change = "Updated"
    }
    Else
    {
        $Change = "No Change"
    }
 
    Return $Change
}

$Import = get-content C:\temp\ADUpdates.csv

Foreach ($user in $Import)
{
    $Account = get-aduser $User.Samaccountname -Properties *

    #First Name Check
    $Test = AD-Check "GivenName" $Account.samaccountname $Account.givenname $user.givenname
    $ChangeGivenName = $Test

    #Initials Check
    $Test = AD-Check "Initials" $Account.samaccountname $Account.Initials $user.Initials
    $ChangeInitials = $Test

    #Last Name Check
    $Test = AD-Check "Surname" $Account.samaccountname $Account.SurnameSurname $user.Surname
    $ChangeSurname = $Test
}

Reply to Theo, cant seem to add this any other way...回复 Theo,似乎无法以其他任何方式添加此内容...

Thanks Theo, it seems to make sense, but getting an error.谢谢 Theo,这似乎有道理,但出现错误。

Select-Object : Cannot convert System.Collections.Specialized.OrderedDictionary+OrderedDictionaryKeyValueCollection to one of the following types {System.String, 
System.Management.Automation.ScriptBlock}.

changed the following to get all properties for testing and it works.更改以下内容以获取所有属性以进行测试,并且可以正常工作。

$Account = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue -Properties $propsToCheck

Left the following and it kicks the error留下以下内容,它会引发错误

$oldProperties = $Account | Select-Object $propsToCheck

Using the following just for testing:仅使用以下内容进行测试:

$propertiesMap = [ordered]@{
    SamAccountName = 'sAMAccountName'
    mail           = 'mail'
    GivenName      = 'givenName'
    Initials       = 'initials'
    Surname        = 'sn'
    Office         = 'physicalDeliveryOfficeName'
    MobilePhone    = 'mobile'
    DistinguishedName = 'DistinguishedName'
}

Starting of with a WARNING:从警告开始:

Replacing user attributes is not something to be taken lightly and you need to check any code that does that on a set of testusers first.替换用户属性不能掉以轻心,您需要首先检查在一组测试用户上执行此操作的任何代码。
Keep the -WhatIf switch to the Set-ADUser cmdlet so you can first run this without causing any problems to the AD.-WhatIf切换到 Set-ADUser cmdlet,这样您就可以首先运行它,而不会对 AD 造成任何问题。
Only once you are satisfied all goes according to plan, remove the -WhatIf switch.只有当您对一切都按计划感到满意时,才删除-WhatIf开关。

Please carefully read all inline comments in the code.请仔细阅读代码中的所有内联注释。

In your code you use an input CSV file, apparently with properties and values to be checked/updated, but instead of using Import-Csv , you do a Get-Content on it, so you'll end up with just lines of text, not an array of parsed properties and values..在您的代码中,您使用输入 CSV 文件,显然带有要检查/更新的属性和值,但不是使用Import-Csv ,而是在其上执行Get-Content ,因此您最终只会得到几行文本,不是解析的属性和值的数组..

Next, as Mathias already commented, you need to use the LDAP attribute names when using either the -Add , -Remove , -Replace , or -Clear parameters of the Set-ADUser cmdlet.接下来,正如Mathias已经评论的那样,在使用 Set-ADUser cmdlet 的 -Add 、 -Remove-Replace-Clear参数时,您需要使用-Add属性名称。

To do what you intend to do, I would first create a hashtable to map the PowerShell attribute names to their LDAP equivalents.要执行您打算执行的操作,我将首先为 map 将 PowerShell 属性名称创建到其 LDAP 等效项的哈希表。 To see which property name maps to what LDAP name, you can use the table here要查看哪个属性名称映射到哪个 LDAP 名称,您可以使用此处的表格

# create a Hashtable to map the properties you want checked/updated
# the Keys are the PowerShell property names as they should appear in the CSV
# the Values are the LDAP AD attribute names in correct casing.
$propertiesMap = [ordered]@{
    SamAccountName = 'sAMAccountName'
    GivenName      = 'givenName'
    Initials       = 'initials'
    Surname        = 'sn'
    Office         = 'physicalDeliveryOfficeName'
    Organization   = 'o'
    MobilePhone    = 'mobile'
    # etcetera
}

# for convenience, store the properties in a string array
$propsToCheck = $propertiesMap.Keys | ForEach-Object { $_.ToString() }

# import your CSV file that has all the properties you need checked/updated
$Import = Import-Csv -Path 'C:\temp\ADUpdates.csv'

# loop through all items in the CSV and collect the outputted old and new values in variable $result
$result = foreach ($user in $Import) {
    $sam = $user.SamAccountName
    # try and find the user by its SamAccountName and retrieve the properties you really want (not ALL)
    $Account = Get-ADUser -Filter "SamAccountName -eq '$sam'" -ErrorAction SilentlyContinue -Properties $propsToCheck
    if (!$Account) {
        Write-Warning "A user with SamAccountName '$sam' does not exist"
        continue  # skip this one and proceed with the next user from the CSV
    }
    # keep an object with the current account properties for later logging
    $oldProperties = $Account | Select-Object $propsToCheck

    # test all the properties and create a Hashtable for the ones that need changing
    $replaceHash = @{}
    foreach ($prop in $propsToCheck) {
        if ($Account.$prop -ne $user.$prop) {
            $ldapAttribute = $propertiesMap[$prop]       # get the LDAP name from the $propertiesMap Hash
            # If any of the properties have a null or empty value Set-ADUser will return an error.
            if (![string]::IsNullOrWhiteSpace($($user.$prop))) {
                $replaceHash[$ldapAttribute] = $user.$prop
            }
            else {
                Write-Warning "Cannot use '-Replace' with empty value for property '$prop'"
            }
        }
    }

    if ($replaceHash.Count -eq 0) {
        Write-Host "User '$sam' does not need updating"
        continue  # skip this one and proceed with the next user from the CSV
    }

    # try and do the replacements
    try {
        ##########################################################################################################
        # for safety, I have added a `-WhatIf` switch, so this wll only show what would happen if the cmdlet runs. 
        # No real action is performed when using '-WhatIf'
        # Obviously, there won't be any difference between the 'OLD_' and 'NEW_' values then
        ##########################################################################################################
        $Account | Set-ADUser -Replace $replaceHash -WhatIf
        # refresh the account data
        $Account = Get-ADUser -Identity $Account.DistinguishedName -Properties $propsToCheck
        $newProperties = $Account | Select-Object $propsToCheck
        # create a Hashtable with the old and new values for log output
        $changes = [ordered]@{}
        foreach ($prop in $propsToCheck) {
            $changes["OLD_$property"] = $oldProperties.$prop
            $changes["NEW_$property"] = $newProperties.$prop
        }
        # output this as object to be collected in variable $result
        [PsCustomObject]$changes
    }
    catch {
        Write-Warning "Error changing properties on user '$sam':`r`n$($_.Exception.Message)"
    }
}

# save the result as CSV file so you can open with Excel
$result | Export-Csv -Path 'C:\temp\ADUpdates_Result.csv' -UseCulture -NoTypeInformation

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM