WSUS 删除 DownstreamServer 中的计算机

问题描述 投票:0回答:1

当我删除下游服务器上的计算机时遇到问题。 我通过 powershell 使用对象 Microsoft.UpdateServices.Administration.ComputerTargetScope 中的类 .Delete() 来完成此操作。 该计算机已从下游服务器中正确删除,但删除未在主服务器上同步,并且该计算机仍然存在于主服务器上。 我尝试同步双方,但计算机仍然存在于主机上。

这是我的脚本:

#Définition des paramètres d'invocation du script
[CmdletBinding()]
param
(
    [Parameter(Mandatory = $true, Position = 1)]
    [string]
    $UpdateServer,

    [Parameter(Mandatory = $true, Position = 2)]
    [int]
    $Port,

    [Parameter()]
    [switch]
    $UseSSL,

    [Parameter()]
    [int]
    $ExclusionPeriod = 0
)

#Création du dossier de logs
if (-not (Test-Path -Path "$PSScriptRoot\WsusDeleteComputersLogs"))
{
    New-Item -Path $PSScriptRoot -Name 'WsusDeleteComputersLogs' -ItemType Directory -Force
}

#Création du fichier de logs qui va restranscrire les output du script
$file = "$PSScriptRoot\WsusDeleteComputersLogs\{0:yyyyMMdd_HHmm}_WSUS_Delete_Computers.log" -f (Get-Date) 

#Début de la retranscription pour écrire tous les logs du script dans le fichier ci-dessus
Start-Transcript -Path $file

#Création de variables contenant les chemins des fichiers où seront listées les mises à jours remplacées et rétablies
$outDeletedList = Join-Path -Path "$PSScriptRoot\WsusDeleteComputersLogs" -ChildPath ('{0:yyyyMMdd_HHmm}_DeletedComputers.csv' -f (Get-Date))

#Création de la ligne des titres dans le fichier CSV des mises à jour remplacées et rétablies
Set-Content -Value 'Server; FullDomainName; LastReportStatusTime; In Stock' -Path $outDeletedList

#Importe le module ActiveDirectory pour se connecter à l'AD
Import-Module ActiveDirectory

#Récupération des pcs présents dans l'OU Stock
$OUstock = (Get-ADComputer -SearchBase "OU=Stock,DC=domain,DC=lan" -Filter * -SearchScope Subtree).DNSHostName

#Création d'une variable pour se connecter au serveur WSUS avec ou sans SSL
try
{
    if ($UseSSL)
    {
        Write-Output -InputObject "Connecting to WSUS server $UpdateServer on Port $Port using SSL... "
    }
    else
    {
        Write-Output -InputObject "Connecting to WSUS server $UpdateServer on Port $Port... "
    }
    
    [reflection.assembly]::LoadWithPartialName('Microsoft.UpdateServices.Administration') | Out-Null
    $wsusMaster = [Microsoft.UpdateServices.Administration.AdminProxy]::GetUpdateServer($UpdateServer, $UseSSL, $Port);
}
catch [System.Exception] 
{
    Write-Output -InputObject 'Failed to connect.'
    Write-Output -InputObject "Error: $($_.Exception.Message)"
    Write-Output -InputObject 'Please make sure that WSUS Admin Console is installed on this machine'
    Write-Output -InputObject ''
    $wsusMaster = $null
}

#Arrête le script si la connexion au serveur a échoué
if ($null -eq $wsusMaster)
{
    return
}

Write-Output -InputObject 'Connected.'

#Création d'une variable qui contiendra tous les serveur en aval
try
{
    #Récupération de la liste des serveur WSUS en aval du Master
    $wsusDownstreamServers = $wsusMaster.GetDownstreamServers()
}
catch [System.Exception]
{
    Write-Output -InputObject 'Failed to get Downstream Servers.'
    Write-Output -InputObject "Error: $($_.Exception.Message)"
    Write-Output -InputObject ''
    return
}

