2012-02-09 14 views
5

Chcę utworzyć plik zip w powłoce powershell, dodać elementy do pliku zip, a następnie skompresować zawartość tego pliku zip jako bajty natychmiast po utworzeniu pliku zip , w tym samym skry. Problem polega na tym, że nie wydaje się, że aplikacja zip napisała swoją zawartość do systemu plików. Jak można zamknąć/przepłukać aplikację zip, aby następna instrukcja rozszerzenia mogła uzyskać dostęp do nowo utworzonego pliku zip?Powershell - Jak skompletować/zamknąć plik zip w powłoce Shell

Przykład:

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 

W "reż test.zip" pokazuje plik zip bez treści, stąd Get-Content nic nie zwraca.

Należy zauważyć, że to wydaje się być problem z asynchronicznym zachowaniem działania kopiowania. Jeśli śpię po linii copyhere, plik zip zostanie zapełniony. Jednak nie wiem, jak długo należy spać, ani nie chcę opóźniać przetwarzania.

Wiele z góry!

+0

Nigdy nie tworzyłem archiwów z PowerShell, ale nie wygląda to tak, jakby działało w ogóle. – Joey

+1

zajrzyj tutaj: http://dotnetzip.codeplex.com/. Inoic.zip jest lepszy w pracy z plikiem zip! –

+0

To rzeczywiście działa. Jeśli spojrzysz na katalog, w którym wykonujesz te instrukcje, okaże się, że został utworzony plik test.zip. –

Odpowiedz

0

Ta metoda pliki zip nie jest odpowiednia do automatycznych skryptów. Ma to ograniczenia w Windows 2003 i Windows XP Server na 3 koncerty. Ponadto nie daje właściwych błędów.

+0

Po przykręceniu tego przez chwilę, muszę się zgodzić. Przywoływanie powłoki do manipulowania suwakiem wymaga dużego nakładu pracy i jest niezwykle pośrednie. Sprawdziłem bibliotekę Inoic.zip, o której wspominał @Christian, i stwierdziłem, że działa ona bardzo dobrze dla mojego przypadku użycia, który tworzy bajty pliku zip bez konieczności zapisu w systemie plików. Dziękuję wszystkim za ich twórcze rozwiązania! –

+0

-DV nie jest odpowiedzią w ogóle ... – GoClimbColorado

0

spróbuj utworzyć pusty plik zip tak:

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

Wtedy reszta kodzie.

ten kod w moim polu działa:

$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) 

aby uzyskać zawartość zip użyj:

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

Dwa razy uruchomisz mój skrypt, za drugim razem uruchamia test.plik zip już tam będzie, ale wyniki będą takie same - nadal będzie puste. Bez względu na to, próbowałem tego z takimi samymi wynikami :-( –

+0

Działa w moim pudełku (xp pro/powershell 2.0) działa: stwórz plik myfile.zip i dodaj plik.txt –

+0

Myślę, że źle mnie zrozumiałeś. nie chcę skompresować zawartości pliku zip po jego utworzeniu Chcę uzyskać sam plik zip (skompresowany) w tym samym skrypcie, który go utworzył, zaraz po utworzeniu pliku zip. Jeśli uruchomisz oba skrypty razem jako jeden (nieznacznie zmodyfikowany, aby poprawić nazwę pliku zip), wynik jest taki sam - pusty plik ZIP –

0

Utwórz plik w zamknięciu, tak że zmienna wykracza poza zakres a powershell zamyka plik ... jeśli zrobiłbyś tę część w podprocedurze, to naturalnie by się zamknął po powrocie.

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

Próbowałem tego, ale tworzenie zamknięcia lub umieszczanie kodu w funkcji nie poprawia rzeczy. –

1

Możesz chcieć ponownie rozważyć użycie biblioteki innej firmy. Jednakże, jeśli trzeba użyć copyhere, spróbuj tego:

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

Jeśli trzeba użyć powłoki do tworzenia plików zip, to to rozwiązanie działa dobrze w określaniu, kiedy asynchroniczna kopia jest kompletna. Nie sądzę, że nadal nie jestem pewien, czy ta metoda spowoduje częściowe zapisanie pliku zip. –

1

Też miałem ten problem, wystarczy tylko poczekać, aż operacja skompresowania nie zostanie zakończona. Więc wymyślam to rozwiązanie, powinieneś umieścić ten kod po wykonaniu polecenia cmdlet "$ folder.copyhere" lub "Copy-ToZip" powerpack.

$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 
     } 
    }