Powershell: запустите пользовательский интерфейс WinMerge — дождитесь завершения — затем запустите следующий пользовательский интерфейс (первый должен оставаться открытым)

Я новичок в PowerShell и пытаюсь написать скрипт, который будет запускать несколько задач winmerge подряд.

Процессам winmerge потребуется доступ к внешним дискам, поэтому я не хочу, чтобы они запускались одновременно, а скорее один за другим. НО пользовательский интерфейс готового сравнения должен оставаться открытым.

Итак, что я хотел бы сделать в 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 пользовательских интерфейса с результатами. На данный момент мне удалось запустить только все пользовательские интерфейсы одновременно (но это замедляет процесс в целом: я обращаюсь к внешнему жесткому диску и 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)

Как я уже сказал, я нуб, и мне трудно понять, каким будет правильный вызов. В большинстве случаев пользовательский интерфейс открывается и выполняет свою работу, но следующий вызов PS не начинается, пока я не закрою его вручную (и, как я уже сказал, в конце я хотел бы, чтобы было открыто несколько пользовательских интерфейсов).

Я предполагаю, что у меня здесь две проблемы: (1) возвращение к PS после открытия пользовательского интерфейса (2) ожидание результата от пользовательского интерфейса (? Могу ли я вообще получить результат? Думаю, это зависит от реализации WinMerge?) для запуска следующий пользовательский интерфейс

ИЗМЕНИТЬ

На самом деле я просто пытаюсь проверить свои файлы на целостность после резервного копирования с помощью robocopy. Я подумал, что было бы неплохо / хорошее упражнение написать свои собственные сценарии резервного копирования в PS, если я не испорчу свои пути :D

Проблема в том, что у меня есть много путей для проверки из-за двух физических дисков + моего облачного провайдера, каждый с зашифрованными/обычными разделами. Я пробовал FCIV и вычислять/сравнивать хэши самостоятельно (с помощью Get-FileHash), но я думаю, что, должно быть, сделал что-то не так, потому что они не обнаруживали изменений. WinMerge отлично работает из коробки, он может сравнивать 3 пути одновременно, и мне нравится его пользовательский интерфейс... но запуск n пользовательских интерфейсов одновременно, вероятно, плохая идея, поэтому я пытался установить их последовательно. Но я открыт для предложений, если у вас есть идеи получше.


person PLB    schedule 26.09.2020    source источник


Ответы (1)


Как приложение с графическим интерфейсом, WinMerge, вероятно, не имеет никаких сигналов, позволяющих PowerShell узнать, что слияние завершено. Это не API. Любой из подходов ожидания, описанных до сих пор, вероятно, потерпит неудачу, потому что он ожидает закрытия процесса, который, по вашему замыслу, никогда не произойдет.

2 вещи для размышления:

  1. Если у WinMerge есть файл журнала, вы можете отслеживать файл журнала на наличие какого-либо сообщения о завершении задания. Вы можете написать процедуру ожидания, ищущую эту строку/текст.
  2. Если есть функция журнала, возможно, используйте журнал для просмотра заданий постфактум. Это может свести на нет необходимость оставлять интерфейс открытым, что решило бы проблему ожидания.

Обновление по комментариям и изменениям:

Я ошибался, я использовал WinMerge раньше как часть Tortoise SVN. Хотя я предпочитаю Beyond Compare.

Я не думаю, что вам нужно проверять файлы после RoboCopy. Достаточно надежно, чтобы коррупция действительно была внешним риском. RoboCopy использует стандартные API-интерфейсы Windows для копирования файлов, и сомнительно, что такой же скептицизм будет сопровождать копирование на основе графического интерфейса. Понятно, что некоторый скептицизм может возникнуть из-за запутанного множества вариантов. Однако эта сложность вращается вокруг того, что копировать, протоколировать и т. д., как только RoboCopy решит скопировать файл, он должен сделать это надежно или с ошибкой. Сама копия должна рассматриваться как отдельная и независимо от любого беспокойства, которое может возникнуть из-за сложности инструмента. И создание соответствующей команды Robocopy обычно является предварительным этапом, включающим тестирование, за которым не часто следуют такие проверки.

Примечание. Вы также можете использовать RoboCopy во второй раз, чтобы либо обновить данные, либо использовать параметр /L, чтобы увидеть, не было ли что-то пропущено или изменено.

Примечание. Когда выполняется копирование файла, RoboCopy устанавливает время изменения любого нового целевого файла на 01.01.1980 и изменяет его в соответствии с источником только после завершения копирования. Если файл отличается по размеру или времени изменения, они также не изменяются до завершения передачи. Вот как можно перезапустить RoboCopy и все равно найти/переписать неполные копии.

Существует по крайней мере одна гипотетическая ситуация, которая может вызвать коррупцию. Когда устройство, например ускоритель WAN, оказывается между источником и получателем. Гипотетически RoboCopy может думать, что все в порядке, основываясь на ошибочных или поврежденных ответах от этого устройства.

