開発環境:Win2000 SP4 VB6.0 SP5
共有メモリを使用して、別プロセスとデータの受け渡しを
したいと思っております。
色々調べた結果、CreateFileMappingを使用するまでは、
理解できたのですが、受け渡すデータについて困っています。
受け取る際のデータの形式が
Public Type typXYData
xx(20000) As Long
yy(20000) As Long
End Type
のユーザー定義型なっていて、64KBを越える為に宣言が
できません。
このような場合はどうやって共有メモリからデータを
受け取ったらよいのでしょうか?
解かる方ご教授お願い致します。
No.2ベストアンサー
- 回答日時:
まずここ読む
http://techtips.belution.com/ja/vc/0001/
んで以下のサンプルをどうぞ。
思いっきりポインタ使っています。
ってか、APIを使用するならC同様、ポインタで扱います。
サンプルは二つのプロジェクトで、両方とも
・フォーム
・標準モジュール
の構成になっています。
標準モジュールは、Project1/Project2兼用です。
'''---------------------------------------------
'''---------- Project1.Form1 ここから ----------
'''---------------------------------------------
Option Explicit
Private pProcID As Long
Private hProcess As Long
Private pShared As Long
Private pSharedLen As Long
Private Const DEF_PROJECT2 As String = "c:\Project2.exe"
Private Const DEF_MAX_ARRAY As Long = 20000
Private pLngXX(1 To DEF_MAX_ARRAY) As Long
'別アプリ起動
Private Sub Command1_Click()
On Error GoTo PGMERR
Dim strParam As String
'別アプリ存在チェック
If Dir(DEF_PROJECT2) = "" Then
MsgBox "EXEがみつからない"
GoTo PGMEND
End If
'共有メモリに値を書き込む
If Not memWrite(hProcess, pShared, VarPtr(pLngXX(1)), pSharedLen) Then
Call MsgBox("共有メモリへの書き込み失敗")
GoTo PGMEND
End If
'パラメータ作成(プロセスID/配列要素数/共有メモリ先頭ポインタ)
strParam = pProcID & " " & DEF_MAX_ARRAY & " " & pShared
'起動
Call Shell(DEF_PROJECT2 & " " & strParam)
PGMEND:
Exit Sub
PGMERR:
Call MsgBox(Err.Description, vbCritical)
GoTo PGMEND
End Sub
'ロード
Private Sub Form_Load()
Me.Command1.Caption = "別アプリ起動"
Me.Command1.Enabled = False
'プロセスIDを取得する
If Not GetThreadProcessId(Me.hwnd, pProcID) Then
Call MsgBox("プロセス情報取得失敗")
GoTo PGMEND
End If
'共有メモリオープン
pSharedLen = (Len(pLngXX(1)) * DEF_MAX_ARRAY)
If Not memOpen(pProcID, pSharedLen, hProcess, pShared) Then
Call MsgBox("共有メモリ確保失敗")
GoTo PGMEND
End If
'ダミーの値をセット
Call setValues
Me.Command1.Enabled = True
PGMEND:
End Sub
'アンロード
Private Sub Form_Unload(Cancel As Integer)
Call memFree(hProcess, pShared)
End Sub
'ダミー値セット
Private Sub setValues()
Dim i As Long
'適当に乱数をセット
For i = 1 To DEF_MAX_ARRAY
pLngXX(i) = Int(30 * Rnd)
Next i
End Sub
'''---------------------------------------------
'''---------- Project1.Form1 ここまで ----------
'''---------------------------------------------
'''---------------------------------------------
'''---------- Project2.Form1 ここから ----------
'''---------------------------------------------
Option Explicit
Private hProcess As Long
Private Sub Form_Load()
Dim strCmd As String
Dim varWk As Variant
strCmd = Command$
If strCmd = "" Then
MsgBox "パラメータなし"
End
End If
'デバッグ用リストボックスクリア
Me.List1.Clear
'パラメータ分解
varWk = Split(strCmd, " ")
'読み取りと画面反映
Call memDataRead(CLng(varWk(0)), CLng(varWk(1)), CLng(varWk(2)))
End Sub
'読み取りと画面反映
Private Sub memDataRead(ByVal inAppID As Long, ByVal inArrayCount As Long, ByVal lngMemPointer As Long)
On Error GoTo PGMEND
Dim lngXX() As Long
Dim dwSize As Long
Dim i As Long
'配列領域確保
ReDim lngXX(1 To inArrayCount) As Long
'メモリサイズを取得
dwSize = Len(lngXX(1)) * inArrayCount
'共有メモリ確保
If Not procOpen(inAppID, hProcess) Then
Call MsgBox("共有メモリ確保失敗")
GoTo PGMEND
End If
'共有メモリから値を読み込む
If Not memRead(hProcess, lngMemPointer, VarPtr(lngXX(1)), dwSize) Then
Call MsgBox("共有メモリからの読み込む失敗")
GoTo PGMEND
End If
'デバッグ用リストボックスへ出力
For i = 1 To inArrayCount
Me.List1.AddItem lngXX(i)
Next i
PGMEND:
Call procFree(hProcess)
Exit Sub
PGMERR:
Call MsgBox(Err.Description, vbCritical)
GoTo PGMEND
End Sub
'''---------------------------------------------
'''---------- Project2.Form1 ここまで ----------
'''---------------------------------------------
'''-----------------------------------------------
'''---------- Project1.Module1 ここから ----------
'''---------- Project2.Module1 ここから ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
Option Explicit
Private Declare Function OpenProcess Lib "kernel32" ( _
ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Private Declare Function VirtualAllocEx Lib "kernel32" ( _
ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal flAllocationType As Long, _
ByVal flProtect As Long) As Long
Private Declare Function VirtualFreeEx Lib "kernel32" ( _
ByVal hProcess As Long, _
ByVal lpAddress As Long, _
ByVal dwSize As Long, _
ByVal dwFreeType As Long) As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" ( _
ByVal hwnd As Long, _
ByRef lpdwProcessId As Long) As Long
Private Declare Function CloseHandle Lib "kernel32" ( _
ByVal hObject As Long) As Long
Private Declare Function WriteProcessMemory Lib "kernel32" ( _
ByVal hProcess As Long, _
ByVal lpBaseAddress As Long, _
ByVal lpBuffer As Long, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Function ReadProcessMemory Lib "kernel32" ( _
ByVal hProcess As Long, ByVal lpBaseAddress As Long, _
ByVal lpBuffer As Long, _
ByVal nSize As Long, _
ByRef lpNumberOfBytesWritten As Long) As Long
Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
Private Const STANDARD_RIGHTS_REQUIRED As Long = &HF0000
Private Const SYNCHRONIZE As Long = &H100000
Private Const PROCESS_TERMINATE As Long = &H1
Private Const PROCESS_CREATE_THREAD As Long = &H2
Private Const PROCESS_SET_SESSIONID As Long = &H4
Private Const PROCESS_VM_OPERATION As Long = &H8
Private Const PROCESS_VM_READ As Long = &H10
Private Const PROCESS_VM_WRITE As Long = &H20
Private Const PROCESS_DUP_HANDLE As Long = &H40
Private Const PROCESS_CREATE_PROCESS As Long = &H80
Private Const PROCESS_SET_QUOTA As Long = &H100
Private Const PROCESS_SET_INFORMATION As Long = &H200
Private Const PROCESS_QUERY_INFORMATION As Long = &H400
Private Const PROCESS_ALL_ACCESS As Long = STANDARD_RIGHTS_REQUIRED Or SYNCHRONIZE Or &HFFF
Private Const PAGE_NOACCESS As Long = &H1
Private Const PAGE_READONLY As Long = &H2
Private Const PAGE_READWRITE As Long = &H4
Private Const PAGE_WRITECOPY As Long = &H8
Private Const PAGE_EXECUTE As Long = &H10
Private Const PAGE_EXECUTE_READ As Long = &H20
Private Const PAGE_EXECUTE_READWRITE As Long = &H40
Private Const PAGE_EXECUTE_WRITECOPY As Long = &H80
Private Const PAGE_GUARD As Long = &H100
Private Const PAGE_NOCACHE As Long = &H200
Private Const PAGE_WRITECOMBINE As Long = &H400
Private Const MEM_COMMIT As Long = &H1000
Private Const MEM_RESERVE As Long = &H2000
Private Const MEM_DECOMMIT As Long = &H4000
Private Const MEM_RELEASE As Long = &H8000
Private Const MEM_FREE As Long = &H10000
Private Const MEM_PRIVATE As Long = &H20000
Private Const MEM_MAPPED As Long = &H40000
Private Const MEM_RESET As Long = &H80000
Private Const MEM_TOP_DOWN As Long = &H100000
Private Const MEM_4MB_PAGES As Long = &H80000000
'プロセスオブジェクトのハンドルを開く
Public Function procOpen(ByVal inAppID As Long, otProc As Long) As Boolean
otProc = OpenProcess(PROCESS_VM_OPERATION Or PROCESS_VM_READ Or PROCESS_VM_WRITE, 0, inAppID)
If otProc = 0 Then
GoTo PGMEND
End If
procOpen = True
PGMEND:
End Function
'プロセスオブジェクトのハンドルを開放する
Public Sub procFree(inProc As Long)
Call CloseHandle(inProc)
inProc = 0
End Sub
'共有メモリをオープン
Public Function memOpen(ByVal inAppID As Long, ByVal inSize As Long, otProc As Long, otSharedAddress As Long) As Boolean
'共有メモリをクローズする
Call memFree(otProc, otSharedAddress)
'プロセスオブジェクトのハンドルを開く
If Not procOpen(inAppID, otProc) Then
GoTo PGMEND
End If
'共有メモリを開放する
otSharedAddress = VirtualAllocEx(otProc, 0, inSize, MEM_RESERVE Or MEM_COMMIT, PAGE_READWRITE)
If otSharedAddress = 0 Then
GoTo PGMEND
End If
memOpen = True
PGMEND:
If Not memOpen Then
Call memFree(otProc, otSharedAddress)
End If
End Function
'共有メモリをクローズ
Public Sub memFree(inProc As Long, inSharedAddress As Long)
'クローズ
Call VirtualFreeEx(inProc, inSharedAddress, 0, MEM_RELEASE)
inSharedAddress = 0
'プロセスオブジェクトのハンドルを開放する
Call procFree(inProc)
End Sub
'共有メモリ領域に書き込む
Public Function memWrite(ByVal inProc As Long, ByVal inSharedAddress As Long, ByVal inMemPnt As Long, ByVal inSize As Long, Optional otSize As Long) As Boolean
Dim lngSts As Long
otSize = 0
lngSts = WriteProcessMemory(inProc, inSharedAddress, ByVal inMemPnt, inSize, otSize)
memWrite = (lngSts <> 0)
End Function
'共有メモリ領域から読み込む
Public Function memRead(ByVal inProc As Long, ByVal inSharedAddress As Long, ByVal inMemPnt As Long, ByVal inSize As Long, Optional otSize As Long) As Boolean
Dim lngSts As Long
otSize = 0
lngSts = ReadProcessMemory(inProc, inSharedAddress, ByVal inMemPnt, inSize, otSize)
memRead = (lngSts <> 0)
End Function
'ハンドルから、プロセスIDとスロッドIDを取得する
Public Function GetThreadProcessId(ByVal inWnd As Long, Optional otProcID As Long, Optional otThred As Long) As Boolean
otProcID = 0
otThred = 0
otThred = GetWindowThreadProcessId(inWnd, otProcID)
GetThreadProcessId = (otThred <> 0)
End Function
'''-----------------------------------------------
'''---------- Project1.Module1 ここまで ----------
'''---------- Project2.Module1 ここまで ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
参考URL:http://techtips.belution.com/ja/vc/0001/
ご回答本当にありがとうございます。
HPからサンプルまで、本当に助かります。
教えていただいたHPとサンプルを使わせて頂き、
プログラムを作成していきます。
その後、また改めて↑返事にお礼を書かせて頂きます。
ありがとうございました。
No.3
- 回答日時:
追記
http://oshiete1.goo.ne.jp/kotaeru.php3?q=317246
の#4でZeroMemoryについて述べられている。
「その型で、文字列以外は領域が決まっている。ただし、固定長文字列は可。」
という意の言葉が、最初の方である。
同様にサンプルも、先頭アドレスと領域サイズさえあれば可。
仕様的には全く一緒。
さらに当たり前ですが、その領域が連続していることが前提条件。
それに添っているのであれば、ユーザ型であろうとなかろうと、関係なく可能です。
でも、宣言できないような型は、共有領域以前の問題。
サイズオーバーなら、型・インターフェースを見直す必要があると思うけど、どうだろう。。。
限界まで共有領域を確保するのは、負荷としても問題ありでは?
No.1
- 回答日時:
xx(20000) As Long
yy(20000) As Long
ユーザー定義型ではなく、配列として受ければよいのでは?
ご回答ありがとうございます。
>ユーザー定義型ではなく、配列として受ければよいのでは?
勉強不足で、このような形を取ってしまいました。
OpenFileMapping,CreateFileMappingなどを
使用して共有メモリのプログラムを組んでいるのですが、
一括でデータを取得する方法(ユーザー定義)しかわからなかったので・・・
配列で受け取る時はループして取得するのでしょうか?
それとも、Cのようにポインタとか使用するのでしょうか?
再度質問するようですが、宜しくお願い致します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
このQ&Aを見た人はこんなQ&Aも見ています
-
夏が終わったと感じる瞬間って、どんな時?
まだまだ暑い今日この頃。 しかしながら、もう夏は終わっている!……はず。 あなたが思う「夏が終わった!」エピソードを教えてください。
-
人生最悪の忘れ物
今までの人生での「最悪の忘れ物」を教えてください。 私の「最悪の忘れ物」は「財布」です。
-
ホテルを選ぶとき、これだけは譲れない条件TOP3は?
ホテルを探す時、予約サイトで希望条件の絞り込みができる便利な世の中。 あなたは宿泊先を決めるとき「これだけは譲れない」と思う条件TOP3を教えてください。
-
昨日見た夢を教えて下さい
たまにすごいドラマチックな夢見ること、ありませんか? 起きてからも妙に記憶に残っているような、そんな夢。
-
14歳の自分に衝撃の事実を告げてください
タイムマシンで14歳の自分のところに現れた未来のあなた。 衝撃的な事実を告げて自分に驚かせるとしたら何を告げますか?
-
既存のアプリのsyslistview32から文字列取得
Visual Basic(VBA)
-
プロセス間通信について
Visual Basic(VBA)
-
VBで他アプリの「syslistview32」のテキストを取得したい
Visual Basic(VBA)
-
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・14歳の自分に衝撃の事実を告げてください
- ・架空の映画のネタバレレビュー
- ・「お昼の放送」の思い出
- ・昨日見た夢を教えて下さい
- ・【お題】絵本のタイトル
- ・【大喜利】世界最古のコンビニについて知ってる事を教えてください【投稿~10/10(木)】
- ・メモのコツを教えてください!
- ・CDの保有枚数を教えてください
- ・ホテルを選ぶとき、これだけは譲れない条件TOP3は?
- ・家・車以外で、人生で一番奮発した買い物
- ・人生最悪の忘れ物
- ・【コナン30周年】嘘でしょ!?と思った○○周年を教えて【ハルヒ20周年】
- ・ハマっている「お菓子」を教えて!
- ・最近、いつ泣きましたか?
- ・夏が終わったと感じる瞬間って、どんな時?
- ・10秒目をつむったら…
- ・人生のプチ美学を教えてください!!
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・都道府県穴埋めゲーム
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
他のアプリケーションをクリッ...
-
C#でのbatファイル実行結果取得
-
VB6.0 SHELLで起動...
-
警告『 別のプロセスで使用され...
-
C++のプログラムをバックグラウ...
-
Windowsでのfork方法
-
Shellでの環境変数
-
実行中のプログラムIDが取得...
-
リモートPCで動作しているプロ...
-
Linux環境におけるgetprocs関数
-
ロードアベレージが高いのです...
-
ウインドウのプロセス終了について
-
共有メモリの同時アクセスにつ...
-
プロセスのアタッチ・デタッチ...
-
Process.Startの戻り値を後で取得
-
sleep関数の精度について
-
外部プロセスを終了したい!!
-
vb.netでEXCEL起動がうまくでき...
-
[C#]リモートコンピューターを...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
explorer.exeが異様にメモリを食う
-
プロセスのアタッチ・デタッチ...
-
C#でのbatファイル実行結果取得
-
タスクマネージャーのプロセス...
-
タスクマネージャーのプロセス...
-
プロセスIDの取得方法について
-
SendMessageが失敗するときがある
-
Process.Startの戻り値を後で取得
-
怪しいプロセス教えてください。
-
VB.NET 自プログラムのプロセス...
-
IISがフリーズ
-
C++のプログラムをバックグラウ...
-
ADOでアクセスのレコードに...
-
共有メモリの同時アクセスにつ...
-
Linuxでのスレッド間メッセージ...
-
VB6.0 SHELLで起動...
-
別のプロセスの関数を呼び出す...
-
非表示になったエクセルは?
-
Windowsでのfork方法
おすすめ情報