138 lines
5.4 KiB
PowerShell
138 lines
5.4 KiB
PowerShell
param(
|
|
[string]$SourcePath,
|
|
[string]$TargetPath
|
|
)
|
|
|
|
Add-Type -AssemblyName System.Windows.Forms
|
|
Add-Type -AssemblyName System.Drawing
|
|
|
|
function Show-GUI {
|
|
$form = New-Object System.Windows.Forms.Form
|
|
$form.Text = "Folder Mirror Tool"
|
|
$form.Size = New-Object System.Drawing.Size(600,400)
|
|
$form.StartPosition = "CenterScreen"
|
|
|
|
# Source Controls
|
|
$lblSource = New-Object Windows.Forms.Label
|
|
$lblSource.Location = New-Object Drawing.Point(10,10)
|
|
$lblSource.Text = "Source Path:"
|
|
$txtSource = New-Object Windows.Forms.TextBox
|
|
$txtSource.Location = New-Object Drawing.Point(120,10)
|
|
$txtSource.Size = New-Object Drawing.Size(350,20)
|
|
$btnSource = New-Object Windows.Forms.Button
|
|
$btnSource.Location = New-Object Drawing.Point(480,10)
|
|
$btnSource.Text = "Browse"
|
|
$btnSource.Add_Click({
|
|
$folder = New-Object Windows.Forms.FolderBrowserDialog
|
|
if($folder.ShowDialog() -eq "OK") { $txtSource.Text = $folder.SelectedPath }
|
|
})
|
|
|
|
# Target Controls
|
|
$lblTarget = New-Object Windows.Forms.Label
|
|
$lblTarget.Location = New-Object Drawing.Point(10,40)
|
|
$lblTarget.Text = "Target Path:"
|
|
$txtTarget = New-Object Windows.Forms.TextBox
|
|
$txtTarget.Location = New-Object Drawing.Point(120,40)
|
|
$txtTarget.Size = New-Object Drawing.Size(350,20)
|
|
$btnTarget = New-Object Windows.Forms.Button
|
|
$btnTarget.Location = New-Object Drawing.Point(480,40)
|
|
$btnTarget.Text = "Browse"
|
|
$btnTarget.Add_Click({
|
|
$folder = New-Object Windows.Forms.FolderBrowserDialog
|
|
if($folder.ShowDialog() -eq "OK") { $txtTarget.Text = $folder.SelectedPath }
|
|
})
|
|
|
|
# Log Box
|
|
$txtLog = New-Object Windows.Forms.RichTextBox
|
|
$txtLog.Location = New-Object Drawing.Point(10,70)
|
|
$txtLog.Size = New-Object Drawing.Size(560,280)
|
|
$txtLog.ReadOnly = $true
|
|
|
|
# Start Button
|
|
$btnStart = New-Object Windows.Forms.Button
|
|
$btnStart.Location = New-Object Drawing.Point(480,350)
|
|
$btnStart.Size = New-Object Drawing.Size(90,30)
|
|
$btnStart.Text = "Start Mirror"
|
|
$btnStart.Add_Click({
|
|
$script:SourcePath = $txtSource.Text
|
|
$script:TargetPath = $txtTarget.Text
|
|
try {
|
|
# Reuse existing validation and mirror logic
|
|
if (-not (Test-Path $SourcePath)) { throw "Source path invalid" }
|
|
if (-not (Test-Path $TargetPath)) { throw "Target path invalid" }
|
|
|
|
$txtLog.Text += "Starting mirror operation...`n"
|
|
$global:logFile = "$PSScriptRoot\MirrorLog_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
|
|
|
Write-Host "Source: $SourcePath"
|
|
Write-Host "Target: $TargetPath"
|
|
Write-Host "Log file: $logFile"
|
|
|
|
# Robocopy parameters:
|
|
# /MIR = Mirror mode (purge files in destination not in source)
|
|
# /NP = No progress percentage
|
|
# /NDL = No directory logging
|
|
# /LOG+: Append to log file
|
|
# /TEE = Output to console and log file
|
|
# /R:5 = 5 retries on failed files
|
|
# /W:5 = 5 second wait between retries
|
|
$robocopyArgs = @($SourcePath, $TargetPath, "/MIR", "/NP", "/NDL", "/LOG+:$logFile", "/TEE", "/R:5", "/W:5")
|
|
$process = Start-Process robocopy -ArgumentList $robocopyArgs -NoNewWindow -PassThru -Wait
|
|
|
|
if ($process.ExitCode -ge 8) {
|
|
throw "Robocopy failed with exit code $($process.ExitCode)"
|
|
}
|
|
|
|
$txtLog.Text += "Operation completed successfully!`n"
|
|
}
|
|
catch {
|
|
$txtLog.Text += "[ERROR] $_`n"
|
|
[Windows.Forms.MessageBox]::Show($_.Exception.Message, "Error")
|
|
}
|
|
})
|
|
|
|
# Add controls to form
|
|
$form.Controls.AddRange(@($lblSource, $txtSource, $btnSource, $lblTarget, $txtTarget, $btnTarget, $txtLog, $btnStart))
|
|
[void]$form.ShowDialog()
|
|
}
|
|
|
|
# Show GUI if no parameters provided
|
|
if(-not $PSBoundParameters.ContainsKey('SourcePath') -or
|
|
-not $PSBoundParameters.ContainsKey('TargetPath')) {
|
|
Show-GUI
|
|
}
|
|
else {
|
|
try {
|
|
if (-not (Test-Path $SourcePath)) { throw "Source path invalid" }
|
|
if (-not (Test-Path $TargetPath)) { throw "Target path invalid" }
|
|
|
|
$logFile = "$PSScriptRoot\MirrorLog_$(Get-Date -Format 'yyyyMMdd_HHmmss').log"
|
|
Write-Host "[$(Get-Date)] Starting mirror operation..."
|
|
|
|
Write-Host "Source: $SourcePath"
|
|
Write-Host "Target: $TargetPath"
|
|
Write-Host "Log file: $logFile"
|
|
|
|
# Robocopy parameters:
|
|
# /MIR = Mirror mode (purge files in destination not in source)
|
|
# /NP = No progress percentage
|
|
# /NDL = No directory logging
|
|
# /LOG+: Append to log file
|
|
# /TEE = Output to console and log file
|
|
# /R:5 = 5 retries on failed files
|
|
# /W:5 = 5 second wait between retries
|
|
$robocopyArgs = @($SourcePath, $TargetPath, "/MIR", "/NP", "/NDL", "/LOG+:$logFile", "/TEE", "/R:5", "/W:5")
|
|
$process = Start-Process robocopy -ArgumentList $robocopyArgs -NoNewWindow -PassThru -Wait
|
|
|
|
if ($process.ExitCode -ge 8) {
|
|
throw "Robocopy failed with exit code $($process.ExitCode)"
|
|
}
|
|
|
|
Write-Host "[$(Get-Date)] Mirror operation completed successfully" -ForegroundColor Green
|
|
Write-Host "Total processing time: $($process.ExitTime - $process.StartTime)"
|
|
}
|
|
catch {
|
|
Write-Host "[ERROR] $_" -ForegroundColor Red
|
|
exit 1
|
|
}
|
|
} |