I. 源电脑(数据发送方)配置
在传输之前,必须确保两台电脑可以相互访问。
1.1 同一网络和工作组
1.1.1 同一网络
确认“源电脑”和“目标电脑”在“同一网段”,同一“专用网络”或“工作网络”。
1.以管理员身份运行 PowerShell 。
2.查看 IP 地址(确保源&目标电脑在同一网段):
1ipconfig
3.获取网络连接的“接口别名”:
1Get-NetConnectionProfile
命令执行后会返回类似以下的结果:
1Name : 网络
2InterfaceAlias : Ethernet0
3InterfaceIndex : 12
4NetworkCategory : Public
5IPv4Connectivity : Internet
6IPv6Connectivity : NoTraffic
记下你要修改的连接的 InterfaceAlias(例如 Ethernet0)和当前的 NetworkCategory。
4.设置网络类型
- 设置为“专用网络”:
1Set-NetConnectionProfile -InterfaceAlias "Ethernet0" -NetworkCategory Private
- 设置为“公用网络”:
1Set-NetConnectionProfile -InterfaceAlias "Ethernet0" -NetworkCategory Public
- 设置为“域网络”:
注意: “域网络”类型通常是系统自动检测并设置的,不建议手动强制设置。但如果确实需要(例如在特定虚拟化环境中),可以使用:
1Set-NetConnectionProfile -InterfaceAlias "Ethernet0" -NetworkCategory DomainAuthenticated
5.验证更改:
再次运行 Get-NetConnectionProfile,检查 NetworkCategory 是否已更新。
6.通过本地安全策略(GUI)
按下【Win + R】打开“运行”对话框,输入:secpol.msc ,进入:网络列表管理器策略 → 网络名称 → [ 选择你当前使用的网络 ] → 属性,在“网络位置”选项卡中选择:Private(专用)或 Public(公用)。
1.1.2 启用网络发现和共享
打开“高级共享设置”找到“专用网络”或“工作网络”:
- ✅启用网络发现(自动设置网络连接的设备)
- ✅文件和打印机共享
1.1.3 同一工作组
确认“源电脑”和“目标电脑”在同一工作组,一般默认 WORKGROUP 工作组。
打开“运行”,输入:sysdm.cpl ,打开“系统属性”查看‘计算机全名’和‘工作组’。
1.2 创建专用账户
1.按下【Win + R】打开“运行”对话框,输入 lusrmgr.msc 打开 “本地用户和组”控制台,创建数据迁移专用账户,配置参考如下图👇
2.确认上面创建的专用账户它只属于 Users 组(不要有 Administrators 组权限)
3.在命令行创建用户。在命令提示符(管理员)或 PowerShell(管理员)中执行
1net user 用户名 密码 /add /passwordchg:no /expires:never
💡默认情况下,新用户会自动加入 Users 组。查看该用户信息
1net user 用户名
确保该用户仅属于 Users 组(如果不在,可手动加入)
1net localgroup Users 用户名 /add
如果该用户还属于 Administrators 或其它组,可通过以下命令删除
1net localgroup Administrators 用户名 /delete
设置用户密码永不过期(可选项)
1wmic useraccount where name='用户名' set PasswordExpires=FALSE
或在 PowerShell 中
1Set-LocalUser -Name "用户名" -PasswordNeverExpires $true
删除用户
1net user 用户名 /delete
1.3 拒绝本地登录
在“运行”对话框中输入 <font style="color:rgb(89, 97, 114);background-color:rgb(241, 243, 244);">secpol.msc</font> 打开“本地安全策略”,配置参考如下图👇
强制立即更新组策略设置,无需等待自动刷新周期
1gpupdate /force
1.4 不显示在登录界面
以管理员身份打开命令提示符,输入以下命令:
1reg add "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v transfer /t REG_DWORD /d 0 /f
若要恢复显示,值设为 1 或删除隐藏项:
1reg delete "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList" /v transfer /f
1.5 共享待发送目录
1.5.1 设置共享权限
右键打开目标文件夹属性 -> 选择“共享”选项卡:
1.5.2 设置文件系统权限
打开“安全”选项卡,配置参考如下图👇
II. 目标电脑(数据接收方)配置
我们需要在这里创建定时任务,因为它将是主动拉取数据的一方。
2.1 同一网络和工作组
1.同一网段:确认“目标电脑”和“源电脑”在"同一网段"。
2.同一网络:确认“目标电脑”和“源电脑”在同一“专用网络”或“工作网络”。
3.同一工作组:确认“目标电脑”和“源电脑”在同一工作组,一般默认为 WORKGROUP 工作组。
2.2 添加 Windows 凭据
在“运行”对话框中输入 <font style="color:rgb(89, 97, 114);background-color:rgb(241, 243, 244);">control.exe keymgr.dll</font> 打开“凭据管理器”,添加在源电脑(数据发送方)上创建的专用账户(服务端名称前不需要添加 \\),配置参考如下图👇
测试连接,在“运行”对话框中输入:\\源电脑的计算机名或 IP 地址(例如 \\DESKTOP-ABC1234 或 \\192.168.1.100)。若能看到一个文件夹,并且能打开,说明共享和网络连接是正常的;若不能,请参考后续章节排查问题。
2.3 编写 Robocopy 脚本
由于 Robocopy 本身只能按“天”来筛选修改时间(通过 /MINAGE 和 /MAXAGE 参数),不能精确到小时/分钟/秒,实际测试如仅删除昨天(00:00:00 - 23:59:59)的文件,在 Windows 批处理脚本(.bat)中无法实现,建议使用 PowerShell 脚本实现。PowerShell 脚本编码格式建议为 UTF-8 with BOM ,否则控制台和产生的日志会有乱码。
1<#
2 PowerShell 自动备份与清理脚本(最终一体版)
3 功能:
4 1. 删除目标目录及日志目录中 14 天前文件;
5 2. 使用 robocopy 按日期区间复制文件;
6 3. 每个目标目录日志记录删除和复制操作;
7 4. 支持每日主日志汇总统计(删除文件数/复制文件数);
8 5. 多线程 robocopy;
9 6. 测试模式。
10#>
11
12# ======================== 配置区域 ========================
13$SourceDir1 = "\\SharePC1\Source1"
14$SourceDir2 = "\\SharePC2\Source2"
15$SourceDir3 = "\\SharePC3\Source3"
16
17$TargetDir1 = "E:\Backup1"
18$TargetDir2 = "E:\Backup2"
19$TargetDir3 = "E:\Backup3"
20
21$LogDir = "E:\Logs"
22
23$DeleteDays = 14
24$Threads = 16
25$TestMode = $false # 设置为 $true 仅打印操作,不实际执行
26
27# ======================== 函数定义 ========================
28
29function Invoke-ForfilesDelete {
30 param(
31 [string]$Path,
32 [int]$Days,
33 [string]$OutputLogPath = $null,
34 [switch]$Quiet
35 )
36
37 if (-not (Test-Path $Path)) { Write-Host "路径不存在,跳过删除: $Path"; return }
38
39 $escapedPath = '"' + $Path + '"'
40 $cmd = "forfiles /P $escapedPath /S /D -$Days /C `"cmd /c del /q @path && echo 已删除: @path`""
41
42 if ($TestMode) { Write-Host "[TEST MODE] Would run: $cmd"; return }
43
44 $output = cmd.exe /c "$cmd" 2>&1 | Where-Object { ($_ -ne "") -and ($_ -notmatch "用指定的搜索标准没有找到文件") }
45
46 $timeHeader = "==== 删除执行时间:$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ===="
47
48 if ($Quiet) { return }
49 elseif ($OutputLogPath) {
50 $isNewFile = -not (Test-Path $OutputLogPath) -or ((Get-Item $OutputLogPath).Length -eq 0)
51 if ($isNewFile) {
52 $logName = Split-Path $OutputLogPath -Leaf
53 $title = "########## $logName 删除与复制记录 ##########"
54 $title | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append
55 "" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append
56 }
57
58 $timeHeader | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append
59 if ($output) { $output | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
60 else { "没有找到可删除的文件。" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
61 "" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append
62 }
63 else {
64 Write-Host $timeHeader
65 if ($output) { $output | Write-Host }
66 else { Write-Host "没有找到可删除的文件。" }
67 Write-Host ""
68 }
69}
70
71function Copy-FilesByDate {
72 param(
73 [string]$SourceDir,
74 [string]$TargetDir,
75 [datetime]$StartTime,
76 [datetime]$EndTime,
77 [string]$Description,
78 [string]$OutputLogPath
79 )
80
81 if (-not (Test-Path $SourceDir)) { Write-Host "源目录不存在: $SourceDir"; return }
82 if (-not (Test-Path $TargetDir)) { New-Item -ItemType Directory -Force -Path $TargetDir | Out-Null }
83
84 $timeHeader = "==== 复制执行时间:$(Get-Date -Format 'yyyy-MM-dd HH:mm:ss') ===="
85 $files = Get-ChildItem -Path $SourceDir -Recurse -File |
86 Where-Object { $_.LastWriteTime -ge $StartTime -and $_.LastWriteTime -le $EndTime }
87
88 if ($TestMode) {
89 Write-Host "[TEST MODE] Would copy $($files.Count) files from $SourceDir to $TargetDir"
90 foreach ($f in $files) { Write-Host " $($f.FullName)" }
91 return
92 }
93
94 if ($OutputLogPath) { $timeHeader | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
95
96 if ($files.Count -eq 0) {
97 if ($OutputLogPath) { "没有找到可复制的文件。" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
98 else { Write-Host "没有找到可复制的文件。" }
99 return
100 }
101
102 foreach ($f in $files) {
103 $relativePath = $f.FullName.Substring($SourceDir.Length)
104 $destPath = Join-Path $TargetDir $relativePath
105 $destDir = Split-Path $destPath -Parent
106 if (-not (Test-Path $destDir)) { New-Item -ItemType Directory -Path $destDir -Force | Out-Null }
107
108 robocopy (Split-Path $f.FullName -Parent) $destDir $f.Name /R:1 /W:1 /MT:$Threads /NFL /NDL /NJH /NJS /NP | Out-Null
109
110 if ($OutputLogPath) { "已复制: $destPath" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
111 }
112
113 if ($OutputLogPath) { "" | Out-File -FilePath $OutputLogPath -Encoding UTF8 -Append }
114}
115
116# 统计日志文件中的删除数量
117function Get-DeletedStats {
118 param([string]$LogPath)
119 if (-not (Test-Path $LogPath)) { return @{Count=0; SizeMB=0} }
120 $deletedLines = Select-String "已删除:" $LogPath | ForEach-Object { $_.Line }
121 $count = $deletedLines.Count
122 return @{Count=$count}
123}
124
125# 统计日志文件中的复制数量和大小
126function Get-CopiedStats {
127 param([string]$LogPath)
128 if (-not (Test-Path $LogPath)) { return @{Count=0; SizeMB=0} }
129 $copiedLines = Select-String "已复制:" $LogPath | ForEach-Object { $_.Line }
130 $count = $copiedLines.Count
131 $size = 0
132 foreach ($line in $copiedLines) {
133 $filePath = $line -replace "已复制: ",""
134 if (Test-Path $filePath) { $size += (Get-Item $filePath).Length }
135 }
136 return @{Count=$count; SizeMB=[math]::Round($size/1MB,2)}
137}
138
139# ======================== 主程序 ========================
140
141$Today = Get-Date
142$Yesterday = $Today.AddDays(-1)
143$TwoDaysAgo = $Today.AddDays(-2)
144
145if (-not (Test-Path $LogDir)) { New-Item -ItemType Directory -Force -Path $LogDir | Out-Null }
146
147$LogFile1 = Join-Path $LogDir "Log1_$($Today.ToString('yyyyMMdd')).log"
148$LogFile2 = Join-Path $LogDir "Log2_$($Today.ToString('yyyyMMdd')).log"
149$LogFile3 = Join-Path $LogDir "Log3_$($Today.ToString('yyyyMMdd')).log"
150$MainLog = Join-Path $LogDir "Main_$($Today.ToString('yyyyMMdd')).log"
151
152Write-Host "========== 开始执行备份与清理 =========="
153
154# 删除旧文件
155Invoke-ForfilesDelete -Path $TargetDir1 -Days $DeleteDays -OutputLogPath $LogFile1
156Invoke-ForfilesDelete -Path $TargetDir2 -Days $DeleteDays -OutputLogPath $LogFile2
157Invoke-ForfilesDelete -Path $TargetDir3 -Days $DeleteDays -OutputLogPath $LogFile3
158
159# 删除旧日志(静默)
160Invoke-ForfilesDelete -Path $LogDir -Days $DeleteDays -Quiet
161
162# 复制文件并写入日志
163Copy-FilesByDate -SourceDir $SourceDir1 -TargetDir $TargetDir1 `
164 -StartTime ($Today.Date) -EndTime $Today -Description "源目录1" -OutputLogPath $LogFile1
165
166Copy-FilesByDate -SourceDir $SourceDir2 -TargetDir $TargetDir2 `
167 -StartTime ($Yesterday.Date) -EndTime ($Today.Date.AddSeconds(-1)) -Description "源目录2" -OutputLogPath $LogFile2
168
169Copy-FilesByDate -SourceDir $SourceDir3 -TargetDir $TargetDir3 `
170 -StartTime ($TwoDaysAgo.Date) -EndTime ($Yesterday.Date.AddSeconds(-1)) -Description "源目录3" -OutputLogPath $LogFile3
171
172# ======================== 汇总主日志 ========================
173
174$stats1Del = Get-DeletedStats $LogFile1
175$stats2Del = Get-DeletedStats $LogFile2
176$stats3Del = Get-DeletedStats $LogFile3
177
178$stats1Copy = Get-CopiedStats $LogFile1
179$stats2Copy = Get-CopiedStats $LogFile2
180$stats3Copy = Get-CopiedStats $LogFile3
181
182$summary = @"
183========== $($Today.ToString('yyyy-MM-dd')) 主日志汇总 ==========
184目标目录1: 删除 $($stats1Del.Count) 个文件, 复制 $($stats1Copy.Count) 个文件, 总大小 $($stats1Copy.SizeMB) MB
185目标目录2: 删除 $($stats2Del.Count) 个文件, 复制 $($stats2Copy.Count) 个文件, 总大小 $($stats2Copy.SizeMB) MB
186目标目录3: 删除 $($stats3Del.Count) 个文件, 复制 $($stats3Copy.Count) 个文件, 总大小 $($stats3Copy.SizeMB) MB
187============================================================
188"@
189
190$summary | Out-File -FilePath $MainLog -Encoding UTF8 -Append
191
192Write-Host "========== 脚本执行完成 =========="
2.4 测试脚本
测试脚本以验证脚本准确性,PowerShell 控制台测试步骤:
1.以管理员身份打开 PowerShell ;
2.首次运行保留 $TestMode = $true ;
3.在 PowerShell 控制台执行脚本(注意替换为你的脚本路径):
1powershell -ExecutionPolicy Bypass -File "E:\Script\backup_task.ps1"
4.查看控制台和日志文件是否符合预期(路径、时间、文件名等);
5.验证无误后改为 $false 再正式执行。
III. 任务计划配置
在“运行”对话框中输入 <font style="color:rgb(89, 97, 114);background-color:rgb(241, 243, 244);">taskschd.msc</font> 打开“任务计划程序”。
1.创建基本任务,输入任务“名称”,描述可选;
2.任务触发器,选择任务执行周期;
3.设置任务开始时间;
4.选择要执行的操作:
- ✅启动程序;
5.启动程序:
- 程序或脚本
1C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- 添加参数
1-ExecutionPolicy Bypass -File "D:\Scripts\backup_and_cleanup.ps1"
6.点击确定完成后,在任务属性【常规】选项卡中:
- 运行任务时用户,选择管理员用户,如
Administrator; - ✅ 不管用户是否登录都要运行;
- ✅ 使用最高权限运行。
7.在【条件】选项卡中:
- ❎(取消勾选)“只有在计算机使用交流电源时才启动此任务”





