Creating a zipped/compressed folder in Windows usi

2019-01-31 08:01发布

I am creating a nightly database schema file and would like to put all the files created each night, one for each database, into a folder and compress that folder. I have a PowerShell script that creates the schema.Only creation script of the db's and then adds all the files to a new folder. The problem lies within the compression portion of this process.

Does anybody have any idea if this can be accomplished with the pre-installed Windows utility that handles folder compression?

It would be best to use that utility if possible rather than something like 7zip (I don't feel like installing 7zip on every customers' server and it may take IT years to do it if I ask them).

6条回答
再贱就再见
2楼-- · 2019-01-31 08:41

Used voithos' answer to zip files up in powershell, just had one problem with the Add-Zip function, the Start-sleep -milliseconds 500 caused problems if the file couldn't be fully zipped up in that time -> the next one starting before it was complete caused errors and some files not to be zipped.

So after playing around for a bit, first trying to get a counter going to check the count of the $zipPackage.Items() and only continuing after the items count increased (which did not work as it would return 0 in some cases when it should not) I found that it will return 0 if the package is still zipping/copying the files up (I think, haha). Added a simple while loop with the start-sleep inside of it, waiting for the zipPackage.Items().count to be a non-zero value before continuing and this seems to solve the problem.

function Add-Zip
{
param([string]$zipfilename)

if(-not (test-path($zipfilename)))
{
    set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
    (dir $zipfilename).IsReadOnly = $false  
}

$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)

foreach($file in $input) 
{ 
        $zipPackage.CopyHere($file.FullName)
        do
        {
            Start-sleep -milliseconds 250
        }
        while ($zipPackage.Items().count -eq 0)
}
}
查看更多
The star\"
3楼-- · 2019-01-31 08:48

Using PowerShell Version 3.0:

Copy-ToZip -File ".\blah" -ZipFile ".\blah.zip" -Force

Hope this helps.

查看更多
Melony?
4楼-- · 2019-01-31 08:54

This compresses .\in contents to .\out.zip with System.IO.Packaging.ZipPackage following the example here

$zipArchive = $pwd.path + "\out.zip"
[System.Reflection.Assembly]::Load("WindowsBase,Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")
$ZipPackage=[System.IO.Packaging.ZipPackage]::Open($zipArchive, [System.IO.FileMode]"OpenOrCreate", [System.IO.FileAccess]"ReadWrite")
$in = gci .\in | select -expand fullName
[array]$files = $in -replace "C:","" -replace "\\","/"
ForEach ($file In $files) {
   $partName=New-Object System.Uri($file, [System.UriKind]"Relative")
   $part=$ZipPackage.CreatePart($partName, "application/zip", [System.IO.Packaging.CompressionOption]"Maximum")
   $bytes=[System.IO.File]::ReadAllBytes($file)
   $stream=$part.GetStream()
   $stream.Write($bytes, 0, $bytes.Length)
   $stream.Close()
                                                    }
$ZipPackage.Close()
查看更多
神经病院院长
5楼-- · 2019-01-31 08:56

A native way with latest .NET 4.5 framework, but entirely feature-less:

Creation:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::CreateFromDirectory("c:\your\directory\to\compress", "yourfile.zip") ;

Extraction:

Add-Type -Assembly "System.IO.Compression.FileSystem" ;
[System.IO.Compression.ZipFile]::ExtractToDirectory("yourfile.zip", "c:\your\destination") ;

As mentioned, totally feature-less, so don't expect an overwrite flag.

查看更多
一纸荒年 Trace。
6楼-- · 2019-01-31 08:57

As of PowersShell 5 there is a Compress-Archive cmdlet that does the task out of the box.

查看更多
Fickle 薄情
7楼-- · 2019-01-31 08:59

Here's a couple of zip-related functions that don't rely on extensions: Compress Files with Windows PowerShell.

The main function that you'd likely be interested in is:

function Add-Zip
{
    param([string]$zipfilename)

    if(-not (test-path($zipfilename)))
    {
        set-content $zipfilename ("PK" + [char]5 + [char]6 + ("$([char]0)" * 18))
        (dir $zipfilename).IsReadOnly = $false  
    }

    $shellApplication = new-object -com shell.application
    $zipPackage = $shellApplication.NameSpace($zipfilename)

    foreach($file in $input) 
    { 
            $zipPackage.CopyHere($file.FullName)
            Start-sleep -milliseconds 500
    }
}

Usage:

dir c:\demo\files\*.* -Recurse | Add-Zip c:\demo\myzip.zip

There is one caveat: the shell.application object's NameSpace() function fails to open up the zip file for writing if the path isn't absolute. So, if you passed a relative path to Add-Zip, it'll fail with a null error, so the path to the zip file must be absolute.

Or you could just add a $zipfilename = resolve-path $zipfilename at the beginning of the function.

查看更多
登录 后发表回答