vb.net 2003 7-zip32.dllの呼び出だしについて

解決


ぽっぽ  2009-02-02 18:12:10  No: 141424  IP: 192.*.*.*

Microsoft Visual Studio .NET 2003
.Net Framework 1.1
vb.net

上記の環境で『7-zip32.dll』を使用したいのですが、
『プロジェクト』→『参照追加』することができませんでした。

どのように行えばよいのかわからず困っています。
どなたか御教授お願い致します。

編集 削除
YuO  2009-02-02 18:53:15  No: 141425  IP: 192.*.*.*

DeclareなりDllImportなりでP/Invokeする必要があります。

参照追加可能なのは,.NET Frameworkのアセンブリか,COMまたはWebサービスに限られます。
# COMにしろWebサービスにしろ,実際には裏でアセンブリを作っているのですが。

編集 削除
ぽっぽ  2009-02-03 13:14:09  No: 141426  IP: 192.*.*.*

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

編集 削除
魔界の仮面弁士  2009-02-03 15:06:31  No: 141427  IP: 192.*.*.*

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

編集 削除
魔界の仮面弁士  2009-02-03 15:09:46  No: 141428  IP: 192.*.*.*

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 に変更。

編集 削除
魔界の仮面弁士  2009-02-03 15:35:51  No: 141429  IP: 192.*.*.*

"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 で手動コンパイルにて検証。

編集 削除
ぽっぽ  2009-02-03 15:52:47  No: 141430  IP: 192.*.*.*

魔界の仮面弁士さん返信ありがとうございました。

上記の内容で実行した所下記の部分で
『'System.DllNotFoundException' のハンドルされていない例外が AJIS.exe で発生しました。
追加情報 : DLL (7-zip32) を読み込めません。』
のエラーが発生しました。

=============================================================
        Dim ver As Short = SevenZipGetVersion()
        Console.WriteLine("バージョン:{0}", ver)
=============================================================



やはり、Microsoft Visual Studio .NET 2003なので、むりなのでしょうか…。

編集 削除
魔界の仮面弁士  2009-02-03 16:17:13  No: 141431  IP: 192.*.*.*

.NET 1.1 の環境でチェックしていますので、動作するはずです。

> 追加情報 : DLL (7-zip32) を読み込めません。』
> のエラーが発生しました。

7-zip32.DLL のファイルを、システムフォルダ(C:\WINDOWS\system32)に
配置してあるかどうかを確認してみてください。

編集 削除
ぽっぽ  2009-02-03 19:27:54  No: 141432  IP: 192.*.*.*

魔界の仮面弁士さんありがとうございます!
無事に圧縮⇒解凍が行えました。
フォルダごと『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)
=============================================================

編集 削除
魔界の仮面弁士  2009-02-04 00:10:16  No: 141433  IP: 192.*.*.*

指定すべきコマンドは、"7-zipCMD.txt" を参照してください。

編集 削除
ぽっぽ  2009-02-04 09:09:32  No: 141434  IP: 192.*.*.*

魔界の仮面弁士さんありがとうございます。

昨日、txtファイルを確認しまして下記の記載で
圧縮がおこなえる様になりました!!
=============================================================
"u -t7z C:\XXXXX.7z C:\XXXXX.csv"
=============================================================

圧縮方法で、後パスワード及び暗号化メソッドを設定しないといけない為、
わかり次第こちらも記載したいと思います。

編集 削除
ぽっぽ  2009-02-04 09:48:34  No: 141435  IP: 192.*.*.*

"-p"の後にパスワード設定を加えることで解凍時にパスワードが
要求されるようになりました。
=============================================================
"u -t7z C:\XXXXX.7z -p@@@@@ C:\XXXXX.csv"
=============================================================
暗号化メソッドは『AES-256』固定なんでしょうか?
デフォルトが『AES-256』であれば問題は無いのですが・・・。

編集 削除
魔界の仮面弁士  2009-02-04 10:11:20  No: 141436  IP: 192.*.*.*

> 暗号化メソッドは『AES-256』固定なんでしょうか?
7-Zip モードでは、AES暗号(Rijndael)は 256 ビットだと思います。

Zip モードでは、AES128,192,256 を選択できるようですが(ZIP 2.0は非対応?)、
Windows のZIP圧縮フォルダは、AES 暗号化に非対応なので注意。
(7z のみを使用するつもりであれば、関係の無い話ですが)。

編集 削除
ぽっぽ  2009-02-04 13:31:54  No: 141437  IP: 192.*.*.*

今回の圧縮方法は7zipのみです。
詳しく教えていただきありがとうございました。
無事に解決致しました。

編集 削除
ぽっぽ  2009-02-05 11:15:26  No: 141438  IP: 192.*.*.*

>=============================================================
>"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』が作成され、エラーが発生してしまいます。
フォルダー名指定する際に半角の空白が発生しているために正しく判断され
ていないのかと思うのですが、解決方法がわかりません。
教えていただけないでしょうか??

編集 削除
YuO  2009-02-05 11:47:27  No: 141439  IP: 192.*.*.*

二重引用符で囲ってください。


"7-zipCMD.txt"の1. コマンドラインの様式に,
>     スペースを含むファイル名は以下の様に""で全体を囲ってください。
という記述がちゃんとあります。
# 7z457001.zipの7-zipCMD.txtの51行目に確認。

編集 削除
ぽっぽ  2009-02-09 19:39:55  No: 141440  IP: 192.*.*.*

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
=============================================================

編集 削除
ぽっぽ  2009-02-10 14:35:43  No: 141441  IP: 192.*.*.*

"x "C:\XXXX.7z" -pXXXXX -o"C:\"
で問題なく解凍できました。

お騒がせしました。

編集 削除