Итак, имеем дело с маловероятным риском повреждения файла. Ваша первоначальная идея использовать Get-FileHash звучит уместно. Однако обратите внимание, что хеширование выполняется только для содержимого файла. Файлы с одинаковым содержимым, но разными метаданными, такими как имя и дата, вернут один и тот же хэш. Это сильно отличается от того, как RoboCopy воспринимает и реагирует на различия файлов, которые во многом зависят от имени, даты и размера.

Примечание. В зависимости от параметров RoboCopy может учитывать другие метаданные; атрибуты и ACL приходят на ум.

Без написания огромного скрипта для вычисления и сравнения хэшей в большом наборе файлов вы можете просто запустить что-то вроде ниже для источника и назначения:

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

Сделайте это в каждой из папок. Затем сравните полученные текстовые файлы в WinMerge, Beyond Compare и т. д.

Примечание. Возможно, вы захотите установить для параметра -Width параметра Out-File очень большое значение. Это может вместить очень длинные пути.

Примечание. Для Get-ChildItem вы можете указать путь как \\?\c:\FolderName, это позволит проходить очень длинные пути, хотя я не уверен, как отреагирует Get-FileHash.

Примечание. Это может занять некоторое время и может привести к созданию огромных текстовых файлов.

Это, вероятно, не должно быть повторяемым процессом. После того, как вы убедились, что RoboCopy копирует с полной точностью, продолжать или пытаться что-то уточнить, вероятно, будет излишним.

Обновление:

Если вы хотите использовать RoboCopy для создания списка, подходящего для сравнения, вам нужно сделать несколько вещей:

  1. Вам нужно будет создать свою команду RoboCopy, чтобы максимально приблизиться к чистой линии/строке пути.
  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::No Size — не регистрировать размеры файлов.
  • /NC :: No Class - не регистрировать классы файлов.
  • /NP :: No Progress — не отображать процент копирования.
  • /NJH :: Нет заголовка задания.
  • /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{} изменит данные на:

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

Вы можете видеть, что он обрезает пустое пространство и удаляет начальную часть пути в соответствии с инструкциями. Как упоминалось ранее, если вы добавите Out-File и запустите как источник, так и место назначения, вы должны получить файлы, достойные сравнения...

Примечание. В примере используется -Replace, поскольку .Replace() чувствителен к регистру. Сообщество pwsh обычно предпочитает использовать нативный подход PowerShell...

person Steven    schedule 26.09.2020
comment
спасибо - я посмотрю на это. относительно (2): я думаю, у меня все еще была бы проблема, что без (1) я не знаю, когда работа будет завершена, поэтому я не знаю, КОГДА это подходящее время, чтобы закрыть пользовательский интерфейс и продолжить (и я также все еще есть проблема, что я не знаю, как вернуть фокус обратно в PS, чтобы на самом деле закрыть окно...). - person PLB; 26.09.2020
comment
Я также добавил РЕДАКТИРОВАТЬ, какова моя цель на самом деле. Еще раз спасибо - person PLB; 26.09.2020
comment
вау, спасибо за подробное объяснение! Я попробую сейчас! - person PLB; 27.09.2020
comment
mhm - у меня есть несколько проблем (1) я исключаю некоторые файлы и каталоги в robocopy, поэтому мои два выходных файла имеют разное количество строк, что раздражает при чтении в WinMerge и дает массу ложных срабатываний. (2) это, кажется, испортило сортировку (3) Мне также нужно было избавиться от несоответствующих частей каждого «пути». Таким образом, большая часть моего вывода WinMerge показывает, что файлы разные. Я начинаю думать, что это не стоит моего времени и что я должен просто доверять robocopy, как вы упомянули. Время от времени я буду запускать WinMerge вручную :( - person PLB; 27.09.2020
comment
Как уже отмечалось, вам не нужен RoboCopy специально для упражнений по листингу/сравнению. Тем не менее, вы можете направить вывод RoboCopy на ForEach-Object{}. Там вы можете использовать типичные манипуляции со строками, такие как .Trim() или -Replace. .SubString() и т. д. Вы можете удалить разные части пути, чтобы сделать файлы пригодными для сравнения. Между прочим, использование Get-ChildItem все равно потребует манипулирования выводом. Однако при первом подходе к объектам PowerShell манипулирование строками было бы проще. Предостережение; RoboCopy немного быстрее. - person Steven; 27.09.2020
comment
Вот некоторые похожие вопросы/ответы, над которыми я работал. Эти демонстрационные параметры регистрации вы можете использовать с RoboCopy. Они также показывают ForEach-Object{} манипулирование строками вывода RoboCopy. RoboCopy, получение 32 лучших файлов также Список быстрых каталогов. Поскольку вы новичок в Pwsh, я бы порекомендовал вам выполнить это упражнение, несмотря на мои более ранние комментарии о доверии к RoboCopy. Подобные методы полезны далеко за пределами текущего проекта. Я также добавлю что-то более конкретное в ответ. - person Steven; 27.09.2020