Hi Dino,
(Note: I’m addressing this post to Dino only because I’m suggesting there
may be a bug in the library. However, all comments, especially those containing helpful suggestions, are welcome.) I apologize for the length of this post, but it takes quite a bit of space to communicate all the necessary information.
I’ve been struggling for several weeks to create a Powershell script that uses DotNetZip to archive (zip) a set of nested folders, and I think I’ve run into a bug in the library. I’ll lay it out for you, and maybe you can tell me what’s going on.
I'm running under Windows 7 SP1 Professional and PowerShell 3.0.
I’m using a slight modification of your ZipUp-Files script at the DotNetZip Home Page on MSDN. (
http://archive.msdn.microsoft.com/DotNetZip/Wiki/View.aspx?title=PowerShell%20Example&referringTitle=Home) At least I was going to
start there. Unfortunately, I didn’t get very far, because of this
alleged bug.
Here is my script as it stands now. Most of the changes I’ve made deal with file and directory names to make the script compatible with my machine’s filesystem.
function ZipUp-Files ( $directory )
{
$children = get-childitem -path $directory
foreach ($o in $children)
{
if (!$BaseDir -or ($BaseDir -eq "")) {
$ix = $o.PSParentPath.IndexOf("::")
$BaseDir = $o.PSParentPath.Substring($ix+2)
$x = get-item $BaseDir
$ix = $x.PSParentPath.IndexOf("::")
$ParentOfBase = $x.PSParentPath.Substring($ix+2) + "\"
}
if ($o.Name -ne "TestResults" -and
$o.Name -ne "obj" -and
$o.Name -ne "bin" -and
$o.Name -ne "NTUSER.DAT" -and
$o.Name -ne "_tfs" -and
$o.Name -ne "notused" -and
$o.Name -ne "AppNote.txt" -and
$o.Name -ne "CodePlex-Readme.txt" -and
$o.Name -ne "ReadThis.txt" -and
$o.Name -ne "Ionic.snk" -and
$o.Name -ne "Ionic.pfx" -and
$o.Name -ne "Debug" -and
$o.Name -ne "Release" -and
$o.Name -ne "Resources")
{
if ($o.PSIsContainer)
{
ZipUp-Files ( $o.FullName )
}
else
{
#Write-output $o.FullName
if ($o.Name -and
$o.Name -ne "" -and
$o.Name -ne ".tfs-ignore" -and
(!$o.Name.EndsWith("~")) -and
(!$o.Name.EndsWith("#")) -and
(!$o.Name.EndsWith(".cache")) -and
(!$o.Name.EndsWith(".zip") )
)
{
Write-output $o.FullName.Replace($ParentOfBase, "")
$e= $zipfile.AddFile($o.FullName.Replace($ParentOfBase, ""))
}
}
}
}
}
$DotNetZip='C:\Windows\System32\WindowsPowerShell\v1.0\DotNetZip'
$DNZ = $DotNetZip
$PS = 'C:\PSScripts' # Development area for my PowerShell scripts
Remove-Item 'c:\DotNetZip-src-v.zip' -Force -ea SilentlyContinue
[System.Reflection.Assembly]::LoadFrom($DNZ+'\Ionic.Zip.Dll')
# [System.Reflection.Assembly]::LoadFrom("c:\\dinoch\\bin\\Ionic.Zip.dll");
$version = get-content -path $DNZ'\AssemblyInfo.cs' | select-string -pattern 'AssemblyFileVersion\("[0-9]+(\.([0-9]+|\*)){1,3}"\)' | %{$_ -replace "[^0-9.]",""}
$ZipFileName = 'c:\DotNetZip-src-v.zip'
$zipfile = new-object Ionic.Zip.ZipFile($ZipFileName);
cd $DNZ; cd ..
ZipUp-Files "DotNetZip"
$zipfile.Save()
$zipfile.Dispose()
cd $PS
As suggested by $DotNetZip= immediately after the
function portion of the script, on my machine, Powershell is installed at C:\Windows\System32\WindowsPowerShell\v1.0, and DotNetZip is stored in a directory therein. For the ISE host, that is sufficient. The variable $DotNetZip points to that directory, and Powershell_ISE is happy. I can run the script, which I have called
ZipUp-Files-WFM.ps1 in that host all day long.
However, the Console-Host is an entirely story: when I attempt to run ZipUp-Files-WFM under simply Powershell, it results in an abnormal termination, with the following messages at the end.
. . . . . . . . . . . . . . . . . . . . . .
DotNetZip\License.zlib.txt
DotNetZip\License_1.txt
DotNetZip\PleaseDonate.txt
DotNetZip\PleaseDonate_1.txt
DotNetZip\Readme.txt
DotNetZip\Readme_1.txt
DotNetZip\Zipit.exe
Exception calling "Save" with "0" argument(s): "C:\Users\Walter\DotNetZip\Apps\ConvertFromCS-Zip.ps1"
At C:\PSScripts\ZipUp-Files-WFM.ps1:68 char:1
+ $zipfile.Save()
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FileNotFoundException
To me most of the error message is essentially nonsense. Maybe it means more to you.
If however, I install a second copy of DotNetZip in
C:\Users\Walter, (which, incidentally, is the value of $Home), keeping the existing copy in
C:\Windows\System32\WindowsPowerShell\v1.0, then both the Console-Host and the ISE host will run the script all day long.
The reason I
suspect there is bug is that neither my $profile nor my script make any reference to the
C:\Users\Walter directory, other than indirectly through $(PS)Home preference variables. Those variables alone, over which I have little or no control, should not be enough to require a second installation (i.e. copy) of DotNetZip. OTOH, if there is a good reason for there to be a second copy of DotNetZip in a directory in $Home (i.e. in
c:\Users\Walter\DotNetZip), then surely both Powershell hosts should behave consistently, which they do not, in that only the non-graphical Console Host requires both copies of the DotNetZip library.
Furthermore, most of the method calls to Ionic.Zip.dll are content to use the $Home directory, and do so correctly. Only the Save() method call fails, and when it does, it yanks an (incorrect) pathname out of thin air. To me, that strongly suggests a bug somewhere in the method code.
Thanks in advance for your help,
Walter