Dalam skrip PowerShell, saya ingin zip folder sebelum menghapus folder. Saya menjalankan yang berikut (Saya tidak ingat di mana saya menemukan potongannya):
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)
}
}
Cuplikan ini sebenarnya memampatkan folder, tetapi dengan cara yang tidak sinkron. Bahkan, metode CopyHere dari objek Shell.Application memulai kompresi dan tidak menunggu penyelesaiannya. Pernyataan skrip saya selanjutnya berantakan (karena proses file zip tidak selesai).
Ada saran? Jika memungkinkan saya ingin menghindari menambahkan file yang dapat dieksekusi dan tetap menggunakan fitur Windows murni.
[sunting] konten penuh file PS1 saya minus nama sebenarnya dari DB. Tujuan skrip adalah untuk mencadangkan sekumpulan SQL db, lalu meng-zip cadangan dalam satu paket dalam folder bernama dengan tanggal saat ini:
$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
sumber
Write-Host "Press any key to continue ..."
Baris2:$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
Jawaban:
Saya akhirnya menemukan cara yang bersih, bermain dengan properti dari objek com. Khususnya, cuplikan berikut ini dapat menguji apakah file tersebut ada di file zip:
Script lengkapnya adalah sebagai berikut:
sumber
Karena itu berfungsi dengan baik ketika Anda menjeda secara manual, berikut ini adalah peretasan sementara yang mungkin dapat Anda gunakan sampai solusi "benar" ditemukan. Umumnya menggunakan "penundaan" dan "timer" seperti ini BUKAN apa yang akan Anda lakukan untuk hal-hal penting misi. Yang mengatakan, sampai jawaban yang lebih baik ditemukan, Anda dapat melakukan ini dan melihat apakah itu berhasil:
Lakukan proses secara manual beberapa kali dan TIME berapa lama dalam hitungan detik biasanya proses zip selesai. Jika ukuran basis data umumnya sama setiap hari maka waktu yang dibutuhkan untuk menyelesaikannya mungkin akan rata-rata pada waktu yang sama.
Katakanlah Anda mendapatkan rata-rata 60 detik dalam tes manual Anda. Bersikaplah konservatif dan kalikan dengan 4 atau lebih karena kemungkinan tidak akan memakan waktu 4 kali lebih lama dari biasanya pada hari "normal". Jadi sekarang Anda memiliki 240 detik (rata-rata 60 detik kali 4).
Jadi untuk saat ini, alih-alih memiliki kode "tekan tombol apa saja untuk melanjutkan" di sana, ganti kode itu dengan DELAY dalam kode tersebut agar skripnya nongkrong sebentar untuk menunggu zip selesai. Ini membutuhkan beberapa penyesuaian dan perkiraan waktu dan bukan pendekatan yang baik. Tapi dalam keadaan darurat ...
Bagaimanapun, jika Anda ingin mencobanya, ubah kode menjadi:
Jika menggunakan PowerShell V1:
Jika menggunakan PowerShell V2, gunakan cmdlet Tidur sebagai gantinya:
Untuk mengacaukan waktu di V1 menggunakan milidetik. (Jadi 10 detik = 10.000)
Untuk mengacaukan waktu di V2 menggunakan detik. (240 = 240 detik)
Saya tidak akan pernah menggunakan ini dalam produksi tetapi jika itu bukan masalah besar, dan terbukti bekerja dengan baik 99% dari waktu, mungkin cukup baik.
sumber