Microsoft Visual Studio .NET 2003
.Net Framework 1.1
vb.net
上記の環境で『7-zip32.dll』を使用したいのですが、
『プロジェクト』→『参照追加』することができませんでした。
どのように行えばよいのかわからず困っています。
どなたか御教授お願い致します。
DeclareなりDllImportなりでP/Invokeする必要があります。
参照追加可能なのは,.NET Frameworkのアセンブリか,COMまたはWebサービスに限られます。
# COMにしろWebサービスにしろ,実際には裏でアセンブリを作っているのですが。
http://dobon.net/vb/dotnet/links/extractarchive.html
上記を元に7-zipに置き換えてみたのですが、
==========================================
'DLLをロード
Dim hmod As Integer = LoadLibrary(dllName)
エラー:'System.DllNotFoundException' のハンドルされていない例外が XXXX.exe で発生しました。 追加情報 : DLL (7-zip32) を読み込めません。
==========================================
のエラーが出てしまいます。
下記のコードが7-zipに置き換えたかたちなのですが、
==========================================
Imports System.Runtime.InteropServices
Imports System.Text
Public Class SevenZip
'セブンジップ圧縮設定DLL
<DllImport("7-zip32")> _
Private Function SevenZip(ByVal hwnd As Integer, ByVal szCmdLine As String, ByVal szOutput As String, ByVal dwsize As Integer)
End Function
<DllImport("7-zip32")> _
Private Shared Function LoadLibrary( _
ByVal lpLibFileName As String) As Integer
End Function
'マップを解除
<DllImport("7-zip32")> _
Private Shared Function FreeLibrary( _
ByVal hLibModule As Integer) As Boolean
End Function
'関数のアドレスを取得
<DllImport("7-zip32")> _
Private Shared Function GetProcAddress( _
ByVal hModule As Integer, ByVal lpProcName As String) As Integer
End Function
'以下使用するAPIのためのInvokeFunc
<DllImport("Invoke", EntryPoint:="InvokeFunc")> _
Private Shared Function InvokeGetVersion( _
ByVal funcptr As Integer) As UInt16
End Function
<DllImport("Invoke", EntryPoint:="InvokeFunc")> _
Private Shared Function InvokeGetRunning( _
ByVal funcptr As Integer) As Boolean
End Function
<DllImport("Invoke", EntryPoint:="InvokeFunc")> _
Private Shared Function InvokeCheckArchive( _
ByVal funcptr As Integer, _
ByVal szFileName As String, _
ByVal iMode As Integer) As Boolean
End Function
<DllImport("Invoke", EntryPoint:="InvokeFunc")> _
Private Shared Function InvokeMain( _
ByVal funcptr As Integer, _
ByVal hwnd As Integer, _
ByVal szCmdLine As String, _
ByVal szOutput As String, _
ByVal dwSize As Integer) As Integer
End Function
''' <summary>
''' 統合アーカイバ仕様のDLLで書庫を展開する
''' </summary>
''' <param name="dllName">DLLファイル名</param>
''' <param name="funcName">APIの頭に付く文字列</param>
''' <param name="command">展開のためのコマンド</param>
''' <param name="archiveFile">書庫ファイル名</param>
''' <param name="extractDir">展開先のフォルダ名</param>
Public Shared Sub ExtractArchive_7z( _
ByVal dllName As String, _
ByVal funcName As String, _
ByVal command As String, _
ByVal archiveFile As String, _
ByVal extractDir As String)
'指定されたファイルがあるか調べる
If Not System.IO.File.Exists(archiveFile) Then
Throw New ApplicationException("ファイルが見つかりません")
End If
'DLLをロード
Dim hmod As Integer = LoadLibrary(dllName)
If hmod = 0 Then
Throw New ApplicationException( _
dllName + "のロードに失敗しました")
End If
Try
Dim funcaddr As Integer
'DLLのチェック
'関数のアドレスを取得
funcaddr = GetProcAddress(hmod, funcName + "GetVersion")
If funcaddr = 0 Then
Throw New ApplicationException( _
dllName + "がインストールされていません")
End If
Dim ver As UInt16 = InvokeGetVersion(funcaddr)
Console.WriteLine("バージョン:{0}", ver)
'動作中かチェック
funcaddr = GetProcAddress(hmod, funcName + "GetRunning")
If funcaddr = 0 Then
Throw New ApplicationException( _
funcName + "GetRunningのアドレスが取得できませんでした")
End If
If InvokeGetRunning(funcaddr) Then
Throw New ApplicationException(dllName + "が動作中")
End If
'展開できるかチェック
funcaddr = GetProcAddress(hmod, funcName + "CheckArchive")
If funcaddr = 0 Then
Throw New ApplicationException( _
funcName + "CheckArchiveのアドレスが取得できませんでした")
End If
If Not InvokeCheckArchive(funcaddr, archiveFile, 0) Then
Throw New ApplicationException( _
archiveFile + "は対応書庫ではありません")
End If
'ファイル名とフォルダ名を修正する
If archiveFile.IndexOf(" "c) > 0 Then
archiveFile = """" + archiveFile + """"
End If
If Not extractDir.EndsWith("\") Then
extractDir += "\"
End If
If extractDir.IndexOf(" "c) > 0 Then
extractDir = """" + extractDir + """"
End If
'展開する
funcaddr = GetProcAddress(hmod, funcName)
If funcaddr = 0 Then
Throw New ApplicationException( _
funcName + "のアドレスが取得できませんでした")
End If
Dim ret As Integer = InvokeMain(funcaddr, 0, _
String.Format(command, archiveFile, extractDir), _
Nothing, 0)
'結果
If ret <> 0 Then
Throw New ApplicationException("書庫の展開に失敗しました")
End If
Finally
'開放する
If hmod <> 0 Then
FreeLibrary(hmod)
End If
End Try
End Sub
End Class
LoadLibrary 経由で無ければならないのでしょうか?
7-zipAPI.txt を見ながら、提示されたソースを LoadLibrary 無しのコードに書き換えてみました。
手元に 2003 が無いので、動作確認は取れませんけれども。
Imports System.Runtime.InteropServices
Imports System.Text
Imports System.IO
Imports System
Public Class Form1
' :
' :
' :
Private Declare Auto Function SevenZip Lib "7-zip32" ( _
ByVal hwnd As IntPtr, _
<[In]()> ByVal szCmdLine As String, _
ByVal szOutput As String, _
ByVal dwSize As UInteger) As Integer
Private Declare Auto Function SevenZipGetVersion Lib "7-zip32" () As Short
Private Declare Auto Function SevenZipGetRunning Lib "7-zip32" () As <MarshalAs(UnmanagedType.Bool)> Boolean
Private Enum CHECKARCHIVE
RAPID
BASIC
FULLCRC
End Enum
Private Declare Auto Function SevenZipCheckArchive Lib "7-zip32" ( _
<[In]()> ByVal szFileName As String, _
ByVal iMode As CHECKARCHIVE) As <MarshalAs(UnmanagedType.Bool)> Boolean
Public Shared Sub Extract7z( _
ByVal command As String, _
ByVal archiveFile As String, _
ByVal extractDir As String)
'指定されたファイルがあるか調べる
If Not File.Exists(archiveFile) Then
Throw New FileNotFoundException("ファイルが見つかりません。", archiveFile)
End If
Dim ver As Short = SevenZipGetVersion()
Console.WriteLine("バージョン:{0}", ver)
'動作中かチェック
If SevenZipGetRunning() Then
Throw New InvalidOperationException("DLLが動作中です。")
End If
'展開できるかチェック
If SevenZipCheckArchive(archiveFile, CHECKARCHIVE.RAPID) Then
Throw New ArgumentOutOfRangeException( _
"archiveFile", archiveFile, "対応書庫ではありません。")
End If
'ファイル名とフォルダ名を修正する
If archiveFile.IndexOf(" "c) > 0 Then
archiveFile = """" & archiveFile & """"
End If
If Not extractDir.EndsWith("\") Then
extractDir &= "\"
End If
If extractDir.IndexOf(" "c) > 0 Then
extractDir = """" & extractDir & """"
End If
'展開する
Dim ret As Integer = SevenZip( _
ActiveForm.Handle, _
String.Format(command, archiveFile, extractDir), _
Nothing, _
0UI)
'結果
If ret <> 0 Then
Throw New ApplicationException("書庫の展開に失敗しました")
End If
End Sub
End Class
SevenZip 関数の宣言を修正。
(2003 では、UInteger を使えないことを忘れていました…)
> Private Declare Auto Function SevenZip Lib "7-zip32" ( _
> :
> ByVal dwSize As UInteger) As Integer
UInteger → Integer に変更。
> Dim ret As Integer = SevenZip( _
> :
> :
> 0UI)
0UI → 0 に変更。
"C:\src.7z" という書庫を、"C:\test\" に解凍するサンプルを書いてみました。
一応、.NET Framework v1.1 + 7-zip.dll v4.57 で動作確認済み。
http://www.vb-user.net/junk/replySamples/2009.02.03.15.32/7zip.txt
# VS2003 が手元に無いため、.NET 1.1 の VBC.EXE で手動コンパイルにて検証。
魔界の仮面弁士さん返信ありがとうございました。
上記の内容で実行した所下記の部分で
『'System.DllNotFoundException' のハンドルされていない例外が AJIS.exe で発生しました。
追加情報 : DLL (7-zip32) を読み込めません。』
のエラーが発生しました。
=============================================================
Dim ver As Short = SevenZipGetVersion()
Console.WriteLine("バージョン:{0}", ver)
=============================================================
やはり、Microsoft Visual Studio .NET 2003なので、むりなのでしょうか…。
.NET 1.1 の環境でチェックしていますので、動作するはずです。
> 追加情報 : DLL (7-zip32) を読み込めません。』
> のエラーが発生しました。
7-zip32.DLL のファイルを、システムフォルダ(C:\WINDOWS\system32)に
配置してあるかどうかを確認してみてください。
魔界の仮面弁士さんありがとうございます!
無事に圧縮⇒解凍が行えました。
フォルダごと『C:\WINDOWS\system32』に置いていました・・・。
ちなみに、解凍⇒圧縮を行う場合は、下記の部分を
archiveFile=csv形式ファイル名
extractDir=7z圧縮フォルダ名
で逆に置き換えて
commandは"x {0} -o{1}"ではなく、違ったcommandを設定しないと
いけないとおもうんですが、わかりやすいサイトもしくは
おしえていただけないでしょうか?
=============================================================
'展開する
Dim ret As Integer = SevenZip( _
IntPtr.Zero, _
String.Format(command, archiveFile, extractDir), _
Nothing, _
0)
=============================================================
指定すべきコマンドは、"7-zipCMD.txt" を参照してください。
編集 削除魔界の仮面弁士さんありがとうございます。
昨日、txtファイルを確認しまして下記の記載で
圧縮がおこなえる様になりました!!
=============================================================
"u -t7z C:\XXXXX.7z C:\XXXXX.csv"
=============================================================
圧縮方法で、後パスワード及び暗号化メソッドを設定しないといけない為、
わかり次第こちらも記載したいと思います。
"-p"の後にパスワード設定を加えることで解凍時にパスワードが
要求されるようになりました。
=============================================================
"u -t7z C:\XXXXX.7z -p@@@@@ C:\XXXXX.csv"
=============================================================
暗号化メソッドは『AES-256』固定なんでしょうか?
デフォルトが『AES-256』であれば問題は無いのですが・・・。
> 暗号化メソッドは『AES-256』固定なんでしょうか?
7-Zip モードでは、AES暗号(Rijndael)は 256 ビットだと思います。
Zip モードでは、AES128,192,256 を選択できるようですが(ZIP 2.0は非対応?)、
Windows のZIP圧縮フォルダは、AES 暗号化に非対応なので注意。
(7z のみを使用するつもりであれば、関係の無い話ですが)。
今回の圧縮方法は7zipのみです。
詳しく教えていただきありがとうございました。
無事に解決致しました。
>=============================================================
>"u -t7z C:\XXXXX.7z -p@@@@@ C:\XXXXX.csv"
>=============================================================
前回、c:\直下に7z形式の圧縮フォルダを置く際は問題なくおこなえたのですが、
=============================================================
"u -t7z C:\Program Files\XXXXX\.7z -p@@@@@ C:\Program Files\XXXXX\.csv"
=============================================================
とした場合、『Program.7z』が作成され、エラーが発生してしまいます。
フォルダー名指定する際に半角の空白が発生しているために正しく判断され
ていないのかと思うのですが、解決方法がわかりません。
教えていただけないでしょうか??
二重引用符で囲ってください。
"7-zipCMD.txt"の1. コマンドラインの様式に,
> スペースを含むファイル名は以下の様に""で全体を囲ってください。
という記述がちゃんとあります。
# 7z457001.zipの7-zipCMD.txtの51行目に確認。
YuOさん返信ありがとうございました。
># 7z457001.zipの7-zipCMD.txtの51行目に確認。
で解決致しました。
もう一点お聞きしたいのですが、
【7-zipCMD.txt】を元にためしてみたのですが、
パスワード付の解凍を行う際にうまく処理が行かない状況です。
=============================================================
【7-zipCMD.txt】の996行目にパスワード付解凍の場合が載っていましたので
こちらを【.zip】を【.7z】に変更し、
パスワードもこちらの指定のパスワードに変更しました。
command="x archive.zip -psecret"
archiveFile=7zが置いてあるフルパス("C:\XXXX.7z")
extractDir=csvを置きたいフルパス("C:\"Program Files"\XXXX.csv")
'解凍処理部分
Dim ret As Integer
ret = SevenZip(IntPtr.Zero, command, Nothing, 0)
'展開する
ret = SevenZip( _
IntPtr.Zero, _
String.Format(command, archiveFile, extractDir), _
Nothing, _
0)
'結果
If ret <> 0 Then
Throw New ApplicationException("書庫の展開に失敗しました。(" & CStr(ret) & ")")
End If
=============================================================
"x "C:\XXXX.7z" -pXXXXX -o"C:\"
で問題なく解凍できました。
お騒がせしました。