プログラム言語 外部プログラム連携

概要

必要な機能が大きく、開発に要する時間が短い昨今、
プログラムの全てを自分で開発するのは効率が悪い。
他人が作ったプログラムをソースでなくDLLのまま利用する為の方法。
他言語で開発されたプログラムであってもそれは可能。

参考

Windowsはなぜ動くのか
Windowsの仕組み(.NET Frameworkとは?)
Windowsプログラミング

マーシャリング

異なるシステムへデータを渡す場合に渡し先で有効な型へ変換すること。
マネージ環境のプログラムから、アンマネージ環境で動作するプログラムを呼び出す際にマーシャリングが必要になる。

マーシャラー

マーシャリングを行うプログラム。

マネージ環境

CLR(CommonLanguageRuntime)によって管理された環境。
ガーベッジコレクション、セキュリティ機能等の.NetFrameworkの機能を提供する実行エンジン。
ガーベッジコレクションの動作を含むメモリ管理、配列・文字列の長さ管理が自動で行われる。

アンマネージ環境

上記以外の環境。
Win32API、COMオブジェクト、C/C++等、多言語で作られたプログラム等。
バッファがオーバーフローしない様、ガーベッジコレクションの動作に該当する使い終わったメモリの破棄等の処理は自動では行われない。

COM相互運用

マーシャリングを行った上で.NetFramework←→WindowsAPIでデータをやり取りを行う事。

ウィンドウハンドル

WindowsAPIにおいて操作対象毎に割り振られる管理番号
操作対象へのポインタ

実例

DLL(API)

APIとは?
Windowsプログラミング/API」参照

using System.Runtime.InteropServices;

class MyWin32
{
  [DllImport(“USER32.DLL”, EntryPoint = “MessageBoxA”)]
  public static extern int myMessageBox(
    int hWnd,
    String lpText,
    String lpCaption,
    uint uType);
  
  ※USER32.DLLにおけるMessageBoxAをmyMessageBoxとして宣言
  
  public const int MB_OK = 0x00000000;
  public const int MB_OKCANCEL = 0x00000001;
  public const int MB_ABORTRETRYIGNORE = 0x00000002;
  public const int MB_YESNOCANCEL = 0x00000003;
  public const int MB_YESNO = 0x00000004;
  public const int MB_RETRYCANCEL = 0x00000005;

}

public partial class MyForm : Form
{
  private void MyForm_Load(object sender, EventArgs e)
  {

    MyWin32.myMessageBox(
      hWnd: 0,
      lpText: “メッセージ”,
      lpCaption: “キャプション”,
      uType: MyWin32.MB_YESNO);
  }
}

VB外部の関数(Windows API/DLL)を呼び出す場合に定義
Public Declare Auto Function GetUserNameA Lib “advapi32” (ByVal buf as string, size as long) As Long

Public Declare Auto Function(又はSub) [VBで使う関数名]
Lib “[DLLファイル名]”
Alias “[DLL内の実際のファイル名]” ([ファイルの引数]) As [戻り値の型]

Lib:DLLファイルを指定。拡張子を抜きもOK

Alias:DLL 内の関数名と別名で呼び出すことができる。指定無しも可
Public Declare Function GetUserName Lib “advapi32” Alias “GetUserNameA” (ByVal buf as string, size as long) As Long
Call GetUserName(引数)

Declare 定義した後は、通常の関数と同じに呼び出せる。
尚、Windows API や C で作られた DLL のパラメタは一般に値渡しなので、ByVal キーワードが必要。

VB外部の関数(Windows API/DLL)を呼び出す場合に定義
Public Declare Function GetUserNameA Lib “advapi32” (ByVal buf as string, size as long) As Long

Public Declare Function(又はSub) [VB.NETで使う関数名]
Lib “[DLLファイル名]”
Alias “[DLL内の実際のファイル名]” ([ファイルの引数]) As [戻り値の型]

Lib:DLLファイルを指定。拡張子を抜きもOK

