Migrate-WindowsUserProfile
<#
.SYNOPSIS
Migrate user state from one PC to another using USMT.
.DESCRIPTION
Migrate user state from one PC to another using USMT. Intended for domain joined computers.
By default, all user profile data except Favorites and Documents will be included.
Tool also allows for user to specify additional folders to include.
.NOTES
USMT environmental variables: https://technet.microsoft.com/en-us/library/cc749104(v=ws.10).aspx
#>
begin {
# Define the script version
$ScriptVersion = "3.3.3"
# Set ScripRoot variable to the path which the script is executed from
$ScriptRoot = if ($PSVersionTable.PSVersion.Major -lt 3) {
Split-Path -Path $MyInvocation.MyCommand.Path
} else {
$PSScriptRoot
}
# Load the options in the Config file
. "$ScriptRoot\Config.ps1"
# Set a value for the wscript comobject
$WScriptShell = New-Object -ComObject wscript.shell
function Update-Log {
param(
[string] $Message,
[string] $Color = 'White',
[switch] $NoNewLine
)
$LogTextBox.SelectionColor = $Color
$LogTextBox.AppendText("$Message")
if (-not $NoNewLine) { $LogTextBox.AppendText("`n") }
$LogTextBox.Update()
$LogTextBox.ScrollToCaret()
}
function Get-IPAddress { (Test-Connection -ComputerName (hostname) -Count 1).IPV4Address.IPAddressToString }
function Get-UserProfileLastLogin {
param(
[string]$Domain,
[string]$UserName
)
$CurrentUser = try { ([ADSI]"WinNT://$Domain/$UserName") } catch { }
if ($CurrentUser.Properties.LastLogin) {
try {
[datetime](-join $CurrentUser.Properties.LastLogin)
} catch {
-join $CurrentUser.Properties.LastLogin
}
} elseif ($CurrentUser.Properties.Name) {
} else {
'N/A'
}
}
function Get-UserProfiles {
# Get all user profiles on this PC and let the user select which ones to migrate
$RegKey = 'Registry::HKey_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\*'
# Return each profile on this computer
Get-ItemProperty -Path $RegKey | ForEach-Object {
try {
$SID = New-object System.Security.Principal.SecurityIdentifier($_.PSChildName)
try {
$User = $SID.Translate([System.Security.Principal.NTAccount]).Value
# Don't show NT Authority accounts
if ($User -notlike 'NT Authority\*') {
$Domain = $User.Split('\')[0]
$UserName = $User.Split('\')[1]
if ($Script:QueryLastLogon) {
$LastLogin = Get-UserProfileLastLogin -Domain $Domain -UserName $UserName
} else {
$LastLogin = 'N/A'
}
$ProfilePath = Get-UserProfilePath -Domain $Domain -UserName $UserName
# Create and return a custom object for each user found
$UserObject = New-Object psobject
$UserObject | Add-Member -MemberType NoteProperty -Name Domain -Value $Domain
$UserObject | Add-Member -MemberType NoteProperty -Name UserName -Value $UserName
$UserObject | Add-Member -MemberType NoteProperty -Name LastLogin -Value $LastLogin
$UserObject | Add-Member -MemberType NoteProperty -Name ProfilePath -Value $ProfilePath
$UserObject
}
} catch {
Update-Log "Error while translating $SID to a user name." -Color 'Yellow'
}
} catch {
Update-Log "Error while translating $($_.PSChildName) to SID." -Color 'Yellow'
}
}
}
function Get-UserProfilePath {
param(
[string]$Domain,
[string]$UserName
)
$UserObject = New-Object System.Security.Principal.NTAccount($Domain, $UserName)
$SID = $UserObject.Translate([System.Security.Principal.SecurityIdentifier])
$User = Get-ItemProperty -Path "Registry::HKey_Local_Machine\Software\Microsoft\Windows NT\CurrentVersion\ProfileList\$($SID.Value)"
$User.ProfileImagePath
}
function Test-IsAdmin {
$UserIdentity = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
if (-not $UserIdentity.IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
Update-Log "You are not running this script as Administrator. " -Color 'Yellow' -NoNewLine
Update-Log "Some tasks may fail if launched as Administrator.`n" -Color 'Yellow'
}
}
function Set-SaveDirectory {
param (
[Parameter(Mandatory = $true)]
[ValidateSet('Destination', 'Source')]
[string] $Type
)
# Bring up file explorer so user can select a directory to add
$OpenDirectoryDialog = New-Object Windows.Forms.FolderBrowserDialog
$OpenDirectoryDialog.RootFolder = 'Desktop'
$OpenDirectoryDialog.SelectedPath = $SaveDestinationTextBox.Text
if ($Type -eq 'Destination') {
$OpenDirectoryDialog.SelectedPath = $SaveDestinationTextBox.Text
} else {
$OpenDirectoryDialog.SelectedPath = $SaveSourceTextBox.Text
}
$OpenDirectoryDialog.ShowDialog() | Out-Null
$SelectedDirectory = $OpenDirectoryDialog.SelectedPath
try {
# If user hits cancel it could cause attempt to add null path, so check that there's something there
if ($SelectedDirectory) {
Update-Log "Changed save directory to [$SelectedDirectory]."
if ($Type -eq 'Destination') {
$SaveDestinationTextBox.Text = $SelectedDirectory
} else {
$SaveSourceTextBox.Text = $SelectedDirectory
}
}
} catch {
Update-Log "There was a problem with the directory you chose: $($_.Exception.Message)" -Color Red
}
}
function Add-ExtraDirectory {
# Bring up file explorer so user can select a directory to add
$OpenDirectoryDialog = New-Object Windows.Forms.FolderBrowserDialog
$OpenDirectoryDialog.RootFolder = 'Desktop'
$OpenDirectoryDialog.SelectedPath = 'C:\'
$Result = $OpenDirectoryDialog.ShowDialog()
$SelectedDirectory = $OpenDirectoryDialog.SelectedPath
try {
# If user hits cancel don't add the path
if ($Result -eq 'OK') {
Update-Log "Adding to extra directories: $SelectedDirectory."
$ExtraDirectoriesDataGridView.Rows.Add($SelectedDirectory)
} else {
Update-Log "Add directory action cancelled by user." -Color Yellow
}
} catch {
Update-Log "There was a problem with the directory you chose: $($_.Exception.Message)" -Color Red
}
}
function Remove-ExtraDirectory {
# Remove selected cell from Extra Directories data grid view
$CurrentCell = $ExtraDirectoriesDataGridView.CurrentCell
Update-Log "Removed [$($CurrentCell.Value)] from extra directories."
$CurrentRow = $ExtraDirectoriesDataGridView.Rows[$CurrentCell.RowIndex]
$ExtraDirectoriesDataGridView.Rows.Remove($CurrentRow)
}
function Set-Config {
$ExtraDirectoryCount = $ExtraDirectoriesDataGridView.RowCount
if ($ExtraDirectoryCount) {
Update-Log "Including $ExtraDirectoryCount extra directories."
$ExtraDirectoryXML = @"
<!-- This component includes the additional directories selected by the user -->
<component type="Documents" context="System">
<displayName>Additional Folders</displayName>
<role role="Data">
<rules>
<include>
<objectSet>
"@
# Include each directory user has added to the Extra Directories data grid view
$ExtraDirectoriesDataGridView.Rows | ForEach-Object {
$CurrentRowIndex = $_.Index
$Path = $ExtraDirectoriesDataGridView.Item(0, $CurrentRowIndex).Value
$ExtraDirectoryXML += @"
<pattern type=`"File`">$Path\* [*]</pattern>"
"@
}
$ExtraDirectoryXML += @"
</objectSet>
</include>
</rules>
</role>
</component>
"@
} else {
Update-Log 'No extra directories will be included.'
}
Update-Log 'Data to be included:'
foreach ($Control in $InclusionsGroupBox.Controls) { if ($Control.Checked) { Update-Log $Control.Text } }
$ExcludedDataXML = @"
$(
if (-not $IncludePrintersCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_PRINTERS%\* [*]</pattern>`n" }
if (-not $IncludeRecycleBinCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_BITBUCKET%\* [*]</pattern>`n" }
if (-not $IncludeMyDocumentsCheckBox.Checked) {
"<pattern type=`"File`">%CSIDL_MYDOCUMENTS%\* [*]</pattern>`n"
"<pattern type=`"File`">%CSIDL_PERSONAL%\* [*]</pattern>`n"
}
if (-not $IncludeDesktopCheckBox.Checked) {
"<pattern type=`"File`">%CSIDL_DESKTOP%\* [*]</pattern>`n"
"<pattern type=`"File`">%CSIDL_DESKTOPDIRECTORY%\* [*]</pattern>`n"
}
if (-not $IncludeFavoritesCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_FAVORITES%\* [*]</pattern>`n" }
if (-not $IncludeMyMusicCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_MYMUSIC%\* [*]</pattern>`n" }
if (-not $IncludeMyPicturesCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_MYPICTURES%\* [*]</pattern>`n" }
if (-not $IncludeMyVideoCheckBox.Checked) { "<pattern type=`"File`">%CSIDL_MYVIDEO%\* [*]</pattern>`n" }
)
"@
$AppDataXML = if ($IncludeAppDataCheckBox.Checked) {
@"
<!-- This component migrates all user app data -->
<component type=`"Documents`" context=`"User`">
<displayName>App Data</displayName>
<paths>
<path type="File">%CSIDL_APPDATA%</path>
</paths>
<role role="Data">
<detects>
<detect>
<condition>MigXmlHelper.DoesObjectExist("File","%CSIDL_APPDATA%")</condition>
</detect>
</detects>
<rules>
<include filter='MigXmlHelper.IgnoreIrrelevantLinks()'>
<objectSet>
<pattern type="File">%CSIDL_APPDATA%\* [*]</pattern>
</objectSet>
</include>
<merge script='MigXmlHelper.DestinationPriority()'>
<objectSet>
<pattern type="File">%CSIDL_APPDATA%\* [*]</pattern>
</objectSet>
</merge>
</rules>
</role>
</component>
"@
}
$LocalAppDataXML = if ($IncludeLocalAppDataCheckBox.Checked) {
@"
<!-- This component migrates all user local app data -->
<component type=`"Documents`" context=`"User`">
<displayName>Local App Data</displayName>
<paths>
<path type="File">%CSIDL_LOCAL_APPDATA%</path>
</paths>
<role role="Data">
<detects>
<detect>
<condition>MigXmlHelper.DoesObjectExist("File","%CSIDL_LOCAL_APPDATA%")</condition>
</detect>
</detects>
<rules>
<include filter='MigXmlHelper.IgnoreIrrelevantLinks()'>
<objectSet>
<pattern type="File">%CSIDL_LOCAL_APPDATA%\* [*]</pattern>
</objectSet>
</include>
<merge script='MigXmlHelper.DestinationPriority()'>
<objectSet>
<pattern type="File">%CSIDL_LOCAL_APPDATA%\* [*]</pattern>
</objectSet>
</merge>
</rules>
</role>
</component>
"@
}
$WallpapersXML = if ($IncludeWallpapersCheckBox.Checked) {
@"
<!-- This component migrates wallpaper settings -->
<component type="System" context="User">
<displayName>Wallpapers</displayName>
<role role="Settings">
<rules>
<include>
<objectSet>
<pattern type="Registry">HKCU\Control Panel\Desktop [Pattern]</pattern>
<pattern type="Registry">HKCU\Control Panel\Desktop [PatternUpgrade]</pattern>
<pattern type="Registry">HKCU\Control Panel\Desktop [TileWallpaper]</pattern>
<pattern type="Registry">HKCU\Control Panel\Desktop [WallPaper]</pattern>
<pattern type="Registry">HKCU\Control Panel\Desktop [WallpaperStyle]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Windows\CurrentVersion\Themes [SetupVersion]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [BackupWallpaper]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [TileWallpaper]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [Wallpaper]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperFileTime]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperLocalFileTime]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [WallpaperStyle]</pattern>
<content filter="MigXmlHelper.ExtractSingleFile(NULL, NULL)">
<objectSet>
<pattern type="Registry">HKCU\Control Panel\Desktop [WallPaper]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [BackupWallpaper]</pattern>
<pattern type="Registry">HKCU\Software\Microsoft\Internet Explorer\Desktop\General [Wallpaper]</pattern>
</objectSet>
</content>
</objectSet>
</include>
</rules>
</role>
</component>
<!-- This component migrates wallpaper files -->
<component type="Documents" context="System">
<displayName>Move JPG and BMP</displayName>
<role role="Data">
<rules>
<include>
<objectSet>
<pattern type="File"> %windir% [*.bmp]</pattern>
<pattern type="File"> %windir%\web\wallpaper [*.jpg]</pattern>
<pattern type="File"> %windir%\web\wallpaper [*.bmp]</pattern>
</objectSet>
</include>
</rules>
</role>
</component>
"@
}
$ConfigContent = @"
<?xml version="1.0" encoding="UTF-8"?>
<migration urlid="http://www.microsoft.com/migration/1.0/migxmlext/config">
<_locDefinition>
<_locDefault _loc="locNone"/>
<_locTag _loc="locData">displayName</_locTag>
</_locDefinition>
$ExtraDirectoryXML
<!-- This component migrates all user data except specified exclusions -->
<component type="Documents" context="User">
<displayName>Documents</displayName>
<role role="Data">
<rules>
<include filter="MigXmlHelper.IgnoreIrrelevantLinks()">
<objectSet>
<script>MigXmlHelper.GenerateDocPatterns ("FALSE","TRUE","FALSE")</script>
</objectSet>
</include>
<exclude filter='MigXmlHelper.IgnoreIrrelevantLinks()'>
<objectSet>
<script>MigXmlHelper.GenerateDocPatterns ("FALSE","FALSE","FALSE")</script>
</objectSet>
</exclude>
<exclude>
<objectSet>
$ExcludedDataXML
</objectSet>
</exclude>
<contentModify script="MigXmlHelper.MergeShellLibraries('TRUE','TRUE')">
<objectSet>
<pattern type="File">*[*.library-ms]</pattern>
</objectSet>
</contentModify>
<merge script="MigXmlHelper.SourcePriority()">
<objectSet>
<pattern type="File">*[*.library-ms]</pattern>
</objectSet>
</merge>
</rules>
</role>
</component>
$AppDataXML
$LocalAppDataXML
$WallpapersXML
</migration>
"@
$Config = "$Destination\Config.xml"
try {
New-Item $Config -ItemType File -Force -ErrorAction Stop | Out-Null
} catch {
Update-Log "Error creating config file [$Config]: $($_.Exception.Message)" -Color 'Red'
return
}
try {
Set-Content $Config $ConfigContent -ErrorAction Stop
} catch {
Update-Log "Error while setting config file content: $($_.Exception.Message)" -Color 'Red'
return
}
# Return the path to the config
$Config
}
function Get-USMT {
# Test that USMT binaries are reachable
if (Test-Path $USMTPath) {
$Script:ScanState = "$USMTPath\scanstate.exe"
$Script:LoadState = "$USMTPath\loadstate.exe"
Update-Log "Using [$USMTPath] as path to USMT binaries."
} else {
Update-Log "Unable to reach USMT binaries. Verify [$USMTPath] exists and restart script.`n" -Color 'Red'
$MigrateButton_OldPage.Enabled = $false
$MigrateButton_NewPage.Enabled = $false
}
}
function Get-USMTResults {
param([string] $ActionType)
if ($PSVersionTable.PSVersion.Major -lt 3) {
# Print back the entire log
$Results = Get-Content "$Destination\$ActionType.log" | Out-String
} else {
# Get the last 4 lines from the log so we can see the results
$Results = Get-Content "$Destination\$ActionType.log" -Tail 4 | ForEach-Object {
($_.Split(']', 2)[1]).TrimStart()
} | Out-String
}
Update-Log $Results -Color 'Cyan'
if ($ActionType -eq 'load') {
Update-Log 'A reboot is recommended.' -Color 'Yellow'
$EmailSubject = "Migration Load Results of $($OldComputerNameTextBox_NewPage.Text) to $($NewComputerNameTextBox_NewPage.Text)"
} else {
$EmailSubject = "Migration Save Results of $($OldComputerNameTextBox_OldPage.Text) to $($NewComputerNameTextBox_OldPage.Text)"
}
if ($EmailCheckBox.Checked) {
if ($SMTPConnectionCheckBox.Checked -or (Test-Connection -ComputerName $SMTPServerTextBox.Text -Quiet)) {
$SMTPConnectionCheckBox.Checked = $true
$EmailRecipients = @()
$EmailRecipientsDataGridView.Rows | ForEach-Object {
$CurrentRowIndex = $_.Index
$EmailRecipients += $EmailRecipientsDataGridView.Item(0, $CurrentRowIndex).Value
}
Update-Log "Emailing migration results to: $EmailRecipients"
try {
$SendMailMessageParams = @{
From = $EmailSenderTextBox.Text
To = $EmailRecipients
Subject = $EmailSubject
Body = $LogTextBox.Text
SmtpServer = $SMTPServerTextBox.Text
Attachments = "$Destination\$ActionType.log"
}
Send-MailMessage @SendMailMessageParams
} catch {
Update-Log "Error occurred sending email: $($_.Exception.Message)" -Color 'Red'
}
} else {
Update-Log "Unable to send email of results because SMTP server [$($SMTPServerTextBox.Text)] is unreachable." -Color 'Yellow'
}
}
}
function Get-USMTProgress {
param(
[string] $Destination,
[string] $ActionType
)
try {
# Get the most recent entry in the progress log
$LastLine = Get-Content "$Destination\$($ActionType)_progress.log" -Tail 1 -ErrorAction SilentlyContinue | Out-String
Update-Log ($LastLine.Split(',', 4)[3]).TrimStart()
} catch { Update-Log '.' -NoNewLine }
}
function Get-SaveState {
# Use the migration folder name to get the old computer name
if (Get-ChildItem $SaveSourceTextBox.Text -ErrorAction SilentlyContinue) {
$SaveSource = Get-ChildItem $SaveSourceTextBox.Text | Where-Object { $_.PSIsContainer } |
Sort-Object -Descending -Property { $_.CreationTime } | Select-Object -First 1
if (Test-Path "$($SaveSource.FullName)\USMT\USMT.MIG") {
$Script:UncompressedSource = $false
} else {
$Script:UncompressedSource = $true
Update-Log -Message "Uncompressed save state detected."
}
$OldComputer = $SaveSource.BaseName
Update-Log -Message "Old computer set to $OldComputer."
} else {
$OldComputer = 'N/A'
Update-Log -Message "No saved state found at [$($SaveSourceTextBox.Text)]." -Color 'Yellow'
}
$OldComputer
}
function Show-DomainInfo {
# Populate old user data if DomainMigration.txt file exists, otherwise disable group box
if (Test-Path "$MigrationStorePath\$($OldComputerNameTextBox_NewPage.Text)\DomainMigration.txt") {
$OldUser = Get-Content "$MigrationStorePath\$($OldComputerNameTextBox_NewPage.Text)\DomainMigration.txt"
$OldDomainTextBox.Text = $OldUser.Split('\')[0]
$OldUserNameTextBox.Text = $OldUser.Split('\')[1]
} else {
$CrossDomainMigrationGroupBox.Enabled = $false
$CrossDomainMigrationGroupBox.Hide()
}
}
function Save-UserState {
param(
[switch] $Debug
)
Update-Log "`nBeginning migration..."
# Run scripts before doing actual data migration
$OldComputerScriptsDataGridView.Rows | ForEach-Object {
$ScriptName = $OldComputerScriptsDataGridView.Item(0, $_.Index).Value
$ScriptPath = "$PSScriptRoot\Scripts\OldComputer\$ScriptName"
Update-Log "Running $ScriptPath"
if (-not $Debug) {
$Result = if ($ScriptPath.EndsWith('ps1')) {
. $ScriptPath
} else {
Start-Process $ScriptPath -Wait -PassThru
}
Update-Log ($Result | Out-String)
}
}
# If we're saving locally, skip network stuff
if ($SaveRemotelyCheckBox.Checked) {
# If connection hasn't been verfied, test now
if (-not $ConnectionCheckBox_OldPage.Checked) {
$TestComputerConnectionParams = @{
ComputerNameTextBox = $NewComputerNameTextBox_OldPage
ComputerIPTextBox = $NewComputerIPTextBox_OldPage
ConnectionCheckBox = $ConnectionCheckBox_OldPage
}
Test-ComputerConnection @TestComputerConnectionParams
}
# Try and use the IP if the user filled that out, otherwise use the name
if ($NewComputerIPTextBox_OldPage.Text -ne '') {
$NewComputer = $NewComputerIPTextBox_OldPage.Text
} else {
$NewComputer = $NewComputerNameTextBox_OldPage.Text
}
}
$OldComputer = $OldComputerNameTextBox_OldPage.Text
# After connection has been verified, continue with save state
if ($ConnectionCheckBox_OldPage.Checked -or (-not $SaveRemotelyCheckBox.Checked)) {
Update-Log 'Connection verified, proceeding with migration...'
# Get the selected profiles
if ($RecentProfilesCheckBox.Checked -eq $true) {
Update-Log "All profiles logged into within the last $($RecentProfilesDaysTextBox.Text) days will be saved."
} elseif ($Script:SelectedProfile) {
Update-Log "Profile(s) selected for save state:"
$Script:SelectedProfile | ForEach-Object { Update-Log $_.UserName }
} else {
Update-Log "You must select a user profile." -Color 'Red'
return
}
if (-not $SaveRemotelyCheckBox.Checked) {
$Script:Destination = "$($SaveDestinationTextBox.Text)\$OldComputer"
} else {
# Set destination folder on new computer
try {
$DriveLetter = $MigrationStorePath.Split(':', 2)[0]
$MigrationStorePath = $MigrationStorePath.TrimStart('C:\')
New-Item "\\$NewComputer\$DriveLetter$\$MigrationStorePath" -ItemType Directory -Force | Out-Null
$Script:Destination = "\\$NewComputer\$DriveLetter$\$MigrationStorePath\$OldComputer"
} catch {
Update-Log "Error while creating migration store [$Destination]: $($_.Exception.Message)" -Color 'Yellow'
return
}
}
# Create destination folder
if (!(Test-Path $Destination)){
try {
New-Item $Destination -ItemType Directory -Force | Out-Null
} catch {
Update-Log "Error while creating migration store [$Destination]: $($_.Exception.Message)" -Color 'Yellow'
return
}
}
#Verify that the Destination folder is valid.
if (Test-Path $Destination){
# If profile is a domain other than $DefaultDomain, save this info to text file
if ($RecentProfilesCheckBox.Checked -eq $false) {
$FullUserName = "$($Script:SelectedProfile.Domain)\$($Script:SelectedProfile.UserName)"
if ($Script:SelectedProfile.Domain -ne $DefaultDomain) {
New-Item "$Destination\DomainMigration.txt" -ItemType File -Value $FullUserName -Force | Out-Null
Update-Log "Text file created with cross-domain information."
}
}
# Clear encryption syntax in case it's already defined.
$EncryptionSyntax = ""
# Determine if Encryption has been requested
if ($Script:EncryptionPasswordSet -eq $True){
#Disable Compression
$Script:UncompressedSource = $false
$Uncompressed = ''
# Set the syntax for the encryption
$EncryptionKey = """$Script:EncryptionPassword"""
$EncryptionSyntax = "/encrypt /key:$EncryptionKey"
}
#Set the value to continue on error if it was specified above
if ($ContinueOnError -eq $True){
$ContinueCommand = "/c"
}
if ($ContinueOnError -eq $False){
$ContinueCommand = ""
}
# Create config syntax for scanstate for custom XMLs.
IF ($SelectedXMLS) {
#Create the scanstate syntax line for the config files.
foreach ($ConfigXML in $SelectedXMLS) {
$ConfigXMLPath = """$Script:USMTPath\$ConfigXML"""
$ScanstateConfig += "/i:$ConfigXMLPath "
}
}
# Create config syntax for scanstate for generated XML.
IF (!($SelectedXMLS)){
# Create the scan configuration
Update-Log 'Generating configuration file...'
$Config = Set-Config
$GeneratedConfig = """$Config"""
$ScanStateConfig = "/i:$GeneratedConfig"
}
# Generate parameter for logging
$Logs = "`"/l:$Destination\scan.log`" `"/progress:$Destination\scan_progress.log`""
# Set parameter for whether save state is compressed
if ($UncompressedCheckBox.Checked -eq $true) {
$Uncompressed = '/nocompress'
} else {
$Uncompressed = ''
}
# Create a string for all users to exclude by default
foreach ($ExcludeProfile in $Script:DefaultExcludeProfile) {
$ExcludeProfile = """$ExcludeProfile"""
$UsersToExclude += "/ue:$ExcludeProfile "
}
# Set the EFS Syntax based on the config.
if ($EFSHandling){
$EFSSyntax = "/efs:$EFSHandling"
}
# Overwrite existing save state, use volume shadow copy method, exclude all but the selected profile(s)
# Get the selected profiles
if ($RecentProfilesCheckBox.Checked -eq $true) {
$Arguments = "`"$Destination`" $ScanStateConfig /o /vsc $UsersToExclude /uel:$($RecentProfilesDaysTextBox.Text) $EncryptionSyntax $Uncompressed $Logs $EFSSyntax $ContinueCommand"
} else {
$UsersToInclude += $Script:SelectedProfile | ForEach-Object { "`"/ui:$($_.Domain)\$($_.UserName)`"" }
$Arguments = "`"$Destination`" $ScanStateConfig /o /vsc /ue:* $UsersToExclude $UsersToInclude $EncryptionSyntax $Uncompressed $Logs $EFSSyntax $ContinueCommand "
}
# Begin saving user state to new computer
# Create a value to show in the log in order to obscure the encryption key if one was used.
$LogArguments = $Arguments -Replace '/key:".*"','/key:(Hidden)'
Update-Log "Command used:"
Update-Log "$ScanState $LogArguments" -Color 'Cyan'
# If we're running in debug mode don't actually start the process
if ($Debug) { return }
Update-Log "Saving state of $OldComputer to $Destination..." -NoNewLine
Start-Process -FilePath $ScanState -ArgumentList $Arguments -Verb RunAs
# Give the process time to start before checking for its existence
Start-Sleep -Seconds 3
# Wait until the save state is complete
try {
$ScanProcess = Get-Process -Name scanstate -ErrorAction Stop
while (-not $ScanProcess.HasExited) {
Get-USMTProgress
Start-Sleep -Seconds 3
}
Update-Log "Complete!" -Color 'Green'
Update-Log 'Results:'
Get-USMTResults -ActionType 'scan'
} catch {
Update-Log $_.Exception.Message -Color 'Red'
}
} ELSE {
Update-Log "Error when trying to access [$Destination] Please verify that the user account running the utility has appropriate permissions to the folder.: $($_.Exception.Message)" -Color 'Yellow'
}
}
}
function Restore-UserState {
param(
[switch] $Debug
)
Update-Log "`nBeginning migration..."
# Run scripts before doing actual data migration
$NewComputerScriptsDataGridView.Rows | ForEach-Object {
$ScriptName = $NewComputerScriptsDataGridView.Item(0, $_.Index).Value
$ScriptPath = "$PSScriptRoot\Scripts\NewComputer\$ScriptName"
Update-Log "Running $ScriptPath"
if (-not $Debug) {
$Result = if ($ScriptPath.EndsWith('ps1')) {
. $ScriptPath
} else {
Start-Process $ScriptPath -Wait -PassThru
}
Update-Log ($Result | Out-String)
}
}
# If override is enabled, skip network checks
if (-not $OverrideCheckBox.Checked) {
# If connection hasn't been verfied, test now
if (-not $ConnectionCheckBox_NewPage.Checked) {
$TestComputerConnectionParams = @{
ComputerNameTextBox = $OldComputerNameTextBox_NewPage
ComputerIPTextBox = $OldComputerIPTextBox_NewPage
ConnectionCheckBox = $ConnectionCheckBox_NewPage
}
Test-ComputerConnection @TestComputerConnectionParams
}
# Try and use the IP if the user filled that out, otherwise use the name
if ($OldComputerIPTextBox_NewPage.Text -ne '') {
$OldComputer = $OldComputerIPTextBox_NewPage.Text
} else {
$OldComputer = $OldComputerNameTextBox_NewPage.Text
}
if ($ConnectionCheckBox_NewPage.Checked) {
Update-Log "Connection verified, checking in with $OldComputer..."
# Check in with the old computer and don't start until the save is complete
if (Get-Process -Name scanstate -ComputerName $OldComputer -ErrorAction SilentlyContinue) {
Update-Log "Waiting on $OldComputer to complete save state..."
while (Get-Process -Name scanstate -ComputerName $OldComputer -ErrorAction SilentlyContinue) {
Get-USMTProgress
Start-Sleep -Seconds 1
}
} else {
Update-Log "Save state process on $OldComputer is complete. Proceeding with migration."
}
} else {
Update-Log "Unable to verify connection with $OldComputer. Migration cancelled." -Color 'Red'
return
}
} else {
$OldComputer = $OldComputerNameTextBox_NewPage.Text
Update-Log "User has verified the save state process on $OldComputer is already completed. Proceeding with migration."
}
$OldComputerName = $OldComputerNameTextBox_NewPage.Text
# Get the location of the save state data
$Script:Destination = "$($SaveSourceTextBox.Text)\$OldComputerName"
# Check that the save state data exists
if (-not (Test-Path $Destination)) {
Update-Log "No saved state found at [$Destination]. Migration cancelled." -Color 'Red'
return
}
# Clear decryption syntax in case it's already defined.
$DecryptionSyntax = ""
# Determine if Encryption has been requested
if ($Script:EncryptionPasswordSet -eq $True){
# Disable Compression
$Script:UncompressedSource = $false
$Uncompressed = ''
# Set the syntax for the encryption
$DecryptionKey = """$Script:EncryptionPassword"""
$DecryptionSnytax = "/decrypt /key:$DecryptionKey"
}
# Set the value to continue on error if it was specified above
if ($ContinueOnError -eq $True){
$ContinueCommand = "/c"
}
if ($ContinueOnError -eq $false){
$ContinueCommand = ""
}
# Set the value for the Config file if one exists.
if (Test-Path "$Destination\Config.xml") {
$LoadStateConfigFile = """$Destination\Config.xml"""
$LoadStateConfig = "/i:$LoadStateConfigFile"
}
# Generate arguments for load state process
$Logs = "`"/l:$Destination\load.log`" `"/progress:$Destination\load_progress.log`""
# Set parameter for whether save state is compressed
if ($UncompressedSource -eq $true) {
$Uncompressed = '/nocompress'
} else {
$Uncompressed = ''
}
# Options for creating local accounts that don't already exist on new computer
$LocalAccountOptions = ''
if ($Script:DefaultLACreate -eq $true) {
$LocalAccountOptions = "`"/lac:$Script:DefaultLAPassword`""
if ($Script:DefaultLACEnable -eq $true) {
$LocalAccountOptions += ' /lae'
}
} else {
''
}
# Check if user to be migrated is coming from a different domain and do a cross-domain migration if so
if ($CrossDomainMigrationGroupBox.Enabled) {
$OldUser = "$($OldDomainTextBox.Text)\$($OldUserNameTextBox.Text)"
$NewUser = "$($NewDomainTextBox.Text)\$($NewUserNameTextBox.Text)"
# Make sure the user entered a new user's user name before continuing
if ($NewUserNameTextBox.Text -eq '') {
Update-Log "New user's user name must not be empty." -Color 'Red'
return
}
Update-Log "$OldUser will be migrated as $NewUser."
$Arguments = "`"$Destination`" $LoadStateConfig $LocalAccountOptions `"/mu:$($OldUser):$NewUser`" $DecryptionSnytax $Uncompressed $Logs $ContinueCommand /v:$Script:VerboseLevel"
} else {
$Arguments = "`"$Destination`" $LoadStateConfig $LocalAccountOptions $DecryptionSnytax $Uncompressed $Logs $ContinueCommand /v:$Script:VerboseLevel"
}
# Begin loading user state to this computer
# Create a value in order to obscure the encryption key if one was specified.
$LogArguments = $Arguments -Replace '/key:".*"','/key:(Hidden)'
Update-Log "Command used:"
Update-Log "$LoadState $LogArguments" -Color 'Cyan'
# If we're running in debug mode don't actually start the process
if ($Debug) { return }
Update-Log "Loading state of $OldComputer..." -NoNewLine
$USMTLoadState = Start-Process -FilePath $LoadState -ArgumentList $Arguments -Verb RunAs -PassThru
$USMTLoadState
# Give the process time to start before checking for its existence
Start-Sleep -Seconds 3
# Wait until the load state is complete
try {
$LoadProcess = Get-Process -Name loadstate -ErrorAction Stop
while (-not $LoadProcess.HasExited) {
Get-USMTProgress
Start-Sleep -Seconds 1
}
Update-Log 'Results:'
Get-USMTResults -ActionType 'load'
# Sometimes loadstate will kill the explorer task and it needs to be start again manually
if (-not (Get-Process -Name explorer -ErrorAction SilentlyContinue)) {
Update-Log 'Restarting Explorer process.'
Start-Process explorer
}
if ($USMTLoadState.ExitCode -eq 0){
Update-Log "Complete!" -Color 'Green'
# Delete the save state data
try {
Get-ChildItem $MigrationStorePath | Remove-Item -Recurse
Update-Log 'Successfully removed old save state data.'
} catch {
Update-Log 'There was an issue when trying to remove old save state data.'
}
} else {
update-log 'There was an issue during the loadstate process, please review the results. The state data was not deleted.'
}
} catch {
Update-Log $_.Exception.Message -Color 'Red'
}
}
function Test-ComputerConnection {
param(
[System.Windows.Forms.TextBox] $ComputerNameTextBox,
[System.Windows.Forms.TextBox] $ComputerIPTextBox,
[System.Windows.Forms.CheckBox] $ConnectionCheckBox
)
$ConnectionCheckBox.Checked = $false
# Try and use the IP if the user filled that out, otherwise use the name
if ($ComputerIPTextBox.Text -ne '') {
$Computer = $ComputerIPTextBox.Text
# Try to update the computer's name with its IP address
if ($ComputerNameTextBox.Text -eq '') {
try {
Update-Log 'Computer name is blank, attempting to resolve...' -Color 'Yellow' -NoNewLine
$HostName = ([System.Net.Dns]::GetHostEntry($Computer)).HostName
$ComputerNameTextBox.Text = $HostName
Update-Log "Computer name set to $HostName."
} catch {
Update-Log "Unable to resolve host name from IP address, you'll need to manually set this." -Color 'Red'
return
}
}
} elseif ($ComputerNameTextBox.Text -ne '') {
$Computer = $ComputerNameTextBox.Text
# Try to update the computer's IP address using its DNS name
try {
Update-Log 'Computer IP address is blank, attempting to resolve...' -Color 'Yellow' -NoNewLine
# Get the first IP address found, which is usually the primary adapter
$IPAddress = ([System.Net.Dns]::GetHostEntry($Computer)).AddressList.IPAddressToString.Split('.', 1)[0]
# Set IP address in text box
$ComputerIPTextBox.Text = $IPAddress
Update-Log "Computer IP address set to $IPAddress."
} catch {
Update-Log "Unable to resolve IP address from host name, you'll need to manually set this." -Color 'Red'
return
}
} else {
$Computer = $null
}
# Don't even try if both fields are empty
if ($Computer) {
# If the computer doesn't appear to have a valid office IP, such as if it's on VPN, don't allow the user to continue
if ($ComputerIPTextBox.Text -notlike $ValidIPAddress) {
Update-Log "$IPAddress does not appear to be a valid IP address. The Migration Tool requires an IP address matching $ValidIPAddress." -Color 'Red'
return
}
Update-Log "Testing connection to $Computer..." -NoNewLine
if (Test-Connection $Computer -Quiet) {
$ConnectionCheckBox.Checked = $true
Update-Log "Connection established." -Color 'Green'
} else {
Update-Log "Unable to reach $Computer." -Color 'Red'
if ($ComputerIPTextBox.Text -eq '') {
Update-Log "Try entering $Computer's IP address." -Color 'Yellow'
}
}
} else {
Update-Log "Enter the computer's name or IP address." -Color 'Red'
}
}
function Set-Logo {
Update-Log " __ __ _ _ _ " -Color 'LightBlue'
Update-Log " | \/ (_) __ _ _ __ __ _| |_(_) ___ _ __ " -Color 'LightBlue'
Update-Log " | |\/| | |/ _`` | '__/ _`` | __| |/ _ \| '_ \ " -Color 'LightBlue'
Update-Log " | | | | | (_| | | | (_| | |_| | (_) | | | |" -Color 'LightBlue'
Update-Log " |_| |_|_|\__, |_| \__,_|\__|_|\___/|_| |_|" -Color 'LightBlue'
Update-Log " _ |___/ _ _ _ " -Color 'LightBlue'
Update-Log " / \ ___ ___(_)___| |_ __ _ _ __ | |_ " -Color 'LightBlue'
Update-Log " / _ \ / __/ __| / __| __/ _`` | '_ \| __| " -Color 'LightBlue'
Update-Log " / ___ \\__ \__ \ \__ \ || (_| | | | | |_ " -Color 'LightBlue'
Update-Log " /_/ \_\___/___/_|___/\__\__,_|_| |_|\__| $ScriptVersion" -Color 'LightBlue'
Update-Log
Update-Log ' by Nick Rodriguez' -Color 'Gold'
Update-Log
}
function Test-IsISE { if ($psISE) { $true } else { $false } }
function Test-PSVersion {
if ($PSVersionTable.PSVersion.Major -lt 3) {
Update-Log "You are running a version of PowerShell less than 3.0 - some features have been disabled."
$ChangeSaveDestinationButton.Enabled = $false
$ChangeSaveSourceButton.Enabled = $false
$AddExtraDirectoryButton.Enabled = $false
}
}
function Test-Email {
$EmailSubject = "Migration Assistant Email Test"
if ($SMTPConnectionCheckBox.Checked -or (Test-Connection -ComputerName $SMTPServerTextBox.Text -Quiet)) {
$SMTPConnectionCheckBox.Checked = $true
$EmailRecipients = @()
$EmailRecipientsDataGridView.Rows | ForEach-Object {
$CurrentRowIndex = $_.Index
$EmailRecipients += $EmailRecipientsDataGridView.Item(0, $CurrentRowIndex).Value
}
Update-Log "Sending test email to: $EmailRecipients"
try {
$SendMailMessageParams = @{
From = $EmailSenderTextBox.Text
To = $EmailRecipients
Subject = $EmailSubject
Body = $LogTextBox.Text
SmtpServer = $SMTPServerTextBox.Text
ErrorAction = Stop
}
Send-MailMessage @SendMailMessageParams
} catch {
Update-Log "Error occurred sending email: $($_.Exception.Message)" -Color 'Red'
}
} else {
Update-Log "Unable to send email of results because SMTP server [$($SMTPServerTextBox.Text)] is unreachable." -Color 'Yellow'
}
}
function Read-Password {
# Set the password set flag to false.
$Script:EncryptionPasswordSet = $Null
# Clear the password reset flag.
$Script:EncryptionPasswordRetry = $Null
# Prompt the user for an encryption password.
$Script:EncryptionPassword = $Null
$Script:EncryptionPassword = Get-Credential -Message "Enter the encryption password" -UserName "Enter a password Below"
# Prompt the user again for confirmation.
$Script:EncryptionPasswordConfirm = $Null
$Script:EncryptionPasswordConfirm = Get-Credential -Message "Please confirm the encryption password" -UserName "Enter a password Below"
# Convert the password strings to plain text so that they can be compared.
if ($Script:EncryptionPassword.Password){
$Script:EncryptionPassword = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($Script:EncryptionPassword.Password))
}
if ($Script:EncryptionPasswordConfirm.Password) {
$Script:EncryptionPasswordConfirm = [Runtime.InteropServices.Marshal]::PtrToStringAuto(
[Runtime.InteropServices.Marshal]::SecureStringToBSTR($Script:EncryptionPasswordConfirm.Password))
}
# Compare the password strings and verify that they match
if ($Script:EncryptionPassword -ne $Script:EncryptionPasswordConfirm -or
$Script:EncryptionPassword -eq "" -or
$Script:EncryptionPassword -eq $Null) {
Update-Log "Password did not match or was blank." -Color 'Yellow'
} else {
# Set a flag that the password was successfully set
$Script:EncryptionPasswordSet = $True
}
# Prompt the user to try again if the strings did not match.
if ($Script:EncryptionPasswordSet -ne $True -and $Script:EncryptionPasswordRetry -ne '7') {
do {
$Script:EncryptionPasswordRetry = $WScriptShell.Popup(
'Encryption password was not successfully set, try again?',
0,
'Retry Password',
4
)
# Prompt again if the user opted to retry
if ($Script:EncryptionPasswordRetry -ne '7'){
Update-Log 'Retrying password prompt.' -Color Yellow
Read-Password
}
} while ($Script:EncryptionPasswordSet -ne $True -and $Script:EncryptionPasswordRetry -ne '7')
}
}
# Hide parent PowerShell window unless run from ISE
if (-not $(Test-IsISE)) {
$ShowWindowAsync = Add-Type -MemberDefinition @"
[DllImport("user32.dll")]
public static extern bool ShowWindowAsync(IntPtr hWnd, int nCmdShow);
"@ -Name "Win32ShowWindowAsync" -Namespace Win32Functions -PassThru
$ShowWindowAsync::ShowWindowAsync((Get-Process -Id $PID).MainWindowHandle, 0) | Out-Null
}
# Load assemblies for building forms
[System.Reflection.Assembly]::LoadWithPartialName("System.Drawing") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") | Out-Null
$Script:Destination = ''
}
process {
# Create form
$Form = New-Object System.Windows.Forms.Form
$Form.Text = 'Migration Assistant by Nick Rodriguez'
$Form.Size = New-Object System.Drawing.Size(1000, 550)
$Form.SizeGripStyle = 'Hide'
$Form.FormBorderStyle = 'FixedToolWindow'
$Form.MaximizeBox = $false
$Form.StartPosition = "CenterScreen"
# Create tab controls
$TabControl = New-object System.Windows.Forms.TabControl
$TabControl.DataBindings.DefaultDataSourceUpdateMode = 0
$TabControl.Location = New-Object System.Drawing.Size(10, 10)
$TabControl.Size = New-Object System.Drawing.Size(480, 490)
$Form.Controls.Add($TabControl)
# Log output text box
$LogTextBox = New-Object System.Windows.Forms.RichTextBox
$LogTextBox.Location = New-Object System.Drawing.Size(500, 30)
$LogTextBox.Size = New-Object System.Drawing.Size(475, 472)
$LogTextBox.ReadOnly = 'True'
$LogTextBox.BackColor = 'Black'
$LogTextBox.ForeColor = 'White'
$LogTextBox.Font = 'Consolas, 10'
$LogTextBox.DetectUrls = $false
Set-Logo
$Form.Controls.Add($LogTextBox)
# Clear log button
$ClearLogButton = New-Object System.Windows.Forms.Button
$ClearLogButton.Location = New-Object System.Drawing.Size(370, 505)
$ClearLogButton.Size = New-Object System.Drawing.Size(80, 20)
$ClearLogButton.FlatStyle = 1
$ClearLogButton.BackColor = 'White'
$ClearLogButton.ForeColor = 'Black'
$ClearLogButton.Text = 'Clear'
$ClearLogButton.Add_Click({ $LogTextBox.Clear() })
$LogTextBox.Controls.Add($ClearLogButton)
# Create old computer tab
$OldComputerTabPage = New-Object System.Windows.Forms.TabPage
$OldComputerTabPage.DataBindings.DefaultDataSourceUpdateMode = 0
$OldComputerTabPage.UseVisualStyleBackColor = $true
$OldComputerTabPage.Text = 'Old Computer'
$TabControl.Controls.Add($OldComputerTabPage)
# Computer info group
$OldComputerInfoGroupBox = New-Object System.Windows.Forms.GroupBox
$OldComputerInfoGroupBox.Location = New-Object System.Drawing.Size(10, 10)
$OldComputerInfoGroupBox.Size = New-Object System.Drawing.Size(450, 87)
$OldComputerInfoGroupBox.Text = 'Computer Info'
$OldComputerTabPage.Controls.Add($OldComputerInfoGroupBox)
# Name label
$ComputerNameLabel_OldPage = New-Object System.Windows.Forms.Label
$ComputerNameLabel_OldPage.Location = New-Object System.Drawing.Size(100, 12)
$ComputerNameLabel_OldPage.Size = New-Object System.Drawing.Size(100, 22)
$ComputerNameLabel_OldPage.Text = 'Computer Name'
$OldComputerInfoGroupBox.Controls.Add($ComputerNameLabel_OldPage)
# IP label
$ComputerIPLabel_OldPage = New-Object System.Windows.Forms.Label
$ComputerIPLabel_OldPage.Location = New-Object System.Drawing.Size(230, 12)
$ComputerIPLabel_OldPage.Size = New-Object System.Drawing.Size(80, 22)
$ComputerIPLabel_OldPage.Text = 'IP Address'
$OldComputerInfoGroupBox.Controls.Add($ComputerIPLabel_OldPage)
# Old Computer name label
$OldComputerNameLabel_OldPage = New-Object System.Windows.Forms.Label
$OldComputerNameLabel_OldPage.Location = New-Object System.Drawing.Size(12, 35)
$OldComputerNameLabel_OldPage.Size = New-Object System.Drawing.Size(80, 22)
$OldComputerNameLabel_OldPage.Text = 'Old Computer'
$OldComputerInfoGroupBox.Controls.Add($OldComputerNameLabel_OldPage)
# Old Computer name text box
$OldComputerNameTextBox_OldPage = New-Object System.Windows.Forms.TextBox
$OldComputerNameTextBox_OldPage.ReadOnly = $true
$OldComputerNameTextBox_OldPage.Location = New-Object System.Drawing.Size(100, 34)
$OldComputerNameTextBox_OldPage.Size = New-Object System.Drawing.Size(120, 20)
$OldComputerNameTextBox_OldPage.Text = $env:COMPUTERNAME
$OldComputerInfoGroupBox.Controls.Add($OldComputerNameTextBox_OldPage)
# Old Computer IP text box
$OldComputerIPTextBox_OldPage = New-Object System.Windows.Forms.TextBox
$OldComputerIPTextBox_OldPage.ReadOnly = $true
$OldComputerIPTextBox_OldPage.Location = New-Object System.Drawing.Size(230, 34)
$OldComputerIPTextBox_OldPage.Size = New-Object System.Drawing.Size(90, 20)
$OldComputerIPTextBox_OldPage.Text = Get-IPAddress
$OldComputerInfoGroupBox.Controls.Add($OldComputerIPTextBox_OldPage)
# New Computer name label
$NewComputerNameLabel_OldPage = New-Object System.Windows.Forms.Label
$NewComputerNameLabel_OldPage.Location = New-Object System.Drawing.Size(12, 57)
$NewComputerNameLabel_OldPage.Size = New-Object System.Drawing.Size(80, 22)
$NewComputerNameLabel_OldPage.Text = 'New Computer'
$OldComputerInfoGroupBox.Controls.Add($NewComputerNameLabel_OldPage)
# New Computer name text box
$NewComputerNameTextBox_OldPage = New-Object System.Windows.Forms.TextBox
$NewComputerNameTextBox_OldPage.Location = New-Object System.Drawing.Size(100, 56)
$NewComputerNameTextBox_OldPage.Size = New-Object System.Drawing.Size(120, 20)
$NewComputerNameTextBox_OldPage.Add_TextChanged({
if ($ConnectionCheckBox_OldPage.Checked) {
Update-Log 'Computer name changed, connection status unverified.' -Color 'Yellow'
$ConnectionCheckBox_OldPage.Checked = $false
}
})
$OldComputerInfoGroupBox.Controls.Add($NewComputerNameTextBox_OldPage)
# New Computer IP text box
$NewComputerIPTextBox_OldPage = New-Object System.Windows.Forms.TextBox
$NewComputerIPTextBox_OldPage.Location = New-Object System.Drawing.Size(230, 56)
$NewComputerIPTextBox_OldPage.Size = New-Object System.Drawing.Size(90, 20)
$NewComputerIPTextBox_OldPage.Add_TextChanged({
if ($ConnectionCheckBox_OldPage.Checked) {
Update-Log 'Computer IP address changed, connection status unverified.' -Color 'Yellow'
$ConnectionCheckBox_OldPage.Checked = $false
}
})
$OldComputerInfoGroupBox.Controls.Add($NewComputerIPTextBox_OldPage)
# Button to test connection to new computer
$TestConnectionButton_OldPage = New-Object System.Windows.Forms.Button
$TestConnectionButton_OldPage.Location = New-Object System.Drawing.Size(335, 33)
$TestConnectionButton_OldPage.Size = New-Object System.Drawing.Size(100, 22)
$TestConnectionButton_OldPage.Text = 'Test Connection'
$TestConnectionButton_OldPage.Add_Click({
$TestComputerConnectionParams = @{
ComputerNameTextBox = $NewComputerNameTextBox_OldPage
ComputerIPTextBox = $NewComputerIPTextBox_OldPage
ConnectionCheckBox = $ConnectionCheckBox_OldPage
}
Test-ComputerConnection @TestComputerConnectionParams
})
$OldComputerInfoGroupBox.Controls.Add($TestConnectionButton_OldPage)
# Connected check box
$ConnectionCheckBox_OldPage = New-Object System.Windows.Forms.CheckBox
$ConnectionCheckBox_OldPage.Enabled = $false
$ConnectionCheckBox_OldPage.Text = 'Connected'
$ConnectionCheckBox_OldPage.Location = New-Object System.Drawing.Size(336, 58)
$ConnectionCheckBox_OldPage.Size = New-Object System.Drawing.Size(100, 20)
$OldComputerInfoGroupBox.Controls.Add($ConnectionCheckBox_OldPage)
# Profile selection group box
$SelectProfileGroupBox = New-Object System.Windows.Forms.GroupBox
$SelectProfileGroupBox.Location = New-Object System.Drawing.Size(240, 220)
$SelectProfileGroupBox.Size = New-Object System.Drawing.Size(220, 100)
$SelectProfileGroupBox.Text = 'Profile Selection'
$OldComputerTabPage.Controls.Add($SelectProfileGroupBox)
# Select profile(s) button
$SelectProfileButton = New-Object System.Windows.Forms.Button
$SelectProfileButton.Location = New-Object System.Drawing.Size(30, 20)
$SelectProfileButton.Size = New-Object System.Drawing.Size(160, 20)
$SelectProfileButton.Text = 'Select Profile(s) to Migrate'
$SelectProfileButton.Add_Click({
Update-Log "Please wait while profiles are found..."
$Script:SelectedProfile = Get-UserProfiles |
Out-GridView -Title 'Profile Selection' -OutputMode Multiple
Update-Log "Profile(s) selected for migration:"
$Script:SelectedProfile | ForEach-Object { Update-Log $_.UserName }
})
$SelectProfileGroupBox.Controls.Add($SelectProfileButton)
# Recent profile day limit text box
$RecentProfilesDaysTextBox = New-Object System.Windows.Forms.TextBox
$RecentProfilesDaysTextBox.Location = New-Object System.Drawing.Size(165, 70)
$RecentProfilesDaysTextBox.Size = New-Object System.Drawing.Size(40, 20)
$RecentProfilesDaysTextBox.Text = 90
$SelectProfileGroupBox.Controls.Add($RecentProfilesDaysTextBox)
# Only recent profiles check box
$RecentProfilesCheckBox = New-Object System.Windows.Forms.CheckBox
$RecentProfilesCheckBox.Text = 'Migrate all profiles logged into within this amount of days:'
$RecentProfilesCheckBox.Location = New-Object System.Drawing.Size(15, 50)
$RecentProfilesCheckBox.Size = New-Object System.Drawing.Size(200, 40)
$RecentProfilesCheckBox.Add_Click({
if ($RecentProfilesCheckBox.Checked -eq $true) {
Update-Log "All profiles logged into within the last $($RecentProfilesDaysTextBox.Text) days will be saved."
$SelectProfileButton.Enabled = $false
} else {
Update-Log "Recent profile save disabled." -Color Yellow
$SelectProfileButton.Enabled = $true
}
})
$SelectProfileGroupBox.Controls.Add($RecentProfilesCheckBox)
# Alternative save location group box
$SaveDestinationGroupBox = New-Object System.Windows.Forms.GroupBox
$SaveDestinationGroupBox.Location = New-Object System.Drawing.Size(240, 110)
$SaveDestinationGroupBox.Size = New-Object System.Drawing.Size(220, 100)
$SaveDestinationGroupBox.Text = 'Save State Destination'
$OldComputerTabPage.Controls.Add($SaveDestinationGroupBox)
# Save path
$SaveDestinationTextBox = New-Object System.Windows.Forms.TextBox
$SaveDestinationTextBox.Text = $MigrationStorePath
$SaveDestinationTextBox.Location = New-Object System.Drawing.Size(5, 20)
$SaveDestinationTextBox.Size = New-Object System.Drawing.Size(210, 20)
$SaveDestinationGroupBox.Controls.Add($SaveDestinationTextBox)
# Alternative save check box
$SaveRemotelyCheckBox = New-Object System.Windows.Forms.CheckBox
$SaveRemotelyCheckBox.Text = 'Save on new computer'
$SaveRemotelyCheckBox.Checked = $true
$SaveRemotelyCheckBox.Location = New-Object System.Drawing.Size(45, 45)
$SaveRemotelyCheckBox.Size = New-Object System.Drawing.Size(150, 20)
$SaveRemotelyCheckBox.Add_Click({
if ($SaveRemotelyCheckBox.Checked -eq $true) {
$OldComputerInfoGroupBox.Enabled = $true
Update-Log 'Local save destination disabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Save state will be stored on the new computer and network checks will be processed normally.'
} else {
$OldComputerInfoGroupBox.Enabled = $false
Update-Log 'Local save destination enabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Save state will be stored locally and network checks will be skipped.'
}
})
$SaveDestinationGroupBox.Controls.Add($SaveRemotelyCheckBox)
# Change save destination button
$ChangeSaveDestinationButton = New-Object System.Windows.Forms.Button
$ChangeSaveDestinationButton.Location = New-Object System.Drawing.Size(35, 70)
$ChangeSaveDestinationButton.Size = New-Object System.Drawing.Size(60, 20)
$ChangeSaveDestinationButton.Text = 'Change'
$ChangeSaveDestinationButton.Add_Click({ Set-SaveDirectory -Type Destination })
$SaveDestinationGroupBox.Controls.Add($ChangeSaveDestinationButton)
# Reset save destination button
$ResetSaveDestinationButton = New-Object System.Windows.Forms.Button
$ResetSaveDestinationButton.Location = New-Object System.Drawing.Size(120, 70)
$ResetSaveDestinationButton.Size = New-Object System.Drawing.Size(65, 20)
$ResetSaveDestinationButton.Text = 'Reset'
$ResetSaveDestinationButton.Add_Click({
Update-Log "Resetting save directory to [$MigrationStorePath]."
$SaveDestinationTextBox.Text = $MigrationStorePath
})
$SaveDestinationGroupBox.Controls.Add($ResetSaveDestinationButton)
# Inclusions group box
$InclusionsGroupBox = New-Object System.Windows.Forms.GroupBox
$InclusionsGroupBox.Location = New-Object System.Drawing.Size(10, 110)
$InclusionsGroupBox.Size = New-Object System.Drawing.Size(220, 140)
$InclusionsGroupBox.Text = 'Data to Include'
$OldComputerTabPage.Controls.Add($InclusionsGroupBox)
# AppData check box CSIDL_APPDATA
$IncludeAppDataCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeAppDataCheckBox.Checked = $DefaultIncludeAppData
$IncludeAppDataCheckBox.Text = 'AppData'
$IncludeAppDataCheckBox.Location = New-Object System.Drawing.Size(10, 15)
$IncludeAppDataCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeAppDataCheckBox.Add_Click({
$ComponentName = $IncludeAppDataCheckBox.Text
if ($IncludeAppDataCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included."
}
})
$InclusionsGroupBox.Controls.Add($IncludeAppDataCheckBox)
# Local AppData check box CSIDL_LOCAL_APPDATA
$IncludeLocalAppDataCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeLocalAppDataCheckBox.Checked = $DefaultIncludeLocalAppData
$IncludeLocalAppDataCheckBox.Text = 'Local AppData'
$IncludeLocalAppDataCheckBox.Location = New-Object System.Drawing.Size(10, 35)
$IncludeLocalAppDataCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeLocalAppDataCheckBox.Add_Click({
$ComponentName = $IncludeLocalAppDataCheckBox.Text
if ($IncludeLocalAppDataCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeLocalAppDataCheckBox)
# Printers check box CSIDL_PRINTERS
$IncludePrintersCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludePrintersCheckBox.Checked = $DefaultIncludePrinters
$IncludePrintersCheckBox.Text = 'Printers'
$IncludePrintersCheckBox.Location = New-Object System.Drawing.Size(10, 55)
$IncludePrintersCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludePrintersCheckBox.Add_Click({
$ComponentName = $IncludePrintersCheckBox.Text
if ($IncludePrintersCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludePrintersCheckBox)
# Recycle Bin check box CSIDL_BITBUCKET
$IncludeRecycleBinCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeRecycleBinCheckBox.Checked = $DefaultIncludeRecycleBin
$IncludeRecycleBinCheckBox.Text = 'Recycle Bin'
$IncludeRecycleBinCheckBox.Location = New-Object System.Drawing.Size(10, 75)
$IncludeRecycleBinCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeRecycleBinCheckBox.Add_Click({
$ComponentName = $IncludeRecycleBinCheckBox.Text
if ($IncludeRecycleBinCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeRecycleBinCheckBox)
# My Documents check box CSIDL_MYDOCUMENTS and CSIDL_PERSONAL
$IncludeMyDocumentsCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeMyDocumentsCheckBox.Checked = $DefaultIncludeMyDocuments
$IncludeMyDocumentsCheckBox.Text = 'My Documents'
$IncludeMyDocumentsCheckBox.Location = New-Object System.Drawing.Size(10, 95)
$IncludeMyDocumentsCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeMyDocumentsCheckBox.Add_Click({
$ComponentName = $IncludeMyDocumentsCheckBox.Text
if ($IncludeMyDocumentsCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeMyDocumentsCheckBox)
# Wallpapers
$IncludeWallpapersCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeWallpapersCheckBox.Checked = $DefaultIncludeWallpapers
$IncludeWallpapersCheckBox.Text = 'Wallpapers'
$IncludeWallpapersCheckBox.Location = New-Object System.Drawing.Size(10, 115)
$IncludeWallpapersCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeWallpapersCheckBox.Add_Click({
$ComponentName = $IncludeWallpapersCheckBox.Text
if ($IncludeWallpapersCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeWallpapersCheckBox)
# Desktop check box CSIDL_DESKTOP and CSIDL_DESKTOPDIRECTORY
$IncludeDesktopCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeDesktopCheckBox.Checked = $DefaultIncludeDesktop
$IncludeDesktopCheckBox.Text = 'Desktop'
$IncludeDesktopCheckBox.Location = New-Object System.Drawing.Size(110, 15)
$IncludeDesktopCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeDesktopCheckBox.Add_Click({
$ComponentName = $IncludeDesktopCheckBox.Text
if ($IncludeDesktopCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeDesktopCheckBox)
# Favorites check box CSIDL_FAVORITES
$IncludeFavoritesCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeFavoritesCheckBox.Checked = $DefaultIncludeFavorites
$IncludeFavoritesCheckBox.Text = 'Favorites'
$IncludeFavoritesCheckBox.Location = New-Object System.Drawing.Size(110, 35)
$IncludeFavoritesCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeFavoritesCheckBox.Add_Click({
$ComponentName = $IncludeFavoritesCheckBox.Text
if ($IncludeFavoritesCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeFavoritesCheckBox)
# My Music check box CSIDL_MYMUSIC
$IncludeMyMusicCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeMyMusicCheckBox.Checked = $DefaultIncludeMyMusic
$IncludeMyMusicCheckBox.Text = 'My Music'
$IncludeMyMusicCheckBox.Location = New-Object System.Drawing.Size(110, 55)
$IncludeMyMusicCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeMyMusicCheckBox.Add_Click({
$ComponentName = $IncludeMyMusicCheckBox.Text
if ($IncludeMyMusicCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeMyMusicCheckBox)
# My Pictures check box CSIDL_MYPICTURES
$IncludeMyPicturesCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeMyPicturesCheckBox.Checked = $DefaultIncludeMyPictures
$IncludeMyPicturesCheckBox.Text = 'My Pictures'
$IncludeMyPicturesCheckBox.Location = New-Object System.Drawing.Size(110, 75)
$IncludeMyPicturesCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeMyPicturesCheckBox.Add_Click({
$ComponentName = $IncludeMyPicturesCheckBox.Text
if ($IncludeMyPicturesCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeMyPicturesCheckBox)
# My Video check box CSIDL_MYVIDEO
$IncludeMyVideoCheckBox = New-Object System.Windows.Forms.CheckBox
$IncludeMyVideoCheckBox.Checked = $DefaultIncludeMyVideo
$IncludeMyVideoCheckBox.Text = 'My Video'
$IncludeMyVideoCheckBox.Location = New-Object System.Drawing.Size(110, 95)
$IncludeMyVideoCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$IncludeMyVideoCheckBox.Add_Click({
$ComponentName = $IncludeMyVideoCheckBox.Text
if ($IncludeMyVideoCheckBox.Checked -eq $true) {
Update-Log "$ComponentName will be included."
if ($SelectedXMLS) {
Remove-variable -Name SelectedXMLS -Scope Script -Force
Update-Log "Checkbox selection was made, removed Custom XML list." -Color Yellow
}
} else {
Update-Log "$ComponentName will not be included." -Color Yellow
}
})
$InclusionsGroupBox.Controls.Add($IncludeMyVideoCheckBox)
# Custom XML Box
$IncludeCustomXMLButton = New-Object System.Windows.Forms.Button
$IncludeCustomXMLButton.Text = 'Custom XML(s)'
$IncludeCustomXMLButton.Location = New-Object System.Drawing.Size(110, 115)
$IncludeCustomXMLButton.Size = New-Object System.Drawing.Size(100, 20)
$IncludeCustomXMLButton.Add_Click({
# Create an array object as well as clear any existing Custom XML list if present
$Script:DiscoveredXMLS = @()
$Script:SelectedXMLS = @()
Update-Log "Please wait while Custom XML Files are found..."
$Script:DiscoveredXMLS = Get-ChildItem "$Script:USMTPath\*.xml" -Exclude "MigLog.xml"
# Create a Description property
$Script:DiscoveredXMLS | Add-Member -NotePropertyName Description -NotePropertyValue "No Description Available"
foreach ($XMLFile in $Script:DiscoveredXMLS) {
$XMLDescriptionFile = $XmlFIle -Replace ".xml",".txt"
if (Test-path $XMLDescriptionFIle) {
$XMLDescription = get-content $XMLDescriptionFile
$XmlFile.Description = $XMLDescription
}
}
$Script:DiscoveredXMLS | Select-Object -Property Name, Description |
Out-GridView -Title 'Custom XML file selection' -OutputMode Multiple |
ForEach-Object { $Script:SelectedXMLS += $_.Name }
Update-Log "Xmls(s) selected for migration:"
foreach ($XML in $Script:SelectedXMLS) { Update-Log $XML }
# Uncheck other Selections
$IncludeAppDataCheckBox.Checked = $False
$IncludeLocalAppDataCheckBox.Checked = $False
$IncludePrintersCheckBox.Checked = $False
$IncludeRecycleBinCheckBox.Checked = $False
$IncludeWallpapersCheckBox.Checked = $False
$IncludeMyDocumentsCheckBox.Checked = $False
$IncludeDesktopCheckBox.Checked = $False
$IncludeFavoritesCheckBox.Checked = $False
$IncludeMyMusicCheckBox.Checked = $False
$IncludeMyPicturesCheckBox.Checked = $False
$IncludeMyPicturesCheckBox.Checked = $False
$IncludeMyVideoCheckBox.Checked = $False
})
$InclusionsGroupBox.Controls.Add($IncludeCustomXMLButton)
# Extra directories selection group box
$ExtraDirectoriesGroupBox = New-Object System.Windows.Forms.GroupBox
$ExtraDirectoriesGroupBox.Location = New-Object System.Drawing.Size(10, 260)
$ExtraDirectoriesGroupBox.Size = New-Object System.Drawing.Size(220, 200)
$ExtraDirectoriesGroupBox.Text = 'Extra Directories to Include'
$OldComputerTabPage.Controls.Add($ExtraDirectoriesGroupBox)
# Extra directories data table
$ExtraDirectoriesDataGridView = New-Object System.Windows.Forms.DataGridView
$ExtraDirectoriesDataGridView.Location = New-Object System.Drawing.Size(5, 20)
$ExtraDirectoriesDataGridView.Size = New-Object System.Drawing.Size(210, 170)
$ExtraDirectoriesDataGridView.ReadOnly = $true
$ExtraDirectoriesDataGridView.AllowUserToAddRows = $false
$ExtraDirectoriesDataGridView.AllowUserToResizeRows = $false
$ExtraDirectoriesDataGridView.AllowUserToResizeColumns = $false
$ExtraDirectoriesDataGridView.MultiSelect = $false
$ExtraDirectoriesDataGridView.ColumnCount = 1
$ExtraDirectoriesDataGridView.AutoSizeColumnsMode = 'Fill'
$ExtraDirectoriesDataGridView.ColumnHeadersVisible = $false
$ExtraDirectoriesDataGridView.RowHeadersVisible = $false
$ExtraDirectoriesGroupBox.Controls.Add($ExtraDirectoriesDataGridView)
# Remove Extra directory button
$RemoveExtraDirectoryButton = New-Object System.Windows.Forms.Button
$RemoveExtraDirectoryButton.Location = New-Object System.Drawing.Size(0, 150)
$RemoveExtraDirectoryButton.Size = New-Object System.Drawing.Size(20, 20)
$RemoveExtraDirectoryButton.Text = '-'
$RemoveExtraDirectoryButton.Font = 'Consolas, 14'
$RemoveExtraDirectoryButton.Add_Click({ Remove-ExtraDirectory })
$ExtraDirectoriesDataGridView.Controls.Add($RemoveExtraDirectoryButton)
# Add Extra directory button
$AddExtraDirectoryButton = New-Object System.Windows.Forms.Button
$AddExtraDirectoryButton.Location = New-Object System.Drawing.Size(20, 150)
$AddExtraDirectoryButton.Size = New-Object System.Drawing.Size(20, 20)
$AddExtraDirectoryButton.Text = '+'
$AddExtraDirectoryButton.Font = 'Consolas, 14'
$AddExtraDirectoryButton.Add_Click({ Add-ExtraDirectory })
$ExtraDirectoriesDataGridView.Controls.Add($AddExtraDirectoryButton)
# Scanstate Encryption check box
$ScanStateEncryptionCheckBox = New-Object System.Windows.Forms.CheckBox
$ScanStateEncryptionCheckBox.Text = 'Encrypt captured Data.'
$ScanStateEncryptionCheckBox.Location = New-Object System.Drawing.Size(280, 340)
$ScanStateEncryptionCheckBox.Size = New-Object System.Drawing.Size(300, 30)
$ScanStateEncryptionCheckBox.Add_Click({
if ($ScanStateEncryptionCheckBox.Checked -eq $true) {
# Prompt for Encryption password
Update-Log 'Encryption for save state enabled, prompting for password.' -Color 'Yellow'
Read-Password
#Disable the use of the encryption password was not sucessfully set.
if ($Script:EncryptionPasswordSet -NE $True){
Update-Log "Encryption password was not set." -Color 'Yellow'
$ScanStateEncryptionCheckBox.Checked = $false
} else {
Update-Log 'Encyption password successfully set.' -Color 'LightBlue'
}
}
})
$OldComputerTabPage.Controls.Add($ScanStateEncryptionCheckBox)
# Uncompressed storage check box
$UncompressedCheckBox = New-Object System.Windows.Forms.CheckBox
$UncompressedCheckBox.Text = 'Uncompressed storage'
$UncompressedCheckBox.Location = New-Object System.Drawing.Size(280, 370)
$UncompressedCheckBox.Size = New-Object System.Drawing.Size(300, 30)
$UncompressedCheckBox.Add_Click({
if ($UncompressedCheckBox.Checked -eq $true) {
Update-Log 'Uncompressed save state enabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Save state will be stored as uncompressed flat files.'
} else {
Update-Log 'Uncompressed save state disabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Save state will be stored as a compressed file.'
}
})
$OldComputerTabPage.Controls.Add($UncompressedCheckBox)
# Migrate button
$MigrateButton_OldPage = New-Object System.Windows.Forms.Button
$MigrateButton_OldPage.Location = New-Object System.Drawing.Size(300, 400)
$MigrateButton_OldPage.Size = New-Object System.Drawing.Size(100, 40)
$MigrateButton_OldPage.Font = New-Object System.Drawing.Font('Calibri', 16, [System.Drawing.FontStyle]::Bold)
$MigrateButton_OldPage.Text = 'Migrate'
$MigrateButton_OldPage.Add_Click({ Save-UserState })
$OldComputerTabPage.Controls.Add($MigrateButton_OldPage)
# Create new computer tab
$NewComputerTabPage = New-Object System.Windows.Forms.TabPage
$NewComputerTabPage.DataBindings.DefaultDataSourceUpdateMode = 0
$NewComputerTabPage.UseVisualStyleBackColor = $true
$NewComputerTabPage.Text = 'New Computer'
$TabControl.Controls.Add($NewComputerTabPage)
# Computer info group
$NewComputerInfoGroupBox = New-Object System.Windows.Forms.GroupBox
$NewComputerInfoGroupBox.Location = New-Object System.Drawing.Size(10, 10)
$NewComputerInfoGroupBox.Size = New-Object System.Drawing.Size(450, 87)
$NewComputerInfoGroupBox.Text = 'Computer Info'
$NewComputerTabPage.Controls.Add($NewComputerInfoGroupBox)
# Alternative save location group box
$SaveSourceGroupBox = New-Object System.Windows.Forms.GroupBox
$SaveSourceGroupBox.Location = New-Object System.Drawing.Size(240, 110)
$SaveSourceGroupBox.Size = New-Object System.Drawing.Size(220, 87)
$SaveSourceGroupBox.Text = 'Save State Source'
$NewComputerTabPage.Controls.Add($SaveSourceGroupBox)
# Save path
$SaveSourceTextBox = New-Object System.Windows.Forms.TextBox
$SaveSourceTextBox.Text = $MigrationStorePath
$SaveSourceTextBox.Location = New-Object System.Drawing.Size(5, 20)
$SaveSourceTextBox.Size = New-Object System.Drawing.Size(210, 20)
$SaveSourceGroupBox.Controls.Add($SaveSourceTextBox)
# Change save destination button
$ChangeSaveSourceButton = New-Object System.Windows.Forms.Button
$ChangeSaveSourceButton.Location = New-Object System.Drawing.Size(5, 50)
$ChangeSaveSourceButton.Size = New-Object System.Drawing.Size(60, 20)
$ChangeSaveSourceButton.Text = 'Change'
$ChangeSaveSourceButton.Add_Click({
Set-SaveDirectory -Type Source
$OldComputerNameTextBox_NewPage.Text = Get-SaveState
Show-DomainInfo
})
$SaveSourceGroupBox.Controls.Add($ChangeSaveSourceButton)
# Reset save destination button
$ResetSaveSourceButton = New-Object System.Windows.Forms.Button
$ResetSaveSourceButton.Location = New-Object System.Drawing.Size(75, 50)
$ResetSaveSourceButton.Size = New-Object System.Drawing.Size(65, 20)
$ResetSaveSourceButton.Text = 'Reset'
$ResetSaveSourceButton.Add_Click({
Update-Log "Resetting save state directory to [$MigrationStorePath]."
$SaveSourceTextBox.Text = $MigrationStorePath
$OldComputerNameTextBox_NewPage.Text = Get-SaveState
Show-DomainInfo
})
$SaveSourceGroupBox.Controls.Add($ResetSaveSourceButton)
# Search for save state in given SaveSourceTextBox path
$ResetSaveSourceButton = New-Object System.Windows.Forms.Button
$ResetSaveSourceButton.Location = New-Object System.Drawing.Size(150, 50)
$ResetSaveSourceButton.Size = New-Object System.Drawing.Size(65, 20)
$ResetSaveSourceButton.Text = 'Search'
$ResetSaveSourceButton.Add_Click({
$OldComputerNameTextBox_NewPage.Text = Get-SaveState
Show-DomainInfo
})
$SaveSourceGroupBox.Controls.Add($ResetSaveSourceButton)
# Name label
$ComputerNameLabel_NewPage = New-Object System.Windows.Forms.Label
$ComputerNameLabel_NewPage.Location = New-Object System.Drawing.Size(100, 12)
$ComputerNameLabel_NewPage.Size = New-Object System.Drawing.Size(100, 22)
$ComputerNameLabel_NewPage.Text = 'Computer Name'
$NewComputerInfoGroupBox.Controls.Add($ComputerNameLabel_NewPage)
# IP label
$ComputerIPLabel_NewPage = New-Object System.Windows.Forms.Label
$ComputerIPLabel_NewPage.Location = New-Object System.Drawing.Size(230, 12)
$ComputerIPLabel_NewPage.Size = New-Object System.Drawing.Size(80, 22)
$ComputerIPLabel_NewPage.Text = 'IP Address'
$NewComputerInfoGroupBox.Controls.Add($ComputerIPLabel_NewPage)
# Old Computer name label
$OldComputerNameLabel_NewPage = New-Object System.Windows.Forms.Label
$OldComputerNameLabel_NewPage.Location = New-Object System.Drawing.Size(12, 35)
$OldComputerNameLabel_NewPage.Size = New-Object System.Drawing.Size(80, 22)
$OldComputerNameLabel_NewPage.Text = 'Old Computer'
$NewComputerInfoGroupBox.Controls.Add($OldComputerNameLabel_NewPage)
# Old Computer name text box
$OldComputerNameTextBox_NewPage = New-Object System.Windows.Forms.TextBox
$OldComputerNameTextBox_NewPage.ReadOnly = $true
$OldComputerNameTextBox_NewPage.Location = New-Object System.Drawing.Size(100, 34)
$OldComputerNameTextBox_NewPage.Size = New-Object System.Drawing.Size(120, 20)
$OldComputerNameTextBox_NewPage.Text = Get-SaveState
$NewComputerInfoGroupBox.Controls.Add($OldComputerNameTextBox_NewPage)
# Old Computer IP text box
$OldComputerIPTextBox_NewPage = New-Object System.Windows.Forms.TextBox
$OldComputerIPTextBox_NewPage.Location = New-Object System.Drawing.Size(230, 34)
$OldComputerIPTextBox_NewPage.Size = New-Object System.Drawing.Size(90, 20)
$OldComputerIPTextBox_NewPage.Add_TextChanged({
if ($ConnectionCheckBox_NewPage.Checked) {
Update-Log 'Computer IP address changed, connection status unverified.' -Color 'Yellow'
$ConnectionCheckBox_NewPage.Checked = $false
}
})
$NewComputerInfoGroupBox.Controls.Add($OldComputerIPTextBox_NewPage)
# New Computer name label
$NewComputerNameLabel_NewPage = New-Object System.Windows.Forms.Label
$NewComputerNameLabel_NewPage.Location = New-Object System.Drawing.Size(12, 57)
$NewComputerNameLabel_NewPage.Size = New-Object System.Drawing.Size(80, 22)
$NewComputerNameLabel_NewPage.Text = 'New Computer'
$NewComputerInfoGroupBox.Controls.Add($NewComputerNameLabel_NewPage)
# New Computer name text box
$NewComputerNameTextBox_NewPage = New-Object System.Windows.Forms.TextBox
$NewComputerNameTextBox_NewPage.ReadOnly = $true
$NewComputerNameTextBox_NewPage.Location = New-Object System.Drawing.Size(100, 56)
$NewComputerNameTextBox_NewPage.Size = New-Object System.Drawing.Size(120, 20)
$NewComputerNameTextBox_NewPage.Text = $env:COMPUTERNAME
$NewComputerInfoGroupBox.Controls.Add($NewComputerNameTextBox_NewPage)
# New Computer IP text box
$NewComputerIPTextBox_NewPage = New-Object System.Windows.Forms.TextBox
$NewComputerIPTextBox_NewPage.ReadOnly = $true
$NewComputerIPTextBox_NewPage.Location = New-Object System.Drawing.Size(230, 56)
$NewComputerIPTextBox_NewPage.Size = New-Object System.Drawing.Size(90, 20)
$NewComputerIPTextBox_NewPage.Text = Get-IPAddress
$NewComputerInfoGroupBox.Controls.Add($NewComputerIPTextBox_NewPage)
# Button to test connection to new computer
$TestConnectionButton_NewPage = New-Object System.Windows.Forms.Button
$TestConnectionButton_NewPage.Location = New-Object System.Drawing.Size(335, 33)
$TestConnectionButton_NewPage.Size = New-Object System.Drawing.Size(100, 22)
$TestConnectionButton_NewPage.Text = 'Test Connection'
$TestConnectionButton_NewPage.Add_Click({
$TestComputerConnectionParams = @{
ComputerNameTextBox = $OldComputerNameTextBox_NewPage
ComputerIPTextBox = $OldComputerIPTextBox_NewPage
ConnectionCheckBox = $ConnectionCheckBox_NewPage
}
Test-ComputerConnection @TestComputerConnectionParams
})
$NewComputerInfoGroupBox.Controls.Add($TestConnectionButton_NewPage)
# Connected check box
$ConnectionCheckBox_NewPage = New-Object System.Windows.Forms.CheckBox
$ConnectionCheckBox_NewPage.Enabled = $false
$ConnectionCheckBox_NewPage.Text = 'Connected'
$ConnectionCheckBox_NewPage.Location = New-Object System.Drawing.Size(336, 58)
$ConnectionCheckBox_NewPage.Size = New-Object System.Drawing.Size(100, 20)
$NewComputerInfoGroupBox.Controls.Add($ConnectionCheckBox_NewPage)
# Cross-domain migration group box
$CrossDomainMigrationGroupBox = New-Object System.Windows.Forms.GroupBox
$CrossDomainMigrationGroupBox.Location = New-Object System.Drawing.Size(10, 110)
$CrossDomainMigrationGroupBox.Size = New-Object System.Drawing.Size(220, 87)
$CrossDomainMigrationGroupBox.Text = 'Cross-Domain Migration'
$NewComputerTabPage.Controls.Add($CrossDomainMigrationGroupBox)
# Domain label
$DomainLabel = New-Object System.Windows.Forms.Label
$DomainLabel.Location = New-Object System.Drawing.Size(70, 12)
$DomainLabel.Size = New-Object System.Drawing.Size(50, 22)
$DomainLabel.Text = 'Domain'
$CrossDomainMigrationGroupBox.Controls.Add($DomainLabel)
# User name label
$UserNameLabel = New-Object System.Windows.Forms.Label
$UserNameLabel.Location = New-Object System.Drawing.Size(125, 12)
$UserNameLabel.Size = New-Object System.Drawing.Size(80, 22)
$UserNameLabel.Text = 'User Name'
$CrossDomainMigrationGroupBox.Controls.Add($UserNameLabel)
# Old user label
$OldUserLabel = New-Object System.Windows.Forms.Label
$OldUserLabel.Location = New-Object System.Drawing.Size(12, 35)
$OldUserLabel.Size = New-Object System.Drawing.Size(50, 22)
$OldUserLabel.Text = 'Old User'
$CrossDomainMigrationGroupBox.Controls.Add($OldUserLabel)
# Old domain text box
$OldDomainTextBox = New-Object System.Windows.Forms.TextBox
$OldDomainTextBox.ReadOnly = $true
$OldDomainTextBox.Location = New-Object System.Drawing.Size(70, 34)
$OldDomainTextBox.Size = New-Object System.Drawing.Size(40, 20)
$OldDomainTextBox.Text = $OldComputerNameTextBox_NewPage.Text
$CrossDomainMigrationGroupBox.Controls.Add($OldDomainTextBox)
# Old user slash label
$OldUserSlashLabel = New-Object System.Windows.Forms.Label
$OldUserSlashLabel.Location = New-Object System.Drawing.Size(110, 33)
$OldUserSlashLabel.Size = New-Object System.Drawing.Size(10, 20)
$OldUserSlashLabel.Text = '\'
$OldUserSlashLabel.Font = New-Object System.Drawing.Font('Calibri', 12)
$CrossDomainMigrationGroupBox.Controls.Add($OldUserSlashLabel)
# Old user name text box
$OldUserNameTextBox = New-Object System.Windows.Forms.TextBox
$OldUserNameTextBox.ReadOnly = $true
$OldUserNameTextBox.Location = New-Object System.Drawing.Size(125, 34)
$OldUserNameTextBox.Size = New-Object System.Drawing.Size(80, 20)
$CrossDomainMigrationGroupBox.Controls.Add($OldUserNameTextBox)
# New user label
$NewUserLabel = New-Object System.Windows.Forms.Label
$NewUserLabel.Location = New-Object System.Drawing.Size(12, 57)
$NewUserLabel.Size = New-Object System.Drawing.Size(55, 22)
$NewUserLabel.Text = 'New User'
$CrossDomainMigrationGroupBox.Controls.Add($NewUserLabel)
# New domain text box
$NewDomainTextBox = New-Object System.Windows.Forms.TextBox
$NewDomainTextBox.ReadOnly = $true
$NewDomainTextBox.Location = New-Object System.Drawing.Size(70, 56)
$NewDomainTextBox.Size = New-Object System.Drawing.Size(40, 20)
$NewDomainTextBox.Text = $DefaultDomain
$CrossDomainMigrationGroupBox.Controls.Add($NewDomainTextBox)
# New user slash label
$NewUserSlashLabel = New-Object System.Windows.Forms.Label
$NewUserSlashLabel.Location = New-Object System.Drawing.Size(110, 56)
$NewUserSlashLabel.Size = New-Object System.Drawing.Size(10, 20)
$NewUserSlashLabel.Text = '\'
$NewUserSlashLabel.Font = New-Object System.Drawing.Font('Calibri', 12)
$CrossDomainMigrationGroupBox.Controls.Add($NewUserSlashLabel)
# New user name text box
$NewUserNameTextBox = New-Object System.Windows.Forms.TextBox
$NewUserNameTextBox.Location = New-Object System.Drawing.Size(125, 56)
$NewUserNameTextBox.Size = New-Object System.Drawing.Size(80, 20)
$NewUserNameTextBox.Text = $env:USERNAME
$CrossDomainMigrationGroupBox.Controls.Add($NewUserNameTextBox)
# Override check box
$OverrideCheckBox = New-Object System.Windows.Forms.CheckBox
$OverrideCheckBox.Text = 'Save state task completed'
$OverrideCheckBox.Location = New-Object System.Drawing.Size(280, 225)
$OverrideCheckBox.Size = New-Object System.Drawing.Size(300, 30)
$OverrideCheckBox.Add_Click({
if ($OverrideCheckBox.Checked -eq $true) {
$NewComputerInfoGroupBox.Enabled = $false
Update-Log 'Network connection override enabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Save state process on old computer is assumed to be completed and no network checks will be processed during load state.'
} else {
$NewComputerInfoGroupBox.Enabled = $true
Update-Log 'Network connection override enabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Network checks will be processed during load state.'
}
})
$NewComputerTabPage.Controls.Add($OverrideCheckBox)
# LoadState Encryption check box
$LoadStateEncryptionCheckBox = New-Object System.Windows.Forms.CheckBox
$LoadStateEncryptionCheckBox.Text = 'Saved data was encrypted.'
$LoadStateEncryptionCheckBox.Location = New-Object System.Drawing.Size(280, 250)
$LoadStateEncryptionCheckBox.Size = New-Object System.Drawing.Size(300, 30)
$LoadStateEncryptionCheckBox.Add_Click({
if ($LoadStateEncryptionCheckBox.Checked -eq $true) {
# Prompt for Encryption password
Update-Log 'Encryption for load state enabled, prompting for password.' -Color 'Yellow'
Read-Password
# Disable the use of the encryption password was not sucessfully set.
if ($Script:EncryptionPasswordSet -NE $True){
Update-Log 'Encryption password was not set.' -Color 'Yellow'
$LoadStateEncryptionCheckBox.Checked = $false
} else {
Update-Log 'Encyption password successfully set.' -Color 'LightBlue'
}
}
})
$NewComputerTabPage.Controls.Add($LoadStateEncryptionCheckBox)
Show-DomainInfo
# Migrate button
$MigrateButton_NewPage = New-Object System.Windows.Forms.Button
$MigrateButton_NewPage.Location = New-Object System.Drawing.Size(300, 400)
$MigrateButton_NewPage.Size = New-Object System.Drawing.Size(100, 40)
$MigrateButton_NewPage.Font = New-Object System.Drawing.Font('Calibri', 16, [System.Drawing.FontStyle]::Bold)
$MigrateButton_NewPage.Text = 'Migrate'
$MigrateButton_NewPage.Add_Click({ Restore-UserState })
$NewComputerTabPage.Controls.Add($MigrateButton_NewPage)
# Create email settings tab
$EmailSettingsTabPage = New-Object System.Windows.Forms.TabPage
$EmailSettingsTabPage.DataBindings.DefaultDataSourceUpdateMode = 0
$EmailSettingsTabPage.UseVisualStyleBackColor = $true
$EmailSettingsTabPage.Text = 'Email Settings'
$TabControl.Controls.Add($EmailSettingsTabPage)
# Email enabled check box
$EmailCheckBox = New-Object System.Windows.Forms.CheckBox
$EmailCheckBox.Text = 'Enabled'
$EmailCheckBox.Location = New-Object System.Drawing.Size(10, 10)
$EmailCheckBox.Size = New-Object System.Drawing.Size(300, 30)
$EmailCheckBox.Checked = $DefaultEmailEnabled
$EmailCheckBox.Add_Click({
if ($EmailCheckBox.Checked -eq $true) {
Update-Log 'Email enabled' -Color 'Yellow' -NoNewLine
Update-Log ' - Results will be emailed to supplied email addresses (if your account has email relay access).'
} else {
Update-Log 'Email disabled' -Color 'Yellow' -NoNewLine
Update-Log ' - No results will be emailed.'
}
})
$EmailSettingsTabPage.Controls.Add($EmailCheckBox)
# SMTP server group box
$SMTPServerGroupBox = New-Object System.Windows.Forms.GroupBox
$SMTPServerGroupBox.Location = New-Object System.Drawing.Size(10, 60)
$SMTPServerGroupBox.Size = New-Object System.Drawing.Size(220, 80)
$SMTPServerGroupBox.Text = 'SMTP Server'
$EmailSettingsTabPage.Controls.Add($SMTPServerGroupBox)
# SMTP server text box
$SMTPServerTextBox = New-Object System.Windows.Forms.TextBox
$SMTPServerTextBox.Location = New-Object System.Drawing.Size(5, 20)
$SMTPServerTextBox.Size = New-Object System.Drawing.Size(210, 25)
$SMTPServerTextBox.Text = $DefaultSMTPServer
$SMTPServerGroupBox.Controls.Add($SMTPServerTextBox)
# Button to test connection to SMTP server
$SMTPConnectionButton = New-Object System.Windows.Forms.Button
$SMTPConnectionButton.Location = New-Object System.Drawing.Size(9, 50)
$SMTPConnectionButton.Size = New-Object System.Drawing.Size(100, 22)
$SMTPConnectionButton.Text = 'Test Connection'
$SMTPConnectionButton.Add_Click({
Update-Log "Testing connection to [$($SMTPServerTextBox.Text)]..." -NoNewLine
if (Test-Connection $SMTPServerTextBox.Text -Quiet) {
Update-Log "reachable."
$SMTPConnectionCheckBox.Checked = $true
} else {
Update-Log "unreachable." -Color 'Yellow'
$SMTPConnectionCheckBox.Checked = $false
}
})
$SMTPServerGroupBox.Controls.Add($SMTPConnectionButton)
# SMTP server reachable check box
$SMTPConnectionCheckBox = New-Object System.Windows.Forms.CheckBox
$SMTPConnectionCheckBox.Enabled = $false
$SMTPConnectionCheckBox.Text = 'Reachable'
$SMTPConnectionCheckBox.Location = New-Object System.Drawing.Size(135, 50)
$SMTPConnectionCheckBox.Size = New-Object System.Drawing.Size(100, 20)
$SMTPServerGroupBox.Controls.Add($SMTPConnectionCheckBox)
# If email is enabled, check if SMTP server is reachable
if ($DefaultEmailEnabled -and -not (Test-Connection -ComputerName $SMTPServerTextBox.Text -Quiet)) {
Update-Log "Email disabled because SMTP server [$($SMTPServerTextBox.Text)] is unreachable." -Color 'Yellow'
$SMTPConnectionCheckBox.Checked = $false
} elseif ($DefaultEmailEnabled -and (Test-Connection -ComputerName $SMTPServerTextBox.Text -Quiet)) {
Update-Log "SMTP server [$($SMTPServerTextBox.Text)] is reachable."
$SMTPConnectionCheckBox.Checked = $true
}
# Email sender group box
$EmailSenderGroupBox = New-Object System.Windows.Forms.GroupBox
$EmailSenderGroupBox.Location = New-Object System.Drawing.Size(10, 150)
$EmailSenderGroupBox.Size = New-Object System.Drawing.Size(220, 50)
$EmailSenderGroupBox.Text = 'Email Sender'
$EmailSettingsTabPage.Controls.Add($EmailSenderGroupBox)
# Email sender text box
$EmailSenderTextBox = New-Object System.Windows.Forms.TextBox
$EmailSenderTextBox.Location = New-Object System.Drawing.Size(5, 20)
$EmailSenderTextBox.Size = New-Object System.Drawing.Size(210, 25)
$EmailSenderTextBox.Text = $DefaultEmailSender
$EmailSenderGroupBox.Controls.Add($EmailSenderTextBox)
# Email recipients selection group box
$EmailRecipientsGroupBox = New-Object System.Windows.Forms.GroupBox
$EmailRecipientsGroupBox.Location = New-Object System.Drawing.Size(10, 230)
$EmailRecipientsGroupBox.Size = New-Object System.Drawing.Size(220, 230)
$EmailRecipientsGroupBox.Text = 'Email Recipients'
$EmailSettingsTabPage.Controls.Add($EmailRecipientsGroupBox)
# Email recipients data table
$EmailRecipientsDataGridView = New-Object System.Windows.Forms.DataGridView
$EmailRecipientsDataGridView.Location = New-Object System.Drawing.Size(5, 20)
$EmailRecipientsDataGridView.Size = New-Object System.Drawing.Size(210, 170)
$EmailRecipientsDataGridView.ReadOnly = $true
$EmailRecipientsDataGridView.AllowUserToAddRows = $false
$EmailRecipientsDataGridView.AllowUserToResizeRows = $false
$EmailRecipientsDataGridView.AllowUserToResizeColumns = $false
$EmailRecipientsDataGridView.MultiSelect = $false
$EmailRecipientsDataGridView.ColumnCount = 1
$EmailRecipientsDataGridView.AutoSizeColumnsMode = 'Fill'
$EmailRecipientsDataGridView.ColumnHeadersVisible = $false
$EmailRecipientsDataGridView.RowHeadersVisible = $false
$EmailRecipientsGroupBox.Controls.Add($EmailRecipientsDataGridView)
# Add default email addresses to data grid view
foreach ($Email in $DefaultEmailRecipients) { $EmailRecipientsDataGridView.Rows.Add($Email) }
# Remove email recipient button
$RemoveEmailRecipientButton = New-Object System.Windows.Forms.Button
$RemoveEmailRecipientButton.Location = New-Object System.Drawing.Size(0, 150)
$RemoveEmailRecipientButton.Size = New-Object System.Drawing.Size(20, 20)
$RemoveEmailRecipientButton.Text = '-'
$RemoveEmailRecipientButton.Font = 'Consolas, 14'
$RemoveEmailRecipientButton.Add_Click({
# Remove selected cell from Email Recipients data grid view
$CurrentCell = $EmailRecipientsDataGridView.CurrentCell
Update-Log "Removed [$($CurrentCell.Value)] from email recipients."
$CurrentRow = $EmailRecipientsDataGridView.Rows[$CurrentCell.RowIndex]
$EmailRecipientsDataGridView.Rows.Remove($CurrentRow)
})
$EmailRecipientsDataGridView.Controls.Add($RemoveEmailRecipientButton)
# Add email recipient button
$AddEmailRecipientButton = New-Object System.Windows.Forms.Button
$AddEmailRecipientButton.Location = New-Object System.Drawing.Size(20, 150)
$AddEmailRecipientButton.Size = New-Object System.Drawing.Size(20, 20)
$AddEmailRecipientButton.Text = '+'
$AddEmailRecipientButton.Font = 'Consolas, 14'
$AddEmailRecipientButton.Add_Click({
Update-Log "Adding to email recipients: $($EmailRecipientToAddTextBox.Text)."
$EmailRecipientsDataGridView.Rows.Add($EmailRecipientToAddTextBox.Text)
})
$EmailRecipientsDataGridView.Controls.Add($AddEmailRecipientButton)
# Email recipient to add text box
$EmailRecipientToAddTextBox = New-Object System.Windows.Forms.TextBox
$EmailRecipientToAddTextBox.Location = New-Object System.Drawing.Size(5, 200)
$EmailRecipientToAddTextBox.Size = New-Object System.Drawing.Size(210, 25)
$EmailRecipientToAddTextBox.Text = 'Recipient@To.Add'
$EmailRecipientsGroupBox.Controls.Add($EmailRecipientToAddTextBox)
# Send test email button
$TestEmailButton = New-Object System.Windows.Forms.Button
$TestEmailButton.Location = New-Object System.Drawing.Size(300, 400)
$TestEmailButton.Size = New-Object System.Drawing.Size(100, 40)
$TestEmailButton.Font = New-Object System.Drawing.Font('Calibri', 14, [System.Drawing.FontStyle]::Bold)
$TestEmailButton.Text = 'Test Email'
$TestEmailButton.Add_Click({ Test-Email })
$EmailSettingsTabPage.Controls.Add($TestEmailButton)
# Create scripts tab
$ScriptsTabPage = New-Object System.Windows.Forms.TabPage
$ScriptsTabPage.DataBindings.DefaultDataSourceUpdateMode = 0
$ScriptsTabPage.UseVisualStyleBackColor = $true
$ScriptsTabPage.Text = 'Scripts'
$TabControl.Controls.Add($ScriptsTabPage)
# Old computer scripts selection group box
$OldComputerScriptsGroupBox = New-Object System.Windows.Forms.GroupBox
$OldComputerScriptsGroupBox.Location = New-Object System.Drawing.Size(10, 10)
$OldComputerScriptsGroupBox.Size = New-Object System.Drawing.Size(450, 220)
$OldComputerScriptsGroupBox.Text = 'Old Computer Scripts'
$ScriptsTabPage.Controls.Add($OldComputerScriptsGroupBox)
# Old computer scripts data table
$OldComputerScriptsDataGridView = New-Object System.Windows.Forms.DataGridView
$OldComputerScriptsDataGridView.Location = New-Object System.Drawing.Size(5, 20)
$OldComputerScriptsDataGridView.Size = New-Object System.Drawing.Size(440, 190)
$OldComputerScriptsDataGridView.ReadOnly = $true
$OldComputerScriptsDataGridView.AllowUserToAddRows = $false
$OldComputerScriptsDataGridView.AllowUserToResizeRows = $false
$OldComputerScriptsDataGridView.AllowUserToResizeColumns = $false
$OldComputerScriptsDataGridView.MultiSelect = $false
$OldComputerScriptsDataGridView.ColumnCount = 1
$OldComputerScriptsDataGridView.AutoSizeColumnsMode = 'Fill'
$OldComputerScriptsDataGridView.ColumnHeadersVisible = $false
$OldComputerScriptsDataGridView.RowHeadersVisible = $false
$OldComputerScriptsGroupBox.Controls.Add($OldComputerScriptsDataGridView)
# Add old computer script to data grid view
$OldComputerScripts = Get-ChildItem -Path "$PSScriptRoot\Scripts\OldComputer" |
Where-Object { -not $_.PSIsContainer }
foreach ($Script in $OldComputerScripts) {
$OldComputerScriptsDataGridView.Rows.Add($Script)
}
# Remove old computer script button
$RemoveOldComputerScriptButton = New-Object System.Windows.Forms.Button
$RemoveOldComputerScriptButton.Location = New-Object System.Drawing.Size(0, 170)
$RemoveOldComputerScriptButton.Size = New-Object System.Drawing.Size(20, 20)
$RemoveOldComputerScriptButton.Text = '-'
$RemoveOldComputerScriptButton.Font = 'Consolas, 14'
$RemoveOldComputerScriptButton.Add_Click({
# Remove selected cell from new computer scripts data grid view
$CurrentCell = $NewComputerScriptsDataGridView.CurrentCell
Update-Log "Removed [$($CurrentCell.Value)] from old computer scripts."
$CurrentRow = $NewComputerScriptsDataGridView.Rows[$CurrentCell.RowIndex]
$NewComputerScriptsDataGridView.Rows.Remove($CurrentRow)
})
$OldComputerScriptsDataGridView.Controls.Add($RemoveOldComputerScriptButton)
# New computer scripts selection group box
$NewComputerScriptsGroupBox = New-Object System.Windows.Forms.GroupBox
$NewComputerScriptsGroupBox.Location = New-Object System.Drawing.Size(10, 240)
$NewComputerScriptsGroupBox.Size = New-Object System.Drawing.Size(450, 220)
$NewComputerScriptsGroupBox.Text = 'New Computer Scripts'
$ScriptsTabPage.Controls.Add($NewComputerScriptsGroupBox)
# New computer scripts data table
$NewComputerScriptsDataGridView = New-Object System.Windows.Forms.DataGridView
$NewComputerScriptsDataGridView.Location = New-Object System.Drawing.Size(5, 20)
$NewComputerScriptsDataGridView.Size = New-Object System.Drawing.Size(440, 190)
$NewComputerScriptsDataGridView.ReadOnly = $true
$NewComputerScriptsDataGridView.AllowUserToAddRows = $false
$NewComputerScriptsDataGridView.AllowUserToResizeRows = $false
$NewComputerScriptsDataGridView.AllowUserToResizeColumns = $false
$NewComputerScriptsDataGridView.MultiSelect = $false
$NewComputerScriptsDataGridView.ColumnCount = 1
$NewComputerScriptsDataGridView.AutoSizeColumnsMode = 'Fill'
$NewComputerScriptsDataGridView.ColumnHeadersVisible = $false
$NewComputerScriptsDataGridView.RowHeadersVisible = $false
$NewComputerScriptsGroupBox.Controls.Add($NewComputerScriptsDataGridView)
# Add new computer script to data grid view
$NewComputerScripts = Get-ChildItem -Path "$PSScriptRoot\Scripts\NewComputer" |
Where-Object { -not $_.PSIsContainer }
foreach ($Script in $NewComputerScripts) {
$NewComputerScriptsDataGridView.Rows.Add($Script)
}
# Remove new computer script button
$RemoveNewComputerScriptButton = New-Object System.Windows.Forms.Button
$RemoveNewComputerScriptButton.Location = New-Object System.Drawing.Size(0, 170)
$RemoveNewComputerScriptButton.Size = New-Object System.Drawing.Size(20, 20)
$RemoveNewComputerScriptButton.Text = '-'
$RemoveNewComputerScriptButton.Font = 'Consolas, 14'
$RemoveNewComputerScriptButton.Add_Click({
# Remove selected cell from new computer scripts data grid view
$CurrentCell = $NewComputerScriptsDataGridView.CurrentCell
Update-Log "Removed [$($CurrentCell.Value)] from new computer scripts."
$CurrentRow = $NewComputerScriptsDataGridView.Rows[$CurrentCell.RowIndex]
$NewComputerScriptsDataGridView.Rows.Remove($CurrentRow)
})
$NewComputerScriptsDataGridView.Controls.Add($RemoveNewComputerScriptButton)
# Debug button
$DebugLabel = New-Object System.Windows.Forms.Label
$DebugLabel.Location = New-Object System.Drawing.Size(974, 495)
$DebugLabel.Size = New-Object System.Drawing.Size(10, 15)
$DebugLabel.Text = '?'
$DebugLabel.Add_Click({
if ($TabControl.SelectedIndex -eq 0) {
Save-UserState -Debug
} elseif ($TabControl.SelectedIndex -eq 1) {
Restore-UserState -Debug
}
})
$Form.Controls.Add($DebugLabel)
# Test if user is using an admin account
Test-IsAdmin
# Test the version of PowerShell and disable incompatible features
Test-PSVersion
# Get the path to the USMT files
Get-USMT
# Show our form
$Form.Add_Shown({$Form.Activate()})
$Form.ShowDialog() | Out-Null
}
that's all enough
enjoy!
/image%2F0881799%2F20140610%2Fob_a8c7fe_logo2.jpg)
Commenter cet article