Powershell:启动 WinMerge UI - 等待完成 - 然后启动下一个 UI(第一个必须保持打开状态)

Powershell: start a WinMerge UI - wait for completion - then start the next UI (first one must stay open)

我是 PowerShell 菜鸟,我正在尝试编写一个脚本,该脚本将 运行 连续执行多个 winmerge 任务。

winmerge 进程将需要访问外部磁盘,因此我不希望它们同时 运行,而是一个接一个地访问。但是完成比较的 UI 应该保持打开状态。

所以我想在 PowerShell 中做的是:

in PS: Start WinMerge UI for "folderA" "folderB"
give the focus back to PS and wait for the UI to complete its task
start a NEW WinMerge UI for "folderC" "folderD"
give the focus back to PS and wait for the UI to complete its task
...

我的计划是让它 运行 并稍后再回来,用 3 UI 打开结果。目前,我只能同时启动所有 UI(但这会减慢整个过程:我正在访问外部 HDD 和 USB)。

我尝试使用的对 WinMerge 的调用如下所示:

winmergeu.exe -r -wl "C:\xxx\Documents\" "Y:\xxx\Documents"

到目前为止我已经尝试过:

cmd /c ... or cmd /c start /wait ...
start-process ...
invoke-command ...
start-job | wait-job | receive-job
a PS wrapper for winMerge (https://communary.net/2016/01/17/invoke-winmerge/)
appending | out-null (this mostly leads to an error)

正如我所说,我有点菜鸟,我很难弄清楚正确的调用是什么。在大多数情况下 UI 打开并完成它的工作,但是下一个 PS 调用直到我手动关闭它才开始(正如我所说我想要几个 UI终于打开了)。

我想我这里有两个问题:(1) 在 UI 打开后回到 PS (2) 等待 UI 的结果(?我可以甚至得到结果?我想这取决于 WinMerge 的实现?)触发下一个 UI

编辑

我实际上只是想在使用 robocopy 备份后检查我的文件的完整性。我认为在 PS 中编写我自己的备份脚本会很好/很好的练习,只要我不搞砸我的路径 :D

问题是我有很多路径要检查,因为有两个物理驱动器 + 我的云提供商,每个驱动器都有 encrypted/plain 个分区。我自己尝试了 FCIV 和 computing/comparing 哈希(使用 Get-FileHash),但我想我一定做错了什么,因为它们没有检测到变化。 WinMerge 开箱即用,它可以同时比较 3 个路径,我喜欢它的 UI... 但是 运行ning n UIs 一次可能是个坏主意,这就是为什么我试图按顺序设置它们。但如果您有更好的想法,我愿意接受建议。

作为 GUI 应用程序,WinMerge 可能没有任何信号让 PowerShell 知道合并已完成。这不是 API。到目前为止描述的任何等待方法都可能会失败,因为它正在等待进程关闭,根据您的设计,这永远不会发生。

需要考虑的 2 件事:

  1. 如果 WinMerge 有日志文件,您可以监视日志文件以获取某种作业完成消息。您可以编写等待例程来查找 line/text.
  2. 如果有日志功能,也许可以使用日志来查看事后的工作。这可能不需要让界面保持打开状态,从而解决等待问题。

根据评论和编辑更新:

我错了,我以前使用 WinMerge 作为 Tortoise SVN 的一部分。虽然我更喜欢Beyond Compare

我认为您不需要在 RoboCopy 之后验证文件。腐败确实是一种外部风险,这一点足够可靠。 RoboCopy 使用标准 Windows APIs 来复制文件,同样的怀疑是否会伴随基于 GUI 的复制是值得怀疑的。 可以理解的是,一些怀疑可能源于令人困惑的选项。然而,这种复杂性围绕着复制什么、记录等……,一旦 RoboCopy 决定复制一个文件,它应该可靠地复制或出错。副本本身应该被视为独立的,并且与您可能对工具的复杂性感到不安的情况不同。而且,制作适当的 Robocopy 命令通常是一项包括测试在内的前端工作,并且通常不会进行此类验证。

注意:您还可以再次使用 RoboCopy 来刷新数据或使用 /L 选项查看是否遗漏或更改后的任何内容。

注意:当文件复制正在进行时,RoboCopy 将任何新目标文件的修改时间设置为 01/01/1980,并且仅在复制完成时将其更改为与源文件匹配。如果文件的大小或修改时间不同,则在传输完成之前它们也不会更改。这就是 RoboCopy 可以重新启动并仍然找到/覆盖不完整副本的方式。

至少存在一种可能导致腐败的假设情况。当设备(例如 WAN 加速器)进入源和目标之间时。假设地,RoboCopy 可能认为基于该设备的错误或损坏响应一切正常。

所以,处理文件损坏的风险。您最初使用 Get-FileHash 的想法听起来很合适。但是,请注意哈希仅对文件内容执行。具有相同内容但不同 meta-data 的文件(如名称和日期)将 return 相同的哈希值。这与 RoboCopy 感知和响应文件差异的方式完全不同,后者在很大程度上依赖于名称、日期和大小。

注意:根据选项,RoboCopy 可能会考虑其他 meta-data;想到属性和 ACL。

无需编写庞大的脚本来计算和比较大量文件的哈希值,您只需 运行 在源和目标上进行如下操作:

Get-ChildItem <Path> -Recurse |
Get-FileHash |
Select Path,Hash |
Out-File <SomeOutputPath>

对每个文件夹执行此操作。然后在 WinMerge、Beyond Compare 等中比较生成的文本文件...

注意:您可能希望将 Out-File-Width 参数设置为一个非常大的数字。这可能适用于很长的路径。

注意:对于 Get-ChildItem,您可能希望像 \?\c:\FolderName 那样声明路径,这将允许遍历很长的路径,但我不确定 Get-FileHash 将如何反应。

注意:运行 这可能需要相当长的时间,并且可能会生成巨大的文本文件。

这可能不需要是一个可重复的过程。一旦您确信 RoboCopy 正在以完全保真度复制,继续或尝试改进可能就有点矫枉过正了。

更新:

如果您想使用 RoboCopy 制作适合比较的列表,您需要做一些事情:

  1. 您必须设计您的 RoboCopy 命令以尽可能接近纯路径 line/string。
  2. 您必须将该输出通过管道传输到 ForEach-Object{} 循环以操作输出字符串;删除路径的不同前导部分。

示例:

RoboCopy C:\temp\TestFiles3 "C:\Empty" /E /FP /NS /NC /NP /NJH /NJS /L |
ForEach-Object{ $_.Trim() -Replace "C:\Temp\" }

这个 RoboCopy 命令:

  • /E :: 复制子目录,包括空目录。
  • /FP :: 在输出中包含文件的完整路径名。
  • /NS :: 无大小 - 不记录文件大小。
  • /NC :: 否 Class - 不记录文件 类.
  • /NP :: 无进度 - 不显示复制的百分比。
  • /NJH :: 没有工作 Header。
  • /NJS :: 没有工作摘要。
  • /L :: 仅列出 - 不要复制、添加时间戳或删除任何文件。

注意:这些描述直接来自帮助文件 RoboCopy /?。值得一读!

这些选项会输出如下内容:

        C:\temp\TestFiles3\
        C:\temp\TestFiles3\TestFiles2\
                        C:\temp\TestFiles3\TestFiles2\Test1000_KB.txt
                        C:\temp\TestFiles3\TestFiles2\Test100_KB.txt 
...

然后 ForEach-Object{} 循环将 cha将数据发送到:

TestFiles3\
TestFiles3\TestFiles2\
TestFiles3\TestFiles2\Test1000_KB.txt
TestFiles3\TestFiles2\Test100_KB.txt

您可以看到它按照说明修剪了白色 space 并删除了路径的前导部分。如前所述,如果您在源和目标上添加 Out-File 和 运行,您应该得到值得比较的文件...

注意:示例中使用了 -Replace,因为 .Replace() 区分大小写。 pwsh 社区通常更喜欢使用 PowerShell 本机方法...