#Initie les filtres pour une liste d'ordinateurs dans une variable
$computerScope = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope

#Indique la date et l'heure actuels
Write-Host "Date du jour : " (Get-Date)
#Définit la plage des dates des derniers rapports des ordinateurs dans la variable initiée ci-dessus

Write-Host "Date limite : "((Get-Date).AddDays(-8))

#Création des variables utilisées dans le script
$countAllComputers = 0
$countOutDatedAll = 0
$countInStockAll = 0
$countDeleted = 0

Foreach($wsusDownstreamserver in $wsusDownstreamServers)
{
    $computerScopeIn = New-Object Microsoft.UpdateServices.Administration.ComputerTargetScope
    $computerScopeIn.ToLastReportedStatusTime = (Get-Date).AddDays(-8)

    Write-Host $wsusDownstreamserver.FullDomainName

    try
    {
        $connectDownstreamserver = (Get-WsusServer -Name $wsusDownstreamserver.FullDomainName -PortNumber "8530")
        Write-Host "Connected to : $($wsusDownstreamserver.FullDomainName)"
        $computerList = $connectDownstreamserver.GetComputerTargets()
        $computerListScope = $connectDownstreamserver.GetComputerTargets($computerScopeIn)
    }
    catch [System.Exception] 
    {
        Write-Output -InputObject 'Failed to connect.'
        Write-Output -InputObject "Error: $($_.Exception.Message)"
        Write-Output -InputObject 'Please make sure that WSUS Admin Console is installed on this machine'
        Write-Output -InputObject ''
        continue
    }

    
    Write-Host "Groupe $($wsusDownstreamserver.FullDomainName) : "
    Write-Host ""
    Foreach($computer in $computerList)
    {
        $countAllComputers++
        if($OUstock -contains $computer.FullDomainName)
        {
            $countStockAll++
            Write-host "L'ordinateur $($computer.FullDomainName) est dans l'OU Stock"
            "$($wsusDownstreamserver.FullDomainName); $($computer.FullDomainName); $($computer.LastReportedStatusTime.ToLocalTime()); TRUE" | Out-File $outDeletedList -Append
            $computer.Delete()
            $countDeleted++
        }
    }

    Foreach($computerScope in $computerListScope)
    {
        $countOutDatedAll++
        Write-host "L'ordinateur $($computerScope.FullDomainName) n'a pas été synchronisé depuis le $($computerScope.LastReportedStatusTime.ToLocalTime())"
        "$($wsusDownstreamserver.FullDomainName); $($computerScope.FullDomainName); $($computerScope.LastReportedStatusTime.ToLocalTime()); FALSE" | Out-File $outDeletedList -Append
        $computerScope.Delete()
        $countDeleted++
    }
    Write-Host ""
    Write-Host "-----"
    Write-Host ""
    $computerListScope = 0
    $computerListScope = 0
}

#Log de sortie contenant les informations de comptage ci-dessus
Write-Output -InputObject 'Summary:'
Write-Output -InputObject '========'
Write-Output -InputObject "All Computers = $($countAllComputers)"
Write-Output -InputObject "All OutDated Computers = $($countOutDatedAll)"
Write-Output -InputObject "All In Stock OU = $($countStockAll)"
Write-Output -InputObject "All Deleted Computers = $($countDeleted)"
Write-Output -InputObject ""
Write-Output -InputObject "---"
Write-Output -InputObject "End"

Stop-Transcript

感谢您的帮助:)

windows powershell windows-server windows-update
1个回答
0
投票

