从 CSV 批量延长 AD 帐户到期日期的 Powershell 脚本

Powershell script to bulk extend AD account expiration dates from CSV

我正在寻求帮助来创建一个脚本,该脚本要求用户输入日期,然后从与脚本位于同一文件夹中的 CSV 文件中导入 AD 用户名,然后延长中列出的所有帐户用户名的到期日期CSV,到输入的日期,然后报告成功 and/or 失败。

到目前为止,下面的脚本完成了大部分工作。我改编自 Tom 在这里帮助我编写的脚本 - .

我一直在尝试为下面的脚本添加额外的功能。我正在尝试获取它,以便脚本将继续通过 CSV 上的空白和错误条目,更重要的是,在屏幕上显示这些错误条目,以便用户可以看到哪些条目失败了。

如果删除 try{}catch{ 并将 $ErrorActionPreference = 'SilentlyContinue' 放在脚本顶部,脚本将继续通过错误条目,但脚本仍会在空白条目处停止并且不通知用户失败的条目。

理想情况下,我希望脚本在 运行 跨越一个条目时说 “无法修改 user_a 的帐户”在 AD 中找不到;例如打字错误或帐户已被删除。

我想也许我可以先通过 AD 运行 CSV 的内容,例如:

(Get-ADUser -Identity $_.user).DnsHostName
If ($null -eq $_.user)

然后让脚本将所有不是 $null 的脚本推送到脚本的其余部分,然后在屏幕上将 AD 中未找到的那些作为失败吐出,其中CSV 中空白单元格的异常,这可能可以通过 运行 对 CSV 内容进行初始 $null 检查来完成。

虽然我不知道如何实现它。我觉得这是可能的。我已经尝试多次迭代此脚本,但都没有成功。

我希望有人喜欢这个挑战。

$ErrorActionPreference = 'Continue'
write-host "Bulk AD Account Expiration Date Changer" 
Write-Host ""
Write-Host "Please add the usernames requiring account expiration date extensions to the bulk_accounts_extension.csv file"
Write-Host "and ensure that the bulk_accounts_extension.csv is in the same location as this script."
Write-Host ""

    $AD_User_date = new-object datetime
    do{
    $Entered_Date = Read-Host "Enter a new expiry date, in the format DD/MM/YYYY"
    $result = [datetime]::tryparseexact($Entered_Date,'dd/MM/yyyy',[cultureinfo]("en-GB"), [globalization.datetimestyles]("None"),[ref]$AD_User_date)
    if(!$result){write-host 'Invalid date entered!'}
    }until($result)
    try{

    Import-Csv ".\bulk_accounts_extension.csv" | foreach-object {Set-ADAccountExpiration -Identity ($_.users = $_.users.Trim()) -DateTime $AD_User_date.AddHours(24)}

    Write-Host "New expiration date for all users is the end of $(($AD_User_date).toString('dd/MM/yyyy'))"
    }catch{
    Write-Host "Unable to set account expiry: $_"

    }

pause 

提前致谢。

变化不大,只有一些改进和您所问的内容:

"Ideally I would like the script to say something like failed to modify account for user_a when it runs across an entry that it doesn't find in AD; like a typo or an account that's been deleted."

$ErrorActionPreference = 'Stop' # 'Continue' => NO BAD :(
$csvPath = "$PSScriptRoot\bulk_accounts_extension.csv"
$status = [System.Collections.Generic.List[pscustomobject]]::new()

if(-not(Test-Path $csvPath))
{
    Write-Warning "bulk_accounts_extension.csv could not be found on $PSScriptRoot"
    Read-Host
    break
}

# Set minimum entered date here, must be above 30 days???
$dateMin = [datetime]::Now.AddDays(30)

@'
Bulk AD Account Expiration Date Changer
---------------------------------------------------------------------

Please add the usernames requiring account expiration date extensions
to the bulk_accounts_extension.csv file and ensure that the
bulk_accounts_extension.csv is in the same location as this script.

---------------------------------------------------------------------
'@ | Write-Host -ForegroundColor Green

while($true)
{
    try
    {
        # Loop until a valid Date is entered and that Date is above $dateMin

        $Entered_Date = [datetime]::ParseExact(
            (Read-Host "Enter a new expiry date, in the format DD/MM/YYYY"),
            'dd/MM/yyyy',
            [System.Globalization.CultureInfo]::new('en-GB')
        )

        if($Entered_Date -lt $dateMin)
        {
            throw
        }

        break
    }
    catch
    {
        Write-Warning "Invalid date entered! Format must be DD/MM/YYYY and higher than $dateMin"
    }
}

$users = Import-Csv $csvPath

foreach($user in $users.users)
{
    try
    {
        $user = $user.Trim()
        Set-ADAccountExpiration -Identity $user -DateTime $Entered_Date.AddHours(24)

        $status.Add(
        [pscustomobject]@{
            Time = [datetime]::Now
            User = $user
            Status = 'SUCCESS'
            Message = 'New Expiration Date: {0}' -f $Entered_Date.ToShortDateString()
        })
    }
    catch
    {
        # If Set-ADAccountExpiration throws, either because of lack of permissions or can't find
        # the account, this will output something like:
       
        # User          Error         
        # ----          -----         
        # ExampleUser01 User not found
        # ExampleUser02 User not found
        # ExampleUser03 Access Denied 
        # ExampleUser04 User not found
        
        $status.Add(
        [pscustomobject]@{
            Time = [datetime]::Now
            User = $user
            Status = 'FAILED'
            Message = $_.Exception.Message
        })
    }
}


$success, $failed = $status.Where({$_.Status -eq 'SUCCESS'},'Split')

$success | Out-String | Write-Host -ForegroundColor Green
$failed | Out-String | Write-Host -ForegroundColor Red