Alias:DLL 内の関数名と別名で呼び出すことができる。指定無しも可
Public Declare Function GetUserName Lib “advapi32” Alias “GetUserNameA” (ByVal buf as string, size as long) As Long
Call GetUserName(引数)

Declare 定義した後は、通常の関数と同じに呼び出せる。
尚、Windows API や C で作られた DLL のパラメタは一般に値渡しなので、ByVal キーワードが必要。

Private Declare Function 公開名 Lib “DLL名” Alias “別名” (ByVal 引数1 As Long, ・・・) As Long
Private Declare Function 公開名 Lib “DLL名” Alias “別名” () As Long
Private Declare Function 公開名 Lib “DLL名” () As Long

Private Declare Sub 公開名 Lib “DLL名” Alias “別名” (ByVal 引数1 As Long, ・・・)
Private Declare Sub 公開名 Lib “DLL名” (ByVal 引数1 As Long, ・・・)
Private Declare Sub 公開名 Lib “DLL名” ()
※DLL名:DLLは実行ファイルと同階層に配置するか、パスを記載する。

Dim myApi As Long
myApi = 公開名(5,5)
Call 別名(5,5)

DLL(ActiveX)

ActiveXとは?
Windowsプログラミング/API」参照

Dim myObj As Object
myObje = CreateObject(“~”)
Call myObje.メソッド(~)
myObje.プロパティ = ~

DLL(COM)

COMとは?
Windowsプログラミング/COM」参照

「参照設定」によるDLLのパス設定が必要
COMコンポーネントでないDLLは参照設定できない。
DLLのCOM登録は「.NETで作成したDLLをVB6から呼び出す方法」参照

Dim myObj As New ~
Call myObje.メソッド(~)
myObje.プロパティ = ~

EXE
非同期で起動。※呼び出し元PGは実行されたまま。

' メモ帳を起動する
Call Shell(“Notepad”, vbNormalFocus)

' タスクIDを取得(≠Windowsハンドル)
Dim RetVal As Variant
RetVal = Shell(“notepad”, vbNormalFocus)
' Windowをアクティブに(≠最小化解除)
Call AppActivate(RetVal)

' ファイルを指定してメモ帳を起動する
Call Shell(“Notepad C:\test.txt”, vbNormalFocus)

' 引数がスペースを含む場合
Call Shell(“””~.exe”” “”2015/05/08 10:00:00″””, vbNormalFocus)

vbHide(0)
フォーカスを持ち、非表示
vbNormalFocus(1)
フォーカスを持ち、元のサイズと位置に復元
vbMinimizedFocus(2)
フォーカスを持ち、最小化表示
vbMaximizedFocus(3)
フォーカスを持ち、最大化表示
vbNormalNoFocus(4)
フォーカスを持たず、最後にウィンドウを閉じたときのサイズと位置に復元
※現在アクティブなウィンドウは、アクティブのまま
vbMinimizedNoFocus(6)
フォーカスを持たず、最小化表示
※現在アクティブなウィンドウは、アクティブのまま

System.Diagnostics.Process p =
  System.Diagnostics.Process.Start(“notepad.exe”);

//コマンドライン引数に「”C:\test\1.txt”」を指定してメモ帳を起動する
System.Diagnostics.Process.Start(“notepad.exe”, @”””C:\test\1.txt”””);

プロセスの終了を検知する
using System.Diagnostics;

static void Main()
{
  // プログラムを起動しプロセスのインスタンスを取得
  Process hProcess = Process.Start(
    fileName: @”C:\Test.exe”,
    arguments: @”prm1 prm2 prm3″);
  
  // ↑プロセスが終了した時にExitedイベントを発生させる
  hProcess.EnableRaisingEvents = true;
  
  // Exitedイベントのハンドラを追加する
  hProcess.Exited += new System.EventHandler(Test_Exited);
  
  // 監視の為にアプリケーションを起動させておく必要あり。
  // タスクバーには表示されないがプロセスは起動する
  Application.Run();
}

private static void Test_Exited(object sender, System.EventArgs e)
{
  プロセス終了時、ここが呼ばれる
}