PowerShellとUWSC間をMemoryMappedFileで通信する

UWSC公式掲示板に、C#UWSCのプロセス間通信のお題があった。
.net環境とUWSCと読み替えて、簡単に答えてみる。
けど、今みたら解決済みだった。
ま、いっか。



スクリプト

まず、.net環境側。
VisualStudioを起動するのが面倒なので、PowerShellで。
これくらいの移植はがんばってね。

$mmf = [System.IO.MemoryMappedFiles.MemoryMappedFile]::CreateNew('my_shared', 500)
$acc = $mmf.CreateViewAccessor()

$data = '転送文ABC123あいうえお'

for($i=0; $i -lt $data.Length; $i++) {
	$acc.Write($i * 2, $data[$i])
}

Read-Host 'ここでUWSCからの読み取り実行'

$acc.Dispose()
$mmf.Dispose()

上記スクリプトPowerShell(.net 4.0以上環境)で実行すると、「ここでUWSCからの読み取り実行」と表示して入力待ちになります。


そしたら、UWSC側を実行。

// 共有メモリ用
Const PAGE_READWRITE = 4
Const FILE_MAP_READ = 4	// 読取専用
Const FILE_MAP_WRITE = 2	// 読書両用
DEF_DLL CreateFileMappingA(Long, Long, Dword, Dword, Dword, String): Hwnd: Kernel32.dll
DEF_DLL MapViewOfFile(Hwnd, Dword, Dword, Dword, Long): Dword: Kernel32.dll
DEF_DLL UnmapViewOfFile(Dword): Bool: Kernel32.dll
DEF_DLL CloseHandle(Hwnd): Bool: Kernel32.dll
DEF_DLL lstrcpyW(var wstring, Long): Long: Kernel32.dll

Dim Hnd_FileMap, read_FileMap
Dim MapName = "my_shared"//共有メモリ名

Hnd_FileMap = CreateFileMappingA(-1, 0, PAGE_READWRITE, 0, 64, MapName)
read_FileMap = MapViewOfFile(Hnd_FileMap, FILE_MAP_WRITE, 0, 0, 0)

Str = Format(Chr(0), 10)
lstrcpyW(Str, read_FileMap)// 文字列読取
MSGBOX("受信:" + str)

UnmapViewOfFile(read_FileMap)
CloseHandle(Hnd_FileMap)

手元の環境ではいけました。
本当は、排他ロック等を入れないといけないですが、ま、いいでしょう。
入力待ちの間に実行しないと、誰も参照していないMemoryMappedFileはOSが解放するので、なくなってしまいます。

解説

質問者さんが提示したソースからの変更点は以下の通り。
.net側

  • 排他ロックのMutex抜いた
  • PowerShellスクリプトにした
  • Writeするだけのところを、Char毎にWriteした
    本当は、WriteArrayを呼ぶところだけど、PowerShellジェネリックメソッドを呼ぶのが面倒なのでforループにした
  • Console.ReadLine()の代わりにRead-Host


UWSC

  • lstrcpy->lstrcpyW
  • lstrcpyWのDEF_DLL

プロセス間通信なら

MemoryMappedFileだと、他PCとの通信ができないから、.net remotingかな、と思ったけど、UWSCに輸入するのが面倒(コストが高い)なので、名前付きパイプがいいね。
いろいろとトリックが書かれているので、判り難いですが、以下の記事を読めば、名前付きパイプが使えるように、、、なるかもしれない。
http://d.hatena.ne.jp/junjun777/20130804