APIの呼び出しDLLファイルの場所を変化させたい

このQ&Aのポイント
  • VB.NETからDLLを呼び出すため、DLLファイルの場所を変える必要があります。現在はソースコード内のファイル場所を毎回書き換えていますが、hostnameを取得することで環境ごとに呼び出すファイルを変える方法があります。
  • Windowsの環境変数のPATHに書き込みたくないため、プログラム内でDLLファイルの場所を指定したいとのことです。
  • ソースコードの例では、固定変数としてDLLファイルの場所を指定していますが、hostnameを取得して条件分岐させることで可変的にDLLファイルを指定できます。
回答を見る
  • ベストアンサー

APIの呼び出しDLLファイルの場所を変化させたい

VB.NETからDLLを呼び出したいのですが、これが私のコンピューターと 顧客側のコンピュータとで環境が違う為、毎回ファイルの場所を変えて 使用しています。(ソース内のファイル場所を毎回書き換える) これを、hostnameの取得により、私のパソコンとその他の環境とで 呼び出す状況を変えたいと思っております。 どの様にすれば良いか、教えて下さい。 Windowsの環境変数のPATHに書き込みはしたくありません。 あくまで、プログラム内で終わらせたいのですが・・ (ソース例) ’↓固定変数でないとダメ? Public Const MyDllFileName As String = "\\ServerName\Kyouyu\MyDllFile.dll" 'Type(1) Public Declare Function ExportDLL1 Lib MyDllFileName (ByRef MyData As MyStructure) As Integer 'Type(2) <DllImport(MyDllFileName)> Public Function ExportDLL2(ByRef MyData As MyStructure) As Integer End Function

質問者が選んだベストアンサー

  • ベストアンサー
回答No.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//

ghost305jp
質問者

お礼

ご回答ありがとうございます。 これが、知りたかった質問の内容と一致しております。 これを参考に、したいと思います。 ありがとうございました。

その他の回答 (4)

回答No.4

以前、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//

ghost305jp
質問者

お礼

ご回答ありがとうございます。 これが、知りたかった質問の内容と一致しております。 これを参考に、したいと思います。 ありがとうございました。

  • todo36
  • ベストアンサー率58% (728/1234)
回答No.3

> Windowsの環境変数のPATHに書き込みはしたくありません。 プロセス単位で設定できます。 http://msdn.microsoft.com/ja-jp/library/96xafkes(v=vs.80).aspx

ghost305jp
質問者

お礼

環境変数をプロセス単位でできるのですね。 DOSの頃には無かった機能! 勉強になりました。 ありがとうございました。

回答No.2

> 他の会社がDLLファイルを提供しています。 他社に、環境変数が通るディレクトリにインストールしてもらうよう 依頼するか、自分が作成するexeに同梱させるかのどちらかでしょうね。 ネイティブなDLLを利用するなら、%SystemRoot%\system32にセットアップされるか、 利用者が自分でセットアップしろという感じで説明書があっても いいような気もしますが・・・。

ghost305jp
質問者

お礼

ご回答ありがとうございます。 DLLを自分のアプリの場所にコピーか、PATHの通っている場所にコピーか を含めて検討致します。 ありがとうございました。

回答No.1

ネットワーク越しにDLLを参照するのですか? exeと同一ディレクトリ内にDLLを設置してはいけないのでしょうか?

ghost305jp
質問者

補足

ご回答ありがとうございます。 他の会社がDLLファイルを提供しています。 その為、そのファイルのある場所を指定しています。 でも、よく考えたらDLLをコピーもありですね^^

