Author Posts

December 20, 2013 at 2:47 pm

Hello,

I'm trying to use ZipFile class from .NET 4.0 System.IO.Compression namespace and code fails to pull Extension method called "CreateEntryFromFile" implemented in ZipFileExtensions class (http://msdn.microsoft.com/en-us/library/system.io.compression.zipfileextensions(v=vs.110).aspx). It states "The ZipFileExtensions class contains only static methods that extend the ZipArchive and ZipArchiveEntry classes. You do not create an instance of the ZipFileExtensions class; instead, you use these methods from instances of ZipArchive or ZipArchiveEntry."

Sample Code below fails with Method invocation failed because [System.IO.Compression.ZipArchive] does not contain a method named 'CreateEntryFromFile'.

What am I missing?

[Reflection.Assembly]::LoadWithPartialName( "System.IO.Compression.FileSystem" )
$zipFile = [System.IO.Compression.ZipFile]::Open($zipFileLocation, "update")
[System.IO.Compression.ZipArchive]$zipFile.CreateEntryFromFile("$PathToOutputResult\$filename.p12", "$filename.p12")

December 20, 2013 at 3:19 pm

System.IO.Compression.ZipArchive does not, in fact, have a CreateEntryFromFile() method. See http://msdn.microsoft.com/en-us/library/system.io.compression.ziparchive(v=vs.110).aspx; as noted, that's an extension method. Providing that as background info for future readers ;).

Using extension methods in PowerShell is somewhat less than straightforward. There's a discussion (http://bartdesmet.net/blogs/bart/archive/2007/09/06/extension-methods-in-windows-powershell.aspx) you might look into.

Extension methods were new in .NET 3.5; PowerShell's syntax was developed around .NET 2.0 and didn't really accommodate extension methods directly. So you sort of have to extend the type using PowerShell's ETS first, pointing to the underlying static method. http://social.technet.microsoft.com/Forums/en-US/bf3fd75b-30a8-44f9-b82d-5e9cc244faba/are-extension-methods-accessible?forum=winserverpowershell is perhaps a more straightforward example. Although whether that works and how you do it depends a lot on exactly what you're trying to get to.

So, very short answer: you can't do that.

December 21, 2013 at 1:10 pm

Those articles appear to have been written prior to PowerShell 3.0's release. If you want to add an extension method these days, it's even easier; no need to produce an XML file first, if you don't want to. For example:

Add-Type -AssemblyName System.IO.Compression.FileSystem

Update-TypeData -TypeName System.IO.Compression.ZipArchive -MemberType ScriptMethod -MemberName CreateEntryFromFile -Value {
    switch ($args.Count)
    {
        2 { [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($this, $args[0], $args[1]) }
        3 { [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($this, $args[0], $args[1], $args[2]) }
        default { throw "No overload for CreateEntryFromFile takes the specified number of parameters." }
    }
}

$zipFile = [System.IO.Compression.ZipFile]::Open($zipFileLocation, 'update')
$zipFile.CreateEntryFromFile("$PathToOutputResult\$filename.p12", "$filename.p12")

You can put the Add-Type and Update-TypeData commands into a module or profile script, and forget about them.

Of course, you don't have to use the "extension method" syntax at all. If you prefer, you can just call them as static methods and not bother with Update-TypeData:

Add-Type -AssemblyName System.IO.Compression.FileSystem

$zipFile = [System.IO.Compression.ZipFile]::Open($zipFileLocation, 'update')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($zipFile, "$PathToOutputResult\$filename.p12", "$filename.p12")