素の.net 3.0以降でZIPファイルを扱う
.net 4.5からZipArchiveクラスが提供されます。
これによりようやくZIPファイルの扱いがまともになるわけですが、、、。
Windows7/8では、素では.net4.5は入っていません。
これをなんとかしたい。
経緯
Explorerの圧縮フォルダー機能でZIPは扱えますが、不安定じゃないですか。
それにMicrosoftも推奨ではない、とか言うし。
dotNetZipとかライブラリーを使えば良いんですけど、ライセンスとかインストールとか面倒。
ZIPと言えば、.net3.0からは、OpenDocument形式のためのクラスがある。
これはちょっと特殊なZIPファイル。(いろいろ制限がある)
でもこれができるなら、扱えるんじゃないの?と探したところ、、、あった。
http://www.codeproject.com/Articles/209731/Csharp-use-Zip-archives-without-external-libraries
登録が面倒だったので、ソースは見てないけど、十分なヒント。
非公開のクラスをリフレクションしまくりでやってみたら、、、できた!
、、、が、日付が更新できない。
今のところ、あとからバイナリー編集して日付を更新する方法しか見つけてない。
追記 2014/08/29
更新日付の変更に対応した、超割切り仕様のクラスを作成しました。
http://d.hatena.ne.jp/junjun777/20140829/dot_net_zip
以下ソース。
日付更新できない版
日付が更新できなくても良いなら、これで良いかと。
using System; using System.Collections.Generic; using System.IO; using System.Reflection; namespace ZipPackageSample { class ZipArchive : IDisposable { private static Type _type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipArchive"); private static MethodInfo _openOnFile = _type.GetMethod("OpenOnFile", BindingFlags.Static | BindingFlags.NonPublic); private static MethodInfo _openOnStream = _type.GetMethod("OpenOnStream", BindingFlags.Static | BindingFlags.NonPublic); public static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) { return new ZipArchive { _zipArchive = _openOnFile.Invoke(null, new object[] { path, mode, access, share, streaming }) }; } public static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming) { return new ZipArchive { _zipArchive = _openOnStream.Invoke(null, new object[] { stream, mode, access, streaming }) }; } private static Type _typeCme = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.CompressionMethodEnum"); private static object _stored = _typeCme.GetField("Stored", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _deflated = _typeCme.GetField("Deflated", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static Type _typeDoe = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.DeflateOptionEnum"); private static object _normal = _typeDoe.GetField("Normal", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _maximum = _typeDoe.GetField("Maximum", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _fast = _typeDoe.GetField("Fast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _superFast = _typeDoe.GetField("SuperFast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _none = _typeDoe.GetField("None", BindingFlags.Static | BindingFlags.Public).GetValue(null); public static CompressionMethodEnum FromInternalCme(object cme) { CompressionMethodEnum ret = CompressionMethodEnum.Stored; if (_deflated.Equals(cme)) ret = CompressionMethodEnum.Deflated; return ret; } public static object ToInternalCme(CompressionMethodEnum cme) { object ret = _stored; if (cme == CompressionMethodEnum.Deflated) ret = _deflated; return ret; } public static DeflateOptionEnum FromInternalDoe(object doe) { DeflateOptionEnum ret = DeflateOptionEnum.None; if (_normal.Equals(doe)) { ret = DeflateOptionEnum.Normal; } else if (_maximum.Equals(doe)) { ret = DeflateOptionEnum.Maximum; } else if (_fast.Equals(doe)) { ret = DeflateOptionEnum.Fast; } else if (_superFast.Equals(doe)) { ret = DeflateOptionEnum.SuperFast; } return ret; } public static object ToInternalDoe(DeflateOptionEnum doe) { object ret = _none; if (doe == DeflateOptionEnum.Normal) { ret = _normal; } else if (doe == DeflateOptionEnum.Maximum) { ret = _maximum; } else if (doe == DeflateOptionEnum.Fast) { ret = _fast; } else if (doe == DeflateOptionEnum.SuperFast) { ret = _superFast; } return ret; } private object _zipArchive = null; private static MethodInfo _addFile = _type.GetMethod("AddFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFile = _type.GetMethod("GetFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _fileExists = _type.GetMethod("FileExists", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _deleteFile = _type.GetMethod("DeleteFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFiles = _type.GetMethod("GetFiles", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _flush = _type.GetMethod("Flush", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _close = _type.GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _dispose = _type.GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public); private static PropertyInfo _openAccess = _type.GetProperty("OpenAccess", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipFileInfoDictionary = _type.GetProperty("ZipFileInfoDictionary", BindingFlags.Instance | BindingFlags.NonPublic); public ZipFileInfo AddFile(string path, CompressionMethodEnum cme, DeflateOptionEnum doe) { return new ZipFileInfo(_addFile.Invoke(_zipArchive, new object[] { path, ToInternalCme(cme), ToInternalDoe(doe) })); } public ZipFileInfo GetFile(string path) { return new ZipFileInfo(_getFile.Invoke(_zipArchive, new object[] { path })); } public bool FileExists(string path) { return (bool)_fileExists.Invoke(_zipArchive, new object[] { path }); } public void DeleteFile(string path) { _deleteFile.Invoke(_zipArchive, new object[] { path }); } private static Type _typeZfic = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipFileInfoCollection"); private static MethodInfo _getEnumerator = _typeZfic.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Instance | BindingFlags.NonPublic); public IEnumerable<ZipFileInfo> GetFiles() { var zfic = _getEnumerator.Invoke(_getFiles.Invoke(_zipArchive, null), null) as System.Collections.IEnumerator; while (zfic.MoveNext()) { yield return new ZipFileInfo(zfic.Current); } } public void Flush() { _flush.Invoke(_zipArchive, null); } public void Close() { _close.Invoke(_zipArchive, null); } public void Dispose() { _dispose.Invoke(_zipArchive, null); } public FileAccess OpenAccess { get { return (FileAccess)_openAccess.GetValue(_zipArchive, null); } } public System.Collections.IDictionary ZipFileInfoDictionary { get { return _zipFileInfoDictionary.GetValue(_zipArchive, null) as System.Collections.IDictionary; } } public class ZipFileInfo { private static Type _type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipFileInfo"); private static MethodInfo _getStream = _type.GetMethod("GetStream", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _name = _type.GetProperty("Name", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipArchive = _type.GetProperty("ZipArchive", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _compressionMethod = _type.GetProperty("CompressionMethod", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _lastModFileDateTime = _type.GetProperty("LastModFileDateTime", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _deflateOption = _type.GetProperty("DeflateOption", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _folderFlag = _type.GetProperty("FolderFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _volumeLabelFlag = _type.GetProperty("VolumeLabelFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _localFileBlock = _type.GetProperty("LocalFileBlock", BindingFlags.Instance | BindingFlags.NonPublic); private static Type _typeL = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipIOLocalFileBlock"); private static PropertyInfo _lastMod = _typeL.GetProperty("LastModFileDateTime", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _compSize = _typeL.GetProperty("CompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _uncompSize = _typeL.GetProperty("UncompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private object _zipFileInfo = null; private object _lfb = null; public ZipFileInfo(object zipFileInfo) { _zipFileInfo = zipFileInfo; } public Stream GetStream(FileMode mode, FileAccess access) { return _getStream.Invoke(_zipFileInfo, new object[] { mode, access }) as Stream; } public string Name { get { return _name.GetValue(_zipFileInfo, null) as string; } } public ZipArchive ZipArchive { get { return new ZipArchive { _zipArchive = _zipArchive.GetValue(_zipFileInfo, null) }; } } public CompressionMethodEnum CompressionMethod { get { return ZipArchive.FromInternalCme(_compressionMethod.GetValue(_zipFileInfo, null)); } } public DateTime LastModFileDateTime { get { return (DateTime)_lastModFileDateTime.GetValue(_zipFileInfo, null); } } public DeflateOptionEnum DeflateOption { get { return ZipArchive.FromInternalDoe(_deflateOption.GetValue(_zipFileInfo, null)); } } public bool FolderFlag { get { return (bool)_folderFlag.GetValue(_zipFileInfo, null); } } public bool VolumeLabelFlag { get { return (bool)_volumeLabelFlag.GetValue(_zipFileInfo, null); } } public long CompressedSize { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_compSize.GetValue(_lfb, null); } } public long UncompressedSize { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_uncompSize.GetValue(_lfb, null); } } } public enum CompressionMethodEnum { Stored, Deflated } public enum DeflateOptionEnum { Normal, Maximum, Fast, SuperFast, None } } }
Powershell版
一部文法がPowershellで使えなかったので(Powershellのバージョンのせいかな)、少し改変した。
$source = @" using System; using System.Collections.Generic; using System.IO; using System.Reflection; public class ZipArchive : IDisposable { private static Assembly _ass = Assembly.GetAssembly(typeof(System.IO.Packaging.Package)); private static Type _type = _ass.GetType("MS.Internal.IO.Zip.ZipArchive"); private static MethodInfo _openOnFile = _type.GetMethod("OpenOnFile", BindingFlags.Static | BindingFlags.NonPublic); private static MethodInfo _openOnStream = _type.GetMethod("OpenOnStream", BindingFlags.Static | BindingFlags.NonPublic); public static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) { return new ZipArchive(_openOnFile.Invoke(null, new object[] { path, mode, access, share, streaming })); } public static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming) { return new ZipArchive(_openOnStream.Invoke(null, new object[] { stream, mode, access, streaming })); } private static Type _typeCme = _ass.GetType("MS.Internal.IO.Zip.CompressionMethodEnum"); private static object _stored = _typeCme.GetField("Stored", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _deflated = _typeCme.GetField("Deflated", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static Type _typeDoe = _ass.GetType("MS.Internal.IO.Zip.DeflateOptionEnum"); private static object _normal = _typeDoe.GetField("Normal", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _maximum = _typeDoe.GetField("Maximum", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _fast = _typeDoe.GetField("Fast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _superFast = _typeDoe.GetField("SuperFast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _none = _typeDoe.GetField("None", BindingFlags.Static | BindingFlags.Public).GetValue(null); public ZipArchive(object zipArchive) { _zipArchive = zipArchive; } public static CompressionMethodEnum FromInternalCme(object cme) { CompressionMethodEnum ret = CompressionMethodEnum.Stored; if (_deflated.Equals(cme)) ret = CompressionMethodEnum.Deflated; return ret; } public static object ToInternalCme(CompressionMethodEnum cme) { object ret = _stored; if (cme == CompressionMethodEnum.Deflated) ret = _deflated; return ret; } public static DeflateOptionEnum FromInternalDoe(object doe) { DeflateOptionEnum ret = DeflateOptionEnum.None; if (_normal.Equals(doe)) { ret = DeflateOptionEnum.Normal; } else if (_maximum.Equals(doe)) { ret = DeflateOptionEnum.Maximum; } else if (_fast.Equals(doe)) { ret = DeflateOptionEnum.Fast; } else if (_superFast.Equals(doe)) { ret = DeflateOptionEnum.SuperFast; } return ret; } public static object ToInternalDoe(DeflateOptionEnum doe) { object ret = _none; if (doe == DeflateOptionEnum.Normal) { ret = _normal; } else if (doe == DeflateOptionEnum.Maximum) { ret = _maximum; } else if (doe == DeflateOptionEnum.Fast) { ret = _fast; } else if (doe == DeflateOptionEnum.SuperFast) { ret = _superFast; } return ret; } private object _zipArchive = null; private static MethodInfo _addFile = _type.GetMethod("AddFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFile = _type.GetMethod("GetFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _fileExists = _type.GetMethod("FileExists", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _deleteFile = _type.GetMethod("DeleteFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFiles = _type.GetMethod("GetFiles", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _flush = _type.GetMethod("Flush", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _close = _type.GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _dispose = _type.GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public); private static PropertyInfo _openAccess = _type.GetProperty("OpenAccess", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipFileInfoDictionary = _type.GetProperty("ZipFileInfoDictionary", BindingFlags.Instance | BindingFlags.NonPublic); public ZipFileInfo AddFile(string path, CompressionMethodEnum cme, DeflateOptionEnum doe) { return new ZipFileInfo(_addFile.Invoke(_zipArchive, new object[] { path, ToInternalCme(cme), ToInternalDoe(doe) })); } public ZipFileInfo GetFile(string path) { return new ZipFileInfo(_getFile.Invoke(_zipArchive, new object[] { path })); } public bool FileExists(string path) { return (bool)_fileExists.Invoke(_zipArchive, new object[] { path }); } public void DeleteFile(string path) { _deleteFile.Invoke(_zipArchive, new object[] { path }); } private static Type _typeZfic = _ass.GetType("MS.Internal.IO.Zip.ZipFileInfoCollection"); private static MethodInfo _getEnumerator = _typeZfic.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Instance | BindingFlags.NonPublic); public IEnumerable<ZipFileInfo> GetFiles() { System.Collections.IEnumerator zfic = _getEnumerator.Invoke(_getFiles.Invoke(_zipArchive, null), null) as System.Collections.IEnumerator; while (zfic.MoveNext()) { yield return new ZipFileInfo(zfic.Current); } } public void Flush() { _flush.Invoke(_zipArchive, null); } public void Close() { _close.Invoke(_zipArchive, null); } public void Dispose() { _dispose.Invoke(_zipArchive, null); } public FileAccess OpenAccess { get { return (FileAccess)_openAccess.GetValue(_zipArchive, null); } } public System.Collections.IDictionary ZipFileInfoDictionary { get { return _zipFileInfoDictionary.GetValue(_zipArchive, null) as System.Collections.IDictionary; } } public class ZipFileInfo { private static Assembly _ass = Assembly.GetAssembly(typeof(System.IO.Packaging.Package)); private static Type _type = _ass.GetType("MS.Internal.IO.Zip.ZipFileInfo"); private static MethodInfo _getStream = _type.GetMethod("GetStream", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _name = _type.GetProperty("Name", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipArchive = _type.GetProperty("ZipArchive", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _compressionMethod = _type.GetProperty("CompressionMethod", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _lastModFileDateTime = _type.GetProperty("LastModFileDateTime", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _deflateOption = _type.GetProperty("DeflateOption", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _folderFlag = _type.GetProperty("FolderFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _volumeLabelFlag = _type.GetProperty("VolumeLabelFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _localFileBlock = _type.GetProperty("LocalFileBlock", BindingFlags.Instance | BindingFlags.NonPublic); private static Type _typeL = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipIOLocalFileBlock"); private static PropertyInfo _offset = _typeL.GetProperty("Offset", BindingFlags.Instance | BindingFlags.Public); private static PropertyInfo _size = _typeL.GetProperty("Size", BindingFlags.Instance | BindingFlags.Public); private static PropertyInfo _compSize = _typeL.GetProperty("CompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _uncompSize = _typeL.GetProperty("UncompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private object _zipFileInfo = null; private object _lfb = null; public ZipFileInfo(object zipFileInfo) { _zipFileInfo = zipFileInfo; } public Stream GetStream(FileMode mode, FileAccess access) { return _getStream.Invoke(_zipFileInfo, new object[] { mode, access }) as Stream; } public string Name { get { return _name.GetValue(_zipFileInfo, null) as string; } } public ZipArchive ZipArchive { get { return new ZipArchive(_zipArchive.GetValue(_zipFileInfo, null)); } } public CompressionMethodEnum CompressionMethod { get { return ZipArchive.FromInternalCme(_compressionMethod.GetValue(_zipFileInfo, null)); } } public DateTime LastModFileDateTime { get { return (DateTime)_lastModFileDateTime.GetValue(_zipFileInfo, null); } } public DeflateOptionEnum DeflateOption { get { return ZipArchive.FromInternalDoe(_deflateOption.GetValue(_zipFileInfo, null)); } } public bool FolderFlag { get { return (bool)_folderFlag.GetValue(_zipFileInfo, null); } } public bool VolumeLabelFlag { get { return (bool)_volumeLabelFlag.GetValue(_zipFileInfo, null); } } public long Offset { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_offset.GetValue(_lfb, null); } } public long Size { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_size.GetValue(_lfb, null); } } public long CompressedSize { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_compSize.GetValue(_lfb, null); } } public long UncompressedSize { get { if (_lfb == null) _lfb = _localFileBlock.GetValue(_zipFileInfo, null); return (long)_uncompSize.GetValue(_lfb, null); } } } public enum CompressionMethodEnum { Stored, Deflated } public enum DeflateOptionEnum { Normal, Maximum, Fast, SuperFast, None } } "@ Add-Type -Language CSharp -TypeDefinition $source -ReferencedAssemblies ('WindowsBase') #([AppDomain]::CurrentDomain).GetAssemblies() | Out-Gridview $zipPath = 'C:\test.zip' $outPath = $zipPath + '.copy.zip' $zip = [ZipArchive]::OpenOnFile($zipPath, 'Open', 'Read', 'Read', $false) $zipCopy = [ZipArchive]::OpenOnFile($outPath, 'CreateNew', 'Write', 'Read', $true) foreach($f in $zip.GetFiles()) { $s = $zipCopy.AddFile($f.Name, $f.CompressionMethod, $f.DeflateOption) $ist = $f.GetStream('Open', 'Read') $ost = $s.GetStream('Open', 'Write') $buf = New-Object byte[] $f.UncompressedSize while(($n = $ist.Read($buf, 0, $buf.Length)) -gt 0) { $ost.Write($buf, 0, $n) } $ost.Dispose() $ist.Dispose() } $zipCopy.Dispose() $zip.Dispose()
参考:ここまで内部に立ち入ってみた
一見更新できるんだけど、展開するとダメ。
バイナリーを確認すると、CentralDirectoryHeaderは更新されていて圧縮フォルダー上は期待した日付だけど、LocalFileHeaderの日付が更新した日付に更新されちゃってダメ。
using System; using System.Collections.Generic; using System.IO; using System.Reflection; namespace ZipPackageSample { class ZipArchive : IDisposable { private static Type _type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipArchive"); private static MethodInfo _openOnFile = _type.GetMethod("OpenOnFile", BindingFlags.Static | BindingFlags.NonPublic); private static MethodInfo _openOnStream = _type.GetMethod("OpenOnStream", BindingFlags.Static | BindingFlags.NonPublic); public static ZipArchive OpenOnFile(string path, FileMode mode, FileAccess access, FileShare share, bool streaming) { return new ZipArchive { _zipArchive = _openOnFile.Invoke(null, new object[] { path, mode, access, share, streaming }) }; } public static ZipArchive OpenOnStream(Stream stream, FileMode mode, FileAccess access, bool streaming) { return new ZipArchive { _zipArchive = _openOnStream.Invoke(null, new object[] { stream, mode, access, streaming }) }; } private static Type _typeCme = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.CompressionMethodEnum"); private static object _stored = _typeCme.GetField("Stored", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _deflated = _typeCme.GetField("Deflated", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static Type _typeDoe = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.DeflateOptionEnum"); private static object _normal = _typeDoe.GetField("Normal", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _maximum = _typeDoe.GetField("Maximum", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _fast = _typeDoe.GetField("Fast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _superFast = _typeDoe.GetField("SuperFast", BindingFlags.Static | BindingFlags.Public).GetValue(null); private static object _none = _typeDoe.GetField("None", BindingFlags.Static | BindingFlags.Public).GetValue(null); public static CompressionMethodEnum FromInternalCme(object cme) { CompressionMethodEnum ret = CompressionMethodEnum.Stored; if (_deflated.Equals(cme)) ret = CompressionMethodEnum.Deflated; return ret; } public static object ToInternalCme(CompressionMethodEnum cme) { object ret = _stored; if (cme == CompressionMethodEnum.Deflated) ret = _deflated; return ret; } public static DeflateOptionEnum FromInternalDoe(object doe) { DeflateOptionEnum ret = DeflateOptionEnum.None; if (_normal.Equals(doe)) { ret = DeflateOptionEnum.Normal; } else if (_maximum.Equals(doe)) { ret = DeflateOptionEnum.Maximum; } else if (_fast.Equals(doe)) { ret = DeflateOptionEnum.Fast; } else if (_superFast.Equals(doe)) { ret = DeflateOptionEnum.SuperFast; } return ret; } public static object ToInternalDoe(DeflateOptionEnum doe) { object ret = _none; if (doe == DeflateOptionEnum.Normal) { ret = _normal; } else if (doe == DeflateOptionEnum.Maximum) { ret = _maximum; } else if (doe == DeflateOptionEnum.Fast) { ret = _fast; } else if (doe == DeflateOptionEnum.SuperFast) { ret = _superFast; } return ret; } private object _zipArchive = null; private static MethodInfo _addFile = _type.GetMethod("AddFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFile = _type.GetMethod("GetFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _fileExists = _type.GetMethod("FileExists", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _deleteFile = _type.GetMethod("DeleteFile", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _getFiles = _type.GetMethod("GetFiles", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _flush = _type.GetMethod("Flush", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _close = _type.GetMethod("Close", BindingFlags.Instance | BindingFlags.NonPublic); private static MethodInfo _dispose = _type.GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public); private static PropertyInfo _openAccess = _type.GetProperty("OpenAccess", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipFileInfoDictionary = _type.GetProperty("ZipFileInfoDictionary", BindingFlags.Instance | BindingFlags.NonPublic); public ZipFileInfo AddFile(string path, CompressionMethodEnum cme, DeflateOptionEnum doe) { return new ZipFileInfo(_addFile.Invoke(_zipArchive, new object[] { path, ToInternalCme(cme), ToInternalDoe(doe) })); } public ZipFileInfo GetFile(string path) { return new ZipFileInfo(_getFile.Invoke(_zipArchive, new object[] { path })); } public bool FileExists(string path) { return (bool)_fileExists.Invoke(_zipArchive, new object[] { path }); } public void DeleteFile(string path) { _deleteFile.Invoke(_zipArchive, new object[] { path }); } private static Type _typeZfic = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipFileInfoCollection"); private static MethodInfo _getEnumerator = _typeZfic.GetMethod("System.Collections.IEnumerable.GetEnumerator", BindingFlags.Instance | BindingFlags.NonPublic); public IEnumerable<ZipFileInfo> GetFiles() { var zfic = _getEnumerator.Invoke(_getFiles.Invoke(_zipArchive, null), null) as System.Collections.IEnumerator; while (zfic.MoveNext()) { yield return new ZipFileInfo(zfic.Current); } } public void Flush() { _flush.Invoke(_zipArchive, null); } public void Close() { _close.Invoke(_zipArchive, null); } public void Dispose() { _dispose.Invoke(_zipArchive, null); } public FileAccess OpenAccess { get { return (FileAccess)_openAccess.GetValue(_zipArchive, null); } } public System.Collections.IDictionary ZipFileInfoDictionary { get { return _zipFileInfoDictionary.GetValue(_zipArchive, null) as System.Collections.IDictionary; } } public class ZipFileInfo { private static Type _type = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipFileInfo"); private static MethodInfo _getStream = _type.GetMethod("GetStream", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _name = _type.GetProperty("Name", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _zipArchive = _type.GetProperty("ZipArchive", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _compressionMethod = _type.GetProperty("CompressionMethod", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _lastModFileDateTime = _type.GetProperty("LastModFileDateTime", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _deflateOption = _type.GetProperty("DeflateOption", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _folderFlag = _type.GetProperty("FolderFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _volumeLabelFlag = _type.GetProperty("VolumeLabelFlag", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _localFileBlock = _type.GetProperty("LocalFileBlock", BindingFlags.Instance | BindingFlags.NonPublic); private static Type _typeLB = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipIOLocalFileBlock"); private static FieldInfo _localFileHeader = _typeLB.GetField("_localFileHeader", BindingFlags.Instance | BindingFlags.NonPublic); private static Type _typeL = typeof(System.IO.Packaging.Package).Assembly.GetType("MS.Internal.IO.Zip.ZipIOLocalFileHeader"); private static PropertyInfo _lastMod = _typeL.GetProperty("LastModFileDateTime", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _compSize = _typeL.GetProperty("CompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private static PropertyInfo _uncompSize = _typeL.GetProperty("UncompressedSize", BindingFlags.Instance | BindingFlags.NonPublic); private object _zipFileInfo = null; private object _lfh = null; public ZipFileInfo(object zipFileInfo) { _zipFileInfo = zipFileInfo; } public Stream GetStream(FileMode mode, FileAccess access) { return _getStream.Invoke(_zipFileInfo, new object[] { mode, access }) as Stream; } public string Name { get { return _name.GetValue(_zipFileInfo, null) as string; } } public ZipArchive ZipArchive { get { return new ZipArchive { _zipArchive = _zipArchive.GetValue(_zipFileInfo, null) }; } } public CompressionMethodEnum CompressionMethod { get { return ZipArchive.FromInternalCme(_compressionMethod.GetValue(_zipFileInfo, null)); } } public DateTime LastModFileDateTime { get { return (DateTime)_lastModFileDateTime.GetValue(_zipFileInfo, null); } set { if (_lfh == null) { var lfb = _localFileBlock.GetValue(_zipFileInfo, null); _lfh = _localFileHeader.GetValue(lfb); } uint date = (((uint)value.Year - 1980 << 9) | ((uint)value.Month << 5) | (uint)value.Day); uint time = (((uint)value.Hour << 11) | ((uint)value.Minute << 5) | ((uint)value.Second / 2)); _lastMod.SetValue(_lfh, date << 16 | time, null); } } public DeflateOptionEnum DeflateOption { get { return ZipArchive.FromInternalDoe(_deflateOption.GetValue(_zipFileInfo, null)); } } public bool FolderFlag { get { return (bool)_folderFlag.GetValue(_zipFileInfo, null); } } public bool VolumeLabelFlag { get { return (bool)_volumeLabelFlag.GetValue(_zipFileInfo, null); } } public long CompressedSize { get { if (_lfh == null) { var lfb = _localFileBlock.GetValue(_zipFileInfo, null); _lfh = _localFileHeader.GetValue(lfb); } return (long)_compSize.GetValue(_lfh, null); } } public long UncompressedSize { get { if (_lfh == null) { var lfb = _localFileBlock.GetValue(_zipFileInfo, null); _lfh = _localFileHeader.GetValue(lfb); } return (long)_uncompSize.GetValue(_lfh, null); } } } public enum CompressionMethodEnum { Stored, Deflated } public enum DeflateOptionEnum { Normal, Maximum, Fast, SuperFast, None } } }