#Module name: O365BulkDatacleaner #Author: Jos Lieben (OGD) #Date: 24-03-2017 #Purpose: make the folderpath supplied compliant with Onedrive for Business limitations #Make SURE you have placed the O365Datacleaner script in the same folder as this script #Parameter1: -csvPath path to the CSV file containing usernames and folder paths #Parameter2: -log will be passed to the child script to use for logging #Parameter3: -commit 1 for read-write mode, 0 for read-only mode Param( [Parameter(Mandatory=$true)] [string]$csvPath, [Parameter(Mandatory=$true)] [string]$log, [Parameter(Mandatory=$true)] [Int]$commit ) Write-Host "Starting...." -ForegroundColor Green try{ $csv = import-csv -Path $csvPath -Delimiter ";" -ErrorAction Stop }catch{ Write-Host "Failed to load CSV file $($Error[0])" -ForeGroundColor Red exit } $debug = $False $maxThreads = 4 $Jobs = @() $SleepTimer = 500 $ISS = [system.management.automation.runspaces.initialsessionstate]::CreateDefault() $RunspacePool = [runspacefactory]::CreateRunspacePool(1, $maxThreads, $ISS, $Host) $RunspacePool.Open() $scriptPath = split-path -parent $MyInvocation.MyCommand.Definition $secondScriptName = "O365Datacleaner_v1.12.ps1" $secondaryScriptPath = Join-Path -Path $scriptPath -ChildPath $secondScriptName function Pause{ Read-Host 'Press Enter to exit...' | Out-Null } function startThread(){ Param( [String]$path, [String]$username, [String]$adminLog, [Int]$commit ) $OFS = "`r`n" $Code = [ScriptBlock]::Create($(Get-Content $secondaryScriptPath)) Remove-Variable OFS $thread = [PowerShell]::Create().AddScript($Code) $thread.AddArgument($path) $thread.AddArgument($username) $thread.AddArgument($adminLog) $thread.AddArgument($commit) $thread.RunspacePool = $RunspacePool $Handle = $thread.BeginInvoke() $Job = "" | Select-Object Handle, Thread, object $Job.Handle = $Handle $Job.Thread = $thread $Job.Object = $username.ToString() return $Job } $csvIndex = 0 $finishedJobs = 0 $runningJobs = 0 $waitingJobs = @($csv).Count $totalJobs = @($csv).Count while($finishedJobs -lt $totalJobs){ #start a job if there are threads and waiting jobs if($RunspacePool.GetAvailableRunspaces() -gt 0 -and $waitingJobs -gt 0){ $Jobs += startThread -path $csv[$csvIndex].homedirpath -username $csv[$csvIndex].username -adminLog $log -commit $commit $csvIndex++ $runningJobs++ $waitingJobs-- } #dispose of finished Jobs ForEach ($Job in $($Jobs | Where-Object {$_.Handle.IsCompleted -eq $True})){ $finishedJobs++ $runningsJobs-- $result = $Job.Thread.EndInvoke($Job.Handle) if($result -eq $True){ Write-Host "$($Job.Object) completed" -ForegroundColor Green }else{ Write-Host "$($Job.Object) failed to start or finish properly, see logs" -ForegroundColor Red } $Job.Thread.Dispose() $Job.Thread = $Null $Job.Handle = $Null } try{$percentComplete = ($finishedJobs / $totalJobs) * 100}catch{$percentComplete = 0} #monitor / report status $RunningJobTitles = "$($($Jobs | Where-Object {$_.Handle.IsCompleted -eq $False}).Object)" Write-Progress -Activity "Waiting for Jobs - $($maxThreads - $($RunspacePool.GetAvailableRunspaces())) of $maxThreads threads running" -PercentComplete $percentComplete -Status "$finishedJobs of $totalJobs completed. Currently working on: $RunningJobTitles" Start-Sleep -Milliseconds $SleepTimer } $RunspacePool.Close() | Out-Null $RunspacePool.Dispose() | Out-Null Write-Host "Finished processing $totalJobs homedirectories" -ForegroundColor Green Pause