【ソフト名】 7-zip32.dll
【バージョン】 9.20.00.02
【使用OS】 Windows7 Professional Sp1 32bit
【PC機種】 HP p6740jp
【質問内容】
お世話になります。 いつも大変便利に活用させていただいております。
現在、Visual Basic 2010で開発を行なっておりまして、ファイル(*.sdf)にパスワード付きで圧縮を掛けるようにしています。 ところが、環境によってSevenZip関数から32798(ERROR_ENOUGH_MEMORY)が返ってくるようになりました。 その際の、第3引数(Output)の中身は以下のようになっています。
--- OutPut -------------------------------------------------------
7-Zip (A) 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18 Scanning
Creating archive 1234.7z
ERROR: Can't allocate required memory!
--------------------------------------------------------------------
調査してみたところ、物理メモリの空きが少ない場合で、かつ圧縮しようとしているファイル(*.sdf)のサイズがある一定以上の大きさの場合にこの 現象が発生するようです。
・ERROR_ENOUGH_MEMORYが発生した段階で、繰り返しSevenZip関数をコールしても、ERROR_ENOUGH_MEMORYが発生する。 ・ERROR_ENOUGH_MEMORYが発生した段階で、圧縮対象のsdfファイルをサイズの小さな同名のsdfファイルに差し替えた場合、改善する場合がある。 ・ERROR_ENOUGH_MEMORYが発生した段階で、常駐ソフトを終了する等の方法で物理メモリの空きを増やすことで改善する場合がある。
上記のような結果から、圧縮対象のファイルサイズに応じて、アーカイバのエンジンが確保するグローバルメモリのサイズが変わるものと勝手に 解釈しておりますが、例えば圧縮する前にエンジン側で要求されるグローバルメモリのサイズを取得する(もしくは計算する)ことは可能なので しょうか?
もしくは、比較的大きなサイズのファイルを圧縮する場合、できるだけエンジン側で要求されるグローバルメモリのサイズを抑える為の圧縮方法は ありませんでしょうか?
7-zipAPI.txt、7-zipCMD.txt等は拝見させていただきましたが、無知なものでご教示いただければ大変助かります。 お手数をお掛け致しますが、よろしくお願い致します。
(※ご参考になるかわかりませんが、ソースコードを掲載致します)
--- ソースコード ---------------------------------------------------------------------------------------------------------------------
Delegate Function TSetUnicodeMode(ByVal bUnicode As Boolean) As Boolean Delegate Function TExecute(ByVal hwnd As IntPtr, ByVal cmdLine As Byte(), ByVal pOutput As IntPtr, ByVal dwsize As Integer) As Integer
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim hModule As IntPtr = LoadLibrary("7-zip32.dll") Try Dim hSetUnicodeMode As IntPtr = GetProcAddress(hModule, "SevenZipSetUnicodeMode") Dim fnSetUnicodeMode As [Delegate] = Marshal.GetDelegateForFunctionPointer(hSetUnicodeMode, GetType(TSetUnicodeMode)) fnSetUnicodeMode.DynamicInvoke(True)
Const FNAME_MAX32 As Integer = 512 Dim pBuffer As IntPtr = Marshal.AllocHGlobal(FNAME_MAX32 + 1) Try Dim szCmdLine As String = "a -t7z ""1234.7z"" -pABCDEFG ""5678.sdf""" Dim hExecute As IntPtr = GetProcAddress(hModule, "SevenZip") Dim fnExecute As [Delegate] = Marshal.GetDelegateForFunctionPointer(hExecute, GetType(TExecute))
If (0 <> fnExecute.DynamicInvoke(Me.Handle, System.Text.Encoding.UTF8.GetBytes(szCmdLine), pBuffer, FNAME_MAX32 + 1)) Then MsgBox(Marshal.PtrToStringUni(pBuffer)) End If Finally Marshal.FreeHGlobal(pBuffer) End Try Finally FreeLibrary(hModule) End Try End Sub
------------------------------------------------------------------------------------------------------------------------------------------ |