Синхронизировать ZIP-файл PowerShell

В сценарии PowerShell я хочу закрепить папку перед удалением папки. Я запускаю следующее (я не помню, где я нашел фрагмент):

function Compress-ToZip { param([string]$zipfilename) if(-not (test-path($zipfilename))) { set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) (Get-ChildItem $zipfilename).IsReadOnly = $false } $shellApplication = new-object -com shell.application $zipPackage = $shellApplication.NameSpace($zipfilename) foreach($file in $input) { $zipPackage.CopyHere($file.FullName) } } 

Этот фрагмент фактически сжимает папку, но с асинхронным способом. Фактически, метод CopyHere объектов Shell.Application запускает сжатие и не ждет его завершения. Следующие утверждения моих скриптов затем беспорядочны (поскольку процесс zip-файла не завершен).

Какие-либо предложения? Если возможно, я бы хотел избежать добавления исполняемых файлов и оставаться в чистых функциях Windows.

[Edit] полное содержимое моего файла PS1 минус фактическое имя БД. Цель скрипта – создать резервную копию SQL db, а затем заархивировать резервные копии в одном пакете в папке с текущей датой:

 $VerbosePreferenceBak = $VerbosePreference $VerbosePreference = "Continue" add-PSSnapin SqlServerCmdletSnapin100 function BackupDB([string] $dbName, [string] $outDir) { Write-Host "Backup de la base : $dbName" $script = "BACKUP DATABASE $dbName TO DISK = '$outDir\$dbName.bak' WITH FORMAT, COPY_ONLY;" Invoke-Sqlcmd -Query "$script" -ServerInstance "." -QueryTimeOut 600 Write-Host "Ok !" } function Compress-ToZip { param([string]$zipfilename) Write-Host "Compression du dossier" if(-not (test-path($zipfilename))) { set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) (Get-ChildItem $zipfilename).IsReadOnly = $false } $shellApplication = new-object -com shell.application $zipPackage = $shellApplication.NameSpace($zipfilename) foreach($file in $input) { $zipPackage.CopyHere($file.FullName) } Write-Host "Press any key to continue ..." $x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown") } $targetDir = "E:\Backup SQL" $date = Get-Date -format "yyyy-MM-dd" $newDir = New-Item -ItemType Directory "$targetDir\$date\sql" -Force BackupDB "database 1" "$newDir" BackupDB "database 2" "$newDir" BackupDB "database 3" "$newDir" Get-Item $newDir | Compress-ToZip "$targetDir\$date\sql_$date.zip" Write-Host "." remove-item $newDir -Force -Confirm:$false -Recurse $VerbosePreference = $VerbosePreferenceBak 

Я наконец нашел чистый способ, играя со свойствами COM-объектов. В частности, следующий фрагмент может проверить, присутствует ли файл в zip-файле:

 foreach($file in $input) { $zipPackage.CopyHere($file.FullName) $size = $zipPackage.Items().Item($file.Name).Size while($zipPackage.Items().Item($file.Name) -Eq $null) { start-sleep -seconds 1 write-host "." -nonewline } } 

Полный скрипт следующий:

 $VerbosePreferenceBak = $VerbosePreference $VerbosePreference = "Continue" add-PSSnapin SqlServerCmdletSnapin100 function BackupDB([string] $dbName, [string] $outDir) { Write-Host "Backup de la base : $dbName" $script = "BACKUP DATABASE $dbName TO DISK = '$outDir\$dbName.bak' WITH FORMAT, COPY_ONLY;" Invoke-Sqlcmd -Query "$script" -ServerInstance "." -QueryTimeOut 600 Write-Host "Ok !" } function Compress-ToZip { param([string]$zipfilename) Write-Host "Compression du dossier" if(-not (test-path($zipfilename))) { set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) (Get-ChildItem $zipfilename).IsReadOnly = $false } $shellApplication = new-object -com shell.application $zipPackage = $shellApplication.NameSpace($zipfilename) foreach($file in $input) { $zipPackage.CopyHere($file.FullName) $size = $zipPackage.Items().Item($file.Name).Size while($zipPackage.Items().Item($file.Name) -Eq $null) { start-sleep -seconds 1 write-host "." -nonewline } write-host "." } } $targetDir = "E:\Backup SQL" $date = Get-Date -format "yyyy-MM-dd" $newDir = New-Item -ItemType Directory "$targetDir\$date\sql" -Force BackupDB "DB1" "$newDir" BackupDB "DB2" "$newDir" BackupDB "DB3" "$newDir" BackupDB "DB4" "$newDir" Get-ChildItem "$newDir" | Compress-ToZip "$targetDir\$date\sql_$date.zip" remove-item $newDir -Force -Confirm:$false -Recurse $VerbosePreference = $VerbosePreferenceBak 

Поскольку он работал нормально, когда вы вручную приостановили его, вот временный взлом, который вы сможете использовать до тех пор, пока не будет найдено «правильное» решение. Обычно использование «задержек» и «таймеров», подобных этому, НЕ является тем, что вы сделали бы для критически важных задач. Тем не менее, пока не будет найден лучший ответ, вы можете это сделать и посмотреть, работает ли он:

  • Выполняйте процесс вручную несколько раз и TIME, сколько времени в секундах обычно требуется для завершения процесса zip. Если размер базы данных, как правило, одинаковый каждый день, то время, которое требуется для завершения, вероятно, будет среднее значение в одно и то же время.

  • Допустим, вы получили в среднем 60 секунд в своих ручных тестах. Будьте консервативны и умножайте их на 4 или около того, так как это, скорее всего, не будет в 4 раза дольше обычного в «обычные» дни. Итак, теперь у вас есть 240 секунд (60 секунд среднее время 4).

  • Итак, вместо этого вместо того, чтобы иметь код «нажмите любую клавишу для продолжения», замените его на DELAY в коде, чтобы просто запустить скрипт, чтобы немного дождаться завершения zip. Это требует некоторой настройки и угадывания таймингов и не является хорошим подходом. Но в крайнем случае …

  • В любом случае, если вы хотите попробовать, измените код на:

Если вы используете PowerShell V1:

 foreach($file in $input) { $zipPackage.CopyHere($file.FullName) } [System.Threading.Thread]::Sleep(240000) 

Если вы используете PowerShell V2, вместо этого используйте командлет Sleep:

 foreach($file in $input) { $zipPackage.CopyHere($file.FullName) } Start-Sleep -Second 240 

Чтобы возиться со временем в V1, он использует миллисекунды. (Таким образом, 10 секунд = 10000)

Чтобы возиться со временем в V2, он использует секунды. (240 = 240 секунд)

Я бы никогда не использовал это в производстве, но если это не так уж и важно, и он работает очень хорошо в 99% случаев, это может быть достаточно хорошо.

  • Рекомендации по созданию и загрузке огромного ZIP (из нескольких BLOB) в WebApp
  • Разархивируйте файл из источника в папку пользователя в нескольких версиях окон
  • Просмотр содержимого архива в Mac OS X
  • Как взломать защищенный паролем zip-файл
  • Ошибка при попытке извлечь файлы из zip-файла
  • Сжатие папок на Mac, без .DS_Store
  • Сжать большой CSV-фильтр? (500MB)
  • Как создать отдельные zip-файлы для каждого выбранного файла / каталога в 7zip?
  • В Java: как zip-файл из массива byte ?
  • Сжатие папки в несколько ZIP-файлов
  • Как правильно собрать действительный файл xlsx из его внутренних подкомпонентов?
  • Давайте будем гением компьютера.