関連するQ&A

  • API FtpPutFileの戻り値

    お世話になっております。 API FtpPutFileを使用しているのですが 確実にFalseになります。一日悩みましたが原因が わかりません。 If FtpPutFile(lngConnect, _ "***.txt", _ "***.txt", _ FTP_TRANSFER_TYPE_ASCII, _ 0&) <> False Then です。必要なものを付け加えておきます。 Private Declare Function FtpPutFile Lib "wininet.dll" _ Alias "FtpPutFileA" _ (ByVal hFtpSession As Long, _ ByRef lpszLocalFile As String, _ ByRef lpszNewRemoteFile As String, _ ByVal dwFlags As Long, _ ByVal dwContext As Long) As Long Private Const FTP_TRANSFER_TYPE_ASCII = &H1& です。環境はWinXP,VB6+SP5 よろしくお願い致します。

  • dllを使用しVB側に文字列を返す2

    No.280310の質問の続きになってしまいますが 「VCで作ったdllを使用し VBに文字列を返すことはできますか」 でVCで作ったdllをVBを呼び出す事ができるようになりました。 Declare宣言で疑問に思ったのですが Declare Function TxtCnt Lib "hoge.dll" (ByVal a As String) As Long aはなぜ値渡しなのでしょうか? 変数が書き換えられて戻ってくるので、byrefで指定していました。 それが問題が起こしていた原因一つでした。 ちなみにint型の数値をポインタで渡した場合はbyrefでうまくいきます。 ご教授願います。

  • マウス関連のAPIについて

    マウスがどのフォーム(自分のフォームでないときも)でも左クリックしたときの状態の取得方法を教えてください。 Public Declare Function SetCursorPos& Lib "user32" (ByVal x As Integer, ByVal y As Integer) Public Declare Function GetCursorPos& Lib "user32" (ByRef lpPoint As POINTAPI) で、マウスの位置の取得設定はわかりました。

  • vc++のAPI(dll)の引数をVBAでうけとる

    Excelで開発しなければならない事情があり、 vc++のAPIが持っている関数を ExcelVBAでコールしておりますが、エラー1041でExcelが強制終了してしまいます。 VBAからVisual C++にchar*型で渡し、ByRef String型でVBAにて受け取ります。 VCの関数の第四引数「char* 型/attribute_value」をVBAの「String 型/sValue」で受け取る際にエラーになっているようです。 VBAでcharに相当する変数型がないためと思われますが、何かよいアイデアがありましたらご教授願います。 --VC-- XDW_GetDocumentAttributeByName(h, attribute_name, &attribute_type, attribute_value, size, NULL); --VBA-- <宣言部> Public Declare Function XDW_GetDocumentAttributeByName Lib "C:\Users\○○○\Desktop\dwsdk710jpn\XDWAPI\DLL\xdwapi.dll" (ByVal lnghandle As Long, ByVal sName As String, ByRef lngType As Long, ByRef sValue As String, ByVal lngSize As Long, ByVal reserved As String) As Long <呼び出し部> Dim lngHandle As Long Dim sName as String Dim lngType As Long Dim sValue As String Dim lngSize as Long Dim tmpSize as Long lngSize = 0 sName = "keiyaku" tmpSize = XDW_GetDocumentAttributeByName(lngHandle, sName, sType, sValue, lngSize, vbNullString) XDW_GetDocumentAttributeByName lngHandle, sName, sType, vbNullString, tmpSize, vbNullString degug.print sValue

  • VB .NetのDLL参照について

    名前付パイプの処理をしているのですが、DLLが参照できません。 Public Class ClsJi01   Public Declare Function MakePipe Lib "\DLL\Point.DLL" (ByVal pipe_name As String, ByVal buf_size As Integer, ByVal max_instances As Short, ByVal hpipe As Integer, ByVal err_code As Integer) As Integer  Public Sub M_Pipe()   Dim r As Integer   Dim rpipe As Integer   Dim err_code As Integer   r = MakePipe("\\.\pipe\RS04", 255, 16, rpipe, err_code)  End Sub End Class Point.DLLは以前VB6.0の時に使用していたDLLで自作です。 これで実行すると「オブジェクト参照がオブジェクト インスタンスに設定されていません。」と出ます。 どうしたら良いのでしょうか?

  • psapi.dllのGetModuleBaseNameについて

    OS:Windows Server 2003 開発言語:visual basic 2005 vb6で作られたアプリを.net2005に移行しています。 その中で、下記のコードの「GetModuleBaseName」が呼び出される箇所がエラーになり、移行することができません。 ----------------------------------- 【コード】 If EnumProcessModules(hProcess, hModules(0), UBound(hModules), lNeeded) <> 0 Then    'モジュール数を取得する    lModules = lNeeded / 4    'モジュールベース名を取得する    lRetValue = GetModuleBaseName(hProcess, hModules(0), tModuleBaseName(0), UBound(tModuleBaseName))    ~~~    ~~~ end if ----------------------------------- 【エラー内容】 AcccessViolationExceptionはハンドルされませんでした。 保護されているメモリに読み取りまたは書き込み操作を行おうとしました。 他のメモリが壊れていることが考えられます。 ----------------------------------- 「GetModuleBaseName」自体は下記のとおり定義しています。 ----------------------------------- Declare Function GetModuleBaseName Lib "Psapi.dll" Alias "GetModuleBaseNameA" (ByVal hProcess As Integer, ByVal hModule As Integer, ByRef lpBaseName As String, ByRef nSize As Integer) As Integer ----------------------------------- 移行前のvb6のアプリでこの箇所がエラーなく通ることを確認しました。 Psapi.dllの使用方法がWindowsServer2003になって変更になったのでしょうか? 使用方法が変更になったのか調べたのですが、WinAPIの知識不足で・・・。 お力をお貸しください。 よろしくお願いいたします。

  • VBAでDLLが見つからないエラー

    CADのVBA(6.0)ですが、DLLが見つからないエラーが出ます ' こっちはエラーが出ない Public Declare Function SearchVBApath Lib _ "C:\Program Files\AppliTool\VB\DDDD.dll" (ByVal env As String, ByVal s As String) As Integer 'こっちだとエラーが出る Public Declare Function SearchVBApath Lib "DDDD.dll" (ByVal env As String, ByVal s As String)    As Integer VBAプロジェクトファイルとDLLは同じフォルダにおいてあります 上記のようにフルパスだとエラーが出ないのですがDLL名だけだとこの関数のところでエラーがでます このDLL関数宣言行の前の方には他のDLL関数も同じようにパス省略で記述しているのですがそちらにはエラーが出ません どなたかヒント下さい、よろしくお願いします。

  • RegQueryValueExwでエラー

    お世話になります。 Declare Function RegQueryValueExString Lib "advapi32.dll" Alias _ "RegQueryValueExA"(ByVal hKey As Integer, ByVal lpValueName As String, ByVal lpReserved As Integer, ByRef lpType As Integer, ByVal lpData As String, ByRef lpcbData As Integer) As Integer RegQueryValueExString(hKey, ValueName, 0, intType, strValue, intSize) この時、ValueNameに2バイト文字が含まれているとエラーになります。 VB 6.0の時は問題なく動いていました。 ご存知の方ご教示お願いいたします。

  • C++で作成したDLLにVBAから配列渡し

    VC++初心者です。よろしくお願いします。 VC++2008ExpressでWindowsアプリケーションのDLLを作成してみました。 Excel2007VBAにて、そのDLLを呼び出して関数を使用したいのですが VBAの配列を参照渡しで渡すと、配列のデータをうまく渡せません。 コードは以下の通りです。 配列ではないデータはうまくいきますが。。。 配列の場合はもっと他に必要なことがあるのでしょうか? よろしくお願いします。 //VC++ DLLコード #include <windows.h> int APIENTRY Add(int[] a) {    return a[0] + a[1] ; } '''VBAのコード Private Declare Function Add Lib "TEST_DLL.dll" (ByRef a() As Integer) As Integer Dim a(1) As Integer Sub test() a(0) = 1 a(1) = 2 MsgBox (Add(a)) End Sub メッセージボックスには3が表示されるはずですが 変な数字に化けてしまいます。 どなたか、ご存知の方、よろしくお願いします。

  • DLLの利用について

    現在、VCで作成したDLLをVB使うということを行っています。 概要は、VBの方で定義した配列に1~9の数字を代入し、その和を求めるというものです。 DLLに値を渡す際は参照による引渡しをし、DLLで変数の変更を行いたいんです。 しかしその変数の変更がうまくいかないんです。 どこがまずいのでしょうか? プログラム内容は以下に示します。 よろしくお願いします。 *****VBのプログラム***** Option Explicit Private Declare Sub Sum Lib "test.dll" (aa as Integer, bb as Integer) Private Sub Command1_Click() Dim a(9) As Integer  '1~9の値の代入先 Dim b As integer   '和 Dim I As Integer For I = 0 To 9 a(I) = I + 1 Next I b = 0 Sum a, b  'DLLでの計算 MsgBox (b) '結果表示 End Sub *****DLLの中身***** _declspec(dllexport) void _stdcall Sum(short *aa, short bb) { int i; for ( i=0; i<=9; i++){ bb=bb+aa[i]; } } *****モジュール定義内容***** EXPORTS Sum

専門家に質問してみよう