Скрипт, не назначающий объекты WMI массиву правильно

Я пытаюсь создать сценарий, который обнаруживает профили пользователей домена, возраст которых не превышает 15 дней, и удаляет их. Это будет связано с заданием, которое будет выходить из любых незанятых сессий до его запуска.

Мне известно, что это обычно делается с помощью GPO, однако по разным причинам это не подходит для этой конкретной бизнес-сферы.

Вот мой код:

#Assign how old the user profile must be for deletion
[int]$NoOfDays = 15

#Get WMI object where it is a domain account and over 15 days old
$Objects = @(Get-WmiObject -Class Win32_UserProfile | Where {
    (!$_.Special) -and
    $_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-15)
})

if ($Objects -eq $null) {
    #If no users returned, write to host.
    Write-Host "no profiles found for deletion"
} else {
    #If users are found, do the following
    foreach ($Object in $Objects) {
        Write-Host "'$($object.LocalPath)' has been identified for deletion"
    }

    foreach ($Object in $Objects) {
        try {
            Write-Host "Attempting to delete profile '$($Object.LocalPath)'"
            Remove-WmiObject
            Write-Host "Deleted profile '$($Object.LocalPath)' successfully."
        } catch {
            Write-Host "Unable to delete profile '$($Object.LocalPath)'" -ErrorAction Continue
        }
    }
}

Нет вывода, он просто возвращается в командную строку без ошибок сразу.

Я попытался закомментировать бит, который удаляет профиль, заканчивая else после первого для каждого оператора, чтобы увидеть, что идентифицировано для удаления, однако это не сработало.

3 ответа

Решение

$Objects = @(...) гарантирует, что $Objects является массивом, даже если команда не возвращает результат. Массив (даже пустой массив) никогда не равен $nullТаким образом, ваше первое условие никогда не срабатывает.

+ Изменить

if ($Objects -eq $null) {

в

if ($Objects.Count -gt 0) {

и код должен делать то, что вы ожидаете.

Итак, получается, что это была комбинация вопросов. Основной является версия PS, на которой он работает, не работает на 4. Следующий этап - попытаться заставить PowerShell запускать его как версию 3. Как указывалось ранее, его не нужно обрабатывать в массиве. Вот мой последний скрипт (не любит возвраты после каждого и условия, поэтому оставил форматирование как есть):

if ($PSVersionTable.PSVersion.Major -eq 4)
{
    Write-host "this script will terminate as machine is running PowerShell version 4"
    exit 1
    }

    Else
    {


Start-Sleep -s 5

Set-Location -Path C:\Users     

#Assign how old the user profile must be for deletion

        [DateTime]$AdjustedDate = (Get-Date).AddDays(-15)  
        [DateTime]$CompareDate = Get-Date $AdjustedDate -Format MM-dd-yyyy
        $Hostname = $env:computername
        #$testdate = Get-WmiObject -Class Win32_UserProfile | select {$_.ConvertToDateTime($_.lastusetime).ToShortDateString()}
        #write-host $testdate
        #Get WMI object where it is a domain account and over 15 days old
        $Objects = Get-WmiObject -Class Win32_UserProfile | Where {(!$_.Special) -and ($_.ConvertToDateTime($_.lastusetime) -lt (Get-Date).AddDays(-15))  -and $_.LocalPath -notlike "*.NET*" -and $_.LocalPath -notlike "*SQL*" -and  $_.LocalPath -notlike "*Admin*" -and $_.LocalPath -notlike "*ADMIN*"}


        #If no users returned, write to host.
        If($Objects.Count -eq 0)
        {
            Write-host "no profiles found for deletion"
        }

        #If users are found, do the following
        Else
        {
            Foreach($Object in $Objects)
            {
            Write-host "'$($object.LocalPath)' has been identified for deletion"
Write-host " "
            }

            Foreach($Object in $Objects)
            {

                            Try{
                            Write-Host "Attempting to delete profile '$($Object.LocalPath)'"
                            $UserSID = (Get-WmiObject Win32_UserProfile | Where {$_.LocalPath -like '$($object.LocalPath)'}).SID
                            Remove-WmiObject -InputObject $Object
                            Write-Host "Deleted profile '$($Object.LocalPath)' successfully."
                            }
                            Catch{
                            Write-Host "Unable to delete profile '$($Object.LocalPath)' due to the following error" 
                            Write-Host "$error" -ErrorAction Continue
                            }

            }       
        }
}

В качестве альтернативы решению Ансгара вы можете избежать назначения $Objects переменная в массив (не вижу, почему это требуется).

$Objects = Get-WmiObject -Class Win32_UserProfile | Where {
    (!$_.Special) -and
    $_.ConvertToDateTime($_.LastUseTime) -lt (Get-Date).AddDays(-15)
}

-eq $null проверка может быть использована. Вы также можете найти [string]::IsNullOrEmpty($Object) полезно, так как это обнаружит пустой массив.

Вы упоминаете, что нет выхода... это подозрительно, так как вы должны получить Write-Hosts печатать что-то. На моей машине я получил ошибку с $_.ConvertToDateTime... Я рекомендую запускать ваш код на одной строке в консоли, чтобы убедиться, что он выполняет то, что вы ожидаете.

Другие вопросы по тегам