You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本无法将AD用户组移除输出写入日志文件

问题分析与修复方案

首先,你的脚本日志写入失败主要有几个关键原因:

  • 你把Start-Transcript放在了foreach循环内部,每次循环都会重新启动转录会话,这会导致日志被反复覆盖,甚至因为会话冲突导致内容无法正常写入。
  • Remove-ADGroupMember默认执行后不会输出任何结果,即使Start-Transcript正常工作,也捕获不到有效操作记录。
  • 你还没实现排除Domain Users组的逻辑,会误删这个需要保留的组。

下面是修复后的完整脚本,同时优化了错误处理和日志记录逻辑:

#Requires -Module ActiveDirectory
Import-Module ActiveDirectory

function Disable-ADUser {
    $logPath = "Y:\Scripts\remove_user_groups.log"
    # 初始化日志文件(如果不存在则创建,存在则追加)
    if (-not (Test-Path $logPath)) {
        New-Item -Path $logPath -ItemType File | Out-Null
    }

    $msg = 'Do you want to remove a user from all Security groups? [Y/N]'
    do {
        $response = Read-Host -Prompt $msg
        if ($response -eq 'y' -or $response -eq 'Y') {
            $firstName = Read-Host "Please provide the First name of the User"
            $lastName = Read-Host "Please provide the Last name of the User"
            
            # 捕获用户查询错误
            try {
                $samName = Get-ADUser -Filter "GivenName -eq '$firstName' -and Surname -eq '$lastName'" | Select-Object -ExpandProperty 'SamAccountName'
                if (-not $samName) {
                    $errorMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - ERROR: No user found with first name '$firstName' and last name '$lastName'"
                    Write-Host $errorMsg -ForegroundColor Red
                    Add-Content -Path $logPath -Value $errorMsg
                    continue
                }
            }
            catch {
                $errorMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - ERROR: Failed to query user: $_"
                Write-Host $errorMsg -ForegroundColor Red
                Add-Content -Path $logPath -Value $errorMsg
                continue
            }

            # 获取用户所属组,排除Domain Users
            try {
                $listGroups = Get-ADUser -Identity $samName -Properties MemberOf | Select-Object -ExpandProperty MemberOf
                $domainUsers = Get-ADGroup -Filter "Name -eq 'Domain Users'" | Select-Object -ExpandProperty DistinguishedName
                $groupsToRemove = $listGroups | Where-Object { $_ -ne $domainUsers }

                if (-not $groupsToRemove) {
                    $infoMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - INFO: User $samName has no groups to remove (except Domain Users)"
                    Write-Host $infoMsg -ForegroundColor Cyan
                    Add-Content -Path $logPath -Value $infoMsg
                }
                else {
                    foreach ($group in $groupsToRemove) {
                        $groupName = (Get-ADGroup -Identity $group).Name
                        try {
                            # 使用-PassThru获取移除操作结果,同时禁止确认提示
                            Remove-ADGroupMember -Identity $group -Members $samName -Confirm:$false -PassThru | Out-Null
                            $successMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - SUCCESS: Removed $samName from group '$groupName' ($group)"
                            Write-Host $successMsg -ForegroundColor Green
                            Add-Content -Path $logPath -Value $successMsg
                        }
                        catch {
                            $errorMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - ERROR: Failed to remove $samName from group '$groupName' ($group): $_"
                            Write-Host $errorMsg -ForegroundColor Red
                            Add-Content -Path $logPath -Value $errorMsg
                        }
                    }
                }

                # 禁用AD用户
                try {
                    Disable-ADAccount -Identity $samName -Confirm:$false
                    $disableMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - SUCCESS: Disabled user account for $samName"
                    Write-Host $disableMsg -ForegroundColor Green
                    Add-Content -Path $logPath -Value $disableMsg
                }
                catch {
                    $errorMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - ERROR: Failed to disable user $samName: $_"
                    Write-Host $errorMsg -ForegroundColor Red
                    Add-Content -Path $logPath -Value $errorMsg
                }
            }
            catch {
                $errorMsg = "$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') - ERROR: Failed to retrieve groups for $samName: $_"
                Write-Host $errorMsg -ForegroundColor Red
                Add-Content -Path $logPath -Value $errorMsg
            }
        }
    } until ($response -eq 'n' -or $response -eq 'N')
}

Disable-ADUser

关键修改说明:

  1. 日志记录优化:

    • 改用Add-Content手动写入日志,避免Start-Transcript的会话冲突问题,同时可以自定义日志格式(包含时间戳、操作状态)。
    • 提前检查并创建日志文件,确保路径有效。
  2. 排除Domain Users组:

    • 通过Get-ADGroup获取Domain Users的DN,在组列表中过滤掉这个组,确保不会误删。
  3. 错误处理增强:

    • 给所有AD操作添加try/catch块,捕获并记录错误信息,同时在控制台显示不同颜色的提示。
    • 处理用户不存在的情况,避免后续操作报错。
  4. 操作可见性提升:

    • 使用-PassThru参数让Remove-ADGroupMember返回操作结果(虽然我们用Out-Null抑制控制台输出,但可以确认操作成功)。
    • 转换组DN为组名称,让日志和控制台输出更易读。
  5. 用户体验优化:

    • 支持大小写不敏感的Y/N输入。
    • 控制台输出区分成功(绿色)、错误(红色)、信息(青色),方便快速识别状态。

额外注意事项:

  • 确保运行脚本的账号有AD组修改和用户禁用的权限,同时对Y:\Scripts\路径有写入权限。
  • 如果网络路径Y:\不稳定,建议改用本地路径或者UNC路径(比如\\server\share\Scripts\remove_user_groups.log)。

内容的提问来源于stack exchange,提问作者David Krause

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 16:33:17