null

Windows PowerShell: Перемещение директорий заблокированных пользователей на терминальном сервере.

Ни для кого не секрет, что в любой компании пользователи приходят и уходят. Как итог - за пару лет пол сотни уволенных сотрудников, пачка пользователей в AD помеченных как "Неактивные"(Disabled) и загаженный их директориями терминальный сервер, который как известно далеко не резиновый. 
"Удалять директории руками ежеминутно сверяясь с таблицей?" Решение, честно говоря, так себе. 
Как итог: мной создан скрипт ниже, для перемещения всех неактивный пользователей. Как обычно - критика приветствуется. 
 
На чём будем использовать: 
1) Windows Server 2008R2 на котором у нас есть полноценный доступ к ActiveDirectory 
2) Терминальный сервер Windows Server 2008R2 на котором данного доступа нет. 
P.S.: В противном случае, если доступ к AD есть и с терминального сервера, можем радостно объединить части и выполнять всё ниже описанное там.
 
Часть 1: Выполняется на сервере с доступом к AD
Сначала получаем список активных пользователей ActiveDirectory:
import-module activedirectory #Загружаем модуль ActiveDirectory

$properties = @(
	'SamAccountName'
	'Enabled'
)

$ADUsersList = Get-ADUser -f {SamAccountName -like '*'} -Properties $properties | Select -Property $properties | Where-Object {$_.Enabled -eq "True"}
$ADUsersList | Out-Gridview
Часть 2: Выполняется непосредственно на терминальном сервере. 
Для начала отступление: PowerShell имеет достаточно большое кол-во операторов сравнения, таких как -eq и -like, однако в случае сравнения двух массивов про эти операторы можно радостно забыть. Очень прилично эту тему в своё время осветил Vadims Podāns: https://www.sysadmins.lv/blog-ru/powershell-massivy-chast-2-poslednyaya.aspx
Оператор сравнения Compare-Object мне так же не подошёл. Как итог: пришлось писать функцию сравнения самому. Привожу ниже: 
########################################### Initialization functions Massive Compare  #######################

function MassiveCompare {
	
	param (
     [Parameter(Mandatory = $true,Position=0,HelpMessage="11")]
        [Array] $FirstMassiv,
	 [Parameter(Mandatory = $true,Position=1,HelpMessage="22")]	
		[Array] $SecondMassiv,
     [Parameter(Mandatory=$True, ValueFromPipeline=$True, HelpMessage='33333')]
    [ValidateLength(4,7)]
    [string]$Muching    
    )
	
    begin {
       
    }
	
    process {
        [Array] $MuchMassivElemetns = @()
        [Array] $NotMuchMassivElemetns = @()
		
	    for ($FirstMassivIndex = 0; $FirstMassivIndex -lt $FirstMassiv.'length'; $FirstMassivIndex++) {
	    
            $matchValuesArraysFound = $false
		    for ($SecondMassivIndex = 0; $SecondMassivIndex -lt `
															  $SecondMassiv.'length'; $SecondMassivIndex++) {
			
		        if ($FirstMassiv[$FirstMassivIndex] -like [string]::Concat( `
																	$SecondMassiv[$SecondMassivIndex],'*')) {
			    
                    $matchValuesArraysFound = $true
				    break					
                }
				
			    else {
				    #do nothing#
			    }
            }
			
		    if ($matchValuesArraysFound -eq $true) { 
                
                $MuchElement = New-Object -TypeName PSObject
                Add-Member -InputObject $MuchElement -MemberType NoteProperty `
									-Name MuchElement_Name_FirstArray -Value $FirstMassiv[$FirstMassivIndex]
                Add-Member -InputObject $MuchElement -MemberType NoteProperty `
									-Name MuchElement_Name_SecondArray -Value $SecondMassiv[$SecondMassivIndex]
                       
			    $MuchMassivElemetns += $MuchElement	 
            }


		    if ($matchValuesArraysFound -eq $false) {
                			
		        $NotMuchElement = New-Object -TypeName PSObject
                Add-Member -InputObject $NotMuchElement -MemberType NoteProperty `
									-Name NotMuchElement_Name -Value $FirstMassiv[$FirstMassivIndex]
                $NotMuchMassivElemetns += $NotMuchElement	
			
            }
		
	    }


    }
    
    end {
            
        if ($Muching -like 'Much') {
            return $MuchMassivElemetns
        }
               
        if ($Muching -like 'NotMuch') {
            return $NotMuchMassivElemetns
        }
    
    }
	
}
#############################################################################################################
Как итог на выходе:
MassiveCompare $Массив№1 $Массив№2 -Muching NotMuch # Получаем все не совпавшие элементы
MassiveCompare $Массив№1 $Массив№2 -Muching Much # Получаем все совпавшие элементы
 
Далее нам необходима функция перемещения директорий в необходимое нам место: 
########################################### Initialization functions Move Directories  ######################

function MoveDir {
	
	param (
     [Parameter(Mandatory = $true,Position=0,HelpMessage="11")]
        [Array] $DirNameList,


     [Parameter(Mandatory=$True, Position=1,ValueFromPipeline=$false, HelpMessage='22222')]
     [ValidateLength(3,50)]
     [string]$OldPath,
     
     [Parameter(Mandatory=$True, Position=2,ValueFromPipeline=$false, HelpMessage='33333')]
     [ValidateLength(3,50)]
     [string]$NewPath 
        
    )

    begin {

        $MoveDirQuantity = $DirNameList.Length
        $report = @()

    }

    process {

        for ($MoveDirIndex = 0; $MoveDirIndex -lt $MoveDirQuantity; $MoveDirIndex++) {
        
            $SelectFolderName = $DirNameList[$MoveDirIndex]
            $SelectFolderOldPath = "$OldPath\$SelectFolderName"
            $SelectFolderNewPath = "$NewPath\$SelectFolderName"


            
            Move-Item -LiteralPath $SelectFolderOldPath -destination $NewPath
             
            $ReportMoveDirObject = New-Object -TypeName PSObject
            Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
															-Name Moved_Folder_Name -Value $SelectFolderName
            Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
															-Name Old_Folder_Path -Value $SelectFolderOldPath
            Add-Member -InputObject $ReportMoveDirObject -MemberType NoteProperty `
															-Name New_Folder_Path -Value $SelectFolderNewPath
            
            $report += $ReportMoveDirObject             
        }

    }

    end {        
        return $report
    }

}