我找到了解决问题的方法。 我必须添加 SQL 命令来删除主机上 SQL 数据库中的计算机,如下所示:

    Foreach($computer in $computerList)
    {
        $countAllComputers++
        if($OUStock -contains $computer.FullDomainName)
        {
            $countInStockAll++
            Write-host "L'ordinateur $($computer.FullDomainName) est dans l'OU Stock"
            "$($wsusDownstreamserver.FullDomainName); $($computer.FullDomainName); $($computer.LastReportedStatusTime.ToLocalTime()); TRUE" | Out-File $outDeletedList -Append
            $computer.Delete()
            $countDeleted++

            $FullDomainName = $computer.FullDomainName

            # Préparation de la requête pour récupérer TargetId et ComputerID
            $queryRetrieval = @"
            SELECT TargetID, ComputerID FROM [SUSDB].[dbo].[tbComputerTarget] WHERE FullDomainName = '$FullDomainName'
"@

            # Exécution de la requête pour récupérer les valeurs
            $result = Invoke-Sqlcmd -Query $queryRetrieval -ServerInstance "np:\\.\pipe\MICROSOFT##WID\tsql\query" -Database "SUSDB" -Encrypt Optional

            # Vérification et affichage des résultats
            if ($result) {
                Write-Output "TargetID: $($result.TargetID)"
                Write-Output "ComputerID: $($result.ComputerID)"

                try{
                    # Préparation de la requête pour supprimer l'entrée
                    $queryDeletion = @"
                    DELETE FROM [SUSDB].[dbo].[tbComputerTarget] WHERE ComputerID = '$($result.ComputerID)'
"@

                    # Exécution de la requête de suppression
                    Invoke-Sqlcmd -Query $queryDeletion -ServerInstance "np:\\.\pipe\MICROSOFT##WID\tsql\query" -Database "SUSDB" -Encrypt Optional
                    Write-Output "Entrée supprimée pour l'ordinateur: $($FullDomainName)"
                }
                catch{
                    Write-Output $_.Exception.Message
                }
            } else {
                Write-Output "Aucun enregistrement trouvé pour $FullDomainName"
            }
        }
    }

    Foreach($computerScope in $computerListScope)
    {
        $countOutDatedAll++
        Write-host "L'ordinateur $($computerScope.FullDomainName) n'a pas été synchronisé depuis le $($computerScope.LastReportedStatusTime.ToLocalTime())"
        "$($wsusDownstreamserver.FullDomainName); $($computerScope.FullDomainName); $($computerScope.LastReportedStatusTime.ToLocalTime()); FALSE" | Out-File $outDeletedList -Append
        $computerScope.Delete()
        $countDeleted++

        $FullDomainName = $computerScope.FullDomainName

        # Préparation de la requête pour récupérer TargetId et ComputerID
        $queryRetrieval = @"
        SELECT TargetID, ComputerID FROM [SUSDB].[dbo].[tbComputerTarget] WHERE FullDomainName = '$FullDomainName'
"@

        # Exécution de la requête pour récupérer les valeurs
        $result = Invoke-Sqlcmd -Query $queryRetrieval -ServerInstance "np:\\.\pipe\MICROSOFT##WID\tsql\query" -Database "SUSDB" -Encrypt Optional

        # Vérification et affichage des résultats
        if ($result) {
            Write-Output "TargetID: $($result.TargetID)"
            Write-Output "ComputerID: $($result.ComputerID)"

            try{
                # Préparation de la requête pour supprimer l'entrée
                $queryDeletion = @"
                DELETE FROM [SUSDB].[dbo].[tbComputerTarget] WHERE ComputerID = '$($result.ComputerID)'
"@

                # Exécution de la requête de suppression
                Invoke-Sqlcmd -Query $queryDeletion -ServerInstance "np:\\.\pipe\MICROSOFT##WID\tsql\query" -Database "SUSDB" -Encrypt Optional
                Write-Output "Entrée supprimée pour l'ordinateur: $($FullDomainName)"
            }
            catch{
                Write-Output $_.Exception.Message
            }
        } else {
            Write-Output "Aucun enregistrement trouvé pour $FullDomainName"
        }
    }

复制此脚本时请注意,脚本中的“@”必须保留在左边距,不要使用制表将其与代码的其余部分对齐。

我不知道我是否处于最佳实践,但它的效果就像我想要的:)

© www.soinside.com 2019 - 2024. All rights reserved.