'Imports System.Runtime.InteropServices
'がソースファイルの一番上に書かれているものとする
'DLL の版の取得
<DllImport("unlha32")> _
Private Shared Function UnlhaGetVersion() As UInt16
End Function'DLL の実行状況の取得
<DllImport("unlha32")> _
Private Shared Function UnlhaGetRunning() As Boolean
End Function'書庫のチェック
<DllImport("unlha32")> _
Private Shared Function UnlhaCheckArchive( _
ByVal szFileName As String, _
ByVal iMode As Integer) As Boolean
End Function'書庫操作一般
<DllImport("unlha32")> _
Private Shared Function Unlha( _
ByVal hwnd As Integer, _
ByVal szCmdLine As String, _
ByVal szOutput As String, _
ByVal dwSize As Integer) As Integer
End Function''' <summary>
''' UNLHA32.DLLで書庫を展開する
''' </summary>
''' <param name="archiveFile">書庫ファイル名</param>
''' <param name="extractDir">展開先のフォルダ名</param>Public Shared Sub LhaExtractArchive( _
ByVal archiveFile As String, _
ByVal extractDir As String)
'指定されたファイルがあるか調べるIf Not System.IO.File.Exists(archiveFile) Then
Throw New ApplicationException("ファイルが見つかりません")
End If'DLLのチェックTry
Dim ver As UInt16 = UnlhaGetVersion()
Console.WriteLine("バージョン:{0}", ver)
Catch
Throw New _
ApplicationException("Unlha32.dllがインストールされていません")
End Try'動作中かチェックIf UnlhaGetRunning() Then
Throw New ApplicationException("DLLが動作中")
End If'展開できるかチェックIf Not UnlhaCheckArchive(archiveFile, 0) Then
Throw New ApplicationException("対応書庫ではありません")
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 = Unlha(0, _
String.Format("x {0} {1} *", archiveFile, extractDir), _
Nothing, 0)
'結果If ret <> 0 Then
Throw New ApplicationException("書庫の展開に失敗しました")
End If
End Sub
'Imports System.Runtime.InteropServices
'がソースファイルの一番上に書かれているものとする
'DLLモジュールをマップ
<DllImport("kernel32")> _
Private Shared Function LoadLibrary( _
ByVal lpLibFileName As String) As Integer
End Function'マップを解除
<DllImport("kernel32")> _
Private Shared Function FreeLibrary( _
ByVal hLibModule As Integer) As Boolean
End Function'関数のアドレスを取得
<DllImport("kernel32")> _
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( _
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
'C#のコードを'C# to VB.NET Translator'で変換し、修正したコードです
'http://www.aspalliance.com/aldotnet/examples/translate.aspxImports System
Imports System.Runtime.InteropServices
Namespace Dobon.Sample.File
Public Class ExtractArchiveWithDll
Public Shared Sub Main(ByVal args() As String)
Dim arg As String
For Each arg In args
'展開先のフォルダ名を決める
'ここではデスクトップ上の書庫ファイル名のフォルダとするDim extractDir As String = _
System.Environment.GetFolderPath( _
System.Environment.SpecialFolder.DesktopDirectory)
extractDir += "\" + _
System.IO.Path.GetFileNameWithoutExtension(arg)
'存在しないフォルダ名を探すIf System.IO.Directory.Exists(extractDir) Then
Dim n As Integer = 1
While System.IO.Directory.Exists( _
extractDir + n.ToString())
n += 1
End While
extractDir += n.ToString()
End If
Console.WriteLine("""{0}""を""{1}""に展開します...", _
arg, extractDir)
'展開するTry
If ExtractArchiveEx(arg, extractDir) Then
Console.WriteLine("展開しました。")
'フォルダを開く
System.Diagnostics.Process.Start(extractDir)
Else
Console.WriteLine("展開できませんでした。")
End If
Catch ex As Exception
Console.WriteLine(("エラー:" + ex.Message))
End Try
Next arg
Console.ReadLine()
End Sub'DLLモジュールをマップ
<DllImport("kernel32")> _
Private Shared Function LoadLibrary( _
ByVal lpLibFileName As String) As Integer
End Function'マップを解除
<DllImport("kernel32")> _
Private Shared Function FreeLibrary( _
ByVal hLibModule As Integer) As Boolean
End Function'関数のアドレスを取得
<DllImport("kernel32")> _
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'DLLの情報Public Structure ArchiverDllInfo
Public FileName As String'DLLファイル名Public FunctionName As String'APIの頭に付く文字列Public CommandToExtract As String'展開のためのコマンドEnd Structure'ArchiverDllInfo
''' <summary>
''' 統合アーカイバ仕様のDLLで書庫を展開する
''' </summary>
''' <param name="archiveFile">書庫ファイル名</param>
''' <param name="extractDir">展開先のフォルダ名</param>
''' <returns>展開できたらTrue</returns>Public Shared Function ExtractArchiveEx( _
ByVal archiveFile As String, _
ByVal extractDir As String) As Boolean'指定されたファイルがあるか調べるIf Not System.IO.File.Exists(archiveFile) Then
Throw New ApplicationException("ファイルが見つかりません")
End If'DLL情報ファイルの存在を確認Dim dllInfoFile As String = GetAppPath() + "\dlls.config"
If Not System.IO.File.Exists(dllInfoFile) Then
Throw New ApplicationException( _
"DLL情報ファイルが見つかりません")
End If'DLLの情報を読み込むDim serializer As _
New System.Xml.Serialization.XmlSerializer( _
GetType(ArchiverDllInfo()))
Dim fs As New System.IO.FileStream(dllInfoFile, _
System.IO.FileMode.Open)
Dim dllInfos() As ArchiverDllInfo
dllInfos = CType(serializer.Deserialize(fs), _
ArchiverDllInfo())
If dllInfos Is Nothing Or dllInfos.Length = 0 Then
Throw New ApplicationException( _
"DLL情報が読み込めませんでした")
End If
Dim di As ArchiverDllInfo
For Each di In dllInfos
Dim dllName As String = di.FileName
Dim funcName As String = di.FunctionName
'DLLをロードDim hmod As Integer = LoadLibrary(dllName)
If hmod = 0 Then
GoTo ContinueForEach1
End If
Try
Dim funcaddr As Integer'DLLのチェック
'関数のアドレスを取得
funcaddr = GetProcAddress(hmod, _
funcName + "GetVersion")
If funcaddr = 0 Then
GoTo ContinueForEach1
End If
Dim ver As UInt16 = InvokeGetVersion(funcaddr)
'展開できるかチェック
funcaddr = GetProcAddress(hmod, _
funcName + "CheckArchive")
If funcaddr = 0 Then
GoTo ContinueForEach1
End If
If Not InvokeCheckArchive(funcaddr, _
archiveFile, 0) Then
GoTo ContinueForEach1
End If
Console.WriteLine("対応DLLは{0}です", dllName)
'動作中かチェック
funcaddr = GetProcAddress(hmod, _
funcName + "GetRunning")
If funcaddr = 0 Then
GoTo ContinueForEach1
End If
If InvokeGetRunning(funcaddr) Then
Throw New ApplicationException( _
dllName + "が動作中です")
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(di.CommandToExtract, archiveFile, _
extractDir), Nothing, 0)
'結果If ret <> 0 Then
Throw New ApplicationException( _
dllName + "での書庫の展開に失敗しました")
Else
Return True
End If
Finally'開放するIf hmod <> 0 Then
FreeLibrary(hmod)
End If
End Try
ContinueForEach1:
Next di
Return False
End Function
Private Shared Function GetAppPath() As String
Dim fi As New System.IO.FileInfo( _
System.Reflection.Assembly.GetExecutingAssembly().Location)
Return fi.DirectoryName
End Function
End Class
End Namespace