#############################################################################################################
Как итог: получаем достаточно удобный в использовании инструмент по перемещению директорий + чёткий репорт на выходе содержащий: что, откуда и куда было перемещено.
Синтаксис: MoveDir $Массив_имён_директорий_для_перемещения $Откуда $Куда
 
Поехали далее: 
Инициализируем первый объект массив . Заполняем его именами всех директорий из C:\Users
$ListTermSRVDirUsers = Get-ChildItem $TermUsersFolderPath | ?{$_.PsIsContainer -eq $true}
Инициализируем второй объект массив. Заполняем его имена активных пользователей AD.
$ListADUsers = @(
	#Массив имён активных пользователей из AD
)
Используем ранее написанную функцию по сравнению двух массивов для выявления не совпавших элементов. 
$NeedMoveUsersDirTermSRV = MassiveCompare $ListTermSRVDirUsers $ListADUsers -Muching NotMuch
$NeedMoveDirNameList = $NeedMoveUsersDirTermSRV | foreach {   
    $_.NotMuchElement_Name
}
Не забывайте, что директория пользователей на терминальном сервере, содержит ещё и служебные директории, такие как Default, Public и т.д.
Их перемещение может вызвать нежелательные последствия. В связи с этим, нам необходимо пометить данные директории как запрещённые к перемещению. Директорию DeletedUsers, в которую мы перемещаем директории неактивных пользователей так же нужно исключить. 
 
Поэтому:
Инициализируем ещё один массив с именами директорий запрещённых к перемещению и повторно прогоняем через функцию сравнения массивов, получая на выходе не совпавшие элементы. 
$ForbiddenMoveUsersDirTermSRV = @(
    'DeletedUsers'
    'Public'
    'e18070'
    'Default'
)
Write-Output ("`n`Исключаю запрещённые к перемещению директории:")
Write-Output ("`n`t$ForbiddenMoveUsersDirTermSRV")
Write-Output ("`n`_________________________________________________________________________________________")

$NeedMoveDirExcludeForbiddenTermSRV = MassiveCompare $NeedMoveDirNameList $ForbiddenMoveUsersDirTermSRV `
																							-Muching NotMuch
$NeedMoveDirExcludeForbiddenNameList = $NeedMoveDirExcludeForbiddenTermSRV | foreach {
    $_.NotMuchElement_Name
}
Далее используя полученный массив имён прогоняем через функцию перемещения директорий. Репорт выводим в формате таблицы.  
MoveDir $NeedMoveDirExcludeForbiddenNameList $TermUsersFolderPath $DeletedUsersFolderPath | FT
$host.ui.RawUI.ReadKey(6)|out-null
Вперед