PowerShell ज़िप फ़ाइल को सिंक्रोनाइज़ करें


10

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)

    }
}

यह स्निपेट वास्तव में फ़ोल्डर को संपीड़ित करता है, लेकिन एक एसिंक्रोनस तरीके से। वास्तव में, Shell.Application ऑब्जेक्ट्स की CopyHere विधि संपीड़न शुरू करती है और इसके पूरा होने की प्रतीक्षा नहीं करती है। मेरी लिपियों के अगले कथन फिर गड़बड़ हो जाते हैं (क्योंकि ज़िप फ़ाइल प्रक्रिया पूरी नहीं हुई है)।

कोई सुझाव? यदि संभव हो तो मैं किसी भी निष्पादन योग्य फ़ाइलों को जोड़ने से बचना चाहता हूं और शुद्ध विंडोज सुविधाओं पर रहना चाहता हूं।

मेरे PS1 फ़ाइल की पूर्ण सामग्री [संपादित करें] 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

बस यह देखने के लिए कि क्या यह काम करता है अगर यह सिंक्रोनस होता है: यदि आप अपने कोड के बाद निम्न कोड जोड़ते हैं तो क्या यह अपेक्षित है? Write-Host "Press any key to continue ..." लाइन १ : लाइन २:$x = $host.UI.RawUI.ReadKey("NoEcho,IncludeKeyDown")
केरी

और परीक्षण के दौरान मैं स्पष्ट रूप से मान रहा हूं कि आप "जारी रखने के लिए कोई भी कुंजी दबाएं नहीं" जब तक कि आप मैन्युअल रूप से पुष्टि नहीं करते कि ज़िप प्रक्रिया पूरी हो चुकी है।
केरी

@ केरी: यह वास्तव में उम्मीद के मुताबिक काम करता है जब मैं आपके मैनुअल टेस्ट
स्टीव बी

जवाबों:


5

मुझे आखिरकार एक साफ रास्ता मिल गया, कॉम वस्तुओं के गुणों के साथ खेलना। विशेष रूप से, निम्न स्निपेट परीक्षण कर सकता है कि क्या फाइल जिप फाइल में मौजूद है:

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

आप इसे VB पर कैसे उपयोग कर सकते हैं?
मैकगीवर

@ लिंड्रो: क्या आपका मतलब वीबी स्क्रिप्ट से है? चूंकि PowerShell और VBScript दोनों ही स्क्रिप्टिंग लैंग्वेज हैं, जो COM ऑब्जेक्ट्स के साथ काम करने में सक्षम हैं, आपको यहां व्यवहार को बिना अधिक कठिनाइयों के दोहराने में सक्षम होना चाहिए
स्टीव बी

1

क्योंकि यह ठीक काम करता है जब आप इसे मैन्युअल रूप से रोकते हैं, तो यहां एक अस्थायी हैक है जिसे आप "सही" समाधान मिलने तक उपयोग करने में सक्षम हो सकते हैं। आम तौर पर "देरी" और "टाइमर" का उपयोग करना इस तरह से नहीं है कि आप मिशन की महत्वपूर्ण चीजों के लिए क्या करेंगे। कहा कि, जब तक एक बेहतर जवाब नहीं मिलता है, आप यह कर सकते हैं और देख सकते हैं कि क्या यह काम करता है:

  • इस प्रक्रिया को मैन्युअल रूप से कुछ समय के लिए करें और सेकंड में कितनी बार करें यह आमतौर पर पूरा करने के लिए ज़िप प्रक्रिया में होता है। यदि डेटाबेस का आकार आम तौर पर प्रतिदिन समान होता है, तो समाप्त होने में लगने वाला समय संभवतः उसी समय के आसपास औसत रहेगा।

  • मान लीजिए कि आपको अपने मैनुअल परीक्षणों में औसतन 60 सेकंड मिलते हैं। रूढ़िवादी रहें और इसे 4 से गुणा करें, क्योंकि यह "सामान्य" दिनों में सामान्य से 4 गुना अधिक समय नहीं लेगा। तो अब आपके पास 240 सेकंड (60 सेकंड औसत 4 बार) है।

  • इसलिए अभी के लिए, वहां "जारी रखने के लिए कोई भी कुंजी दबाएं" कोड रखने के बजाय, उस कोड में एक DELAY के साथ बदलें बस ज़िप को समाप्त करने के लिए प्रतीक्षा करने के लिए स्क्रिप्ट को थोड़ा बाहर लटका देना है। इसके लिए कुछ समय और अनुमान लगाना आवश्यक है और यह एक अच्छा तरीका नहीं है। लेकिन एक चुटकी में ...

  • वैसे भी, यदि आप इसे आज़माना चाहते हैं, तो कोड को इसमें बदलें:

यदि PowerShell V1 का उपयोग कर रहे हैं:

foreach($file in $input)
{
  $zipPackage.CopyHere($file.FullName)       
}

[System.Threading.Thread]::Sleep(240000)

यदि PowerShell V2 का उपयोग कर रहे हैं, तो इसके बजाय स्लीप cmdlet का उपयोग करें:

foreach($file in $input)
{
   $zipPackage.CopyHere($file.FullName)       
}

Start-Sleep -Second 240

V1 में समय के साथ गड़बड़ करने के लिए यह मिलीसेकंड का उपयोग करता है। (तो 10 सेकंड = 10000)

V2 में समय के साथ गड़बड़ करने के लिए यह सेकंड का उपयोग करता है। (240 = 240 सेकंड)

मैं उत्पादन में इसका उपयोग कभी नहीं करूंगा, लेकिन अगर यह सौदा का बड़ा हिस्सा नहीं है, और यह 99% समय के लिए ठीक काम करता है, तो यह काफी अच्छा हो सकता है।


मैंने आखिरकार इसका हल ढूंढ लिया। मैं वैसे भी आपकी मदद की सराहना करता हूं। Thx
स्टीव बी
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.