- ベストアンサー
APIの呼び出しDLLファイルの場所を変化させたい
- VB.NETからDLLを呼び出すため、DLLファイルの場所を変える必要があります。現在はソースコード内のファイル場所を毎回書き換えていますが、hostnameを取得することで環境ごとに呼び出すファイルを変える方法があります。
- Windowsの環境変数のPATHに書き込みたくないため、プログラム内でDLLファイルの場所を指定したいとのことです。
- ソースコードの例では、固定変数としてDLLファイルの場所を指定していますが、hostnameを取得して条件分岐させることで可変的にDLLファイルを指定できます。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
前の書き込みの続きです。 ※以下が、サンプルソース(2)です。。 //DllLoader.vb Start// Imports System.Runtime.InteropServices ''' <summary> ''' 動的DLLローダー ''' </summary> ''' <remarks></remarks> Public Class DllLoader Implements IDisposable Private Class kernel32API <DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _ Public Shared Function LoadLibrary(ByVal lpFileName As String) As IntPtr End Function <DllImport("kernel32", CharSet:=CharSet.Auto, SetLastError:=True)> _ Public Shared Function FreeLibrary(ByVal hModule As IntPtr) As Boolean End Function <DllImport("kernel32", CharSet:=CharSet.Ansi, SetLastError:=True)> _ Public Shared Function GetProcAddress(ByVal hModule As IntPtr, ByVal lpProcName As String) As IntPtr End Function End Class Private _ptrModule As IntPtr = IntPtr.Zero #Region "APIで発生した最後のエラー" Private _lastErrorNo As Integer = 0 Public ReadOnly Property LastErrorNo() As Integer Get Return _lastErrorNo End Get End Property #End Region #Region "コンストラクタ" ''' <summary> ''' コンストラクタ ''' </summary> ''' <param name="p_strDllFullPath">DLLのフルパス</param> ''' <remarks></remarks> Public Sub New(p_strDllFullPath As String) _ptrModule = kernel32API.LoadLibrary(p_strDllFullPath) If (_ptrModule = IntPtr.Zero) Then _lastErrorNo = Marshal.GetHRForLastWin32Error Dim ex As Exception = Marshal.GetExceptionForHR(_lastErrorNo) Throw ex End If End Sub #End Region #Region "ロードしたDLLの解放処理" ''' <summary> ''' ロードしたDLLの解放処理 ''' </summary> ''' <remarks></remarks> Private Sub FreeLoder() If (_ptrModule = IntPtr.Zero) Then Return End If If Not kernel32API.FreeLibrary(_ptrModule) Then _lastErrorNo = Marshal.GetHRForLastWin32Error Dim ex As Exception = Marshal.GetExceptionForHR(_lastErrorNo) Throw ex End If End Sub #End Region #Region "Delegateの取得" ''' <summary> ''' Delegateの取得 ''' </summary> ''' <param name="p_strProcName">発行を行うメソッド名</param> ''' <param name="p_typProcType">発行を行うメソッド型</param> ''' <returns></returns> ''' <remarks></remarks> Public Function GetDelegate(ByVal p_strProcName As String, ByVal p_typProcType As Type) As [Delegate] If (_ptrModule = IntPtr.Zero) Then Return Nothing End If Dim l_ptrProcAddress As IntPtr = kernel32API.GetProcAddress(_ptrModule, p_strProcName) If (l_ptrProcAddress = IntPtr.Zero) Then _lastErrorNo = Marshal.GetHRForLastWin32Error Dim ex As Exception = Marshal.GetExceptionForHR(_lastErrorNo) Throw ex End If Return Marshal.GetDelegateForFunctionPointer(l_ptrProcAddress, p_typProcType) End Function #End Region #Region "IDisposable Support" Private disposedValue As Boolean ' 重複する呼び出しを検出するには Protected Overridable Sub Dispose(disposing As Boolean) If (Not Me.disposedValue) Then If (disposing) Then Call FreeLoder() End If End If Me.disposedValue = True End Sub Public Sub Dispose() Implements IDisposable.Dispose Dispose(True) GC.SuppressFinalize(Me) End Sub #End Region End Class //DllLoader.vb End//
その他の回答 (4)
- 1050 円(@1050YEN)
- ベストアンサー率69% (477/687)
以前、DllLoaderという動的DLLを起動するライブラリを作ったので、それを張っておきます。 ※参考資料を求めるのであれば、以下のキーワードを参考にしてください。 LoadLibrary GetProcAddress FreeLibrary ※以下が、ライブラリを起動するための構成です。 1.[Class1.vb]→→→→「2のサンプル」の起動 2.[Sample.vb]→→→→「3のDllLoader」呼出実行例 3.[DllLoader.vb]→→→ライブライリの本体 文字制限で全部を張る事ができないので、ソースを分割します。 ※以下が、サンプルソース(1)です。。 //Class1.vb Start// Public Class Class1 Shared Sub Main() Dim l_SampleStatic As New Sample.静的() l_SampleStatic.実行() Dim l_SampleDynamic As New Sample.動的() l_SampleDynamic.実行() End Sub End Class //Class1.vb End// //Sample.vb Start// Imports System.Runtime.InteropServices Public Class Sample <StructLayout(LayoutKind.Sequential)> _ Private Structure RECT Public left As Int32 Public top As Int32 Public right As Int32 Public bottom As Int32 End Structure Private Shared Sub 取得情報表示(p_rectWk As RECT) '取得した情報を出力 Dim l_aryPrms As New List(Of String)() l_aryPrms.Add(ControlChars.CrLf) l_aryPrms.Add(p_rectWk.left.ToString()) l_aryPrms.Add(p_rectWk.right.ToString()) l_aryPrms.Add(p_rectWk.top.ToString()) l_aryPrms.Add(p_rectWk.bottom.ToString()) Dim l_strMsg As String = String.Format("Left:{1}{0}Right:{2}{0}Top:{3}{0}Bottom:{4}", l_aryPrms.ToArray()) MsgBox(l_strMsg, MsgBoxStyle.Information, "デスクトップ矩形情報") End Sub #Region "静的なDLLの利用" Public Class 静的 <DllImport("user32.dll")> _ Private Shared Function GetWindowRect(ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer End Function <DllImport("user32.dll")> _ Private Shared Function GetDesktopWindow() As IntPtr End Function Public Sub 実行() '矩形情報を格納する変数 Dim l_rectWk As New RECT 'デスクトップハンドルを取得 Dim l_ptrDeskTop As IntPtr = GetDesktopWindow() 'デスクトップハンドルから矩形を取得 Call GetWindowRect(l_ptrDeskTop, l_rectWk) Call 取得情報表示(l_rectWk) End Sub End Class #End Region #Region "動的なDLLの利用" Public Class 動的 Private Delegate Function GetWindowRectDelegate(ByVal hwnd As IntPtr, ByRef lpRect As RECT) As Integer Private Delegate Function GetDesktopWindowDelegate() As IntPtr Public Sub 実行() Dim l_strDllPath As String = String.Empty If Not OpenFileDialog(l_strDllPath) Then Return End If Using l_dll As New DllLoader(l_strDllPath) 'GetDesktopWindow Dim l_method_GetDesktopWindow As GetDesktopWindowDelegate = l_dll.GetDelegate("GetDesktopWindow", GetType(GetDesktopWindowDelegate)) 'GetWindowRect Dim l_method_GetWindowRect As GetWindowRectDelegate = l_dll.GetDelegate("GetWindowRect", GetType(GetWindowRectDelegate)) '矩形情報を格納する変数 Dim l_rectWk As New RECT 'デスクトップハンドルを取得 Dim l_ptrDeskTop As IntPtr = l_method_GetDesktopWindow.Invoke() 'デスクトップハンドルから矩形を取得 Call l_method_GetWindowRect.Invoke(l_ptrDeskTop, l_rectWk) Call 取得情報表示(l_rectWk) End Using End Sub Private Function OpenFileDialog(ByRef p_strRetPath As String) As Boolean Using l_dlgOpen As New OpenFileDialog() l_dlgOpen.Title = "DLLを指定" l_dlgOpen.Filter = "user32.dllファイル(user32.dll)|user32.dll|DLLファイル(*.dll)|*.dll" l_dlgOpen.FileName = "user32.dll" If Not (l_dlgOpen.ShowDialog() = DialogResult.OK) Then Return False End If p_strRetPath = l_dlgOpen.FileName End Using Return True End Function End Class #End Region End Class //Sample.vb End//
お礼
ご回答ありがとうございます。 これが、知りたかった質問の内容と一致しております。 これを参考に、したいと思います。 ありがとうございました。
- todo36
- ベストアンサー率58% (728/1234)
> Windowsの環境変数のPATHに書き込みはしたくありません。 プロセス単位で設定できます。 http://msdn.microsoft.com/ja-jp/library/96xafkes(v=vs.80).aspx
お礼
環境変数をプロセス単位でできるのですね。 DOSの頃には無かった機能! 勉強になりました。 ありがとうございました。
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
> 他の会社がDLLファイルを提供しています。 他社に、環境変数が通るディレクトリにインストールしてもらうよう 依頼するか、自分が作成するexeに同梱させるかのどちらかでしょうね。 ネイティブなDLLを利用するなら、%SystemRoot%\system32にセットアップされるか、 利用者が自分でセットアップしろという感じで説明書があっても いいような気もしますが・・・。
お礼
ご回答ありがとうございます。 DLLを自分のアプリの場所にコピーか、PATHの通っている場所にコピーか を含めて検討致します。 ありがとうございました。
- めとろいと(@naktak)
- ベストアンサー率36% (785/2139)
ネットワーク越しにDLLを参照するのですか? exeと同一ディレクトリ内にDLLを設置してはいけないのでしょうか?
補足
ご回答ありがとうございます。 他の会社がDLLファイルを提供しています。 その為、そのファイルのある場所を指定しています。 でも、よく考えたらDLLをコピーもありですね^^
お礼
ご回答ありがとうございます。 これが、知りたかった質問の内容と一致しております。 これを参考に、したいと思います。 ありがとうございました。