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