2012-02-09 1 views
5

Voglio creare un file zip in PowerShell, aggiungere elementi al file zip, quindi ottenere il contenuto compresso di tale file zip come byte subito dopo la creazione del file zip , nella stessa scipt. Il problema è che non sembra che l'applicazione zip abbia scritto il suo contenuto nel file system. Come si chiude/svuota l'applicazione zip in modo che la prossima istruzione PowerShell possa accedere al file zip appena creato?PowerShell - Come completare/chiudere un file zip in PowerShell

Esempio:

new-item -type File test.zip -force 
$zip = (get-item test.zip).fullname 
$app = new-object -com shell.application 
$folder = $app.namespace($zip) 
$item = new-item file.txt -itemtype file -value "Mooo" -force 
$folder.copyhere($item.fullname) 
dir test.zip # <---- Empty test.zip file 
Get-Content -Encoding byte $zip | echo # <-- nothing echoed 

Il "dir test.zip" mostra un file zip senza contenuti, così il Get-Content restituisce nulla.

Si noti che questo sembra essere un problema con il comportamento asincrono dell'azione copyhere. Se dormo dopo la linea copyhere, il file zip verrà popolato. Tuttavia, non so per quanto tempo si deve dormire, né voglio ritardare l'elaborazione.

Molto Grazie in anticipo!

+0

Non ho mai creato archivi da PowerShell, ma questo non sembra funzionare affatto. – Joey

+1

dai uno sguardo qui: http://dotnetzip.codeplex.com/. Inoic.zip è un modo migliore per lavorare con il file zip! –

+0

Lo fa, anzi funziona. Se si guarda la directory in cui si eseguono queste istruzioni, si scoprirà che è stato creato un file test.zip. –

risposta

0

Questo metodo di comprimere file non è appropriato per gli script automatizzati. Questo ha limitazioni in Windows 2003 e Windows xp server per 3 concerti. Inoltre, non dà errori corretti.

+0

Dopo aver fallito con questo per un po ', devo essere d'accordo. Invocare la shell per manipolare uno zip richiede un sacco di spese generali ed è estremamente indiretta. Ho controllato la libreria Inoic.zip che @Christian ha menzionato e ho trovato che funziona molto bene per il mio caso d'uso, che sta creando i byte del file zip senza dover scrivere sul file system. Ringrazio tutti per le loro soluzioni creative! –

+0

-DV non è affatto una risposta ... – GoClimbColorado

0

provare a creare il file vuoto zip in questo modo:

$zipfilename = "myzip.zip" 
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 

Poi il resto del codice.

questo codice nella mia casella di opere:

$zipfilename = "a.zip" 
set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18)) 
$app = new-object -com shell.application 
$zip = (get-item a.zip).fullname 
$folder = $app.namespace($zip) 
$item = new-item file.txt -itemtype file -value "Mooo" -force 
$folder.copyhere($item.fullname) 

per ottenere il contenuto di una zip utilizzare questo:

$zipfilename = "myzip.zip" 
$shellApplication = new-object -com shell.application 
$zipPackage = $shellApplication.NameSpace($zipfilename) 
$zipPackage.Items() | Select Path 
+0

Ho eseguito il mio script due volte, la seconda volta esegue il test.il file zip sarà già lì, ma i risultati sono uguali: sarà comunque vuoto. Nondimeno, ho provato questo con gli stessi risultati :-( –

+0

Nel mio box (xp pro/powershell 2.0) funziona: crea un file myfile.zip e aggiungi un file.txt. –

+0

Penso che tu mi fraintenda. 'Voglio ottenere il contenuto non compresso del file zip dopo averlo creato. Voglio ottenere il file zip vero e proprio (compresso) nello stesso script che lo ha creato, subito dopo aver creato il file .zip Se esegui i tuoi due script insieme come uno (leggermente modificato per correggere il nome del file zip), il risultato è lo stesso: un file zip vuoto –

0

Creare il file in una chiusura, in modo che la variabile va fuori del campo di applicazione e powershell chiude il file ... se avessi fatto quella parte in una subroutine, si sarebbe chiusa naturalmente al tuo ritorno.

new-item -type File test.zip -force 
{ 
    $zip = (get-item test.zip).fullname 
    $app = new-object -com shell.application 
    $folder = $app.namespace($zip) 
    $item = new-item file.txt -itemtype file -value "Mooo" -force 
    $folder.copyhere($item.fullname) 
} 
dir test.zip # <---- Empty test.zip file 
Get-Content -Encoding byte $zip 
+0

Ho provato, ma la creazione di una chiusura o il posizionamento del codice in una funzione non migliorano le cose –

1

È possibile riconsiderare l'utilizzo di una libreria di terze parti. Tuttavia, se è necessario utilizzare CopyHere, provate questo:

new-item -type File test.zip -force 
$zip = (get-item test.zip).fullname 
$app = new-object -com shell.application 
$folder = $app.namespace($zip) 
$item = new-item file.txt -itemtype file -value "Mooo" -force 
$folder.copyhere($item.fullname) 
while($folder.Items().Item($item.Name) -Eq $null) 
{ 
    start-sleep -seconds 0.01 
    write-host "." -nonewline 
} 
dir test.zip # <---- Empty test.zip file 
Get-Content -Encoding byte $zip 
+0

Se si deve usare la shell per creare i file zip, allora questa soluzione funziona bene per determinare quando la copia asincrona è completa. No, non sono ancora sicuro se questo metodo si tradurrà in una scrittura parziale del file zip. –

1

Ho anche avuto questo problema, tutto ciò che serve è attendere che l'operazione di zipping non sia completata. Quindi, trovo questa soluzione, dovresti inserire questo codice dopo aver eseguito il cmdlet powerpack "$ folder.copyhere" o "Copy-ToZip".

$isCompleted = $false 
    $guid = [Guid]::NewGuid().ToString() 
    $tmpFileName = $zipFileName + $guid 
    # The main idea is to try to rename target ZIP file. If it success then archiving operation is complete. 
    while(!$isCompleted) 
    { 
     start-sleep -seconds 1 
     Rename-Item $zipFileName $tmpFileName -ea 0 #Try to rename with suppressing errors 
     if (Test-Path $tmpFileName) 
     { 
      Rename-Item $tmpFileName $zipFileName #Rename it back 
      $isCompleted = $true 
     } 
    }