EnhancedDeviceMigrationAO.psm1
#Region '.\Public\Add-LocalUser.ps1' -1 function Add-LocalUser { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TempUser, [Parameter(Mandatory = $true)] [string]$TempUserPassword, [Parameter(Mandatory = $true)] [string]$Description, [Parameter(Mandatory = $true)] [string]$Group ) Begin { Write-EnhancedLog -Message "Starting Add-LocalUser function" -Level "INFO" Log-Params -Params @{ TempUser = $TempUser TempUserPassword = $TempUserPassword Description = $Description Group = $Group } } Process { try { Write-EnhancedLog -Message "Creating Local User Account" -Level "INFO" $Password = ConvertTo-SecureString -AsPlainText $TempUserPassword -Force New-LocalUser -Name $TempUser -Password $Password -Description $Description -AccountNeverExpires Add-LocalGroupMember -Group $Group -Member $TempUser } catch { Write-EnhancedLog -Message "An error occurred while adding local user: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Add-LocalUser function" -Level "INFO" } } # # Define parameters # $AddLocalUserParams = @{ # TempUser = "YourTempUser" # TempUserPassword = "YourTempUserPassword" # Description = "account for autologin" # Group = "Administrators" # } # # Example usage with splatting # Add-LocalUser @AddLocalUserParams #EndRegion '.\Public\Add-LocalUser.ps1' 54 #Region '.\Public\Analyze-CopyOperationStatus.ps1' -1 function Analyze-CopyOperationStatus { [CmdletBinding()] param ( [Parameter(Mandatory = $true, HelpMessage = "Provide the log folder path.")] [string]$LogFolder, [Parameter(Mandatory = $true, HelpMessage = "Provide the status file name.")] [string]$StatusFileName ) # Define the status file path $statusFile = Join-Path -Path $LogFolder -ChildPath $StatusFileName # Retry mechanism parameters $maxRetries = 5 $retryInterval = 5 $retryCount = 0 $fileFound = $false # Retry loop to check if the status file exists while ($retryCount -lt $maxRetries -and -not $fileFound) { if (Test-Path -Path $statusFile) { $fileFound = $true Write-EnhancedLog -Message "Status file found: $statusFile" -Level "INFO" } else { Write-EnhancedLog -Message "Status file not found: $statusFile. Retrying in $retryInterval seconds..." -Level "WARNING" Start-Sleep -Seconds $retryInterval $retryCount++ } } # If the file is still not found after retries, exit if (-not $fileFound) { Write-EnhancedLog -Message "Status file not found after $maxRetries retries: $statusFile" -Level "ERROR" return } # Read the status file $statusData = Get-Content -Path $statusFile | ConvertFrom-Json # Analyze the status of each operation foreach ($entry in $statusData) { $sourcePath = $entry.SourcePath $backupFolderName = $entry.BackupFolderName $backupStatus = $entry.BackupStatus $timestamp = $entry.Timestamp if ($backupStatus -eq "Success") { Write-EnhancedLog -Message "Backup operation succeeded: Source: $sourcePath, Backup Folder: $backupFolderName, Timestamp: $timestamp" -Level "INFO" } elseif ($backupStatus -eq "Failed") { Write-EnhancedLog -Message "Backup operation failed: Source: $sourcePath, Backup Folder: $backupFolderName, Timestamp: $timestamp" -Level "ERROR" if ($entry.VerificationResults) { foreach ($result in $entry.VerificationResults) { Write-EnhancedLog -Message "Discrepancy: Status: $($result.Status), Source Path: $($result.SourcePath), Expected/Actual Path: $($result.ExpectedPath -or $result.ActualPath)" -Level "WARNING" } } } else { Write-EnhancedLog -Message "Unknown backup status for Source: $sourcePath, Backup Folder: $backupFolderName, Timestamp: $timestamp" -Level "WARNING" } } } # # Example usage with splatting # $AnalyzeParams = @{ # LogFolder = "C:\ProgramData\BackupLogs" # StatusFileName = "UserFilesBackupStatus.json" # } # Analyze-CopyOperationStatus @AnalyzeParams #EndRegion '.\Public\Analyze-CopyOperationStatus.ps1' 72 #Region '.\Public\Analyze-OneDriveSyncStatus.ps1' -1 function Analyze-OneDriveSyncStatus { [CmdletBinding()] param ( [string]$LogFolder, # Parameter for the log folder path [string]$StatusFileName # Parameter for the status file name ) # Define the status file path $statusFile = Join-Path -Path $LogFolder -ChildPath $StatusFileName # Retry mechanism parameters $maxRetries = 5 $retryInterval = 5 $retryCount = 0 $fileFound = $false # Retry loop to check if the status file exists while ($retryCount -lt $maxRetries -and -not $fileFound) { if (Test-Path -Path $statusFile) { $fileFound = $true Write-EnhancedLog -Message "Status file found: $statusFile" -Level "INFO" } else { Write-EnhancedLog -Message "Status file not found: $statusFile. Retrying in $retryInterval seconds..." -Level "WARNING" Start-Sleep -Seconds $retryInterval $retryCount++ } } # If the file is still not found after retries, exit if (-not $fileFound) { Write-EnhancedLog -Message "Status file not found after $maxRetries retries: $statusFile" -Level "ERROR" return } # Read the status file $Status = Get-Content -Path $statusFile | ConvertFrom-Json # Check the status properties $Success = @( "Shared", "UpToDate", "Up To Date" ) $InProgress = @( "SharedSync", "Shared Sync", "Syncing" ) $Failed = @( "Error", "ReadOnly", "Read Only", "OnDemandOrUnknown", "On Demand or Unknown", "Paused") ForEach ($s in $Status) { $StatusString = $s.StatusString $DisplayName = $s.DisplayName $User = $s.UserName if ($StatusString -in $Success) { Write-EnhancedLog -Message "OneDrive sync status is healthy: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "INFO" } elseif ($StatusString -in $InProgress) { Write-EnhancedLog -Message "OneDrive sync status is currently syncing: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "WARNING" } elseif ($StatusString -in $Failed) { Write-EnhancedLog -Message "OneDrive sync status is in a known error state: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "ERROR" } else { Write-EnhancedLog -Message "Unable to get OneDrive Sync Status for Display Name: $DisplayName, User: $User" -Level "WARNING" } } } # # Example usage with splatting # $AnalyzeParams = @{ # LogFolder = "C:\ProgramData\AADMigration\logs" # StatusFileName = "OneDriveSyncStatus.json" # } # Analyze-OneDriveSyncStatus @AnalyzeParams #EndRegion '.\Public\Analyze-OneDriveSyncStatus.ps1' 70 #Region '.\Public\Analyze-OneDriveSynUtilcStatus.ps1' -1 function Analyze-OneDriveSyncUtilStatus { <# .SYNOPSIS Analyzes the OneDrive sync status from a JSON file. .DESCRIPTION The Analyze-OneDriveSyncUtilStatus function reads the OneDrive sync status from a specified JSON file, and categorizes the status as healthy, in progress, or failed based on predefined conditions. .PARAMETER LogFolder The path to the folder where the log files are stored. .PARAMETER StatusFileName The name of the JSON file containing the OneDrive sync status. .EXAMPLE $params = @{ LogFolder = "C:\ProgramData\AADMigration\logs" StatusFileName = "OneDriveSyncStatus.json" } Analyze-OneDriveSyncUtilStatus @params Analyzes the OneDrive sync status from the specified JSON file. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$LogFolder, [Parameter(Mandatory = $true)] [string]$StatusFileName ) Begin { Write-EnhancedLog -Message "Starting Analyze-OneDriveSyncUtilStatus function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Define the status file path $statusFile = Join-Path -Path $LogFolder -ChildPath $StatusFileName } Process { try { # Retry mechanism parameters $maxRetries = 5 $retryInterval = 5 $retryCount = 0 $fileFound = $false # Retry loop to check if the status file exists while ($retryCount -lt $maxRetries -and -not $fileFound) { if (Test-Path -Path $statusFile) { $fileFound = $true Write-EnhancedLog -Message "Status file found: $statusFile" -Level "INFO" } else { Write-EnhancedLog -Message "Status file not found: $statusFile. Retrying in $retryInterval seconds..." -Level "WARNING" Start-Sleep -Seconds $retryInterval $retryCount++ } } # If the file is still not found after retries, exit if (-not $fileFound) { $errorMessage = "Status file not found after $maxRetries retries: $statusFile" Write-EnhancedLog -Message $errorMessage -Level "ERROR" throw $errorMessage } # Read the status file $Status = Get-Content -Path $statusFile | ConvertFrom-Json # Define the status categories $Success = @("Synced", "UpToDate", "Up To Date") $InProgress = @("Syncing", "SharedSync", "Shared Sync") $Failed = @("Error", "ReadOnly", "Read Only", "OnDemandOrUnknown", "On Demand or Unknown", "Paused") # Analyze the status $StatusString = $Status.CurrentStateString $UserName = $Status.UserName if ($StatusString -in $Success) { Write-EnhancedLog -Message "OneDrive sync status is healthy: User: $UserName, Status: $StatusString" -Level "INFO" } elseif ($StatusString -in $InProgress) { Write-EnhancedLog -Message "OneDrive sync status is currently syncing: User: $UserName, Status: $StatusString" -Level "WARNING" } elseif ($StatusString -in $Failed) { Write-EnhancedLog -Message "OneDrive sync status is in a known error state: User: $UserName, Status: $StatusString" -Level "ERROR" } else { Write-EnhancedLog -Message "Unable to determine OneDrive Sync Status for User: $UserName" -Level "WARNING" } } catch { Write-EnhancedLog -Message "An error occurred in Analyze-OneDriveSyncUtilStatus function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Analyze-OneDriveSyncUtilStatus function" -Level "Notice" } } # # # Example usage # $params = @{ # LogFolder = "C:\ProgramData\AADMigration\logs" # StatusFileName = "ODSyncUtilStatus.json" # } # Analyze-OneDriveSyncUtilStatus @params #EndRegion '.\Public\Analyze-OneDriveSynUtilcStatus.ps1' 111 #Region '.\Public\Backup-ChromeBookmarkstoOneDrive-Archived.ps1' -1 # function Backup-ChromeBookmarksToOneDrive { # <# # .SYNOPSIS # Backs up the Chrome bookmarks to OneDrive. # .DESCRIPTION # This function copies the Chrome bookmarks file from the Chrome user profile to a specified OneDrive backup directory using Robocopy. It verifies the existence of the OneDrive directory and uses logging for the backup process. # .PARAMETER ChromeProfilePath # The path to the Chrome user profile directory. # .PARAMETER BackupFolderName # The name of the backup folder within OneDrive. # .PARAMETER Exclude # The directories or files to exclude from the copy operation. Default is ".git". # .PARAMETER RetryCount # The number of retries if a copy fails. Default is 2. # .PARAMETER WaitTime # The wait time between retries in seconds. Default is 5. # .PARAMETER RequiredSpaceGB # The required free space in gigabytes at the destination. Default is 10 GB. # .EXAMPLE # $params = @{ # ChromeProfilePath = "$env:USERPROFILE\AppData\Local\Google\Chrome\User Data\Default" # BackupFolderName = "ChromeBackup" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-ChromeBookmarksToOneDrive @params # #> # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ChromeProfilePath, # [Parameter(Mandatory = $true)] # [string]$BackupFolderName, # [Parameter(Mandatory = $false)] # [string[]]$Exclude = ".git", # [Parameter(Mandatory = $false)] # [int]$RetryCount = 2, # [Parameter(Mandatory = $false)] # [int]$WaitTime = 5, # [Parameter(Mandatory = $false)] # [int]$RequiredSpaceGB = 10 # ) # Begin { # Write-EnhancedLog -Message "Starting Backup-ChromeBookmarksToOneDrive function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # # Check for OneDrive directory existence # $oneDriveDirectory = (Get-ChildItem -Path "$env:USERPROFILE" -Filter "OneDrive - *" -Directory).FullName # if (-not $oneDriveDirectory) { # Throw "OneDrive directory not found. Please ensure OneDrive is set up correctly." # } # Write-EnhancedLog -Message "OneDrive directory found: $oneDriveDirectory" -Level "INFO" # # Check if the Chrome profile directory exists # if (-not (Test-Path -Path $ChromeProfilePath)) { # Write-EnhancedLog -Message "Chrome profile directory not found. It seems Google Chrome is not installed or used." -Level "Warning" # return # } # Write-EnhancedLog -Message "Chrome profile directory found: $ChromeProfilePath" -Level "INFO" # # Define the destination path within the OneDrive directory # $backupPath = Join-Path -Path $oneDriveDirectory -ChildPath $BackupFolderName # # Check if destination path exists, if not create it # if (-not (Test-Path -Path $backupPath)) { # New-Item -Path $backupPath -ItemType Directory -Force | Out-Null # Write-EnhancedLog -Message "Created backup directory at: $backupPath" -Level "INFO" # } # # Temporary directory for copying the specific file # $tempDir = "C:\Users\Admin-Abdullah\AppData\Local\Temp\ChromeTemp" # # Ensure the temporary directory exists # if (-not (Test-Path -Path $tempDir)) { # New-Item -ItemType Directory -Path $tempDir # } # # Files to back up # $filesToBackup = @("Bookmarks") # foreach ($file in $filesToBackup) { # $sourceFilePath = $ChromeProfilePath # Robocopy uses directory paths # $destinationFilePath = $backupPath # Robocopy destination directory # # Check if the source file exists before attempting to copy # if (Test-Path -Path (Join-Path -Path $sourceFilePath -ChildPath $file)) { # try { # # Copy the Bookmarks file to the temporary directory # Copy-Item -Path (Join-Path -Path $sourceFilePath -ChildPath $file) -Destination $tempDir # # Use splatting for function parameters # $params = @{ # Source = $tempDir # Destination = $destinationFilePath # FilePattern = $file # Exclude = $Exclude # RetryCount = $RetryCount # WaitTime = $WaitTime # RequiredSpaceGB = $RequiredSpaceGB # } # # Execute the function with splatting # Copy-FilesWithRobocopy @params # Write-EnhancedLog -Message "Successfully backed up '$file' to '$destinationFilePath'." -Level "INFO" # # Remove the temporary directory # Remove-Item -Path $tempDir -Recurse -Force # } # catch { # Write-EnhancedLog -Message "An error occurred while backing up '$file': $_" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # else { # Write-EnhancedLog -Message "'$file' does not exist in the source directory and will not be backed up." -Level "Warning" # } # } # } # catch { # Write-EnhancedLog -Message "An error occurred in Backup-ChromeBookmarksToOneDrive function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Backup-ChromeBookmarksToOneDrive function" -Level "Notice" # } # } # # # Example usage # # $params = @{ # # ChromeProfilePath = "$env:USERPROFILE\AppData\Local\Google\Chrome\User Data\Default" # # BackupFolderName = "ChromeBackup" # # Exclude = ".git" # # RetryCount = 2 # # WaitTime = 5 # # RequiredSpaceGB = 10 # # } # # Backup-ChromeBookmarksToOneDrive @params #EndRegion '.\Public\Backup-ChromeBookmarkstoOneDrive-Archived.ps1' 161 #Region '.\Public\Backup-DownloadsToOneDrive-Archived.ps1' -1 # function Backup-DownloadsToOneDrive { # <# # .SYNOPSIS # Backs up the Downloads folder to OneDrive. # .DESCRIPTION # This function copies all files from the Downloads folder to a specified OneDrive backup directory using Robocopy. It verifies the existence of the OneDrive directory and uses logging for the backup process. # .PARAMETER DownloadsPath # The path to the Downloads folder. # .PARAMETER BackupFolderName # The name of the backup folder within OneDrive. # .PARAMETER Exclude # The directories or files to exclude from the copy operation. Default is ".git". # .PARAMETER RetryCount # The number of retries if a copy fails. Default is 2. # .PARAMETER WaitTime # The wait time between retries in seconds. Default is 5. # .PARAMETER RequiredSpaceGB # The required free space in gigabytes at the destination. Default is 10 GB. # .EXAMPLE # $params = @{ # DownloadsPath = "$env:USERPROFILE\Downloads" # BackupFolderName = "DownloadsBackup" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-DownloadsToOneDrive @params # #> # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$DownloadsPath, # [Parameter(Mandatory = $true)] # [string]$BackupFolderName, # [Parameter(Mandatory = $false)] # [string[]]$Exclude = ".git", # [Parameter(Mandatory = $false)] # [int]$RetryCount = 2, # [Parameter(Mandatory = $false)] # [int]$WaitTime = 5, # [Parameter(Mandatory = $false)] # [int]$RequiredSpaceGB = 10 # ) # Begin { # Write-EnhancedLog -Message "Starting Backup-DownloadsToOneDrive function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # # Check for OneDrive directory existence # $oneDriveDirectory = (Get-ChildItem -Path "$env:USERPROFILE" -Filter "OneDrive - *" -Directory).FullName # if (-not $oneDriveDirectory) { # Throw "OneDrive directory not found. Please ensure OneDrive is set up correctly." # } # Write-EnhancedLog -Message "OneDrive directory found: $oneDriveDirectory" -Level "INFO" # # Check if the Downloads directory exists # if (-not (Test-Path -Path $DownloadsPath)) { # Throw "Downloads directory not found. Please ensure the path is correct." # } # Write-EnhancedLog -Message "Downloads directory found: $DownloadsPath" -Level "INFO" # # Define the destination path within the OneDrive directory # $backupPath = Join-Path -Path $oneDriveDirectory -ChildPath $BackupFolderName # # Check if destination path exists, if not create it # if (-not (Test-Path -Path $backupPath)) { # New-Item -Path $backupPath -ItemType Directory -Force | Out-Null # Write-EnhancedLog -Message "Created backup directory at: $backupPath" -Level "INFO" # } # # Use splatting for function parameters # $params = @{ # Source = $DownloadsPath # Destination = $backupPath # FilePattern = '*' # Exclude = $Exclude # RetryCount = $RetryCount # WaitTime = $WaitTime # RequiredSpaceGB = $RequiredSpaceGB # } # # Execute the function with splatting # Copy-FilesWithRobocopy @params # Write-EnhancedLog -Message "Backup of Downloads to OneDrive completed successfully." -Level "INFO" # } # catch { # Write-EnhancedLog -Message "An error occurred in Backup-DownloadsToOneDrive function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Backup-DownloadsToOneDrive function" -Level "Notice" # } # } # # Example usage # # $params = @{ # # DownloadsPath = "$env:USERPROFILE\Downloads" # # BackupFolderName = "DownloadsBackup" # # Exclude = ".git" # # RetryCount = 2 # # WaitTime = 5 # # RequiredSpaceGB = 10 # # } # # Backup-DownloadsToOneDrive @params #EndRegion '.\Public\Backup-DownloadsToOneDrive-Archived.ps1' 126 #Region '.\Public\Backup-OutlookSignaturestoOneDrive-Archived.ps1' -1 # function Backup-OutlookSignaturesToOneDrive { # <# # .SYNOPSIS # Backs up the Outlook Signatures folder to OneDrive. # .DESCRIPTION # This function copies all files from the Outlook Signatures folder to a specified OneDrive backup directory using Robocopy. It verifies the existence of the OneDrive directory and uses logging for the backup process. # .PARAMETER SignaturePath # The path to the Outlook Signatures folder. # .PARAMETER BackupFolderName # The name of the backup folder within OneDrive. # .PARAMETER Exclude # The directories or files to exclude from the copy operation. Default is ".git". # .PARAMETER RetryCount # The number of retries if a copy fails. Default is 2. # .PARAMETER WaitTime # The wait time between retries in seconds. Default is 5. # .PARAMETER RequiredSpaceGB # The required free space in gigabytes at the destination. Default is 10 GB. # .EXAMPLE # $params = @{ # SignaturePath = "$env:USERPROFILE\AppData\Roaming\Microsoft\Signatures" # BackupFolderName = "OutlookSignatures" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-OutlookSignaturesToOneDrive @params # #> # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$SignaturePath, # [Parameter(Mandatory = $true)] # [string]$BackupFolderName, # [Parameter(Mandatory = $false)] # [string[]]$Exclude = ".git", # [Parameter(Mandatory = $false)] # [int]$RetryCount = 2, # [Parameter(Mandatory = $false)] # [int]$WaitTime = 5, # [Parameter(Mandatory = $false)] # [int]$RequiredSpaceGB = 10 # ) # Begin { # Write-EnhancedLog -Message "Starting Backup-OutlookSignaturesToOneDrive function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # # Check for OneDrive directory existence # $oneDriveDirectory = (Get-ChildItem -Path "$env:USERPROFILE" -Filter "OneDrive - *" -Directory).FullName # if (-not $oneDriveDirectory) { # Throw "OneDrive directory not found. Please ensure OneDrive is set up correctly." # } # Write-EnhancedLog -Message "OneDrive directory found: $oneDriveDirectory" -Level "INFO" # # Check if the Outlook Signatures directory exists # if (-not (Test-Path -Path $SignaturePath)) { # Write-EnhancedLog -Message "Outlook Signatures directory not found. It seems Outlook is not set up." -Level "Warning" # return # } # Write-EnhancedLog -Message "Outlook Signatures directory found: $SignaturePath" -Level "INFO" # # Define the destination path within the OneDrive directory # $backupPath = Join-Path -Path $oneDriveDirectory -ChildPath $BackupFolderName # # Check if destination path exists, if not create it # if (-not (Test-Path -Path $backupPath)) { # New-Item -Path $backupPath -ItemType Directory -Force | Out-Null # Write-EnhancedLog -Message "Created backup directory at: $backupPath" -Level "INFO" # } # # Use splatting for function parameters # $params = @{ # Source = $SignaturePath # Destination = $backupPath # FilePattern = '*' # Exclude = $Exclude # RetryCount = $RetryCount # WaitTime = $WaitTime # RequiredSpaceGB = $RequiredSpaceGB # } # # Execute the function with splatting # Copy-FilesWithRobocopy @params # Write-EnhancedLog -Message "Backup of Outlook Signatures to OneDrive completed successfully." -Level "INFO" # } # catch { # Write-EnhancedLog -Message "An error occurred in Backup-OutlookSignaturesToOneDrive function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Backup-OutlookSignaturesToOneDrive function" -Level "Notice" # } # } # # # Example usage # # $params = @{ # # SignaturePath = "$env:USERPROFILE\AppData\Roaming\Microsoft\Signatures" # # BackupFolderName = "OutlookSignatures" # # Exclude = ".git" # # RetryCount = 2 # # WaitTime = 5 # # RequiredSpaceGB = 10 # # } # # Backup-OutlookSignaturesToOneDrive @params #EndRegion '.\Public\Backup-OutlookSignaturestoOneDrive-Archived.ps1' 127 #Region '.\Public\Backup-UserFilesToOneDrive.ps1' -1 function Backup-UserFilesToOneDrive { <# .SYNOPSIS Backs up user files to a specified OneDrive folder and logs the results. .DESCRIPTION The Backup-UserFilesToOneDrive function copies files from a specified source directory to a OneDrive backup directory. It verifies the operation, logs the results, and saves the status to a JSON file. The function handles errors gracefully and appends the backup status to the JSON file. .PARAMETER SourcePath The path to the directory containing the files to be backed up. .PARAMETER BackupFolderName The name of the folder where the backup will be stored in the OneDrive directory. .PARAMETER Exclude A list of files or directories to exclude from the backup operation. .PARAMETER RetryCount The number of times to retry the backup operation if it fails. .PARAMETER WaitTime The time to wait between retry attempts, in seconds. .PARAMETER RequiredSpaceGB The amount of free space required at the destination in gigabytes. .PARAMETER OneDriveBackupPath The path to the OneDrive directory where the backup will be stored. .PARAMETER Scriptbasepath The base path of the script, used to determine where to store logs. .PARAMETER ClearPreviousStatus If set to $true, removes the existing JSON status file before starting the backup. Defaults to $false. .EXAMPLE Backup-UserFilesToOneDrive -SourcePath "$env:USERPROFILE\AppData\Local\Google\Chrome\User Data\Default" ` -BackupFolderName "ChromeBackup" ` -OneDriveBackupPath "$env:OneDrive\Backups" ` -Scriptbasepath "$PSScriptRoot" ` -ClearPreviousStatus $true This command backs up Chrome bookmarks to the OneDrive backup folder and removes the existing JSON status file before starting. .EXAMPLE Backup-UserFilesToOneDrive -SourcePath "$env:USERPROFILE\AppData\Roaming\Microsoft\Signatures" ` -BackupFolderName "OutlookSignatures" ` -OneDriveBackupPath "$env:OneDrive\Backups" ` -Scriptbasepath "$PSScriptRoot" This command backs up Outlook signatures to the OneDrive backup folder without clearing the existing JSON status file. .NOTES The function handles verification of the copy operation and appends the results to a JSON log file. .LINK https://docs.microsoft.com/en-us/powershell/scripting #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$SourcePath, [Parameter(Mandatory = $true)] [string]$BackupFolderName, [Parameter(Mandatory = $false)] [string[]]$Exclude, [Parameter(Mandatory = $false)] [int]$RetryCount = 2, [Parameter(Mandatory = $false)] [int]$WaitTime = 5, [Parameter(Mandatory = $false)] [int]$RequiredSpaceGB = 10, [Parameter(Mandatory = $true)] [string]$OneDriveBackupPath, [Parameter(Mandatory = $true)] [string]$Scriptbasepath # [Parameter(Mandatory = $false)] # [bool]$ClearPreviousStatus = $true ) Begin { Write-EnhancedLog -Message "Starting Backup-UserFilesToOneDrive function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Define the log file path $logFolder = Join-Path -Path (Get-Item -Path $Scriptbasepath).Parent.FullName -ChildPath "logs" $statusFile = Join-Path -Path $logFolder -ChildPath "UserFilesBackupStatus.json" # Ensure the log directory exists if (-not (Test-Path -Path $logFolder)) { New-Item -Path $logFolder -ItemType Directory | Out-Null } # # Clear the existing JSON status file if specified # if ($ClearPreviousStatus -and (Test-Path -Path $statusFile)) { # Remove-Item -Path $statusFile -Force # Write-EnhancedLog -Message "Previous JSON status file removed: $statusFile" -Level "INFO" # } # Ensure the backup directory exists $backupPath = Join-Path -Path $OneDriveBackupPath -ChildPath $BackupFolderName if (-not (Test-Path -Path $backupPath)) { New-Item -Path $backupPath -ItemType Directory | Out-Null } } Process { try { # Perform the backup operation $CopyFilesWithRobocopyParams = @{ Source = $SourcePath Destination = $backupPath Exclude = $Exclude RetryCount = $RetryCount WaitTime = $WaitTime RequiredSpaceGB = $RequiredSpaceGB } Copy-FilesWithRobocopy @CopyFilesWithRobocopyParams # Verify the copy operation $verificationResults = Verify-CopyOperation -SourcePath $SourcePath -DestinationPath $backupPath # $DBG # Determine backup status based on verification results $backupStatus = if ($verificationResults.Count -eq 0) { "Success" } else { "Failed" } # Prepare the status entry $status = @{ SourcePath = $SourcePath BackupFolderName = $BackupFolderName BackupPath = $backupPath BackupStatus = $backupStatus VerificationResults = if ($verificationResults.Count -eq 0) { @() } else { $verificationResults } Timestamp = (Get-Date).ToString("o") } # Load existing JSON file content if it exists, ensuring it's treated as an array $existingStatus = @() if (Test-Path -Path $statusFile) { $existingStatus = Get-Content -Path $statusFile | ConvertFrom-Json if ($existingStatus -isnot [System.Collections.ArrayList] -and $existingStatus -is [PSCustomObject]) { $existingStatus = @($existingStatus) } } # Append the new status entry $updatedStatus = $existingStatus + $status # Save the updated status to the JSON file $updatedStatus | ConvertTo-Json -Depth 5 | Out-File -FilePath $statusFile -Force -Encoding utf8 Write-EnhancedLog -Message "Backup status has been saved to $statusFile" -Level "INFO" } catch { $status = @{ SourcePath = $SourcePath BackupFolderName = $BackupFolderName BackupPath = $backupPath BackupStatus = "Failed" ErrorMessage = $_.Exception.Message Timestamp = (Get-Date).ToString("o") } # Load existing JSON file content if it exists, ensuring it's treated as an array $existingStatus = @() if (Test-Path -Path $statusFile) { $existingStatus = Get-Content -Path $statusFile | ConvertFrom-Json if ($existingStatus -isnot [System.Collections.ArrayList] -and $existingStatus -is [PSCustomObject]) { $existingStatus = @($existingStatus) } } # Append the new failure entry $updatedStatus = $existingStatus + $status # Save the updated status to the JSON file $updatedStatus | ConvertTo-Json -Depth 5 | Out-File -FilePath $statusFile -Force -Encoding utf8 Write-EnhancedLog -Message "An error occurred during backup: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Backup-UserFilesToOneDrive function" -Level "Notice" } } #EndRegion '.\Public\Backup-UserFilesToOneDrive.ps1' 192 #Region '.\Public\Block-UserInput.ps1' -1 function Block-UserInput { <# .SYNOPSIS Blocks or unblocks user input. .DESCRIPTION The Block-UserInput function blocks or unblocks user input using the user32.dll library. This can be useful during critical operations to prevent user interference. .PARAMETER Block A boolean value indicating whether to block (true) or unblock (false) user input. .EXAMPLE $params = @{ Block = $true } Block-UserInput @params Blocks user input. .EXAMPLE $params = @{ Block = $false } Block-UserInput @params Unblocks user input. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [bool]$Block ) Begin { Write-EnhancedLog -Message "Starting Block-UserInput function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $code = @" [DllImport("user32.dll")] public static extern bool BlockInput(bool fBlockIt); "@ $userInput = Add-Type -MemberDefinition $code -Name Blocker -Namespace UserInput -PassThru Write-EnhancedLog -Message "Blocking user input: $Block" -Level "INFO" $null = $userInput::BlockInput($Block) } catch { Write-EnhancedLog -Message "An error occurred in Block-UserInput function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Block-UserInput function" -Level "Notice" } } # # Example usage # $params = @{ # Block = $true # } # Block-UserInput @params #EndRegion '.\Public\Block-UserInput.ps1' 66 #Region '.\Public\Check-OneDriveBackupStatus.ps1' -1 function Check-OneDriveBackupStatus { [CmdletBinding()] param () Begin { Write-EnhancedLog -Message "Starting Check-OneDriveBackupStatus function" -Level "INFO" } Process { try { # Attempt to find the OneDrive directory $oneDriveDirectory = (Get-ChildItem "$env:USERPROFILE" -Filter "OneDrive - *" -Directory).FullName # Check if the OneDrive directory exists if (-not $oneDriveDirectory) { Write-EnhancedLog -Message "OneDrive directory does not exist. Remediation is not possible for now." -Level "WARNING" exit 0 } # Define the backup path within the OneDrive directory $backupPath = Join-Path $oneDriveDirectory "DownloadsBackup" # Check if the DownloadsBackup folder exists and contains files if (Test-Path $backupPath) { $fileCount = (Get-ChildItem -Path $backupPath -Recurse -File).Count if ($fileCount -gt 0) { Write-EnhancedLog -Message "DownloadsBackup folder detected with files at $backupPath. Remediation needed." -Level "WARNING" exit 1 } else { Write-EnhancedLog -Message "DownloadsBackup folder exists at $backupPath but is empty. Remediation needed." -Level "WARNING" exit 1 } } else { Write-EnhancedLog -Message "DownloadsBackup folder does not exist at $backupPath. Remediation needed." -Level "WARNING" exit 1 } } catch { Write-EnhancedLog -Message "An error occurred in Check-OneDriveBackupStatus function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Check-OneDriveBackupStatus function" -Level "INFO" } } # Example usage # Check-OneDriveBackupStatus #EndRegion '.\Public\Check-OneDriveBackupStatus.ps1' 51 #Region '.\Public\Check-OneDriveSyncStatus-Archive.ps1' -1 # function Check-OneDriveSyncStatus { # [CmdletBinding()] # param ( # [string]$OneDriveLibPath, # [string]$Scriptbasepath # ) # Begin { # Write-EnhancedLog -Message "Starting Check-OneDriveSyncStatus function" -Level "NOTICE" # Log-Params -Params @{ OneDriveLibPath = $OneDriveLibPath } # # Check if running elevated; do not elevate if not # $isAdmin = CheckAndElevate -ElevateIfNotAdmin $false # if ($isAdmin) { # Write-EnhancedLog -Message "Script is running with elevated privileges. Attempting to de-elevate for OneDrive sync status check..." -Level "WARNING" # try { # try { # try { # $powerShellPath = Get-PowerShellPath # # Temporary file to store the output # $tempFile = [System.IO.Path]::GetTempFileName() # # Start a non-elevated PowerShell process to run the external script and capture output # $startProcessParams = @{ # FilePath = $powerShellPath # ArgumentList = @("-NoProfile", "-ExecutionPolicy", "Bypass", "-File", "$Scriptbasepath\Check-OneDriveSyncStatus-ScriptBlock.ps1", "-OneDriveLibPath", "`"$OneDriveLibPath`"", "> `"$tempFile`" 2>&1") # NoNewWindow = $true # Wait = $true # } # Start-Process @startProcessParams # # Read the output from the temporary file # $nonElevatedStatus = Get-Content -Path $tempFile # # Clean up the temporary file # Remove-Item -Path $tempFile -Force # if ($nonElevatedStatus) { # Write-EnhancedLog -Message "De-elevated process output: $nonElevatedStatus" -Level "INFO" # } # else { # Write-EnhancedLog -Message "No output was captured from the de-elevated process." -Level "WARNING" # } # return $nonElevatedStatus # } # catch { # Write-EnhancedLog -Message "Failed to de-elevate and check OneDrive sync status: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # catch { # Write-EnhancedLog -Message "Failed to de-elevate and check OneDrive sync status: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # catch { # Write-EnhancedLog -Message "Failed to de-elevate and check OneDrive sync status: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # # If not elevated, proceed normally # try { # if (-not (Test-Path $OneDriveLibPath)) { # Write-EnhancedLog -Message "The specified OneDriveLib.dll path does not exist: $OneDriveLibPath" -Level "ERROR" # throw "The specified OneDriveLib.dll path does not exist." # } # Import-Module $OneDriveLibPath # Write-EnhancedLog -Message "Successfully imported OneDriveLib module from $OneDriveLibPath" -Level "INFO" # Get-ODStatus # $Status = Get-ODStatus # if (-not $Status) { # Write-EnhancedLog -Message "OneDrive is not running or the user is not logged in to OneDrive." -Level "WARNING" # return # } # $Success = @( "Shared", "UpToDate", "Up To Date" ) # $InProgress = @( "SharedSync", "Shared Sync", "Syncing" ) # $Failed = @( "Error", "ReadOnly", "Read Only", "OnDemandOrUnknown", "On Demand or Unknown", "Paused") # ForEach ($s in $Status) { # $StatusString = $s.StatusString # $DisplayName = $s.DisplayName # $User = $s.UserName # if ($StatusString -in $Success) { # Write-EnhancedLog -Message "OneDrive sync status is healthy: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "INFO" # } # elseif ($StatusString -in $InProgress) { # Write-EnhancedLog -Message "OneDrive sync status is currently syncing: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "INFO" # } # elseif ($StatusString -in $Failed) { # Write-EnhancedLog -Message "OneDrive sync status is in a known error state: Display Name: $DisplayName, User: $User, Status: $StatusString" -Level "ERROR" # } # else { # Write-EnhancedLog -Message "Unable to get OneDrive Sync Status for Display Name: $DisplayName, User: $User" -Level "WARNING" # } # } # } # catch { # Write-EnhancedLog -Message "An error occurred while checking OneDrive sync status: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Check-OneDriveSyncStatus function" -Level "NOTICE" # } # } # # Example usage # $params = @{ # OneDriveLibPath = "C:\ProgramData\AADMigration\Files\OneDriveLib.dll" # Scriptbasepath = "$PSScriptroot" # } # Check-OneDriveSyncStatus @params #EndRegion '.\Public\Check-OneDriveSyncStatus-Archive.ps1' 139 #Region '.\Public\Clear-OneDriveCache.ps1' -1 function Clear-OneDriveCache { <# .SYNOPSIS Clears the OneDrive cache. .DESCRIPTION The Clear-OneDriveCache function clears the OneDrive cache by restarting the OneDrive process. .EXAMPLE Clear-OneDriveCache Clears the OneDrive cache by restarting the OneDrive process. #> [CmdletBinding()] param () Begin { Write-EnhancedLog -Message "Starting Clear-OneDriveCache function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Restarting OneDrive process to clear cache" -Level "INFO" $oneDrivePath = "C:\Program Files (x86)\Microsoft OneDrive\OneDrive.exe" if (Test-Path -Path $oneDrivePath) { Stop-Process -Name "OneDrive" -Force -ErrorAction SilentlyContinue Start-Process -FilePath $oneDrivePath -ErrorAction Stop Write-EnhancedLog -Message "Successfully restarted OneDrive process" -Level "INFO" } else { Write-EnhancedLog -Message "OneDrive executable not found at path: $oneDrivePath" -Level "WARNING" } } catch { Write-EnhancedLog -Message "An error occurred in Clear-OneDriveCache function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Clear-OneDriveCache function" -Level "Notice" } } # Example usage # Clear-OneDriveCache #EndRegion '.\Public\Clear-OneDriveCache.ps1' 49 #Region '.\Public\Create-EventLogSource.ps1' -1 function Create-EventLogSource { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$LogName, [Parameter(Mandatory = $true)] [string]$Source ) Begin { Write-EnhancedLog -Message "Starting Create-EventLogSource function" -Level "INFO" Log-Params -Params @{ LogName = $LogName Source = $Source } } Process { try { if (-not (Get-EventLog -LogName $LogName -Source $Source -ErrorAction SilentlyContinue)) { New-EventLog -LogName $LogName -Source $Source -ErrorAction Stop } } catch { Write-EnhancedLog -Message "An error occurred while creating the event log source: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-EventLogSource function" -Level "INFO" } } # $CreateEventLogSourceParams = @{ # LogName = "Application" # Source = "AAD_Migration_Script" # } # Create-EventLogSource @CreateEventLogSourceParams #EndRegion '.\Public\Create-EventLogSource.ps1' 41 #Region '.\Public\Create-OneDriveRemediationTask.ps1' -1 function Create-OneDriveRemediationTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OneDriveExePath, [Parameter(Mandatory = $true)] [string]$ScheduledTaskName, [Parameter(Mandatory = $true)] [string]$ScheduledTaskDescription, [Parameter(Mandatory = $false)] [string]$ScheduledTaskArgumentList ) Begin { Write-EnhancedLog -Message "Starting Create-OneDriveRemediationTask function" -Level "INFO" Log-Params -Params @{ OneDriveExePath = $OneDriveExePath ScheduledTaskName = $ScheduledTaskName ScheduledTaskDescription = $ScheduledTaskDescription ScheduledTaskArgumentList = $ScheduledTaskArgumentList } } Process { try { # $userId = (Get-WmiObject -Class Win32_ComputerSystem).UserName $userId = $env:UserName if (-not $userId) { throw "Unable to retrieve the current user ID." } Write-EnhancedLog -Message "User ID retrieved: $userId" -Level "INFO" $actionParams = @{ Execute = $OneDriveExePath } if ($ScheduledTaskArgumentList) { $actionParams.Argument = $ScheduledTaskArgumentList } $action = New-ScheduledTaskAction @actionParams $trigger = New-ScheduledTaskTrigger -AtLogOn $principalParams = @{ UserId = $userId } $principal = New-ScheduledTaskPrincipal @principalParams $taskParams = @{ Action = $action Trigger = $trigger Principal = $principal TaskName = $ScheduledTaskName Description = $ScheduledTaskDescription Force = $true } $task = Register-ScheduledTask @taskParams Start-ScheduledTask -TaskName $ScheduledTaskName # $DBG Start-Sleep -Seconds 5 Unregister-ScheduledTask -TaskName $ScheduledTaskName -Confirm:$false } catch { Write-EnhancedLog -Message "An error occurred in Create-OneDriveRemediationTask function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-OneDriveRemediationTask function" -Level "INFO" } } # $CreateOneDriveRemediationTaskParams = @{ # OneDriveExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" # ScheduledTaskName = "OneDriveRemediation" # ScheduledTaskDescription = "Restart OneDrive to kick off KFM sync" # ScheduledTaskArgumentList = "" # } # Create-OneDriveRemediationTask @CreateOneDriveRemediationTaskParams #EndRegion '.\Public\Create-OneDriveRemediationTask.ps1' 87 #Region '.\Public\Create-OneDriveSyncStatusTask.ps1' -1 function Create-OneDriveSyncStatusTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TaskPath, [Parameter(Mandatory = $true)] [string]$TaskName, [Parameter(Mandatory = $true)] [string]$ScriptDirectory, [Parameter(Mandatory = $true)] [string]$ScriptName, [Parameter(Mandatory = $true)] [string]$TaskArguments, [Parameter(Mandatory = $true)] [string]$TaskRepetitionDuration, [Parameter(Mandatory = $true)] [string]$TaskRepetitionInterval, [Parameter(Mandatory = $true)] [string]$TaskPrincipalGroupId, [Parameter(Mandatory = $true)] [string]$PowerShellPath, [Parameter(Mandatory = $true)] [string]$TaskDescription ) Begin { Write-EnhancedLog -Message "Starting Create-OneDriveSyncStatusTask function" -Level "Notice" Log-Params -Params @{ TaskPath = $TaskPath TaskName = $TaskName ScriptDirectory = $ScriptDirectory ScriptName = $ScriptName TaskArguments = $TaskArguments TaskRepetitionDuration = $TaskRepetitionDuration TaskRepetitionInterval = $TaskRepetitionInterval TaskPrincipalGroupId = $TaskPrincipalGroupId PowerShellPath = $PowerShellPath TaskDescription = $TaskDescription } } Process { try { $arguments = $TaskArguments.Replace("{ScriptPath}", "$ScriptDirectory\$ScriptName") $actionParams = @{ Execute = $PowerShellPath Argument = $arguments } $action = New-ScheduledTaskAction @actionParams $triggerParams = @{ AtLogOn = $true } $trigger = New-ScheduledTaskTrigger @triggerParams $principalParams = @{ GroupId = $TaskPrincipalGroupId } $principal = New-ScheduledTaskPrincipal @principalParams $registerTaskParams = @{ Principal = $principal Action = $action Trigger = $trigger TaskName = $TaskName Description = $TaskDescription TaskPath = $TaskPath } $Task = Register-ScheduledTask @registerTaskParams $Task.Triggers.Repetition.Duration = $TaskRepetitionDuration $Task.Triggers.Repetition.Interval = $TaskRepetitionInterval $Task | Set-ScheduledTask } catch { Write-EnhancedLog -Message "An error occurred while creating the OneDrive sync status task: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-OneDriveSyncStatusTask function" -Level "Notice" } } # # Example usage with splatting # $CreateOneDriveSyncStatusTaskParams = @{ # TaskPath = "AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # ScriptDirectory = "C:\ProgramData\AADMigration\Scripts" # ScriptName = "Check-OneDriveSyncStatus.ps1" # TaskArguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file `"{ScriptPath}`"" # TaskRepetitionDuration = "P1D" # TaskRepetitionInterval = "PT30M" # TaskPrincipalGroupId = "BUILTIN\Users" # PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" # TaskDescription = "Get current OneDrive Sync Status and write to event log" # } # Create-OneDriveSyncStatusTask @CreateOneDriveSyncStatusTaskParams #EndRegion '.\Public\Create-OneDriveSyncStatusTask.ps1' 102 #Region '.\Public\Create-OneDriveSyncUtilStatusTask.ps1' -1 function Create-OneDriveSyncUtilStatusTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TaskPath, [Parameter(Mandatory = $true)] [string]$TaskName, [Parameter(Mandatory = $true)] [string]$ScriptDirectory, [Parameter(Mandatory = $true)] [string]$ScriptName, [Parameter(Mandatory = $true)] [string]$TaskArguments, [Parameter(Mandatory = $true)] [string]$TaskRepetitionDuration, [Parameter(Mandatory = $true)] [string]$TaskRepetitionInterval, [Parameter(Mandatory = $true)] [string]$TaskPrincipalGroupId, [Parameter(Mandatory = $true)] [string]$PowerShellPath, [Parameter(Mandatory = $true)] [string]$TaskDescription ) Begin { Write-EnhancedLog -Message "Starting Create-OneDriveSyncUtilStatusTask function" -Level "Notice" Log-Params -Params @{ TaskPath = $TaskPath TaskName = $TaskName ScriptDirectory = $ScriptDirectory ScriptName = $ScriptName TaskArguments = $TaskArguments TaskRepetitionDuration = $TaskRepetitionDuration TaskRepetitionInterval = $TaskRepetitionInterval TaskPrincipalGroupId = $TaskPrincipalGroupId PowerShellPath = $PowerShellPath TaskDescription = $TaskDescription } } Process { try { $arguments = $TaskArguments.Replace("{ScriptPath}", "$ScriptDirectory\$ScriptName") $actionParams = @{ Execute = $PowerShellPath Argument = $arguments } $action = New-ScheduledTaskAction @actionParams $triggerParams = @{ AtLogOn = $true } $trigger = New-ScheduledTaskTrigger @triggerParams $principalParams = @{ GroupId = $TaskPrincipalGroupId } $principal = New-ScheduledTaskPrincipal @principalParams $registerTaskParams = @{ Principal = $principal Action = $action Trigger = $trigger TaskName = $TaskName Description = $TaskDescription TaskPath = $TaskPath } $Task = Register-ScheduledTask @registerTaskParams $Task.Triggers.Repetition.Duration = $TaskRepetitionDuration $Task.Triggers.Repetition.Interval = $TaskRepetitionInterval $Task | Set-ScheduledTask } catch { Write-EnhancedLog -Message "An error occurred while creating the OneDrive sync status task: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-OneDriveSyncUtilStatusTask function" -Level "Notice" } } # # Example usage with splatting # $CreateOneDriveSyncStatusTaskParams = @{ # TaskPath = "AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # ScriptDirectory = "C:\ProgramData\AADMigration\Scripts" # ScriptName = "Check-OneDriveSyncStatus.ps1" # TaskArguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file `"{ScriptPath}`"" # TaskRepetitionDuration = "P1D" # TaskRepetitionInterval = "PT30M" # TaskPrincipalGroupId = "BUILTIN\Users" # PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" # TaskDescription = "Get current OneDrive Sync Status and write to event log" # } # Create-OneDriveSyncUtilStatusTask @CreateOneDriveSyncStatusTaskParams #EndRegion '.\Public\Create-OneDriveSyncUtilStatusTask.ps1' 102 #Region '.\Public\Create-PPKG.ps1' -1 function Create-PPKG { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ICDPath, [Parameter(Mandatory = $true)] [string]$CustomizationXMLPath, [Parameter(Mandatory = $true)] [string]$PackagePath, [Parameter(Mandatory = $false)] [string]$ProductName, [Parameter(Mandatory = $false)] [string]$StoreFile, [Parameter(Mandatory = $false)] [string]$MSPackageRoot, [Parameter(Mandatory = $false)] [string]$OEMInputXML, [Parameter(Mandatory = $false)] [hashtable]$Variables, [Parameter(Mandatory = $false)] [bool]$Encrypted = $false, [Parameter(Mandatory = $false)] [bool]$Overwrite = $true ) Begin { Write-EnhancedLog -Message "Starting Create-PPKG function" -Level "INFO" Log-Params -Params @{ ICDPath = $ICDPath CustomizationXMLPath = $CustomizationXMLPath PackagePath = $PackagePath ProductName = $ProductName StoreFile = $StoreFile MSPackageRoot = $MSPackageRoot OEMInputXML = $OEMInputXML Variables = $Variables Encrypted = $Encrypted Overwrite = $Overwrite } # Ensure ICD.exe exists if (-not (Test-Path -Path $ICDPath)) { throw "ICD.exe not found at: $ICDPath" } # Ensure Customization XML file exists if (-not (Test-Path -Path $CustomizationXMLPath)) { throw "Customization XML file not found at: $CustomizationXMLPath" } } Process { try { # Build the command line arguments using a list $ICD_args = [System.Collections.Generic.List[string]]::new() $ICD_args.Add("/Build-ProvisioningPackage") $ICD_args.Add("/CustomizationXML:`"$CustomizationXMLPath`"") $ICD_args.Add("/PackagePath:`"$PackagePath`"") if ($Encrypted) { $ICD_args.Add("+Encrypted") } else { $ICD_args.Add("-Encrypted") } if ($Overwrite) { $ICD_args.Add("+Overwrite") } else { $ICD_args.Add("-Overwrite") } if ($ProductName) { $ICD_args.Add("/ProductName:`"$ProductName`"") } if ($StoreFile) { $ICD_args.Add("/StoreFile:`"$StoreFile`"") } if ($MSPackageRoot) { $ICD_args.Add("/MSPackageRoot:`"$MSPackageRoot`"") } if ($OEMInputXML) { $ICD_args.Add("/OEMInputXML:`"$OEMInputXML`"") } if ($Variables) { foreach ($key in $Variables.Keys) { $ICD_args.Add("/Variables:`"$key=$($Variables[$key])`"") } } $ICD_args_string = $ICD_args -join " " Write-EnhancedLog -Message "Running ICD.exe with arguments: $ICD_args_string" -Level "INFO" Start-Process -FilePath $ICDPath -ArgumentList $ICD_args_string -Wait -NoNewWindow } catch { Write-EnhancedLog -Message "An error occurred while processing the Create-PPKG function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-PPKG function" -Level "INFO" } } # Example usage # $ppkgParams = @{ # ICDPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Imaging and Configuration Designer\x86\ICD.exe" # CustomizationXMLPath = "C:\code\CB\Entra\DeviceMigration\Files\customizations.xml" # PackagePath = "C:\code\CB\Entra\DeviceMigration\Files\ProvisioningPackage.ppkg" # Encrypted = $false # Overwrite = $true # } # Create-PPKG @ppkgParams #EndRegion '.\Public\Create-PPKG.ps1' 128 #Region '.\Public\Create-ProvPackageAADEnrollment-Archive.ps1' -1 # function Create-ProvPackageAADEnrollment { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$Source, # [Parameter(Mandatory = $true)] # [string]$Destination # ) # Begin { # Write-EnhancedLog -Message "Starting Create-ProvPackage-AADEnrollment function" -Level "INFO" # Log-Params -Params @{ # Source = $Source # Destination = $Destination # } # } # Process { # try { # # Create a provisioning package for AAD bulk enrollment (placeholder as the actual creation depends on your environment) # # Assuming you have a script or method to create it # # Copy the provisioning package to the Files folder # Copy-Item -Path $Source -Destination $Destination -Force # } catch { # Write-EnhancedLog -Message "An error occurred while processing the Create-ProvPackage-AADEnrollment function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Create-ProvPackage-AADEnrollment function" -Level "INFO" # } # } # # Example usage # # Create-ProvPackageAADEnrollment -Source 'C:\Path\To\Your\ProvisioningPackage.ppkg' -Destination 'C:\YourPath\Files\ProvisioningPackage.ppkg' #EndRegion '.\Public\Create-ProvPackageAADEnrollment-Archive.ps1' 38 #Region '.\Public\Create-UserFileBackupTask.ps1' -1 function Create-UserFileBackupTask { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TaskPath, [Parameter(Mandatory = $true)] [string]$TaskName, [Parameter(Mandatory = $true)] [string]$BackupScriptPath, [Parameter(Mandatory = $true)] [string]$TaskRepetitionDuration, [Parameter(Mandatory = $true)] [string]$TaskRepetitionInterval, [Parameter(Mandatory = $true)] [string]$TaskPrincipalGroupId, [Parameter(Mandatory = $true)] [string]$PowerShellPath, [Parameter(Mandatory = $true)] [string]$TaskDescription ) Begin { Write-EnhancedLog -Message "Starting Create-UserFileBackupTask function" -Level "Notice" Log-Params -Params @{ TaskPath = $TaskPath TaskName = $TaskName BackupScriptPath = $BackupScriptPath TaskRepetitionDuration = $TaskRepetitionDuration TaskRepetitionInterval = $TaskRepetitionInterval TaskPrincipalGroupId = $TaskPrincipalGroupId PowerShellPath = $PowerShellPath TaskDescription = $TaskDescription } } Process { try { $arguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -File `"$BackupScriptPath`"" $actionParams = @{ Execute = $PowerShellPath Argument = $arguments } $action = New-ScheduledTaskAction @actionParams $triggerParams = @{ AtLogOn = $true } $trigger = New-ScheduledTaskTrigger @triggerParams $principalParams = @{ GroupId = $TaskPrincipalGroupId } $principal = New-ScheduledTaskPrincipal @principalParams $registerTaskParams = @{ Principal = $principal Action = $action Trigger = $trigger TaskName = $TaskName Description = $TaskDescription TaskPath = $TaskPath } $Task = Register-ScheduledTask @registerTaskParams # Set repetition properties $Task.Triggers.Repetition.Duration = $TaskRepetitionDuration $Task.Triggers.Repetition.Interval = $TaskRepetitionInterval $Task | Set-ScheduledTask } catch { Write-EnhancedLog -Message "An error occurred while creating the user file backup task: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Create-UserFileBackupTask function" -Level "Notice" } } # # Example usage with splatting # $CreateUserFileBackupTaskParams = @{ # TaskPath = "Backup Tasks" # TaskName = "User File Backup" # BackupScriptPath = "C:\Scripts\BackupUserFiles.ps1" # TaskRepetitionDuration = "P1D" # 1 day # TaskRepetitionInterval = "PT1H" # 1 hour # TaskPrincipalGroupId = "BUILTIN\Administrators" # PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" # TaskDescription = "Backup user files to a designated location" # } # Create-UserFileBackupTask @CreateUserFileBackupTaskParams #EndRegion '.\Public\Create-UserFileBackupTask.ps1' 95 #Region '.\Public\Disable-LocalUserAccounts.ps1' -1 function Disable-LocalUserAccounts { <# .SYNOPSIS Disables all enabled local user accounts except for default accounts. .DESCRIPTION The Disable-LocalUserAccounts function disables all enabled local user accounts except for default accounts. .EXAMPLE Disable-LocalUserAccounts Disables all enabled local user accounts except for default accounts. #> [CmdletBinding()] param () Begin { Write-EnhancedLog -Message "Starting Disable-LocalUserAccounts function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $users = Get-LocalUser | Where-Object { $_.Enabled -eq $true -and $_.Name -notlike 'default*' } foreach ($user in $users) { Write-EnhancedLog -Message "Disabling local user account: $($user.Name)" -Level "INFO" Disable-LocalUser -Name $user.Name -ErrorAction Stop Write-EnhancedLog -Message "Successfully disabled local user account: $($user.Name)" -Level "INFO" } } catch { Write-EnhancedLog -Message "An error occurred in Disable-LocalUserAccounts function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Disable-LocalUserAccounts function" -Level "Notice" } } # Example usage # Disable-LocalUserAccounts #EndRegion '.\Public\Disable-LocalUserAccounts.ps1' 46 #Region '.\Public\Disable-OOBEPrivacy.ps1' -1 function Disable-OOBEPrivacy { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OOBERegistryPath, [Parameter(Mandatory = $true)] [string]$OOBEName, [Parameter(Mandatory = $true)] [string]$OOBEValue, [Parameter(Mandatory = $true)] [string]$AnimationRegistryPath, [Parameter(Mandatory = $true)] [string]$AnimationName, [Parameter(Mandatory = $true)] [string]$AnimationValue, [Parameter(Mandatory = $true)] [string]$LockRegistryPath, [Parameter(Mandatory = $true)] [string]$LockName, [Parameter(Mandatory = $true)] [string]$LockValue ) Begin { Write-EnhancedLog -Message "Starting Disable-OOBEPrivacy function" -Level "INFO" Log-Params -Params @{ OOBERegistryPath = $OOBERegistryPath OOBEName = $OOBEName OOBEValue = $OOBEValue AnimationRegistryPath = $AnimationRegistryPath AnimationName = $AnimationName AnimationValue = $AnimationValue LockRegistryPath = $LockRegistryPath LockName = $LockName LockValue = $LockValue } } Process { try { Write-EnhancedLog -Message "Disabling privacy experience" -Level "INFO" if (-not (Test-Path -Path $OOBERegistryPath)) { New-Item -Path $OOBERegistryPath -Force | Out-Null } New-ItemProperty -Path $OOBERegistryPath -Name $OOBEName -Value $OOBEValue -PropertyType DWORD -Force -Verbose Write-EnhancedLog -Message "Disabling first logon animation" -Level "INFO" if (-not (Test-Path -Path $AnimationRegistryPath)) { New-Item -Path $AnimationRegistryPath -Force | Out-Null } New-ItemProperty -Path $AnimationRegistryPath -Name $AnimationName -Value $AnimationValue -PropertyType DWORD -Force -Verbose Write-EnhancedLog -Message "Removing lock screen" -Level "INFO" if (-not (Test-Path -Path $LockRegistryPath)) { New-Item -Path $LockRegistryPath -Force | Out-Null } New-ItemProperty -Path $LockRegistryPath -Name $LockName -Value $LockValue -PropertyType DWORD -Force -Verbose } catch { Write-EnhancedLog -Message "An error occurred while disabling OOBE privacy: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Disable-OOBEPrivacy function" -Level "INFO" } } # # Example usage with splatting # $DisableOOBEPrivacyParams = @{ # OOBERegistryPath = 'HKLM:\Software\Policies\Microsoft\Windows\OOBE' # OOBEName = 'DisablePrivacyExperience' # OOBEValue = '1' # AnimationRegistryPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' # AnimationName = 'EnableFirstLogonAnimation' # AnimationValue = '0' # LockRegistryPath = 'HKLM:\Software\Policies\Microsoft\Windows\Personalization' # LockName = 'NoLockScreen' # LockValue = '1' # } # Disable-OOBEPrivacy @DisableOOBEPrivacyParams #EndRegion '.\Public\Disable-OOBEPrivacy.ps1' 91 #Region '.\Public\Download-ADKOffline.ps1' -1 function Download-ADKOffline { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ADKUrl = "https://go.microsoft.com/fwlink/?linkid=2271337", [Parameter(Mandatory = $true)] [string]$DownloadPath = "$env:TEMP\adksetup.exe", [Parameter(Mandatory = $true)] [string]$OfflinePath = "$env:TEMP\ADKOffline" ) Begin { Write-EnhancedLog -Message "Starting Download-ADKOffline function" -Level "INFO" Log-Params -Params @{ ADKUrl = $ADKUrl DownloadPath = $DownloadPath OfflinePath = $OfflinePath } } Process { try { # Download the ADK setup file Write-EnhancedLog -Message "Downloading ADK from: $ADKUrl to: $DownloadPath" -Level "INFO" Invoke-WebRequest -Uri $ADKUrl -OutFile $DownloadPath # Create offline path if it does not exist if (-not (Test-Path -Path $OfflinePath)) { New-Item -ItemType Directory -Path $OfflinePath -Force } # Download the ADK components for offline installation Write-EnhancedLog -Message "Downloading ADK components for offline installation to: $OfflinePath" -Level "INFO" Start-Process -FilePath $DownloadPath -ArgumentList "/quiet", "/layout $OfflinePath" -Wait -NoNewWindow } catch { Write-EnhancedLog -Message "An error occurred while processing the Download-ADKOffline function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Download-ADKOffline function" -Level "INFO" } } # Example usage # $adkParams = @{ # ADKUrl = 'https://go.microsoft.com/fwlink/?linkid=2271337' # DownloadPath = "$env:TEMP\adksetup.exe" # OfflinePath = "$env:TEMP\ADKOffline" # } # Download-ADKOffline @adkParams #EndRegion '.\Public\Download-ADKOffline.ps1' 56 #Region '.\Public\Download-InstallMDT.ps1' -1 # function Download-InstallMDT { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$Url, # [Parameter(Mandatory = $true)] # [string]$Destination, # [Parameter(Mandatory = $true)] # [string]$FilesFolder # ) # Begin { # Write-EnhancedLog -Message "Starting Download-Install-MDT function" -Level "INFO" # Log-Params -Params @{ # Url = $Url # Destination = $Destination # FilesFolder = $FilesFolder # } # } # Process { # try { # # Download and install Microsoft Deployment Toolkit # Invoke-WebRequest -Uri $Url -OutFile $Destination # Start-Process -FilePath $Destination -ArgumentList "/quiet" -Wait # # Copy ServiceUI.exe to Files folder # Copy-Item -Path "C:\Program Files\Microsoft Deployment Toolkit\Templates\Distribution\Tools\x64\ServiceUI.exe" -Destination $FilesFolder # } catch { # Write-EnhancedLog -Message "An error occurred while processing the Download-InstallMDT function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Download-Install-MDT function" -Level "INFO" # } # } # # Example usage # # Download-InstallMDT -Url 'https://download.microsoft.com/download/9/e/1/9e1e94ec-5463-46b7-9f3c-b225034c3a70/MDT_KB4564442.exe' -Destination 'C:\YourPath\Files\MDT.exe' -FilesFolder 'C:\YourPath\Files' #EndRegion '.\Public\Download-InstallMDT.ps1' 44 #Region '.\Public\Download-MigrationTool.ps1' -1 function Download-MigrationTool { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Url, [Parameter(Mandatory = $true)] [string]$Destination ) Begin { Write-EnhancedLog -Message "Starting Download-MigrationTool function" -Level "INFO" Log-Params -Params @{ Url = $Url Destination = $Destination } } Process { try { # Download Migration Tool Invoke-WebRequest -Uri $Url -OutFile $Destination } catch { Write-EnhancedLog -Message "An error occurred while processing the Download-MigrationTool function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Download-MigrationTool function" -Level "INFO" } } # Example usage # Download-MigrationTool -Url "https://example.com/tool.zip" -Destination "C:\path\to\destination" #EndRegion '.\Public\Download-MigrationTool.ps1' 36 #Region '.\Public\Download-ODSyncUtil.ps1' -1 function Download-ODSyncUtil { <# .SYNOPSIS Downloads and extracts the latest ODSyncUtil from the OneDrive Sync Utility GitHub repository for Windows 11. .DESCRIPTION The Download-ODSyncUtil function retrieves the latest release of ODSyncUtil from the GitHub repository, downloads the ZIP file, extracts it, and places the executable in the specified destination folder. .PARAMETER Destination The destination folder where ODSyncUtil.exe will be stored. .PARAMETER ApiUrl The GitHub API URL to retrieve the latest release information. .PARAMETER ZipFileName The name of the ZIP file to be downloaded (e.g., "ODSyncUtil-64-bit.zip"). .PARAMETER ExecutableName The name of the executable to be extracted from the ZIP file (e.g., "ODSyncUtil.exe"). .PARAMETER MaxRetries The maximum number of retries for the download process. .EXAMPLE $params = @{ Destination = "C:\YourPath\Files\ODSyncUtil.exe" ApiUrl = "https://api.github.com/repos/rodneyviana/ODSyncUtil/releases/latest" ZipFileName = "ODSyncUtil-64-bit.zip" ExecutableName = "ODSyncUtil.exe" MaxRetries = 3 } Download-ODSyncUtil @params Downloads and extracts ODSyncUtil.exe to the specified destination folder. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Destination, [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$ZipFileName, [Parameter(Mandatory = $true)] [string]$ExecutableName, [Parameter(Mandatory = $false)] [int]$MaxRetries = 3 ) Begin { Write-EnhancedLog -Message "Starting Download-ODSyncUtil function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { # Get the latest release info from GitHub Write-EnhancedLog -Message "Retrieving latest release info from GitHub API: $ApiUrl" -Level "INFO" $releaseInfo = Invoke-RestMethod -Uri $ApiUrl # Find the download URL for the specified ZIP file $downloadUrl = $releaseInfo.assets | Where-Object { $_.name -eq $ZipFileName } | Select-Object -ExpandProperty browser_download_url if (-not $downloadUrl) { $errorMessage = "No matching file found for $ZipFileName" Write-EnhancedLog -Message $errorMessage -Level "Critical" throw $errorMessage } # Define the ZIP file path $zipFilefolder = Split-Path -Path $Destination -Parent $zipFilePath = Join-Path -Path (Split-Path -Path $Destination -Parent) -ChildPath $ZipFileName #Remove the Existing Zip Folder Folder if found if (Test-Path -Path $zipFilefolder) { Write-EnhancedLog -Message "Found $zipFilefolder. Removing it..." -Level "INFO" try { Remove-Item -Path $zipFilefolder -Recurse -Force Write-EnhancedLog -Message "Successfully removed $zipFilefolder." -Level "INFO" } catch { Write-EnhancedLog -Message "Failed to remove $zipFilefolder $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } else { Write-EnhancedLog -Message "$zipFilefolder not found. No action required." -Level "INFO" } # $DBG # Define the splatting parameters for the download $downloadParams = @{ Source = $downloadUrl Destination = $zipFilePath MaxRetries = $MaxRetries } Write-EnhancedLog -Message "Downloading $ZipFileName from: $downloadUrl to: $zipFilePath" -Level "INFO" Start-FileDownloadWithRetry @downloadParams # Extract the executable from the ZIP file Write-EnhancedLog -Message "Extracting $ZipFileName to: $(Split-Path -Path $Destination -Parent)" -Level "INFO" Expand-Archive -Path $zipFilePath -DestinationPath (Split-Path -Path $Destination -Parent) -Force # Move the extracted executable to the desired location $extractedExePath = Join-Path -Path (Split-Path -Path $Destination -Parent) -ChildPath $ExecutableName if (Test-Path -Path $extractedExePath) { Write-EnhancedLog -Message "Moving $ExecutableName to: $Destination" -Level "INFO" Move-Item -Path $extractedExePath -Destination $Destination -Force # Remove the downloaded ZIP file and the extracted folder # Write-EnhancedLog -Message "Cleaning up: Removing downloaded ZIP file from $zipFilePath and extracted files from $extractedExePath" -Level "INFO" # Remove-Item -Path $zipFilePath -Force # Remove-Item -Path (Split-Path -Path $extractedExePath -Parent) -Recurse -Force } else { $errorMessage = "$ExecutableName not found after extraction." Write-EnhancedLog -Message $errorMessage -Level "Critical" throw $errorMessage } } catch { Write-EnhancedLog -Message "An error occurred in Download-ODSyncUtil function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Download-ODSyncUtil function" -Level "Notice" } } # # # # Example usage # $params = @{ # Destination = "C:\code\IntuneDeviceMigration\DeviceMigration\Files\ODSyncUtil\ODSyncUtil.exe" # ApiUrl = "https://api.github.com/repos/rodneyviana/ODSyncUtil/releases/latest" # ZipFileName = "ODSyncUtil-64-bit.zip" # ExecutableName = "ODSyncUtil.exe" # MaxRetries = 3 # } # Download-ODSyncUtil @params #EndRegion '.\Public\Download-ODSyncUtil.ps1' 152 #Region '.\Public\Download-OneDriveLib.ps1' -1 function Download-OneDriveLib { <# .SYNOPSIS Downloads the latest OneDriveLib.dll from the OneDrive Sync Util GitHub repository. .DESCRIPTION The Download-OneDriveLib function retrieves the latest release of OneDriveLib.dll from the GitHub repository of the OneDrive Sync Util and downloads it to the specified destination folder. .PARAMETER Destination The destination folder where OneDriveLib.dll will be stored. .PARAMETER ApiUrl The GitHub API URL to retrieve the latest release information. .PARAMETER FileName The name of the file to be downloaded (e.g., "OneDriveLib.dll"). .PARAMETER MaxRetries The maximum number of retries for the download process. .EXAMPLE $params = @{ Destination = "C:\YourPath\Files\OneDriveLib.dll" ApiUrl = "https://api.github.com/repos/rodneyviana/ODSyncService/releases/latest" FileName = "OneDriveLib.dll" MaxRetries = 3 } Download-OneDriveLib @params Downloads OneDriveLib.dll to the specified destination folder. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Destination, [Parameter(Mandatory = $true)] [string]$ApiUrl, [Parameter(Mandatory = $true)] [string]$FileName, [Parameter(Mandatory = $false)] [int]$MaxRetries = 3 ) Begin { Write-EnhancedLog -Message "Starting Download-OneDriveLib function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { # Get the latest release info from GitHub Write-EnhancedLog -Message "Retrieving latest release info from GitHub API: $ApiUrl" -Level "INFO" $releaseInfo = Invoke-RestMethod -Uri $ApiUrl # Find the download URL for the specified file $downloadUrl = $releaseInfo.assets | Where-Object { $_.name -eq $FileName } | Select-Object -ExpandProperty browser_download_url if (-not $downloadUrl) { $errorMessage = "No matching file found for $FileName" Write-EnhancedLog -Message $errorMessage -Level "Critical" throw $errorMessage } # Define the splatting parameters for the download $downloadParams = @{ Source = $downloadUrl Destination = $Destination MaxRetries = $MaxRetries } Write-EnhancedLog -Message "Downloading $FileName from: $downloadUrl to: $Destination" -Level "INFO" Start-FileDownloadWithRetry @downloadParams } catch { Write-EnhancedLog -Message "An error occurred in Download-OneDriveLib function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Download-OneDriveLib function" -Level "Notice" } } # # Example usage # $params = @{ # Destination = "C:\YourPath\Files\OneDriveLib.dll" # ApiUrl = "https://api.github.com/repos/rodneyviana/ODSyncService/releases/latest" # FileName = "OneDriveLib.dll" # MaxRetries = 3 # } # Download-OneDriveLib @params #EndRegion '.\Public\Download-OneDriveLib.ps1' 97 #Region '.\Public\Download-PSAppDeployToolkit-Archive.ps1' -1 # function Download-PSAppDeployToolkit { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$Url, # [Parameter(Mandatory = $true)] # [string]$Destination, # [Parameter(Mandatory = $true)] # [string]$ToolkitFolder # ) # Begin { # Write-EnhancedLog -Message "Starting Download-PSAppDeployToolkit function" -Level "INFO" # Log-Params -Params @{ # Url = $Url # Destination = $Destination # ToolkitFolder = $ToolkitFolder # } # } # Process { # try { # # Download and extract PSAppDeployToolkit # Invoke-WebRequest -Uri $Url -OutFile $Destination # Expand-Archive -Path $Destination -DestinationPath $ToolkitFolder -Force # } catch { # Write-EnhancedLog -Message "An error occurred while processing the Download-PSAppDeployToolkit function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Download-PSAppDeployToolkit function" -Level "INFO" # } # } # # Example usage # # Download-PSAppDeployToolkit -Url 'https://github.com/PSAppDeployToolkit/PSAppDeployToolkit/releases/download/v3.8.4/PSAppDeployToolkit_v3.8.4.zip' -Destination 'C:\YourPath\Files\PSAppDeployToolkit.zip' -ToolkitFolder 'C:\YourPath\Toolkit' #EndRegion '.\Public\Download-PSAppDeployToolkit-Archive.ps1' 41 #Region '.\Public\Escrow-BitLockerKey.ps1' -1 function Test-Bitlocker { <# .SYNOPSIS Tests if BitLocker is enabled on the specified drive. .DESCRIPTION The Test-Bitlocker function tests if BitLocker is enabled on the specified drive. .PARAMETER BitlockerDrive The drive letter of the BitLocker protected drive. .EXAMPLE Test-Bitlocker -BitlockerDrive "C:" Tests if BitLocker is enabled on drive C:. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$BitlockerDrive ) Begin { Write-EnhancedLog -Message "Starting Test-Bitlocker function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $bitlockerVolume = Get-BitLockerVolume -MountPoint $BitlockerDrive -ErrorAction Stop Write-EnhancedLog -Message "BitLocker is enabled on drive: $BitlockerDrive" -Level "INFO" return $bitlockerVolume } catch { Write-EnhancedLog -Message "BitLocker is not enabled on drive: $BitlockerDrive. Terminating script!" -Level "ERROR" throw $_ } } End { Write-EnhancedLog -Message "Exiting Test-Bitlocker function" -Level "Notice" } } function Get-KeyProtectorId { <# .SYNOPSIS Retrieves the key protector ID for the specified drive. .DESCRIPTION The Get-KeyProtectorId function retrieves the key protector ID for the specified BitLocker protected drive. .PARAMETER BitlockerDrive The drive letter of the BitLocker protected drive. .EXAMPLE Get-KeyProtectorId -BitlockerDrive "C:" Retrieves the key protector ID for drive C:. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$BitlockerDrive ) Begin { Write-EnhancedLog -Message "Starting Get-KeyProtectorId function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $bitlockerVolume = Get-BitLockerVolume -MountPoint $BitlockerDrive $keyProtector = $bitlockerVolume.KeyProtector | Where-Object { $_.KeyProtectorType -eq 'RecoveryPassword' } Write-EnhancedLog -Message "Retrieved key protector ID for drive: $BitlockerDrive" -Level "INFO" return $keyProtector.KeyProtectorId } catch { Write-EnhancedLog -Message "Failed to retrieve key protector ID for drive: $BitlockerDrive" -Level "ERROR" throw $_ } } End { Write-EnhancedLog -Message "Exiting Get-KeyProtectorId function" -Level "Notice" } } function Invoke-BitlockerEscrow { <# .SYNOPSIS Escrows the BitLocker recovery key to Azure AD. .DESCRIPTION The Invoke-BitlockerEscrow function escrows the BitLocker recovery key for the specified drive to Azure AD. .PARAMETER BitlockerDrive The drive letter of the BitLocker protected drive. .PARAMETER BitlockerKey The key protector ID to be escrowed. .EXAMPLE Invoke-BitlockerEscrow -BitlockerDrive "C:" -BitlockerKey "12345678-1234-1234-1234-123456789012" Escrows the BitLocker recovery key for drive C: to Azure AD. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$BitlockerDrive, [Parameter(Mandatory = $true)] [string]$BitlockerKey ) Begin { Write-EnhancedLog -Message "Starting Invoke-BitlockerEscrow function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Escrowing the BitLocker recovery key to Azure AD for drive: $BitlockerDrive" -Level "INFO" BackupToAAD-BitLockerKeyProtector -MountPoint $BitlockerDrive -KeyProtectorId $BitlockerKey -ErrorAction SilentlyContinue Write-EnhancedLog -Message "Attempted to escrow key in Azure AD - Please verify manually!" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while escrowing the BitLocker key to Azure AD" -Level "ERROR" throw $_ } } End { Write-EnhancedLog -Message "Exiting Invoke-BitlockerEscrow function" -Level "Notice" } } function Escrow-BitLockerKey { <# .SYNOPSIS Escrows the BitLocker recovery key to Azure AD. .DESCRIPTION The Escrow-BitLockerKey function tests if BitLocker is enabled on the specified drive, retrieves the key protector ID, and escrows the BitLocker recovery key to Azure AD. .PARAMETER DriveLetter The drive letter of the BitLocker protected drive. .EXAMPLE $params = @{ DriveLetter = "C:" } Escrow-BitLockerKey @params Escrows the BitLocker recovery key for drive C: to Azure AD. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$DriveLetter ) Begin { Write-EnhancedLog -Message "Starting Escrow-BitLockerKey function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $bitlockerVolume = Test-Bitlocker -BitlockerDrive $DriveLetter $keyProtectorId = Get-KeyProtectorId -BitlockerDrive $DriveLetter Invoke-BitlockerEscrow -BitlockerDrive $DriveLetter -BitlockerKey $keyProtectorId } catch { Write-EnhancedLog -Message "An error occurred in Escrow-BitLockerKey function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Escrow-BitLockerKey function" -Level "Notice" } } # # Example usage # $params = @{ # DriveLetter = "C:" # } # Escrow-BitLockerKey @params #EndRegion '.\Public\Escrow-BitLockerKey.ps1' 193 #Region '.\Public\Execute-MigrationToolkit.ps1' -1 function Execute-MigrationToolkit { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ServiceUI, [Parameter(Mandatory = $true)] [string]$ExePath ) Begin { Write-EnhancedLog -Message "Starting Execute-MigrationToolkit function" -Level "INFO" Log-Params -Params @{ ServiceUI = $ServiceUI ExePath = $ExePath } } Process { try { $targetProcesses = @(Get-WmiObject -Query "Select * FROM Win32_Process WHERE Name='explorer.exe'" -ErrorAction SilentlyContinue) if ($targetProcesses.Count -eq 0) { Write-EnhancedLog -Message "No user logged in, running without ServiceUI" -Level "INFO" Start-Process -FilePath $ExePath -ArgumentList '-DeployMode "NonInteractive"' -Wait -NoNewWindow } else { foreach ($targetProcess in $targetProcesses) { $Username = $targetProcess.GetOwner().User Write-EnhancedLog -Message "$Username logged in, running with ServiceUI" -Level "INFO" } Start-Process -FilePath $ServiceUI -ArgumentList "-Process:explorer.exe $ExePath" -NoNewWindow } } catch { $ErrorMessage = $_.Exception.Message Write-EnhancedLog -Message "An error occurred: $ErrorMessage" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Install Exit Code = $LASTEXITCODE" -Level "INFO" Write-EnhancedLog -Message "Exiting Execute-MigrationToolkit function" -Level "INFO" Exit $LASTEXITCODE } } # # Define paths # $ToolkitPaths = @{ # ServiceUI = "C:\ProgramData\AADMigration\Files\ServiceUI.exe" # ExePath = "C:\ProgramData\AADMigration\Toolkit\Deploy-Application.exe" # } # # Example usage with splatting # Execute-MigrationToolkit @ToolkitPaths #EndRegion '.\Public\Execute-MigrationToolkit.ps1' 54 #Region '.\Public\Get-PowerShellPath.ps1' -1 function Get-PowerShellPath { <# .SYNOPSIS Retrieves the path to the installed PowerShell executable. .DESCRIPTION This function checks for the existence of PowerShell 7 and PowerShell 5 on the system. It returns the path to the first version found, prioritizing PowerShell 7. If neither is found, an error is thrown. .EXAMPLE $pwshPath = Get-PowerShellPath Write-Host "PowerShell found at: $pwshPath" .NOTES Author: Abdullah Ollivierre Date: 2024-08-15 #> [CmdletBinding()] param () Begin { Write-EnhancedLog -Message "Starting Get-PowerShellPath function" -Level "NOTICE" } Process { $pwsh7Path = "C:\Program Files\PowerShell\7\pwsh.exe" $pwsh5Path = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" if (Test-Path $pwsh7Path) { Write-EnhancedLog -Message "PowerShell 7 found at $pwsh7Path" -Level "INFO" return $pwsh7Path } elseif (Test-Path $pwsh5Path) { Write-EnhancedLog -Message "PowerShell 5 found at $pwsh5Path" -Level "INFO" return $pwsh5Path } else { $errorMessage = "Neither PowerShell 7 nor PowerShell 5 was found on this system." Write-EnhancedLog -Message $errorMessage -Level "ERROR" throw $errorMessage } } End { Write-EnhancedLog -Message "Exiting Get-PowerShellPath function" -Level "NOTICE" } } # # Get the path to the installed PowerShell executable # try { # $pwshPath = Get-PowerShellPath # Write-Host "PowerShell executable found at: $pwshPath" # # Example: Start a new PowerShell session using the found path # Start-Process -FilePath $pwshPath -ArgumentList "-NoProfile", "-Command", "Get-Process" -NoNewWindow -Wait # } # catch { # Write-Host "Error: $($_.Exception.Message)" -ForegroundColor Red # } #EndRegion '.\Public\Get-PowerShellPath.ps1' 63 #Region '.\Public\Install-ADKFromMSI.ps1' -1 function Install-ADKFromMSI { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OfflinePath, [Parameter(Mandatory = $true)] [string]$ICDPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Imaging and Configuration Designer\x86\ICD.exe" ) Begin { Write-EnhancedLog -Message "Starting Install-ADKFromMSI function" -Level "INFO" Log-Params -Params @{ OfflinePath = $OfflinePath ICDPath = $ICDPath } # Ensure offline path exists if (-not (Test-Path -Path $OfflinePath)) { throw "Offline path not found: $OfflinePath" } } Process { try { # Get all MSI files in the offline path $MSIFiles = Get-ChildItem -Path $OfflinePath -Filter *.msi if (-not $MSIFiles) { throw "No MSI files found in: $OfflinePath" } # Install each MSI file foreach ($MSI in $MSIFiles) { Write-EnhancedLog -Message "Installing MSI: $($MSI.FullName)" -Level "INFO" Start-Process -FilePath "msiexec.exe" -ArgumentList "/i `"$($MSI.FullName)`" /quiet /norestart" -Wait -NoNewWindow } # Check if ICD.exe exists if (Test-Path -Path $ICDPath) { Write-EnhancedLog -Message "ICD.exe found at: $ICDPath" -Level "INFO" } else { throw "ICD.exe not found at: $ICDPath" } } catch { Write-EnhancedLog -Message "An error occurred while processing the Install-ADKFromMSI function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Install-ADKFromMSI function" -Level "INFO" } } # # Example usage # $installParams = @{ # OfflinePath = "$env:TEMP\ADKOffline\Installers" # ICDPath = "C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Imaging and Configuration Designer\x86\ICD.exe" # } # Install-ADKFromMSI @installParams #EndRegion '.\Public\Install-ADKFromMSI.ps1' 64 #Region '.\Public\Install-OneDrive-Archive.ps1' -1 # Function to validate OneDrive installation via registry # function Validate-OneDriveInstallation { # param ( # [string]$ODRegKey # ) # if (-not (Test-Path $ODRegKey)) { # Write-Log "Registry path not found: $ODRegKey" -Level "ERROR" # return @{ IsInstalled = $false } # } # try { # $installedVersion = Get-ItemPropertyValue -Path $ODRegKey -Name Version # Write-Log "Found installed OneDrive version: $installedVersion" -Level "INFO" # return @{ # IsInstalled = $true # Version = [System.Version]::new($installedVersion) # } # } # catch { # Write-Log "An error occurred while retrieving OneDrive version: $($_.Exception.Message)" -Level "ERROR" # return @{ IsInstalled = $false } # } # } # function Download-OneDriveSetup { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ODSetupUri, # [Parameter(Mandatory = $true)] # [string]$ODSetupPath # ) # Begin { # Write-EnhancedLog -Message "Starting Download-OneDriveSetup function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # Invoke-WebRequest -Uri $ODSetupUri -OutFile $ODSetupPath # Write-EnhancedLog -Message "Downloaded OneDrive setup to $ODSetupPath" -Level "INFO" # } # catch { # Write-EnhancedLog -Message "An error occurred while downloading OneDrive setup: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Download-OneDriveSetup function" -Level "Notice" # } # } # function Get-OneDriveSetupVersion { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ODSetupPath # ) # Begin { # Write-EnhancedLog -Message "Starting Get-OneDriveSetupVersion function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # $ODSetupVersion = (Get-ChildItem -Path $ODSetupPath).VersionInfo.FileVersion # Write-EnhancedLog -Message "OneDrive setup version: $ODSetupVersion" -Level "INFO" # return $ODSetupVersion # } # catch { # Write-EnhancedLog -Message "An error occurred while getting OneDrive setup version: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Get-OneDriveSetupVersion function" -Level "Notice" # } # } # function Get-InstalledOneDriveVersion { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ODRegKey # ) # Begin { # Write-EnhancedLog -Message "Starting Get-InstalledOneDriveVersion function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # $InstalledVer = if (Test-Path -Path $ODRegKey) { # Get-ItemPropertyValue -Path $ODRegKey -Name Version # } else { # [System.Version]::new("0.0.0.0") # } # Write-EnhancedLog -Message "Installed OneDrive version: $InstalledVer" -Level "INFO" # return $InstalledVer # } # catch { # Write-EnhancedLog -Message "An error occurred while getting installed OneDrive version: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Get-InstalledOneDriveVersion function" -Level "Notice" # } # } # function Install-OneDriveSetup { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ODSetupPath, # [Parameter(Mandatory = $true)] # [string]$SetupArgumentList # ) # Begin { # Write-EnhancedLog -Message "Starting Install-OneDriveSetup function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # Write-EnhancedLog -Message "Installing OneDrive setup" -Level "INFO" # Start-Process -FilePath $ODSetupPath -ArgumentList $SetupArgumentList -Wait -NoNewWindow # } # catch { # Write-EnhancedLog -Message "An error occurred while installing OneDrive setup: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Install-OneDriveSetup function" -Level "Notice" # } # } # function Perform-KFMSync { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$OneDriveExePath, # [Parameter(Mandatory = $true)] # [string]$ScheduledTaskName, # [Parameter(Mandatory = $true)] # [string]$ScheduledTaskDescription # ) # Begin { # Write-EnhancedLog -Message "Starting Perform-KFMSync function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # } # Process { # try { # Write-EnhancedLog -Message "Performing KFM sync" -Level "INFO" # $ODProcess = Get-Process -Name OneDrive -ErrorAction SilentlyContinue # if ($ODProcess) { # $ODProcess | Stop-Process -Confirm:$false -Force # Start-Sleep -Seconds 5 # Unregister-ScheduledTaskWithLogging -TaskName $ScheduledTaskName # $CreateOneDriveRemediationTaskParams = @{ # OneDriveExePath = $OneDriveExePath # ScheduledTaskName = $ScheduledTaskName # ScheduledTaskDescription = $ScheduledTaskDescription # } # Create-OneDriveRemediationTask @CreateOneDriveRemediationTaskParams # } # } # catch { # Write-EnhancedLog -Message "An error occurred while performing KFM sync: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Perform-KFMSync function" -Level "Notice" # } # } # function Install-OneDrive { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$MigrationPath, # [Parameter(Mandatory = $false)] # [bool]$OneDriveKFM = $false, # [Parameter(Mandatory = $true)] # [string]$ODSetupUri, # [Parameter(Mandatory = $true)] # [string]$ODSetupFile, # [Parameter(Mandatory = $true)] # [string]$ODRegKey, # [Parameter(Mandatory = $true)] # [string]$OneDriveExePath, # [Parameter(Mandatory = $true)] # [string]$ScheduledTaskName, # [Parameter(Mandatory = $true)] # [string]$ScheduledTaskDescription, # [Parameter(Mandatory = $true)] # [string]$SetupArgumentList # ) # Begin { # Write-EnhancedLog -Message "Starting Install-OneDrive function" -Level "Notice" # Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # $ODSetupPath = Join-Path -Path $MigrationPath -ChildPath $ODSetupFile # $ODSetupVersion = $null # } # Process { # try { # if (-not (Test-Path -Path $ODSetupPath)) { # Download-OneDriveSetup -ODSetupUri $ODSetupUri -ODSetupPath $ODSetupPath # } # $ODSetupVersion = Get-OneDriveSetupVersion -ODSetupPath $ODSetupPath # $InstalledVer = Get-InstalledOneDriveVersion -ODRegKey $ODRegKey # if (-not $InstalledVer -or ([System.Version]$InstalledVer -lt [System.Version]$ODSetupVersion)) { # Install-OneDriveSetup -ODSetupPath $ODSetupPath -SetupArgumentList $SetupArgumentList # } elseif ($OneDriveKFM) { # Perform-KFMSync -OneDriveExePath $OneDriveExePath -ScheduledTaskName $ScheduledTaskName -ScheduledTaskDescription $ScheduledTaskDescription # } # } # catch { # Write-EnhancedLog -Message "An error occurred in Install-OneDrive function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # throw $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Install-OneDrive function" -Level "Notice" # } # } # # $InstallOneDriveParams = @{ # # MigrationPath = "C:\ProgramData\AADMigration" # # OneDriveKFM = $true # # ODSetupUri = "https://go.microsoft.com/fwlink/?linkid=844652" # # ODSetupFile = "Files\OneDriveSetup.exe" # # ODRegKey = "HKLM:\SOFTWARE\Microsoft\OneDrive" # # OneDriveExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" # # ScheduledTaskName = "OneDriveRemediation" # # ScheduledTaskDescription = "Restart OneDrive to kick off KFM sync" # # ScheduledTaskArgumentList = "" # # SetupArgumentList = "/allusers" # # } # # Install-OneDrive @InstallOneDriveParams #EndRegion '.\Public\Install-OneDrive-Archive.ps1' 289 #Region '.\Public\Install-OneDrive.ps1' -1 # Function to download OneDrive setup with retry logic function Download-OneDriveSetup { <# .SYNOPSIS Downloads the OneDrive setup executable. .DESCRIPTION Downloads the OneDrive setup executable from the specified URL to the given destination path. Uses the Start-FileDownloadWithRetry function for robust download handling with retries. .PARAMETER ODSetupUri The URL of the OneDrive setup executable. .PARAMETER ODSetupPath The file path where the OneDrive setup executable will be saved. .EXAMPLE Download-OneDriveSetup -ODSetupUri "https://go.microsoft.com/fwlink/?linkid=844652" -ODSetupPath "C:\Temp\OneDriveSetup.exe" .NOTES Author: Abdullah Ollivierre Date: 2024-08-15 #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ODSetupUri, [Parameter(Mandatory = $true)] [string]$ODSetupPath ) Begin { Write-EnhancedLog -Message "Starting Download-OneDriveSetup function" -Level "NOTICE" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { Write-EnhancedLog -Message "Starting Start-FileDownloadWithRetry function" -Level "NOTICE" Start-FileDownloadWithRetry -Source $ODSetupUri -Destination $ODSetupPath -MaxRetries 3 Write-EnhancedLog -Message "Downloaded OneDrive setup to $ODSetupPath" -Level "INFO" } End { Write-EnhancedLog -Message "Exiting Download-OneDriveSetup function" -Level "NOTICE" } } # Function to install OneDrive function Install-OneDriveSetup { param ( [string]$ODSetupPath, [string]$SetupArgumentList ) Write-Log "Installing OneDrive setup from $ODSetupPath..." -Level "INFO" $startProcessParams = @{ FilePath = $ODSetupPath ArgumentList = $SetupArgumentList Wait = $true NoNewWindow = $true } try { Start-Process @startProcessParams Write-Log "OneDrive installation completed." -Level "INFO" } catch { Write-Log "An error occurred during OneDrive installation: $($_.Exception.Message)" -Level "ERROR" throw $_ } } # Main function to manage the entire OneDrive installation and configuration function Install-Software { <# .SYNOPSIS Installs a specified software and performs pre- and post-installation validation. .DESCRIPTION This function handles the installation of software by downloading the installer, validating the software before and after installation, and performing any necessary post-installation tasks such as syncing or configuring the software. .PARAMETER MigrationPath The base directory path where the setup file will be stored. .PARAMETER SoftwareName The name of the software to be installed, used for validation. .PARAMETER SetupUri The URL from which the setup executable will be downloaded. .PARAMETER SetupFile The name of the setup executable file. .PARAMETER RegKey The registry key path used for validating the installed version. .PARAMETER MinVersion The minimum required version of the software to validate the installation. .PARAMETER ExePath The path to the executable file used for file-based validation. .PARAMETER ScheduledTaskName The name of the scheduled task used for any post-installation tasks. .PARAMETER ScheduledTaskDescription A description for the scheduled task. .PARAMETER SetupArgumentList The arguments passed to the installer executable during installation. .PARAMETER KFM Specifies whether to perform a Known Folder Move (KFM) sync after installation. Default is $false. .PARAMETER TimestampPrefix A prefix used for naming the timestamped folder in the TEMP directory. Default is 'Setup_'. .EXAMPLE $installParams = @{ MigrationPath = "C:\Migration" SoftwareName = "OneDrive" SetupUri = "https://go.microsoft.com/fwlink/?linkid=844652" SetupFile = "OneDriveSetup.exe" RegKey = "HKLM:\SOFTWARE\Microsoft\OneDrive" MinVersion = [version]"23.143.0712.0001" ExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" ScheduledTaskName = "OneDriveRemediation" ScheduledTaskDescription= "Restart OneDrive to kick off KFM sync" SetupArgumentList = "/allusers" KFM = $true TimestampPrefix = "OneDriveSetup_" } Install-Software @installParams .NOTES Author: Abdullah Ollivierre Date: 2024-08-15 #> [CmdletBinding()] param ( [string]$MigrationPath, [string]$SoftwareName, [string]$SetupUri, [string]$SetupFile, [string]$RegKey, [version]$MinVersion, [string]$ExePath, [string]$ScheduledTaskName, [string]$ScheduledTaskDescription, [string]$SetupArgumentList, [bool]$KFM = $false, [string]$TimestampPrefix # Default prefix for the timestamped folder ) Begin { Write-EnhancedLog -Message "Starting Install-Software function for $SoftwareName" -Level "NOTICE" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Ensure the script is running with elevated privileges CheckAndElevate # Generate a timestamped folder within the TEMP directory $timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss") $destinationFolder = [System.IO.Path]::Combine($env:TEMP, "$TimestampPrefix$timestamp") $SetupPath = [System.IO.Path]::Combine($destinationFolder, $SetupFile) } Process { # Step 1: Pre-installation validation Write-EnhancedLog -Message "Step 1: Performing pre-installation validation for $SoftwareName..." -Level "INFO" $preInstallParams = @{ SoftwareName = $SoftwareName MinVersion = $MinVersion RegistryPath = $RegKey ExePath = $ExePath MaxRetries = 3 DelayBetweenRetries = 5 } $preInstallCheck = Validate-SoftwareInstallation @preInstallParams if ($preInstallCheck.IsInstalled) { Write-EnhancedLog -Message "$SoftwareName version $($preInstallCheck.Version) is already installed. Skipping installation." -Level "INFO" return } Write-EnhancedLog -Message "$SoftwareName is not currently installed or needs an update." -Level "INFO" # Step 2: Download the setup file if not already present Write-EnhancedLog -Message "Step 2: Downloading $SoftwareName setup..." -Level "INFO" if (-not (Test-Path -Path $SetupPath)) { Download-OneDriveSetup -ODSetupUri $SetupUri -ODSetupPath $SetupPath } else { Write-EnhancedLog -Message "$SoftwareName setup already downloaded at $SetupPath" -Level "INFO" } # Step 3: Install the software Write-EnhancedLog -Message "Step 3: Installing $SoftwareName..." -Level "INFO" Install-OneDriveSetup -ODSetupPath $SetupPath -SetupArgumentList $SetupArgumentList # Step 4: Post-installation validation Write-EnhancedLog -Message "Step 4: Performing post-installation validation for $SoftwareName..." -Level "INFO" $postInstallCheck = Validate-SoftwareInstallation @preInstallParams if ($postInstallCheck.IsInstalled) { Write-EnhancedLog -Message "$SoftwareName version $($postInstallCheck.Version) installed successfully." -Level "INFO" } else { Write-EnhancedLog -Message "$SoftwareName installation failed." -Level "ERROR" throw "$SoftwareName installation validation failed." } # Step 5: Perform KFM sync if enabled if ($KFM) { Write-EnhancedLog -Message "Step 5: Performing KFM sync for $SoftwareName..." -Level "INFO" Perform-KFMSync -OneDriveExePath $ExePath -ScheduledTaskName $ScheduledTaskName -ScheduledTaskDescription $ScheduledTaskDescription } } End { Write-EnhancedLog -Message "Exiting Install-Software function for $SoftwareName" -Level "NOTICE" } } # $installParams = @{ # MigrationPath = "C:\ProgramData\AADMigration" # SoftwareName = "OneDrive" # SetupUri = "https://go.microsoft.com/fwlink/?linkid=844652" # SetupFile = "OneDriveSetup.exe" # RegKey = "HKLM:\SOFTWARE\Microsoft\OneDrive" # MinVersion = [version]"24.146.0721.0003" # ExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" # ScheduledTaskName = "OneDriveRemediation" # ScheduledTaskDescription = "Restart OneDrive to kick off KFM sync" # SetupArgumentList = "/allusers" # KFM = $true # TimestampPrefix = "OneDriveSetup_" # } # Install-Software @installParams #EndRegion '.\Public\Install-OneDrive.ps1' 241 #Region '.\Public\Install-PPKG.ps1' -1 function Install-PPKG { <# .SYNOPSIS Installs a provisioning package (PPKG). .DESCRIPTION The Install-PPKG function installs a provisioning package (PPKG) from a specified path. It logs the installation process and handles errors gracefully. .PARAMETER PPKGName The name of the provisioning package to be installed. .PARAMETER MigrationPath The path to the migration files directory containing the provisioning package. .EXAMPLE $params = @{ PPKGName = "MyProvisioningPackage.ppkg" MigrationPath = "C:\ProgramData\AADMigration" } Install-PPKG @params Installs the specified provisioning package. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$PPKGName, [Parameter(Mandatory = $true)] [string]$MigrationPath ) Begin { Write-EnhancedLog -Message "Starting Install-PPKG function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { $ppkgPath = Join-Path -Path $MigrationPath -ChildPath "Files\$PPKGName" if (-not (Test-Path -Path $ppkgPath)) { Throw "Provisioning package file not found: $ppkgPath" } Write-EnhancedLog -Message "Installing provisioning package: $ppkgPath" -Level "INFO" $params = @{ PackagePath = $ppkgPath ForceInstall = $true QuietInstall = $true } Install-ProvisioningPackage @params Write-EnhancedLog -Message "Provisioning package installed successfully." -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred in Install-PPKG function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Install-PPKG function" -Level "Notice" } } # # Example usage # $params = @{ # PPKGName = "MyProvisioningPackage.ppkg" # MigrationPath = "C:\ProgramData\AADMigration" # } # Install-PPKG @params #EndRegion '.\Public\Install-PPKG.ps1' 74 #Region '.\Public\Main-MigrateToAADJOnly.ps1' -1 function Main-MigrateToAADJOnly { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$PPKGName, [Parameter(Mandatory = $false)] [string]$DomainLeaveUser, [Parameter(Mandatory = $false)] [string]$DomainLeavePassword, [Parameter(Mandatory = $true)] [string]$TempUser, [Parameter(Mandatory = $true)] [string]$TempUserPassword, [Parameter(Mandatory = $true)] [string]$ScriptPath ) Begin { Write-EnhancedLog -Message "Starting Main-MigrateToAADJOnly function" -Level "Notice" Log-Params -Params @{ PPKGName = $PPKGName; DomainLeaveUser = $DomainLeaveUser; DomainLeavePassword = $DomainLeavePassword; TempUser = $TempUser; TempUserPassword = $TempUserPassword; ScriptPath = $ScriptPath; } # Initialize steps $global:steps = @() Add-Step -description "Testing provisioning package" -action { $TestProvisioningPackParams = @{ PPKGName = $PPKGName } Test-ProvisioningPack @TestProvisioningPackParams } # Add-Step -description "Adding local user" -action { Add-LocalUser -TempUser $TempUser -TempUserPassword $TempUserPassword } Add-Step -description "Adding local user" -action { $AddLocalUserParams = @{ TempUser = $TempUser TempUserPassword = $TempUserPassword Description = "account for autologin" Group = "Administrators" } # Example usage with splatting Add-LocalUser @AddLocalUserParams } Add-Step -description "Setting autologin" -action { # Example usage with splatting $SetAutologinParams = @{ TempUser = $TempUser TempUserPassword = $TempUserPassword RegPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' AutoAdminLogonName = 'AutoAdminLogon' AutoAdminLogonValue = '1' DefaultUsernameName = 'DefaultUsername' DefaultPasswordName = 'DefaultPassword' } Set-Autologin @SetAutologinParams } Add-Step -description "Disabling OOBE privacy" -action { # Example usage with splatting $DisableOOBEPrivacyParams = @{ OOBERegistryPath = 'HKLM:\Software\Policies\Microsoft\Windows\OOBE' OOBEName = 'DisablePrivacyExperience' OOBEValue = '1' AnimationRegistryPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' AnimationName = 'EnableFirstLogonAnimation' AnimationValue = '0' LockRegistryPath = 'HKLM:\Software\Policies\Microsoft\Windows\Personalization' LockName = 'NoLockScreen' LockValue = '1' } Disable-OOBEPrivacy @DisableOOBEPrivacyParams } Add-Step -description "Setting RunOnce script" -action { # Example usage with splatting $SetRunOnceParams = @{ ScriptPath = $ScriptPath RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" ExecutionPolicy = "Unrestricted" RunOnceName = "NextRun" } Set-RunOnce @SetRunOnceParams } Add-Step -description "Suspending BitLocker With Reboot Count" -action { # Example usage with splatting $SuspendBitLockerWithRebootParams = @{ MountPoint = "C:" RebootCount = 3 } Suspend-BitLockerWithReboot @SuspendBitLockerWithRebootParams } Add-Step -description "Removing Intune management" -action { # $RemoveCompanyPortalParams = @{ # AppxPackageName = "Microsoft.CompanyPortal" # } # Remove-CompanyPortal @RemoveCompanyPortalParams $RemoveIntuneMgmtParams = @{ OMADMPath = "HKLM:\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts\*" EnrollmentBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments" TrackedBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked" PolicyManagerBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager" ProvisioningBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning" CertCurrentUserPath = "cert:\CurrentUser" CertLocalMachinePath = "cert:\LocalMachine" TaskPathBase = "\Microsoft\Windows\EnterpriseMgmt" MSDMProviderID = "MS DM Server" RegistryPathsToRemove = @( "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\Status", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\AdmxInstalled", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\Providers", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Logger", "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Sessions" ) UserCertIssuer = "CN=SC_Online_Issuing" DeviceCertIssuers = @("CN=Microsoft Intune Root Certification Authority", "CN=Microsoft Intune MDM Device CA") } Remove-IntuneMgmt @RemoveIntuneMgmtParams } Add-Step -description "Removing hybrid join" -action { Remove-Hybrid } Add-Step -description "Removing AD join" -action { $RemoveADJoinParams = @{ # DomainLeaveUser = $DomainLeaveUser # DomainLeavePassword = $DomainLeavePassword TempUser = $TempUser TempUserPassword = $TempUserPassword ComputerName = "localhost" TaskName = "AADM Launch PSADT for Interactive Migration" } Remove-ADJoin @RemoveADJoinParams } } Process { try { foreach ($step in $global:steps) { Log-And-Execute-Step -Step $step } } catch { Write-EnhancedLog -Message "An error occurred: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Main-MigrateToAADJOnly function" -Level "Notice" } } # $MainMigrateParams = @{ # PPKGName = "YourProvisioningPackName" # DomainLeaveUser = "YourDomainUser" # DomainLeavePassword = "YourDomainPassword" # TempUser = "YourTempUser" # TempUserPassword = "YourTempUserPassword" # ScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce.ps1" # } # Main-MigrateToAADJOnly @MainMigrateParams #EndRegion '.\Public\Main-MigrateToAADJOnly.ps1' 199 #Region '.\Public\New-MigrationTask-Archive.ps1' -1 # function New-MigrationTask { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$StartBoundary, # [Parameter(Mandatory = $true)] # [string]$ScriptPath, # [Parameter(Mandatory = $true)] # [string]$TaskPath, # [Parameter(Mandatory = $true)] # [string]$TaskName, # [Parameter(Mandatory = $true)] # [string]$Description, # [Parameter(Mandatory = $true)] # [string]$UserId, # [Parameter(Mandatory = $true)] # [string]$RunLevel, # [Parameter(Mandatory = $true)] # [string]$Delay, # [Parameter(Mandatory = $true)] # [string]$ExecutePath, # [Parameter(Mandatory = $true)] # [string]$Arguments # ) # Begin { # Write-EnhancedLog -Message "Starting New-MigrationTask function" -Level "INFO" # Log-Params -Params @{ # StartBoundary = $StartBoundary # ScriptPath = $ScriptPath # TaskPath = $TaskPath # TaskName = $TaskName # Description = $Description # UserId = $UserId # RunLevel = $RunLevel # Delay = $Delay # ExecutePath = $ExecutePath # Arguments = $Arguments # } # } # Process { # try { # $action = New-ScheduledTaskAction -Execute $ExecutePath -Argument $Arguments # $trigger = New-ScheduledTaskTrigger -AtLogOn # $trigger.Delay = $Delay # $trigger.StartBoundary = $StartBoundary # $principal = New-ScheduledTaskPrincipal -UserId $UserId -RunLevel $RunLevel # Register-ScheduledTask -Principal $principal -Action $action -Trigger $trigger -TaskName $TaskName -Description $Description -TaskPath $TaskPath # } catch { # Write-EnhancedLog -Message "An error occurred while creating the migration task: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting New-MigrationTask function" -Level "INFO" # } # } # Define parameters # $MigrationTaskParams = @{ # StartBoundary = "2024-07-11T12:00:00" # ScriptPath = "C:\ProgramData\AADMigration\Scripts\Launch-DeployApplication_SchTask.ps1" # TaskPath = "AAD Migration" # TaskName = "AADM Launch PSADT for Interactive Migration" # Description = "AADM Launch PSADT for Interactive Migration" # UserId = "SYSTEM" # RunLevel = "Highest" # Delay = "PT1M" # ExecutePath = "PowerShell.exe" # Arguments = "-executionpolicy Bypass -file `"$ScriptPath`"" # } # # Example usage with splatting # New-MigrationTask @MigrationTaskParams #EndRegion '.\Public\New-MigrationTask-Archive.ps1' 89 #Region '.\Public\Perform-KFMSync.ps1' -1 function Perform-KFMSync { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OneDriveExePath, [Parameter(Mandatory = $true)] [string]$ScheduledTaskName, [Parameter(Mandatory = $true)] [string]$ScheduledTaskDescription ) Begin { Write-EnhancedLog -Message "Starting Perform-KFMSync function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Performing KFM sync" -Level "INFO" $ODProcess = Get-Process -Name OneDrive -ErrorAction SilentlyContinue if ($ODProcess) { $ODProcess | Stop-Process -Confirm:$false -Force Start-Sleep -Seconds 5 Unregister-ScheduledTaskWithLogging -TaskName $ScheduledTaskName $CreateOneDriveRemediationTaskParams = @{ OneDriveExePath = $OneDriveExePath ScheduledTaskName = $ScheduledTaskName ScheduledTaskDescription = $ScheduledTaskDescription } Create-OneDriveRemediationTask @CreateOneDriveRemediationTaskParams } } catch { Write-EnhancedLog -Message "An error occurred while performing KFM sync: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Perform-KFMSync function" -Level "Notice" } } #EndRegion '.\Public\Perform-KFMSync.ps1' 50 #Region '.\Public\PostRunOnce.ps1' -1 # # Example usage # $params = @{ # MigrationConfigPath = "C:\ProgramData\AADMigration\scripts\MigrationConfig.psd1" # ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" # RunOnceScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce2.ps1" # RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" # PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" # ExecutionPolicy = "Unrestricted" # RunOnceName = "NextRun" # } # Start-MigrationProcess @params #EndRegion '.\Public\PostRunOnce.ps1' 12 #Region '.\Public\PostRunOnce2.ps1' -1 function PostRunOnce2 { <# .SYNOPSIS Executes post-run operations for the second phase of the migration process. .DESCRIPTION The PostRunOnce2 function blocks user input, displays a migration in progress form, creates a scheduled task for post-migration cleanup, escrows the BitLocker recovery key, sets various registry values, and restarts the computer. .PARAMETER ImagePath The path to the image file to be displayed on the migration progress form. .PARAMETER TaskPath The path of the task in Task Scheduler. .PARAMETER TaskName The name of the scheduled task. .PARAMETER ScriptPath The path to the PowerShell script to be executed by the scheduled task. .PARAMETER BitlockerDrives An array of drive letters for the BitLocker protected drives. .PARAMETER RegistrySettings A hashtable of registry settings to be applied. .EXAMPLE $params = @{ ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" TaskPath = "AAD Migration" TaskName = "Run Post-migration cleanup" ScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce3.ps1" BitlockerDrives = @("C:", "D:") RegistrySettings = @{ "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" = @{ "AutoAdminLogon" = @{ "Type" = "DWORD" "Data" = "0" } } "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" = @{ "dontdisplaylastusername" = @{ "Type" = "DWORD" "Data" = "1" } "legalnoticecaption" = @{ "Type" = "String" "Data" = "Migration Completed" } "legalnoticetext" = @{ "Type" = "String" "Data" = "This PC has been migrated to Azure Active Directory. Please log in to Windows using your email address and password." } } } } PostRunOnce2 @params Executes the post-run operations. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ImagePath, [Parameter(Mandatory = $true)] [string]$TaskPath, [Parameter(Mandatory = $true)] [string]$TaskName, [Parameter(Mandatory = $true)] [string]$ScriptPath, [Parameter(Mandatory = $true)] [string[]]$BitlockerDrives, [Parameter(Mandatory = $true)] [hashtable]$RegistrySettings ) Begin { Write-EnhancedLog -Message "Starting PostRunOnce2 function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { # Start-Transcript -Path "C:\ProgramData\AADMigration\Logs\AD2AADJ-R2.txt" -Append -Verbose # Block user input $blockParams = @{ Block = $true } Block-UserInput @blockParams # Show migration in progress form $formParams = @{ ImagePath = $ImagePath } Show-MigrationInProgressForm @formParams # Create scheduled task for post-migration cleanup $taskParams = @{ TaskPath = $TaskPath TaskName = $TaskName ScriptPath = $ScriptPath } Create-ScheduledTask @taskParams # $schedulerconfigPath = Join-Path -Path $PSScriptRoot -ChildPath "config.psd1" # $taskParams = @{ # ConfigPath = $schedulerconfigPath # FileName = "run-ps-hidden.vbs" # Scriptroot = $PSScriptRoot # } # CreateAndExecuteScheduledTask @taskParams # Escrow BitLocker recovery key for each drive foreach ($drive in $BitlockerDrives) { $escrowParams = @{ DriveLetter = $drive } Escrow-BitLockerKey @escrowParams } # Set registry values foreach ($regPath in $RegistrySettings.Keys) { foreach ($regName in $RegistrySettings[$regPath].Keys) { $regSetting = $RegistrySettings[$regPath][$regName] $regParams = @{ RegKeyPath = $regPath RegValName = $regName RegValType = $regSetting["Type"] RegValData = $regSetting["Data"] } Set-RegistryValue @regParams } } # Stop-Transcript # Unblock user input and close form Block-UserInput -Block $false Restart-Computer } catch { Write-EnhancedLog -Message "An error occurred in PostRunOnce2 function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting PostRunOnce2 function" -Level "Notice" } } # Example usage # $params = @{ # ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" # TaskPath = "AAD Migration" # TaskName = "Run Post-migration cleanup" # ScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce3.ps1" # BitlockerDrives = @("C:", "D:") # RegistrySettings = @{ # "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" = @{ # "AutoAdminLogon" = @{ # "Type" = "DWORD" # "Data" = "0" # } # } # "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" = @{ # "dontdisplaylastusername" = @{ # "Type" = "DWORD" # "Data" = "1" # } # "legalnoticecaption" = @{ # "Type" = "String" # "Data" = "Migration Completed" # } # "legalnoticetext" = @{ # "Type" = "String" # "Data" = "This PC has been migrated to Azure Active Directory. Please log in to Windows using your email address and password." # } # } # } # } # PostRunOnce2 @params # Example usage # PostRunOnce2 #EndRegion '.\Public\PostRunOnce2.ps1' 196 #Region '.\Public\PostRunOnce3.ps1' -1 function PostRunOnce3 { <# .SYNOPSIS Executes post-run operations for the third phase of the migration process. .DESCRIPTION The PostRunOnce3 function performs cleanup tasks after migration, including removing temporary user accounts, disabling local user accounts, removing scheduled tasks, clearing OneDrive cache, and setting registry values. .PARAMETER TempUser The name of the temporary user account to be removed. .PARAMETER RegistrySettings A hashtable of registry settings to be applied. .PARAMETER MigrationDirectories An array of directories to be removed as part of migration cleanup. .EXAMPLE $params = @{ TempUser = "TempUser" RegistrySettings = @{ "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" = @{ "dontdisplaylastusername" = @{ "Type" = "DWORD" "Data" = "0" } "legalnoticecaption" = @{ "Type" = "String" "Data" = $null } "legalnoticetext" = @{ "Type" = "String" "Data" = $null } } "HKLM:\Software\Policies\Microsoft\Windows\Personalization" = @{ "NoLockScreen" = @{ "Type" = "DWORD" "Data" = "0" } } } MigrationDirectories = @( "C:\ProgramData\AADMigration\Files", "C:\ProgramData\AADMigration\Scripts", "C:\ProgramData\AADMigration\Toolkit" ) } PostRunOnce3 @params Executes the post-run operations. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TempUser, [Parameter(Mandatory = $true)] [hashtable]$RegistrySettings, [Parameter(Mandatory = $true)] [string[]]$MigrationDirectories ) Begin { Write-EnhancedLog -Message "Starting PostRunOnce3 function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Start-Transcript -Path "C:\ProgramData\AADMigration\Logs\AD2AADJ-R3.txt" -Append -Force # Remove temporary user account $removeUserParams = @{ UserName = $TempUser } Remove-LocalUserAccount @removeUserParams # Disable local user accounts Disable-LocalUserAccounts # Set registry values foreach ($regPath in $RegistrySettings.Keys) { foreach ($regName in $RegistrySettings[$regPath].Keys) { $regSetting = $RegistrySettings[$regPath][$regName] $regParams = @{ RegKeyPath = $regPath RegValName = $regName RegValType = $regSetting["Type"] RegValData = $regSetting["Data"] } Set-RegistryValue @regParams } } # Remove scheduled tasks $taskParams = @{ TaskPath = "AAD Migration" } Remove-ScheduledTasks @taskParams # Remove migration files $removeFilesParams = @{ Directories = $MigrationDirectories } Remove-MigrationFiles @removeFilesParams # Clear OneDrive cache Clear-OneDriveCache Stop-Transcript } catch { Write-EnhancedLog -Message "An error occurred in PostRunOnce3 function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting PostRunOnce3 function" -Level "Notice" } } # Example usage # $PostRunOnce3params = @{ # TempUser = "TempUser" # RegistrySettings = @{ # "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" = @{ # "dontdisplaylastusername" = @{ # "Type" = "DWORD" # "Data" = "0" # } # "legalnoticecaption" = @{ # "Type" = "String" # "Data" = $null # } # "legalnoticetext" = @{ # "Type" = "String" # "Data" = $null # } # } # "HKLM:\Software\Policies\Microsoft\Windows\Personalization" = @{ # "NoLockScreen" = @{ # "Type" = "DWORD" # "Data" = "0" # } # } # } # MigrationDirectories = @( # "C:\ProgramData\AADMigration\Files", # "C:\ProgramData\AADMigration\Scripts", # "C:\ProgramData\AADMigration\Toolkit" # ) # } # PostRunOnce3 @PostRunOnce3params #EndRegion '.\Public\PostRunOnce3.ps1' 157 #Region '.\Public\Prepare-AADMigration.ps1' -1 function Prepare-AADMigration { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$MigrationPath, [Parameter(Mandatory = $true)] [string]$PSScriptbase, [Parameter(Mandatory = $true)] [string]$ConfigBaseDirectory, [Parameter(Mandatory = $true)] [string]$ConfigFileName, [Parameter(Mandatory = $true)] [string]$TenantID, [Parameter(Mandatory = $true)] [bool]$OneDriveKFM, [Parameter(Mandatory = $true)] [bool]$InstallOneDrive ) Begin { Write-EnhancedLog -Message "Starting Prepare-AADMigration function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { # Ensure the target directory exists if (-not (Test-Path -Path $MigrationPath)) { New-Item -Path $MigrationPath -ItemType Directory -Force | Out-Null } # Copy the entire content of $PSScriptRoot to $MigrationPath # Define the source and destination paths $sourcePath1 = $PSScriptbase # $sourcePath2 = "C:\code\modulesv2" $destinationPath1 = $MigrationPath # $destinationPath2 = "$MigrationPath\modulesv2" # Copy files from $PSScriptRoot using the Copy-FilesToPath function # Copy-FilesToPath -SourcePath $sourcePath1 -DestinationPath $destinationPath1 Stop-ProcessesUsingOneDriveLib -OneDriveLibPath "C:\ProgramData\AADMigration\Files\OneDriveLib.dll" # $DBG Remove-ScheduledTaskFilesWithLogging -Path $destinationPath1 # Copy-FilesToPathWithKill -SourcePath $sourcePath1 -DestinationPath $destinationPath1 # Ensure the destination directory exists if (Test-Path -Path $destinationPath1) { Write-EnhancedLog -Message "Destination directory already exists. Removing: $destinationPath1" -Level "WARNING" Remove-Item -Path $destinationPath1 -Recurse -Force Write-EnhancedLog -Message "Destination directory removed: $destinationPath1" -Level "INFO" } # Create a new destination directory New-Item -Path $destinationPath1 -ItemType Directory | Out-Null Write-EnhancedLog -Message "New destination directory created: $destinationPath1" -Level "INFO" $params = @{ Source = $sourcePath1 Destination = $destinationPath1 Exclude = ".git" RetryCount = 2 WaitTime = 5 RequiredSpaceGB = 10 } # Execute the function with splatting Copy-FilesWithRobocopy @params $DBG # Verify the copy operation for $PSScriptRoot Verify-CopyOperation -SourcePath $sourcePath1 -DestinationPath $destinationPath1 #################################################################################### # Copy files from C:\code\modules using the Copy-FilesToPath function # Copy-FilesToPath -SourcePath $sourcePath2 -DestinationPath $destinationPath2 # Copy-FilesToPathWithKill -SourcePath $sourcePath2 -DestinationPath $destinationPath2 # Ensure the destination directory exists # if (-not (Test-Path -Path $destinationPath2)) { # New-Item -Path $destinationPath2 -ItemType Directory | Out-Null # } # $params = @{ # Source = $sourcePath2 # Destination = $destinationPath2 # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Execute the function with splatting # Copy-FilesWithRobocopy @params # Verify the copy operation for C:\code\modulesv2 # Verify-CopyOperation -SourcePath $sourcePath2 -DestinationPath $destinationPath2 # $DBG # Write-EnhancedLog -Message "Copied content from $PSScriptRoot to $MigrationPath" -Level "INFO" # $DBG # Import migration configuration $MigrationConfig = Import-LocalizedData -BaseDirectory $ConfigBaseDirectory -FileName $ConfigFileName $TenantID = $MigrationConfig.TenantID $OneDriveKFM = $MigrationConfig.UseOneDriveKFM $InstallOneDrive = $MigrationConfig.InstallOneDrive # $DBG # Set OneDrive KFM settings if required if ($OneDriveKFM) { # $TenantID = "YourTenantID" $RegistrySettings = @( @{ RegValName = "AllowTenantList" RegValType = "STRING" RegValData = $TenantID }, @{ RegValName = "SilentAccountConfig" RegValType = "DWORD" RegValData = "1" }, @{ RegValName = "KFMOptInWithWizard" RegValType = "STRING" RegValData = $TenantID }, @{ RegValName = "KFMSilentOptIn" RegValType = "STRING" RegValData = $TenantID }, @{ RegValName = "KFMSilentOptInDesktop" RegValType = "DWORD" RegValData = "1" }, @{ RegValName = "KFMSilentOptInDocuments" RegValType = "DWORD" RegValData = "1" }, @{ RegValName = "KFMSilentOptInPictures" RegValType = "DWORD" RegValData = "1" } ) $SetODKFMRegistrySettingsParams = @{ TenantID = $TenantID RegKeyPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" RegistrySettings = $RegistrySettings } Set-ODKFMRegistrySettings @SetODKFMRegistrySettingsParams $DBG Unregister-ScheduledTaskWithLogging -TaskName "AADM Get OneDrive Sync Status" # # Example usage with splatting # $CreateOneDriveSyncStatusTaskParams = @{ # TaskPath = "AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # ScriptDirectory = "C:\ProgramData\AADMigration\Scripts" # ScriptName = "Check-OneDriveSyncStatus.ps1" # TaskArguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file `"{ScriptPath}`"" # TaskRepetitionDuration = "P1D" # TaskRepetitionInterval = "PT30M" # TaskPrincipalGroupId = "BUILTIN\Users" # PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" # TaskDescription = "Get current OneDrive Sync Status and write to event log" # } # Create-OneDriveSyncStatusTask @CreateOneDriveSyncStatusTaskParams # $DBG } # Install OneDrive if required if ($InstallOneDrive) { # Example usage $installParams = @{ MigrationPath = "C:\ProgramData\AADMigration" SoftwareName = "OneDrive" SetupUri = "https://go.microsoft.com/fwlink/?linkid=844652" SetupFile = "OneDriveSetup.exe" RegKey = "HKLM:\SOFTWARE\Microsoft\OneDrive" MinVersion = [version]"24.146.0721.0003" ExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" ScheduledTaskName = "OneDriveRemediation" ScheduledTaskDescription = "Restart OneDrive to kick off KFM sync" SetupArgumentList = "/allusers" KFM = $true TimestampPrefix = "OneDriveSetup_" } Install-Software @installParams $DBG } # # Example usage with splatting # $CreateOneDriveSyncStatusTaskParams = @{ # TaskPath = "AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # ScriptDirectory = "C:\ProgramData\AADMigration\Scripts" # ScriptName = "Check-OneDriveSyncStatus.ps1" # TaskArguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file `"{ScriptPath}`"" # TaskRepetitionDuration = "P1D" # TaskRepetitionInterval = "PT30M" # TaskPrincipalGroupId = "BUILTIN\Users" # PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" # TaskDescription = "Get current OneDrive Sync Status and write to event log" # } # Create-OneDriveSyncStatusTask @CreateOneDriveSyncStatusTaskParams $CreateOneDriveSyncStatusTaskParams = @{ TaskPath = "AAD Migration" TaskName = "AADM Get OneDrive Sync Util Status" ScriptDirectory = "C:\ProgramData\AADMigration\Scripts" ScriptName = "Check-ODSyncUtilStatus.ps1" TaskArguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file `"{ScriptPath}`"" TaskRepetitionDuration = "P1D" TaskRepetitionInterval = "PT30M" TaskPrincipalGroupId = "BUILTIN\Users" PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" TaskDescription = "Get current OneDrive Sync Status and write to event log" } Create-OneDriveSyncUtilStatusTask @CreateOneDriveSyncStatusTaskParams # Should we check OneDrive Sync before OR after the prep ? Currently this is being called after the Prep and I wonder if we should call it BEFORE the Prep instead # Check-OneDriveSyncStatus -OneDriveLibPath "C:\ProgramData\AADMigration\Files\OneDriveLib.dll" # Example usage # Define parameters using a hashtable # $taskParams = @{ # TaskPath = "\AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # } # # Trigger OneDrive Sync Status Scheduled Task # Trigger-ScheduledTask @taskParams $taskParams = @{ TaskPath = "\AAD Migration" TaskName = "AADM Get OneDrive Sync Util Status" } # Trigger OneDrive Sync Status Scheduled Task Trigger-ScheduledTask @taskParams # # Example usage with splatting # $AnalyzeParams = @{ # LogFolder = "C:\ProgramData\AADMigration\logs" # StatusFileName = "OneDriveSyncStatus.json" # } # Analyze-OneDriveSyncStatus @AnalyzeParams # # # Example usage $AnalyzeOneDriveSyncUtilStatusParams = @{ LogFolder = "C:\ProgramData\AADMigration\logs" StatusFileName = "ODSyncUtilStatus.json" } Analyze-OneDriveSyncUtilStatus @AnalyzeOneDriveSyncUtilStatusParams #Todo now we have OneDrive installed and running we need to actually start using our OneDrive for Business location on the local machine to copy user specific files into it as part of our On-prem AD to Entra ID migration prep so we need to copy the following PR4B projects from before # 1- copy Outlook Signatures # 2- copy Downloads folders # any other user specific files $CreateUserFileBackupTaskParams = @{ TaskPath = "AAD Migration" TaskName = "User File Backup to OneDrive" BackupScriptPath = "C:\ProgramData\AADMigration\Scripts\BackupUserFiles.ps1" TaskRepetitionDuration = "P1D" # 1 day TaskRepetitionInterval = "PT1H" # 1 hour TaskPrincipalGroupId = "BUILTIN\USERS" PowerShellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe" TaskDescription = "Backup user files to a designated location" } Create-UserFileBackupTask @CreateUserFileBackupTaskParams $taskParams = @{ TaskPath = "\AAD Migration" TaskName = "User File Backup to OneDrive" } # Call the function with splatting Trigger-ScheduledTask @taskParams # # Example usage with splatting $AnalyzeParams = @{ LogFolder = "C:\ProgramData\AADMigration\logs" StatusFileName = "UserFilesBackupStatus.json" } Analyze-CopyOperationStatus @AnalyzeParams # # Example usage # $BackupChromeBookmarksToOneDriveParams = @{ # ChromeProfilePath = "$env:USERPROFILE\AppData\Local\Google\Chrome\User Data\Default" # BackupFolderName = "ChromeBackup" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-ChromeBookmarksToOneDrive @BackupChromeBookmarksToOneDriveParams # $BackupOutlookSignaturesToOneDrive = @{ # SignaturePath = "$env:USERPROFILE\AppData\Roaming\Microsoft\Signatures" # BackupFolderName = "OutlookSignatures" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-OutlookSignaturesToOneDrive @BackupOutlookSignaturesToOneDrive # $BackupDownloadsToOneDriveParams = @{ # DownloadsPath = "$env:USERPROFILE\Downloads" # BackupFolderName = "DownloadsBackup" # Exclude = ".git" # RetryCount = 2 # WaitTime = 5 # RequiredSpaceGB = 10 # } # Backup-DownloadsToOneDrive @BackupDownloadsToOneDriveParams } catch { Write-EnhancedLog -Message "An error occurred in Prepare-AADMigration: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Prepare-AADMigration function" -Level "Notice" } } # # Define parameters # $PrepareAADMigrationParams = @{ # MigrationPath = "C:\ProgramData\AADMigration" # PSScriptRoot = "C:\SourcePath" # ConfigBaseDirectory = "C:\ConfigDirectory\Scripts" # ConfigFileName = "MigrationConfig.psd1" # TenantID = "YourTenantID" # OneDriveKFM = $true # InstallOneDrive = $true # } # # Example usage with splatting # Prepare-AADMigration @PrepareAADMigrationParams #EndRegion '.\Public\Prepare-AADMigration.ps1' 414 #Region '.\Public\Prepare-DeviceMigration-Archive.ps1' -1 # function Prepare-DeviceMigration { # [CmdletBinding()] # param () # Begin { # Write-EnhancedLog -Message "Starting Prepare-DeviceMigration function" -Level "INFO" # } # Process { # try { # Start-Transcript -Path C:\ProgramData\AADMigration\Logs\AD2AADJ-Prep.txt -Append -Force # $MigrationConfig = Import-LocalizedData -BaseDirectory "." -FileName "MigrationConfig.psd1" # $MigrationPath = $MigrationConfig.MigrationPath # $TenantID = $MigrationConfig.TenantID # $OneDriveKFM = $MigrationConfig.UseOneDriveKFM # $InstallOneDrive = $MigrationConfig.InstallOneDrive # $StartBoundary = $MigrationConfig.StartBoundary # function Add-MigrationDirectory { # # Expand AAD Migration zip file to ProgramData # Expand-Archive -Path "$PSScriptRoot\AADMigration.zip" -DestinationPath C:\ProgramData -Force # Copy-Item -Path "$PSScriptRoot\MigrationConfig.psd1" -Destination "$MigrationPath\Module" # } # function Set-RegistryValue { # [CmdletBinding()] # param ( # [string]$RegKeyPath, # [string]$RegValName, # [string]$RegValType, # [string]$RegValData # ) # # Test to see if the registry key exists, if it does not, create it # $RegKeyPathExists = Test-Path -Path $RegKeyPath # if (-not $RegKeyPathExists) { # New-Item -Path $RegKeyPath -Force | Out-Null # } # # Check to see if the value exists # try { # $CurrentValue = Get-ItemPropertyValue -Path $RegKeyPath -Name $RegValName # } catch { # # If the value does not exist, catch the error and create the key # Set-ItemProperty -Path $RegKeyPath -Name $RegValName -Type $RegValType -Value $RegValData -Force # } # if ($CurrentValue -ne $RegValData) { # # If the value exists but the data is wrong, update the value # Set-ItemProperty -Path $RegKeyPath -Name $RegValName -Type $RegValType -Value $RegValData -Force # } # } # function Set-ODKFMSettings { # # Set registry values for enabling KFM to set tenant # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "AllowTenantList" -RegValType "STRING" -RegValData $TenantID # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "SilentAccountConfig" -RegValType "DWORD" -RegValData "1" # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "KFMOptInWithWizard" -RegValType "STRING" -RegValData $TenantID # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "KFMSilentOptIn" -RegValType "STRING" -RegValData $TenantID # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "KFMSilentOptInDesktop" -RegValType "DWORD" -RegValData "1" # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "KFMSilentOptInDocuments" -RegValType "DWORD" -RegValData "1" # Set-RegistryValue -RegKeyPath "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" -RegValName "KFMSilentOptInPictures" -RegValType "DWORD" -RegValData "1" # # Create EventLog Source # New-EventLog -LogName 'Application' -Source 'AAD_Migration_Script' -ErrorAction Stop # # Create scheduled task to check OneDrive sync status # $TaskPath = "AAD Migration" # $TaskName = "AADM Get OneDrive Sync Status" # $ScriptPath = "C:\ProgramData\AADMigration\Scripts" # $ScriptName = "Check-OneDriveSyncStatus.ps1" # $arguments = "-NoProfile -WindowStyle Hidden -ExecutionPolicy Bypass -file $ScriptPath\$ScriptName" # $action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument $arguments # $trigger = New-ScheduledTaskTrigger -AtLogOn # $trigger.Delay = 'PT1M' # $principal = New-ScheduledTaskPrincipal -GroupId "BUILTIN\Users" # $Task = Register-ScheduledTask -Principal $principal -Action $action -Trigger $trigger -TaskName $TaskName -Description "Get current OneDrive Sync Status and write to event log" -TaskPath $TaskPath # $Task.Triggers.Repetition.Duration = "P1D" # $Task.Triggers.Repetition.Interval = "PT30M" # $Task | Set-ScheduledTask # } # function Install-OneDrive { # # Check for OneDrive machine-wide installer, check version number if it exists # $ODSetupVersion = (Get-ChildItem -Path "$PSScriptRoot\AADMigration\Files\OneDriveSetup.exe").VersionInfo.FileVersion # if (-not $ODSetupVersion) { # Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/?linkid=844652" -OutFile "$PSScriptRoot\Files\OneDriveSetup.exe" -Wait # $ODSetupVersion = (Get-ChildItem -Path "$PSScriptRoot\Files\OneDriveSetup.exe").VersionInfo.FileVersion # } # $ODRegKey = "HKLM:\SOFTWARE\Microsoft\OneDrive" # $InstalledVer = Get-ItemPropertyValue -Path $ODRegKey -Name Version # if (-not $ODRegKey -or ([System.Version]$InstalledVer -lt [System.Version]$ODSetupVersion)) { # # Install OneDrive setup # $Installer = "$PSScriptRoot\Files\OneDriveSetup.exe" # $Arguments = "/allusers" # Start-Process -FilePath $Installer -ArgumentList $Arguments # } elseif ($OneDriveKFM) { # # If OneDrive is already installed, stop the process and restart to kick off KFM sync if required # Get-Process -Name OneDrive | Stop-Process -Confirm:$false -Force # Start-Sleep -Seconds 5 # $action = New-ScheduledTaskAction -Execute "C:\Program Files\Microsoft Onedrive\OneDrive.exe" # $trigger = New-ScheduledTaskTrigger -AtLogOn # $principal = New-ScheduledTaskPrincipal -UserId (Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty UserName) # $task = New-ScheduledTask -Action $action -Trigger $trigger -Principal $principal # Register-ScheduledTask -TaskName OneDriveRemediation -InputObject $task # Start-ScheduledTask -TaskName OneDriveRemediation # Start-Sleep -Seconds 5 # Unregister-ScheduledTask -TaskName OneDriveRemediation -Confirm:$false # } # } # function New-MigrationTask { # # Create Scheduled task to launch interactive migration task # $TaskPath = "AAD Migration" # $TaskName = "AADM Launch PSADT for Interactive Migration" # $ScriptPath = "C:\ProgramData\AADMigration\Scripts" # $ScriptName = "Launch-DeployApplication_SchTask.ps1" # $arguments = "-executionpolicy Bypass -file $ScriptPath\$ScriptName" # $action = New-ScheduledTaskAction -Execute 'PowerShell.exe' -Argument $arguments # $trigger = New-ScheduledTaskTrigger -AtLogOn # $trigger.Delay = 'PT1M' # $trigger.StartBoundary = $StartBoundary # $principal = New-ScheduledTaskPrincipal -UserId "SYSTEM" -RunLevel Highest # $Task = Register-ScheduledTask -Principal $principal -Action $action -Trigger $trigger -TaskName $TaskName -Description "AADM Launch PSADT for Interactive Migration" -TaskPath $TaskPath # } # Add-MigrationDirectory # New-MigrationTask # if ($OneDriveKFM) { # Set-ODKFMSettings # } # if ($InstallOneDrive) { # Install-OneDrive # } # Stop-Transcript # } catch { # Write-EnhancedLog -Message "An error occurred in Prepare-DeviceMigration: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Prepare-DeviceMigration function" -Level "INFO" # } # } # # Example usage # # Prepare-DeviceMigration #EndRegion '.\Public\Prepare-DeviceMigration-Archive.ps1' 159 #Region '.\Public\Prepare-SolutionDirectory.ps1' -1 function Prepare-SolutionDirectory { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ToolkitFolder, [Parameter(Mandatory = $true)] [string]$FilesFolder ) Begin { Write-EnhancedLog -Message "Starting Prepare-SolutionDirectory function" -Level "INFO" Log-Params -Params @{ ToolkitFolder = $ToolkitFolder FilesFolder = $FilesFolder } } Process { try { # Create necessary directories New-Item -ItemType Directory -Path $ToolkitFolder -Force New-Item -ItemType Directory -Path $FilesFolder -Force } catch { Write-EnhancedLog -Message "An error occurred while processing the Prepare-SolutionDirectory function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Prepare-SolutionDirectory function" -Level "INFO" } } # Example usage # Prepare-SolutionDirectory -ToolkitFolder "C:\path\to\toolkit" -FilesFolder "C:\path\to\files" #EndRegion '.\Public\Prepare-SolutionDirectory.ps1' 37 #Region '.\Public\Remove-ADJoin.ps1' -1 function Remove-ADJoin { [CmdletBinding()] param ( [Parameter(Mandatory = $false)] [string]$DomainLeaveUser, [Parameter(Mandatory = $false)] [string]$DomainLeavePassword, [Parameter(Mandatory = $true)] [string]$TempUser, [Parameter(Mandatory = $true)] [string]$TempUserPassword, [Parameter(Mandatory = $true)] [string]$ComputerName = "localhost", [Parameter(Mandatory = $true)] [string]$TaskName = "AADM Launch PSADT for Interactive Migration" ) Begin { Write-EnhancedLog -Message "Starting Remove-ADJoin function" -Level "INFO" Log-Params -Params @{ DomainLeaveUser = $DomainLeaveUser DomainLeavePassword = $DomainLeavePassword TempUser = $TempUser TempUserPassword = $TempUserPassword ComputerName = $ComputerName TaskName = $TaskName } } Process { try { Write-EnhancedLog -Message "Checking if device is domain joined" -Level "INFO" $ComputerSystem = Get-WmiObject -Class Win32_ComputerSystem $Domain = $ComputerSystem.Domain $PartOfDomain = $ComputerSystem.PartOfDomain if ($PartOfDomain) { Write-EnhancedLog -Message "Computer is domain member, removing domain membership" -Level "INFO" if (Test-Connection -ComputerName $Domain -Count 1 -Quiet) { Write-EnhancedLog -Message "Connected to domain, attempting to leave domain." -Level "INFO" if ($DomainLeaveUser) { $SecurePassword = ConvertTo-SecureString -String $DomainLeavePassword -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($DomainLeaveUser, $SecurePassword) try { Remove-Computer -ComputerName $ComputerName -Credential $Credentials -Verbose -Force -ErrorAction Stop Disable-ScheduledTask -TaskName $TaskName Stop-Transcript Restart-Computer } catch { Write-EnhancedLog -Message "Leaving domain with domain credentials failed. Will leave domain with local account." -Level "ERROR" } } $SecurePassword = ConvertTo-SecureString -String $TempUserPassword -AsPlainText -Force $Credentials = New-Object System.Management.Automation.PSCredential($TempUser, $SecurePassword) $ConnectedAdapters = Get-NetAdapter | Where-Object { $_.MediaConnectionState -eq "Connected" } foreach ($Adapter in $ConnectedAdapters) { Write-EnhancedLog -Message "Disabling network adapter $($Adapter.Name)" -Level "INFO" Disable-NetAdapter -Name $Adapter.Name -Confirm:$false } Start-Sleep -Seconds 5 Remove-Computer -ComputerName $ComputerName -Credential $Credentials -Verbose -Force foreach ($Adapter in $ConnectedAdapters) { Write-EnhancedLog -Message "Enabling network adapter $($Adapter.Name)" -Level "INFO" Enable-NetAdapter -Name $Adapter.Name -Confirm:$false } Start-Sleep -Seconds 15 Write-EnhancedLog -Message "Computer removed from domain. Network adapters re-enabled. Restarting." -Level "INFO" Disable-ScheduledTask -TaskName $TaskName Stop-Transcript Restart-Computer } else { Write-Verbose "Removing computer from domain and forcing restart" Write-EnhancedLog -Message "Stopping transcript and calling Remove-Computer with -Restart switch." -Level "INFO" Stop-Transcript Remove-Computer -ComputerName $ComputerName -Credential $Credentials -Verbose -Force -ErrorAction Stop Disable-ScheduledTask -TaskName $TaskName Stop-Transcript Restart-Computer } } else { Write-EnhancedLog -Message "Computer is not a domain member, restarting computer." -Level "INFO" Disable-ScheduledTask -TaskName $TaskName Stop-Transcript Restart-Computer } } catch { Write-EnhancedLog -Message "An error occurred while removing AD join: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Remove-ADJoin function" -Level "INFO" } } # $RemoveADJoinParams = @{ # DomainLeaveUser = "YourDomainUser" # DomainLeavePassword = "YourDomainPassword" # TempUser = "YourTempUser" # TempUserPassword = "YourTempUserPassword" # ComputerName = "localhost" # TaskName = "AADM Launch PSADT for Interactive Migration" # } # Remove-ADJoin @RemoveADJoinParams #EndRegion '.\Public\Remove-ADJoin.ps1' 121 #Region '.\Public\Remove-CompanyPortal.ps1' -1 function Remove-CompanyPortal { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$AppxPackageName ) Begin { Write-EnhancedLog -Message "Starting Remove-CompanyPortal function" -Level "INFO" Log-Params -Params @{ AppxPackageName = $AppxPackageName } } Process { try { Write-EnhancedLog -Message "Removing AppxPackage: $AppxPackageName" -Level "INFO" Get-AppxPackage -AllUsers -Name $AppxPackageName | Remove-AppxPackage -Confirm:$false } catch { Write-EnhancedLog -Message "An error occurred while removing AppxPackage: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Remove-CompanyPortal function" -Level "INFO" } } # $RemoveCompanyPortalParams = @{ # AppxPackageName = "Microsoft.CompanyPortal" # } # Remove-CompanyPortal @RemoveCompanyPortalParams #EndRegion '.\Public\Remove-CompanyPortal.ps1' 33 #Region '.\Public\Remove-Hybrid.ps1' -1 function Remove-Hybrid { [CmdletBinding()] param () Begin { Write-EnhancedLog -Message "Starting Remove-Hybrid function" -Level "INFO" } Process { try { Write-EnhancedLog -Message "Checking if device is Azure AD joined" -Level "INFO" $Dsregcmd = New-Object PSObject Dsregcmd /status | Where-Object { $_ -match ' : ' } | ForEach-Object { $Item = $_.Trim() -split '\s:\s' $Dsregcmd | Add-Member -MemberType NoteProperty -Name $($Item[0] -replace '[:\s]', '') -Value $Item[1] -ErrorAction SilentlyContinue } $AzureADJoined = $Dsregcmd.AzureAdJoined if ($AzureADJoined -eq 'Yes') { Write-EnhancedLog -Message "Device is Azure AD joined. Removing hybrid join." -Level "INFO" & "C:\Windows\System32\dsregcmd.exe" /leave } } catch { Write-EnhancedLog -Message "An error occurred while removing hybrid join: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Remove-Hybrid function" -Level "INFO" } } # Example usage # Remove-Hybrid #EndRegion '.\Public\Remove-Hybrid.ps1' 37 #Region '.\Public\Remove-IntuneMgmt.ps1' -1 function Remove-IntuneMgmt { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OMADMPath, [Parameter(Mandatory = $true)] [string]$EnrollmentBasePath, [Parameter(Mandatory = $true)] [string]$TrackedBasePath, [Parameter(Mandatory = $true)] [string]$PolicyManagerBasePath, [Parameter(Mandatory = $true)] [string]$ProvisioningBasePath, [Parameter(Mandatory = $true)] [string]$CertCurrentUserPath, [Parameter(Mandatory = $true)] [string]$CertLocalMachinePath, [Parameter(Mandatory = $true)] [string]$TaskPathBase, [Parameter(Mandatory = $true)] [string]$MSDMProviderID, [Parameter(Mandatory = $true)] [string[]]$RegistryPathsToRemove, [Parameter(Mandatory = $true)] [string]$UserCertIssuer, [Parameter(Mandatory = $true)] [string[]]$DeviceCertIssuers ) Begin { Write-EnhancedLog -Message "Starting Remove-IntuneMgmt function" -Level "INFO" Log-Params -Params @{ OMADMPath = $OMADMPath EnrollmentBasePath = $EnrollmentBasePath TrackedBasePath = $TrackedBasePath PolicyManagerBasePath = $PolicyManagerBasePath ProvisioningBasePath = $ProvisioningBasePath CertCurrentUserPath = $CertCurrentUserPath CertLocalMachinePath = $CertLocalMachinePath TaskPathBase = $TaskPathBase MSDMProviderID = $MSDMProviderID RegistryPathsToRemove = $RegistryPathsToRemove UserCertIssuer = $UserCertIssuer DeviceCertIssuers = $DeviceCertIssuers } } Process { try { Write-EnhancedLog -Message "Checking Intune enrollment status" -Level "INFO" $Account = (Get-ItemProperty -Path $OMADMPath -ErrorAction SilentlyContinue).PSChildName $Enrolled = $true $EnrollmentPath = "$EnrollmentBasePath\$Account" $EnrollmentUPN = (Get-ItemProperty -Path $EnrollmentPath -ErrorAction SilentlyContinue).UPN $ProviderID = (Get-ItemProperty -Path $EnrollmentPath -ErrorAction SilentlyContinue).ProviderID if (-not $EnrollmentUPN -or $ProviderID -ne $MSDMProviderID) { $Enrolled = $false } if ($Enrolled) { Write-EnhancedLog -Message "Device is enrolled in Intune. Proceeding with unenrollment." -Level "INFO" # Delete Task Schedule tasks Get-ScheduledTask -TaskPath "$TaskPathBase\$Account\*" | Unregister-ScheduledTask -Confirm:$false -ErrorAction SilentlyContinue # Delete registry keys foreach ($RegistryPath in $RegistryPathsToRemove) { Remove-Item -Path "$RegistryPath\$Account" -Recurse -Force -ErrorAction SilentlyContinue } # Delete enrollment certificates $UserCerts = Get-ChildItem -Path $CertCurrentUserPath -Recurse $IntuneCerts = $UserCerts | Where-Object { $_.Issuer -eq $UserCertIssuer } foreach ($Cert in $IntuneCerts) { $Cert | Remove-Item -Force } $DeviceCerts = Get-ChildItem -Path $CertLocalMachinePath -Recurse $IntuneCerts = $DeviceCerts | Where-Object { $DeviceCertIssuers -contains $_.Issuer } foreach ($Cert in $IntuneCerts) { $Cert | Remove-Item -Force -ErrorAction SilentlyContinue } } } catch { Write-EnhancedLog -Message "An error occurred while removing Intune management: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Remove-IntuneMgmt function" -Level "INFO" } } # $RemoveIntuneMgmtParams = @{ # OMADMPath = "HKLM:\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts\*" # EnrollmentBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments" # TrackedBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked" # PolicyManagerBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager" # ProvisioningBasePath = "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning" # CertCurrentUserPath = "cert:\CurrentUser" # CertLocalMachinePath = "cert:\LocalMachine" # TaskPathBase = "\Microsoft\Windows\EnterpriseMgmt" # MSDMProviderID = "MS DM Server" # RegistryPathsToRemove = @( # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Enrollments\Status", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\EnterpriseResourceManager\Tracked", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\AdmxInstalled", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PolicyManager\Providers", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Accounts", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Logger", # "Registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Provisioning\OMADM\Sessions" # ) # UserCertIssuer = "CN=SC_Online_Issuing" # DeviceCertIssuers = @("CN=Microsoft Intune Root Certification Authority", "CN=Microsoft Intune MDM Device CA") # } # Remove-IntuneMgmt @RemoveIntuneMgmtParams #EndRegion '.\Public\Remove-IntuneMgmt.ps1' 133 #Region '.\Public\Remove-LocalUserAccount.ps1' -1 function Remove-LocalUserAccount { <# .SYNOPSIS Removes a local user account. .DESCRIPTION The Remove-LocalUserAccount function removes a specified local user account. .PARAMETER UserName The name of the local user account to be removed. .EXAMPLE $params = @{ UserName = "TempUser" } Remove-LocalUserAccount @params Removes the local user account named TempUser. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$UserName ) Begin { Write-EnhancedLog -Message "Starting Remove-LocalUserAccount function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Removing local user account: $UserName" -Level "INFO" Remove-LocalUser -Name $UserName -ErrorAction Stop Write-EnhancedLog -Message "Successfully removed local user account: $UserName" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred in Remove-LocalUserAccount function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Remove-LocalUserAccount function" -Level "Notice" } } # # Example usage # $params = @{ # UserName = "TempUser" # } # Remove-LocalUserAccount @params #EndRegion '.\Public\Remove-LocalUserAccount.ps1' 54 #Region '.\Public\Remove-MigrationFiles.ps1' -1 function Remove-MigrationFiles { <# .SYNOPSIS Removes specified directories used during the migration process. .DESCRIPTION The Remove-MigrationFiles function deletes specified directories used during the migration process, leaving the log folder intact. .PARAMETER Directories An array of directories to be removed. .EXAMPLE $params = @{ Directories = @( "C:\ProgramData\AADMigration\Files", "C:\ProgramData\AADMigration\Scripts", "C:\ProgramData\AADMigration\Toolkit" ) } Remove-MigrationFiles @params Removes the specified directories. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string[]]$Directories ) Begin { Write-EnhancedLog -Message "Starting Remove-MigrationFiles function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { foreach ($directory in $Directories) { if (Test-Path -Path $directory) { Write-EnhancedLog -Message "Removing directory: $directory" -Level "INFO" Remove-Item -Path $directory -Recurse -Force -ErrorAction Stop Write-EnhancedLog -Message "Successfully removed directory: $directory" -Level "INFO" } else { Write-EnhancedLog -Message "Directory not found: $directory" -Level "WARNING" } } } catch { Write-EnhancedLog -Message "An error occurred in Remove-MigrationFiles function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Remove-MigrationFiles function" -Level "Notice" } } # # Example usage # $params = @{ # Directories = @( # "C:\ProgramData\AADMigration\Files", # "C:\ProgramData\AADMigration\Scripts", # "C:\ProgramData\AADMigration\Toolkit" # ) # } # Remove-MigrationFiles @params #EndRegion '.\Public\Remove-MigrationFiles.ps1' 70 #Region '.\Public\Remove-ScheduledTasks.ps1' -1 function Remove-ScheduledTasks { <# .SYNOPSIS Removes scheduled tasks created for the migration. .DESCRIPTION The Remove-ScheduledTasks function removes all scheduled tasks under a specified task path. .PARAMETER TaskPath The path of the task in Task Scheduler. .EXAMPLE $params = @{ TaskPath = "AAD Migration" } Remove-ScheduledTasks @params Removes all scheduled tasks under the "AAD Migration" task path. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TaskPath ) Begin { Write-EnhancedLog -Message "Starting Remove-ScheduledTasks function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Removing scheduled tasks under task path: $TaskPath" -Level "INFO" $tasks = Get-ScheduledTask -TaskPath "\$TaskPath\" foreach ($task in $tasks) { Unregister-ScheduledTask -TaskName $task.TaskName -Confirm:$false -ErrorAction Stop Write-EnhancedLog -Message "Successfully removed scheduled task: $($task.TaskName)" -Level "INFO" } $scheduler = New-Object -ComObject "Schedule.Service" $scheduler.Connect() $rootFolder = $scheduler.GetFolder("\") $rootFolder.DeleteFolder($TaskPath, $null) Write-EnhancedLog -Message "Successfully removed task folder: $TaskPath" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred in Remove-ScheduledTasks function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Remove-ScheduledTasks function" -Level "Notice" } } # # Example usage # $params = @{ # TaskPath = "AAD Migration" # } # Remove-ScheduledTasks @params #EndRegion '.\Public\Remove-ScheduledTasks.ps1' 62 #Region '.\Public\Replace-BannerImage.ps1' -1 function Replace-BannerImage { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Source, [Parameter(Mandatory = $true)] [string]$Destination ) Begin { Write-EnhancedLog -Message "Starting Replace-BannerImage function" -Level "INFO" Log-Params -Params @{ Source = $Source Destination = $Destination } } Process { try { # Replace the banner image in the toolkit folder Copy-Item -Path $Source -Destination $Destination -Force } catch { Write-EnhancedLog -Message "An error occurred while processing the Replace-BannerImage function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Replace-BannerImage function" -Level "INFO" } } # Example usage # Replace-BannerImage -Source 'C:\YourPath\YourBannerImage.png' -Destination 'C:\YourPath\Toolkit\AppDeployToolkit\AppDeployToolkitBanner.png' #EndRegion '.\Public\Replace-BannerImage.ps1' 36 #Region '.\Public\Replace-DeployApplicationPS1.ps1' -1 function Replace-DeployApplicationPS1 { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Source, [Parameter(Mandatory = $true)] [string]$Destination ) Begin { Write-EnhancedLog -Message "Starting Replace-DeployApplicationPS1 function" -Level "INFO" Log-Params -Params @{ Source = $Source Destination = $Destination } } Process { try { # Replace Deploy-Application.ps1 in the toolkit folder Copy-Item -Path $Source -Destination $Destination -Force } catch { Write-EnhancedLog -Message "An error occurred while processing the Replace-DeployApplicationPS1 function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Replace-DeployApplicationPS1 function" -Level "INFO" } } # Example usage # Replace-DeployApplicationPS1 -Source 'C:\YourPath\Scripts\Deploy-Application.ps1' -Destination 'C:\YourPath\Toolkit\Deploy-Application.ps1' #EndRegion '.\Public\Replace-DeployApplicationPS1.ps1' 36 #Region '.\Public\Set-Autologin.ps1' -1 function Set-Autologin { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TempUser, [Parameter(Mandatory = $true)] [string]$TempUserPassword, [Parameter(Mandatory = $true)] [string]$RegPath , [Parameter(Mandatory = $true)] [string]$AutoAdminLogonName , [Parameter(Mandatory = $true)] [string]$AutoAdminLogonValue , [Parameter(Mandatory = $true)] [string]$DefaultUsernameName, [Parameter(Mandatory = $true)] [string]$DefaultPasswordName , [Parameter(Mandatory = $false)] [string]$DefaultDomainName ) Begin { Write-EnhancedLog -Message "Starting Set-Autologin function" -Level "INFO" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Setting user account $TempUser to Auto Login" -Level "INFO" $autoLoginParams = @{ Path = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" Name = "AutoAdminLogon" Value = "1" } if (Test-Path -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\AutoAdminLogon") { Remove-ItemProperty @autoLoginParams } # Set AutoAdminLogon Set-ItemProperty -Path $RegPath -Name $AutoAdminLogonName -Value $AutoAdminLogonValue -Type String -Verbose # Set DefaultUserName Set-ItemProperty -Path $RegPath -Name $DefaultUsernameName -Value $TempUser -Type String -Verbose # Set DefaultPassword Set-ItemProperty -Path $RegPath -Name $DefaultPasswordName -Value $TempUserPassword -Type String -Verbose # Set DefaultDomainName if provided if ($PSBoundParameters.ContainsKey('DefaultDomainName')) { Set-ItemProperty -Path $RegPath -Name 'DefaultDomainName' -Value $DefaultDomainName -Type String -Verbose } # Create UserList key if it doesn't exist and add the user $userListPath = "$RegPath\SpecialAccounts\UserList" if (-not (Test-Path -Path $userListPath)) { Write-EnhancedLog -Message "Creating UserList registry path: $userListPath" -Level "INFO" New-Item -Path $userListPath -Force } New-ItemProperty -Path $userListPath -Name $TempUser -Value 0 -PropertyType DWord -Force -Verbose Write-EnhancedLog -Message "Auto-login set for user '$TempUser'." -Level 'INFO' } catch { Write-EnhancedLog -Message "An error occurred while setting autologin: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Set-Autologin function" -Level "INFO" } } # # Example usage with splatting # $SetAutologinParams = @{ # TempUser = 'YourTempUser' # TempUserPassword = 'YourTempUserPassword' # RegPath = 'HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon' # AutoAdminLogonName = 'AutoAdminLogon' # AutoAdminLogonValue = '1' # DefaultUsernameName = 'DefaultUserName' # DefaultPasswordName = 'DefaultPassword' # DefaultDomainName = $env:COMPUTERNAME # } # Set-Autologin @SetAutologinParams #EndRegion '.\Public\Set-Autologin.ps1' 95 #Region '.\Public\Set-ODKFMRegistrySettings.ps1' -1 function Set-ODKFMRegistrySettings { <# .SYNOPSIS Sets OneDrive Known Folder Move (KFM) registry settings. .DESCRIPTION The Set-ODKFMRegistrySettings function sets specified registry values for OneDrive Known Folder Move (KFM) based on provided tenant ID, registry key path, and an array of registry settings. .PARAMETER TenantID The tenant ID for OneDrive. .PARAMETER RegKeyPath The path to the registry key. .PARAMETER RegistrySettings An array of registry settings to be applied. Each setting should include RegValName, RegValType, and RegValData. .EXAMPLE $settings = @( @{ RegValName = "KFMValue1" RegValType = "String" RegValData = "Value1" }, @{ RegValName = "KFMValue2" RegValType = "DWORD" RegValData = "1" } ) $params = @{ TenantID = "your-tenant-id" RegKeyPath = "HKLM:\Software\Policies\Microsoft\OneDrive" RegistrySettings = $settings } Set-ODKFMRegistrySettings @params Sets the specified OneDrive KFM registry values. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$TenantID, [Parameter(Mandatory = $true)] [string]$RegKeyPath, [Parameter(Mandatory = $true)] [array]$RegistrySettings ) Begin { Write-EnhancedLog -Message "Starting Set-ODKFMRegistrySettings function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { foreach ($setting in $RegistrySettings) { # Define the parameters to be splatted $splatParams = @{ RegKeyPath = $RegKeyPath RegValName = $setting.RegValName RegValType = $setting.RegValType RegValData = $setting.RegValData } # Call the function with splatted parameters Set-RegistryValue @splatParams } } catch { Write-EnhancedLog -Message "An error occurred while setting OneDrive KFM registry values: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Set-ODKFMRegistrySettings function" -Level "Notice" } } # # Example usage # $settings = @( # @{ # RegValueName = "KFMValue1" # RegValType = "String" # RegValData = "Value1" # }, # @{ # RegValueName = "KFMValue2" # RegValType = "DWORD" # RegValData = "1" # } # ) # $params = @{ # TenantID = "your-tenant-id" # RegKeyPath = "HKLM:\Software\Policies\Microsoft\OneDrive" # RegistrySettings = $settings # } # Set-ODKFMRegistrySettings @params # $TenantID = "YourTenantID" # $RegistrySettings = @( # @{ # RegValueName = "AllowTenantList" # RegValType = "STRING" # RegValData = $TenantID # }, # @{ # RegValueName = "SilentAccountConfig" # RegValType = "DWORD" # RegValData = "1" # }, # @{ # RegValueName = "KFMOptInWithWizard" # RegValType = "STRING" # RegValData = $TenantID # }, # @{ # RegValueName = "KFMSilentOptIn" # RegValType = "STRING" # RegValData = $TenantID # }, # @{ # RegValueName = "KFMSilentOptInDesktop" # RegValType = "DWORD" # RegValData = "1" # }, # @{ # RegValueName = "KFMSilentOptInDocuments" # RegValType = "DWORD" # RegValData = "1" # }, # @{ # RegValueName = "KFMSilentOptInPictures" # RegValType = "DWORD" # RegValData = "1" # } # ) # $SetODKFMRegistrySettingsParams = @{ # TenantID = $TenantID # RegKeyPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" # RegistrySettings = $RegistrySettings # } # Set-ODKFMRegistrySettings @SetODKFMRegistrySettingsParams #optionally you can create an event source here using Create-EventLogSource.ps1 #EndRegion '.\Public\Set-ODKFMRegistrySettings.ps1' 155 #Region '.\Public\Set-RegistryValue.ps1' -1 # function Set-RegistryValue { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$RegKeyPath, # [Parameter(Mandatory = $true)] # [string]$RegValueName, # [Parameter(Mandatory = $true)] # [string]$RegValType, # [Parameter(Mandatory = $true)] # [string]$RegValData # ) # Begin { # Write-EnhancedLog -Message "Starting Set-RegistryValue function" -Level "INFO" # Log-Params -Params @{ # RegKeyPath = $RegKeyPath # RegValueName = $RegValueName # RegValType = $RegValType # RegValData = $RegValData # } # } # Process { # try { # # Check if registry key exists, create if it does not # if (-not (Test-Path -Path $RegKeyPath)) { # Write-EnhancedLog -Message "Registry key path does not exist, creating: $RegKeyPath" -Level "INFO" # New-Item -Path $RegKeyPath -Force | Out-Null # } else { # Write-EnhancedLog -Message "Registry key path exists: $RegKeyPath" -Level "INFO" # } # # Check if registry value exists and its current value # $currentValue = $null # try { # $currentValue = Get-ItemPropertyValue -Path $RegKeyPath -Name $RegValueName # } catch { # Write-EnhancedLog -Message "Registry value not found, setting new value: $RegValueName" -Level "INFO" # New-ItemProperty -Path $RegKeyPath -Name $RegValueName -PropertyType $RegValType -Value $RegValData -Force # } # # If value exists but data is incorrect, update the value # if ($currentValue -ne $RegValData) { # Write-EnhancedLog -Message "Updating registry value: $RegValueName with new data: $RegValData" -Level "INFO" # Set-ItemProperty -Path $RegKeyPath -Name $RegValueName -Value $RegValData -Force # } # } catch { # Write-EnhancedLog -Message "An error occurred while processing the Set-RegistryValue function: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Set-RegistryValue function" -Level "INFO" # } # } # # Example usage # # Set-RegistryValue -RegKeyPath "HKCU:\Software\MyApp" -RegValueName "MyValue" -RegValType "String" -RegValData "MyData" function Set-RegistryValue { <# .SYNOPSIS Sets a registry value. .DESCRIPTION The Set-RegistryValue function sets a registry value at a specified registry path. It creates the registry key if it does not exist and updates the value if it differs from the provided data. .PARAMETER RegKeyPath The path to the registry key. .PARAMETER RegValName The name of the registry value. .PARAMETER RegValType The type of the registry value (e.g., String, DWORD). .PARAMETER RegValData The data to be set for the registry value. .EXAMPLE $params = @{ RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" RegValName = "AutoAdminLogon" RegValType = "DWORD" RegValData = "0" } Set-RegistryValue @params Sets the AutoAdminLogon registry value to 0. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$RegKeyPath, [Parameter(Mandatory = $true)] [string]$RegValName, [Parameter(Mandatory = $true)] [string]$RegValType, [Parameter(Mandatory = $true)] [string]$RegValData ) Begin { Write-EnhancedLog -Message "Starting Set-RegistryValue function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Check if running as administrator # if (-not ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) { # Write-EnhancedLog -Message "Script is not running as administrator. Attempting to elevate." -Level "INFO" # Start-Process -FilePath "powershell" -ArgumentList "-NoProfile -ExecutionPolicy Bypass -File `"$($MyInvocation.MyCommand.Path)`"" -Verb RunAs # Exit # } CheckAndElevate } Process { try { # Test to see if registry key exists, if it does not exist create it if (-not (Test-Path -Path $RegKeyPath)) { New-Item -Path $RegKeyPath -Force | Out-Null Write-EnhancedLog -Message "Created registry key: $RegKeyPath" -Level "INFO" } # Check if value exists and if it needs updating try { $CurrentValue = Get-ItemPropertyValue -Path $RegKeyPath -Name $RegValName } catch { # If value does not exist, create it Set-ItemProperty -Path $RegKeyPath -Name $RegValName -Type $RegValType -Value $RegValData -Force Write-EnhancedLog -Message "Created registry value: $RegValName with data: $RegValData" -Level "INFO" return } if ($CurrentValue -ne $RegValData) { # If value exists but data is wrong, update the value Set-ItemProperty -Path $RegKeyPath -Name $RegValName -Type $RegValType -Value $RegValData -Force Write-EnhancedLog -Message "Updated registry value: $RegValName with data: $RegValData" -Level "INFO" } else { Write-EnhancedLog -Message "Registry value: $RegValName already has the correct data: $RegValData" -Level "INFO" } } catch { Write-EnhancedLog -Message "An error occurred in Set-RegistryValue function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Set-RegistryValue function" -Level "Notice" } } # # Example call to the function # $RegistrySettings = @( # @{ # RegValName = "AllowTenantList" # RegValType = "String" # RegValData = "b5dae566-ad8f-44e1-9929-5669f1dbb343" # } # ) # foreach ($setting in $RegistrySettings) { # # Define the parameters to be splatted # $splatParams = @{ # RegKeyPath = "HKLM:\SOFTWARE\Policies\Microsoft\OneDrive" # RegValName = $setting.RegValName # RegValType = $setting.RegValType # RegValData = $setting.RegValData # } # # Call the function with splatted parameters # Set-RegistryValue @splatParams # } # # Example usage # $params = @{ # RegKeyPath = "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" # RegValName = "AutoAdminLogon" # RegValType = "DWORD" # RegValData = "0" # } # Set-RegistryValue @params #EndRegion '.\Public\Set-RegistryValue.ps1' 206 #Region '.\Public\Set-RunOnce.ps1' -1 # function Set-RunOnce { # [CmdletBinding()] # param ( # [Parameter(Mandatory = $true)] # [string]$ScriptPath, # [Parameter(Mandatory = $true)] # [string]$RunOnceKey, # [Parameter(Mandatory = $true)] # [string]$PowershellPath, # [Parameter(Mandatory = $true)] # [string]$ExecutionPolicy, # [Parameter(Mandatory = $true)] # [string]$RunOnceName # ) # Begin { # Write-EnhancedLog -Message "Starting Set-RunOnce function" -Level "INFO" # Log-Params -Params @{ # ScriptPath = $ScriptPath # RunOnceKey = $RunOnceKey # PowershellPath = $PowershellPath # ExecutionPolicy = $ExecutionPolicy # RunOnceName = $RunOnceName # } # } # Process { # try { # Write-EnhancedLog -Message "Setting RunOnce script" -Level "INFO" # $RunOnceValue = "$PowershellPath -executionPolicy $ExecutionPolicy -File $ScriptPath" # Set-ItemProperty -Path $RunOnceKey -Name $RunOnceName -Value $RunOnceValue -Verbose # } catch { # Write-EnhancedLog -Message "An error occurred while setting RunOnce script: $($_.Exception.Message)" -Level "ERROR" # Handle-Error -ErrorRecord $_ # } # } # End { # Write-EnhancedLog -Message "Exiting Set-RunOnce function" -Level "INFO" # } # } # # # Example usage with splatting # # $SetRunOnceParams = @{ # # ScriptPath = "C:\YourScriptPath.ps1" # # RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" # # PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" # # ExecutionPolicy = "Unrestricted" # # RunOnceName = "NextRun" # # } # # Set-RunOnce @SetRunOnceParams function Set-RunOnce { <# .SYNOPSIS Sets a RunOnce registry key to execute a specified script on the next system startup. .DESCRIPTION The Set-RunOnce function sets a RunOnce registry key to execute a specified PowerShell script on the next system startup. This can be useful for scheduling post-reboot tasks. .PARAMETER ScriptPath The path to the PowerShell script to be executed on the next system startup. .PARAMETER RunOnceKey The registry key path for the RunOnce entry. .PARAMETER PowershellPath The path to the PowerShell executable. .PARAMETER ExecutionPolicy The execution policy for running the PowerShell script. .PARAMETER RunOnceName The name of the RunOnce entry. .EXAMPLE $params = @{ ScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce2.ps1" RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" ExecutionPolicy = "Unrestricted" RunOnceName = "NextRun" } Set-RunOnce @params Sets the RunOnce registry key to execute the specified script on the next system startup. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ScriptPath, [Parameter(Mandatory = $true)] [string]$RunOnceKey, [Parameter(Mandatory = $true)] [string]$PowershellPath, [Parameter(Mandatory = $true)] [string]$ExecutionPolicy, [Parameter(Mandatory = $true)] [string]$RunOnceName ) Begin { Write-EnhancedLog -Message "Starting Set-RunOnce function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Log-Params -Params @{ # ScriptPath = $ScriptPath # RunOnceKey = $RunOnceKey # PowershellPath = $PowershellPath # ExecutionPolicy = $ExecutionPolicy # RunOnceName = $RunOnceName # } } Process { try { # Validate script path if (-not (Test-Path -Path $ScriptPath)) { Throw "Script file not found: $ScriptPath" } Write-EnhancedLog -Message "Setting RunOnce registry key for script: $ScriptPath" -Level "INFO" $RunOnceValue = "$PowershellPath -executionPolicy $ExecutionPolicy -File $ScriptPath" $params = @{ Path = $RunOnceKey Name = $RunOnceName Value = $RunOnceValue } Set-ItemProperty @params Write-EnhancedLog -Message "RunOnce registry key set successfully." -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred in Set-RunOnce function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Set-RunOnce function" -Level "Notice" } } # # Example usage with splatting # $params = @{ # ScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce2.ps1" # RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" # PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" # ExecutionPolicy = "Unrestricted" # RunOnceName = "NextRun" # } # Set-RunOnce @params #EndRegion '.\Public\Set-RunOnce.ps1' 169 #Region '.\Public\Show-MigrationInProgressForm.ps1' -1 function Show-MigrationInProgressForm { <# .SYNOPSIS Displays a migration in progress form. .DESCRIPTION The Show-MigrationInProgressForm function displays a form with a "Migration in Progress" message and an image to indicate that a migration process is ongoing. The form is displayed in full-screen mode and prevents user interaction with other windows. .PARAMETER ImagePath The path to the image file to be displayed on the form. .EXAMPLE $params = @{ ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" } Show-MigrationInProgressForm @params Displays the migration in progress form with the specified image. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$ImagePath ) Begin { Write-EnhancedLog -Message "Starting Show-MigrationInProgressForm function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { if (-not (Test-Path -Path $ImagePath)) { Throw "Image file not found: $ImagePath" } [void][reflection.assembly]::LoadWithPartialName("System.Drawing") [void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms") $img = [System.Drawing.Image]::FromFile($ImagePath) [System.Windows.Forms.Application]::EnableVisualStyles() $form = New-Object Windows.Forms.Form $form.Text = "Migration in Progress" $form.WindowState = 'Maximized' $form.BackColor = "#000000" $form.TopMost = $true $pictureBox = New-Object Windows.Forms.PictureBox $pictureBox.Width = $img.Size.Width $pictureBox.Height = $img.Size.Height $pictureBox.Dock = "Fill" $pictureBox.SizeMode = "StretchImage" $pictureBox.Image = $img $form.Controls.Add($pictureBox) $form.Add_Shown({ $form.Activate() }) $form.Show() Write-EnhancedLog -Message "Displayed migration in progress form." -Level "INFO" # Keep the form open while ($form.Visible) { [System.Windows.Forms.Application]::DoEvents() } } catch { Write-EnhancedLog -Message "An error occurred in Show-MigrationInProgressForm function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Show-MigrationInProgressForm function" -Level "Notice" } } # # Example usage # $params = @{ # ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" # } # Show-MigrationInProgressForm @params #EndRegion '.\Public\Show-MigrationInProgressForm.ps1' 81 #Region '.\Public\Start-BitsTransferWithRetry-Archive.ps1' -1 # function Start-BitsTransferWithRetry { # param ( # [string]$Source, # [string]$Destination, # [int]$MaxRetries = 3 # ) # $attempt = 0 # $success = $false # while ($attempt -lt $MaxRetries -and -not $success) { # try { # $attempt++ # if (-not (Test-Path -Path (Split-Path $Destination -Parent))) { # throw "Destination path does not exist: $(Split-Path $Destination -Parent)" # } # $bitsTransferParams = @{ # Source = $Source # Destination = $Destination # ErrorAction = "Stop" # } # Start-BitsTransfer @bitsTransferParams # $success = $true # } # catch { # Write-Log "Attempt $attempt failed: $_" -Level "ERROR" # if ($attempt -eq $MaxRetries) { # throw "Maximum retry attempts reached. Download failed." # } # Start-Sleep -Seconds 5 # } # } # } #EndRegion '.\Public\Start-BitsTransferWithRetry-Archive.ps1' 33 #Region '.\Public\Start-FileDownloadWithRetry.ps1' -1 function Start-FileDownloadWithRetry { <# .SYNOPSIS Downloads a file from a specified URL with retry logic. Falls back to using WebClient if BITS transfer fails. .DESCRIPTION This function attempts to download a file from a specified source URL to a destination path using BITS (Background Intelligent Transfer Service). If BITS fails after a specified number of retries, the function falls back to using the .NET WebClient class for the download. .PARAMETER Source The URL of the file to download. .PARAMETER Destination The file path where the downloaded file will be saved. .PARAMETER MaxRetries The maximum number of retry attempts if the download fails. Default is 3. .EXAMPLE Start-FileDownloadWithRetry -Source "https://example.com/file.zip" -Destination "C:\Temp\file.zip" .NOTES Author: Abdullah Ollivierre Date: 2024-08-15 #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$Source, [Parameter(Mandatory = $true)] [string]$Destination, [Parameter(Mandatory = $false)] [int]$MaxRetries = 3 ) Begin { Write-EnhancedLog -Message "Starting Start-FileDownloadWithRetry function" -Level "NOTICE" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters # Ensure the destination folder exists, create it if necessary $destinationFolder = Split-Path -Path $Destination -Parent if (-not (Test-Path -Path $destinationFolder)) { Write-EnhancedLog -Message "Destination folder does not exist. Creating folder: $destinationFolder" -Level "INFO" New-Item -Path $destinationFolder -ItemType Directory | Out-Null } } Process { $attempt = 0 $success = $false while ($attempt -lt $MaxRetries -and -not $success) { try { $attempt++ Write-EnhancedLog -Message "Attempt $attempt to download from $Source to $Destination" -Level "INFO" if (-not (Test-Path -Path $destinationFolder)) { throw "Destination folder does not exist: $destinationFolder" } # Attempt download using BITS $bitsTransferParams = @{ Source = $Source Destination = $Destination ErrorAction = "Stop" } Start-BitsTransfer @bitsTransferParams # Validate file existence and size after download if (Test-Path $Destination) { $fileInfo = Get-Item $Destination if ($fileInfo.Length -gt 0) { Write-EnhancedLog -Message "Download successful using BITS on attempt $attempt. File size: $($fileInfo.Length) bytes" -Level "INFO" $success = $true } else { Write-EnhancedLog -Message "Download failed: File is empty after BITS transfer." -Level "ERROR" throw "Download failed due to empty file after BITS transfer." } } else { Write-EnhancedLog -Message "Download failed: File not found after BITS transfer." -Level "ERROR" throw "Download failed due to missing file after BITS transfer." } } catch { Write-EnhancedLog -Message "BITS transfer failed on attempt $attempt $($_.Exception.Message)" -Level "ERROR" if ($attempt -eq $MaxRetries) { Write-EnhancedLog -Message "Maximum retry attempts reached. Falling back to WebClient for download." -Level "WARNING" try { $webClient = [System.Net.WebClient]::new() $webClient.DownloadFile($Source, $Destination) # Validate file existence and size after download if (Test-Path $Destination) { $fileInfo = Get-Item $Destination if ($fileInfo.Length -gt 0) { Write-EnhancedLog -Message "Download successful using WebClient. File size: $($fileInfo.Length) bytes" -Level "INFO" $success = $true } else { Write-EnhancedLog -Message "Download failed: File is empty after WebClient download." -Level "ERROR" throw "Download failed due to empty file after WebClient download." } } else { Write-EnhancedLog -Message "Download failed: File not found after WebClient download." -Level "ERROR" throw "Download failed due to missing file after WebClient download." } } catch { Write-EnhancedLog -Message "WebClient download failed: $($_.Exception.Message)" -Level "ERROR" throw "Download failed after multiple attempts using both BITS and WebClient." } } else { Start-Sleep -Seconds 5 } } } } End { Write-EnhancedLog -Message "Exiting Start-FileDownloadWithRetry function" -Level "NOTICE" } } # # Generate a timestamped folder within the TEMP directory # $timestamp = (Get-Date).ToString("yyyyMMdd_HHmmss") # $destinationFolder = [System.IO.Path]::Combine($env:TEMP, "OneDriveSetup_$timestamp") # # Set up the parameters for downloading OneDrive Setup # $downloadParams = @{ # Source = "https://go.microsoft.com/fwlink/?linkid=844652" # OneDrive Setup URL # Destination = [System.IO.Path]::Combine($destinationFolder, "OneDriveSetup.exe") # Local destination path in the timestamped folder # MaxRetries = 3 # Number of retry attempts # } # # Call the Start-FileDownloadWithRetry function with splatted parameters # Start-FileDownloadWithRetry @downloadParams #EndRegion '.\Public\Start-FileDownloadWithRetry.ps1' 147 #Region '.\Public\Start-MigrationProcess.ps1' -1 function Start-MigrationProcess { <# .SYNOPSIS Starts the migration process by configuring settings, blocking user input, displaying a progress form, and installing a provisioning package. .DESCRIPTION The Start-MigrationProcess function configures migration settings, blocks user input, displays a migration progress form, sets a RunOnce script for post-reboot tasks, installs a provisioning package, and then restarts the computer. .PARAMETER MigrationConfigPath The path to the migration configuration file. .PARAMETER ImagePath The path to the image file to be displayed on the migration progress form. .PARAMETER RunOnceScriptPath The path to the PowerShell script to be executed on the next system startup. .PARAMETER RunOnceKey The registry key path for the RunOnce entry. .PARAMETER PowershellPath The path to the PowerShell executable. .PARAMETER ExecutionPolicy The execution policy for running the PowerShell script. .PARAMETER RunOnceName The name of the RunOnce entry. .EXAMPLE $params = @{ MigrationConfigPath = "C:\ProgramData\AADMigration\scripts\MigrationConfig.psd1" ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" RunOnceScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce2.ps1" RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" ExecutionPolicy = "Unrestricted" RunOnceName = "NextRun" } Start-MigrationProcess @params Starts the migration process. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$MigrationConfigPath, [Parameter(Mandatory = $true)] [string]$ImagePath, [Parameter(Mandatory = $true)] [string]$RunOnceScriptPath, [Parameter(Mandatory = $true)] [string]$RunOnceKey, [Parameter(Mandatory = $true)] [string]$PowershellPath, [Parameter(Mandatory = $true)] [string]$ExecutionPolicy, [Parameter(Mandatory = $true)] [string]$RunOnceName ) Begin { Write-EnhancedLog -Message "Starting Start-MigrationProcess function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Start-Transcript -Path "C:\ProgramData\AADMigration\Logs\AD2AADJ-R1.txt" -NoClobber $MigrationConfig = Import-LocalizedData -BaseDirectory (Split-Path -Path $MigrationConfigPath) -FileName (Split-Path -Path $MigrationConfigPath -Leaf) $PPKGName = $MigrationConfig.ProvisioningPack $MigrationPath = $MigrationConfig.MigrationPath # Block user input $blockParams = @{ Block = $true } Block-UserInput @blockParams # Show migration in progress form $formParams = @{ ImagePath = $ImagePath } Show-MigrationInProgressForm @formParams # Set RunOnce script $runOnceParams = @{ ScriptPath = $RunOnceScriptPath RunOnceKey = $RunOnceKey PowershellPath = $PowershellPath ExecutionPolicy = $ExecutionPolicy RunOnceName = $RunOnceName } Set-RunOnce @runOnceParams # Install provisioning package $installParams = @{ PPKGName = $PPKGName MigrationPath = $MigrationPath } Install-PPKG @installParams Stop-Transcript # Unblock user input and close form Block-UserInput -Block $false Restart-Computer } catch { Write-EnhancedLog -Message "An error occurred during the migration process: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Start-MigrationProcess function" -Level "Notice" } } # # Example usage # $params = @{ # MigrationConfigPath = "C:\ProgramData\AADMigration\scripts\MigrationConfig.psd1" # ImagePath = "C:\ProgramData\AADMigration\Files\MigrationInProgress.bmp" # RunOnceScriptPath = "C:\ProgramData\AADMigration\Scripts\PostRunOnce2.ps1" # RunOnceKey = "HKLM:\Software\Microsoft\Windows\CurrentVersion\RunOnce" # PowershellPath = "C:\Windows\System32\WindowsPowerShell\v1.0\Powershell.exe" # ExecutionPolicy = "Unrestricted" # RunOnceName = "NextRun" # } # Start-MigrationProcess @params #EndRegion '.\Public\Start-MigrationProcess.ps1' 139 #Region '.\Public\Stop-ProcessesUsingOneDriveLib.ps1' -1 function Stop-ProcessesUsingOneDriveLib { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OneDriveLibPath ) Begin { Write-EnhancedLog -Message "Starting Stop-ProcessesUsingOneDriveLib function" -Level "INFO" Log-Params -Params @{ OneDriveLibPath = $OneDriveLibPath } } Process { try { # Validate before removal $initialProcesses = Validate-OneDriveLibUsage -OneDriveLibPath $OneDriveLibPath if ($initialProcesses.Count -eq 0) { Write-EnhancedLog -Message "No processes found using OneDriveLib.dll before attempting termination." -Level "INFO" } # Terminate processes foreach ($process in $initialProcesses) { Write-EnhancedLog -Message "Found process using OneDriveLib.dll: $($process.ProcessName) (ID: $($process.ProcessId)). Attempting to terminate." -Level "WARNING" Stop-Process -Id $process.ProcessId -Force -ErrorAction Stop } # Validate after removal $remainingProcesses = Validate-OneDriveLibUsage -OneDriveLibPath $OneDriveLibPath if ($remainingProcesses.Count -eq 0) { Write-EnhancedLog -Message "Successfully terminated all processes using OneDriveLib.dll." -Level "INFO" } else { Write-EnhancedLog -Message "Some processes could not be terminated. Manual intervention may be required." -Level "ERROR" foreach ($process in $remainingProcesses) { Write-EnhancedLog -Message "Process still running: $($process.ProcessName) (ID: $($process.ProcessId))." -Level "ERROR" } } } catch { Write-EnhancedLog -Message "An error occurred in Stop-ProcessesUsingOneDriveLib function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Stop-ProcessesUsingOneDriveLib function" -Level "INFO" } } # Example usage # Stop-ProcessesUsingOneDriveLib -OneDriveLibPath "C:\ProgramData\AADMigration\Files\OneDriveLib.dll" #EndRegion '.\Public\Stop-ProcessesUsingOneDriveLib.ps1' 52 #Region '.\Public\Suspend-BitLockerWithReboot.ps1' -1 function Suspend-BitLockerWithReboot { <# .SYNOPSIS Suspends BitLocker and configures the system to reboot a specified number of times. .DESCRIPTION The Suspend-BitLockerWithReboot function suspends BitLocker protection on the specified drive and configures the system to reboot a specified number of times. .PARAMETER MountPoint The drive letter of the BitLocker protected drive. .PARAMETER RebootCount The number of reboots to suspend BitLocker protection for. .EXAMPLE $params = @{ MountPoint = "C:" RebootCount = 2 } Suspend-BitLockerWithReboot @params Suspends BitLocker on drive C: for 2 reboots. #> [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$MountPoint, [Parameter(Mandatory = $true)] [int]$RebootCount ) Begin { Write-EnhancedLog -Message "Starting Suspend-BitLockerWithReboot function" -Level "Notice" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { try { Write-EnhancedLog -Message "Suspending BitLocker on drive $MountPoint for $RebootCount reboots" -Level "INFO" Suspend-BitLocker -MountPoint $MountPoint -RebootCount $RebootCount -Verbose Write-EnhancedLog -Message "Successfully suspended BitLocker on drive $MountPoint" -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while suspending BitLocker: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Suspend-BitLockerWithReboot function" -Level "Notice" } } # # Example usage # $params = @{ # MountPoint = "C:" # RebootCount = 2 # } # Suspend-BitLockerWithReboot @params #EndRegion '.\Public\Suspend-BitLockerWithReboot.ps1' 62 #Region '.\Public\Test-ProvisioningPack.ps1' -1 function Test-ProvisioningPack { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$PPKGName ) Begin { Write-EnhancedLog -Message "Starting Test-ProvisioningPack function" -Level "INFO" Log-Params -Params @{'PPKGName' = $PPKGName} } Process { try { Write-EnhancedLog -Message "Testing to see if provisioning package previously installed" -Level "INFO" $PPKGStatus = Get-ProvisioningPackage | Where-Object { $_.PackagePath -like "*$PPKGName*" } if ($PPKGStatus) { Write-EnhancedLog -Message "Provisioning package previously installed. Removing PPKG." -Level "INFO" $PPKGID = $PPKGStatus.PackageID Remove-ProvisioningPackage -PackageId $PPKGID } } catch { Write-EnhancedLog -Message "An error occurred while testing provisioning pack: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } } End { Write-EnhancedLog -Message "Exiting Test-ProvisioningPack function" -Level "INFO" } } # # Example usage with splatting # $TestProvisioningPackParams = @{ # PPKGName = "YourProvisioningPackName" # } # Test-ProvisioningPack @TestProvisioningPackParams #EndRegion '.\Public\Test-ProvisioningPack.ps1' 39 #Region '.\Public\Trigger-ScheduledTask.ps1' -1 function Trigger-ScheduledTask { [CmdletBinding()] param ( [string]$TaskPath, [string]$TaskName ) Begin { Write-EnhancedLog -Message "Starting Trigger-ScheduledTask function" -Level "NOTICE" CheckAndElevate -ElevateIfNotAdmin $true } Process { try { Write-EnhancedLog -Message "Triggering the scheduled task '$TaskName' under the '$TaskPath' folder..." -Level "INFO" $startTaskParams = @{ TaskPath = $TaskPath TaskName = $TaskName } Start-ScheduledTask @startTaskParams Write-EnhancedLog -Message "Scheduled task triggered successfully." -Level "INFO" } catch { Write-EnhancedLog -Message "An error occurred while triggering the scheduled task: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ throw $_ } } End { Write-EnhancedLog -Message "Exiting Trigger-ScheduledTask function" -Level "NOTICE" } } # # Example usage # # Define parameters using a hashtable # $taskParams = @{ # TaskPath = "\AAD Migration" # TaskName = "AADM Get OneDrive Sync Status" # } # # Call the function with splatting # Trigger-ScheduledTask @taskParams #EndRegion '.\Public\Trigger-ScheduledTask.ps1' 47 #Region '.\Public\Validate-OneDriveLibUsage.ps1' -1 function Validate-OneDriveLibUsage { [CmdletBinding()] param ( [Parameter(Mandatory = $true)] [string]$OneDriveLibPath ) $processesUsingLib = [System.Collections.Generic.List[PSCustomObject]]::new() try { # Get all processes $processes = Get-Process # Iterate over each process and check if it has loaded OneDriveLib.dll foreach ($process in $processes) { try { $modules = $process.Modules | Where-Object { $_.FileName -eq $OneDriveLibPath } if ($modules) { $processesUsingLib.Add([PSCustomObject]@{ ProcessName = $process.ProcessName ProcessId = $process.Id }) } } catch { # Handle any errors encountered while accessing process modules Write-EnhancedLog -Message "Could not access modules for process: $($process.ProcessName) (ID: $($process.Id)). Error: $($_.Exception.Message)" -Level "WARNING" } } } catch { Write-EnhancedLog -Message "An error occurred in Validate-OneDriveLibUsage function: $($_.Exception.Message)" -Level "ERROR" Handle-Error -ErrorRecord $_ } return $processesUsingLib } #EndRegion '.\Public\Validate-OneDriveLibUsage.ps1' 38 #Region '.\Public\Validate-SoftwareInstallation.ps1' -1 function Validate-SoftwareInstallation { [CmdletBinding()] param ( [string]$SoftwareName, [version]$MinVersion = [version]"0.0.0.0", [string]$RegistryPath = "", [string]$ExePath = "", [int]$MaxRetries = 3, [int]$DelayBetweenRetries = 5 ) Begin { Write-EnhancedLog -Message "Starting Validate-SoftwareInstallation function" -Level "NOTICE" Log-Params -Params $PSCmdlet.MyInvocation.BoundParameters } Process { $retryCount = 0 $validationSucceeded = $false while ($retryCount -lt $MaxRetries -and -not $validationSucceeded) { # Registry-based validation if ($RegistryPath -or $SoftwareName) { $registryPaths = @( "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", "HKLM:\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall", "HKCU:\Software\Microsoft\Windows\CurrentVersion\Uninstall" ) if ($RegistryPath) { if (Test-Path $RegistryPath) { $app = Get-ItemProperty -Path $RegistryPath -ErrorAction SilentlyContinue if ($app -and $app.DisplayName -like "*$SoftwareName*") { $installedVersion = [version]$app.DisplayVersion.Split(" ")[0] # Extract only the version number if ($installedVersion -ge $MinVersion) { $validationSucceeded = $true return @{ IsInstalled = $true Version = $installedVersion ProductCode = $app.PSChildName } } } } } else { foreach ($path in $registryPaths) { $items = Get-ChildItem -Path $path -ErrorAction SilentlyContinue foreach ($item in $items) { $app = Get-ItemProperty -Path $item.PsPath -ErrorAction SilentlyContinue if ($app.DisplayName -like "*$SoftwareName*") { $installedVersion = [version]$app.DisplayVersion.Split(" ")[0] # Extract only the version number if ($installedVersion -ge $MinVersion) { $validationSucceeded = $true return @{ IsInstalled = $true Version = $installedVersion ProductCode = $app.PSChildName } } } } } } } # File-based validation if ($ExePath) { if (Test-Path $ExePath) { $appVersionString = (Get-ItemProperty -Path $ExePath).VersionInfo.ProductVersion.Split(" ")[0] # Extract only the version number $appVersion = [version]$appVersionString if ($appVersion -ge $MinVersion) { Write-EnhancedLog -Message "Validation successful: $SoftwareName version $appVersion is installed at $ExePath." -Level "INFO" return @{ IsInstalled = $true Version = $appVersion Path = $ExePath } } else { Write-EnhancedLog -Message "Validation failed: $SoftwareName version $appVersion does not meet the minimum version requirement ($MinVersion)." -Level "ERROR" } } else { Write-EnhancedLog -Message "Validation failed: $SoftwareName executable was not found at $ExePath." -Level "ERROR" } } $retryCount++ Write-EnhancedLog -Message "Validation attempt $retryCount failed: $SoftwareName not found or version does not meet the minimum requirement ($MinVersion). Retrying in $DelayBetweenRetries seconds..." -Level "WARNING" Start-Sleep -Seconds $DelayBetweenRetries } return @{ IsInstalled = $false } } End { Write-EnhancedLog -Message "Exiting Validate-SoftwareInstallation function" -Level "NOTICE" } } # # Parameters for validating OneDrive installation # $oneDriveValidationParams = @{ # SoftwareName = "OneDrive" # MinVersion = [version]"24.146.0721.0003" # Example minimum version # RegistryPath = "HKLM:\SOFTWARE\Microsoft\OneDrive" # Example registry path for OneDrive metadata # ExePath = "C:\Program Files\Microsoft OneDrive\OneDrive.exe" # Path to the OneDrive executable # MaxRetries = 3 # DelayBetweenRetries = 5 # } # # Perform the validation # $oneDriveValidationResult = Validate-SoftwareInstallation @oneDriveValidationParams # # Check the results of the validation # if ($oneDriveValidationResult.IsInstalled) { # Write-Host "OneDrive version $($oneDriveValidationResult.Version) is installed and validated." -ForegroundColor Green # Write-Host "Executable Path: $($oneDriveValidationResult.Path)" # } else { # Write-Host "OneDrive is not installed or does not meet the minimum version requirement." -ForegroundColor Red # } #EndRegion '.\Public\Validate-SoftwareInstallation.ps1' 125 |