http://oshiete1.goo.ne.jp/kotaeru.php3?q=1087139
の続きです。仕様の都合でMoveMemoryを使って構造体をファイルマッピングできないため、一度文字列にして…と考えていたんですが、どうも文字列にすると別な問題が出るようなのでLong型のポインタにしたいと思ってます。
何故Longかと言うとこれも仕様の都合なので…Byte配列にとは出来ないんですが…同じ、ですよね?
蛇足が長々と続きましたが、本題は…
1、VarPtrを使ってLong型のポインタに変換(してると思ってます)
2、それを別の構造体に格納、その構造体を共有メモリに移す。
3、別ウインドウから取り出し、最初のLongのポインタを引き抜く
4、Long型ポインタから構造体に戻す
となれば完成で、3までは進めるのですが…最後の4ができません。
ここから再び蛇足ですが、そもそも何故こんな面倒な事を?といいますと、共有メモリを扱うOCXを作る必要がありまして、さらに受け取ったデータをCue構造にしなければならないのです。その辺りを操作してるのが2つ目の構造体です。1と4はOCXを扱う側、2と3はOCX内で行ってます。
出来れば全部OCX内で出来るといいなーとは思ってますが…すいません、本当に蛇足でした。
No.15ベストアンサー
- 回答日時:
> ついでを言えば、共有メモリを扱うクラスもあります。
こんな感じです。ということでどんな実装になっているかがわかったので、
対応策を。
対応策1
Cue構造の要素1つずつに個別の領域をSetBuffName()を使って割り当てて行き、要素の位置はアドレスではなく領域名を導き出せる数字等(たとえば"Cue1"だったら1)を別の構造体に格納して連結していく
対応策2
要素1つずつに個別の共有メモリを割り当てるのではなく一括にしか取得できない場合は、VarPtr()で取得されるローカルの変数のアドレスを入れるのではなく、共有メモリに書き込む大きな領域の先頭からのオフセットを入れておく。
みたいな感じでできそうですね。
やっぱり対応策1が楽かな。
つまり…BufNameをバッファ名として渡された場合、BufName_1、BufName_2、みたいな感じでOCX内で定義してバッファを並べればいい訳ですね?で、それを管理する構造体を作り、読み込む構造体の名前を格納しておく…ってなんだか分かったような分かって無いような言い方してますが、出来てるので分かったんだと思います。まあ、アドレスにこだわったのがそもそもの間違いだと…
お二人には大変ご迷惑をおかけいたしました。おかげさまで足りない頭でも何とか完成には至れました…分かってみれば単純な理屈でしたけど。何故これが思いつかなかったのかと…
初めからこの実装を出していれば話もこじれずに済んだのかもしれませんが…色々と勉強させていただいただきました。Lenやポインタの事もどこかでそのうち参考にさせていただきます。
本当にありがとうございました。
No.14
- 回答日時:
>「どっちが書く」なんてことは、確かに全然重要ではないように思いますがいかがですか?
単なる「共有メモリのサンプル」でしたら重用ではないですけど、「OCXを使った共有メモリのサンプル」となった時点で非常に重要になると思っています。ポイントがここではないのなら、元のサンプルだけで十分かと。
>っていか、突っ込みばかりですが、オタクは何がベストだと思っているの?
現在Chirs_Elfirdさんが使われているOCX中での共有メモリの実装にもとづいた対応策です。
OCXを選択している時点で他のプロセスでも使用していると考えるのが当然でしょう。
つまり、処理が既に出来上がっていると考えるべきです。
>これを回避するには、OCX側で共有メモリの領域をどのように確保しているか、
>複数回確保の要求があった場合、どのように割り当てているかの
>実装方法に依存してくるため、ここでは記述できません。
>#2の方の参考urlのようにOCXでReadProcessMemory()も
>ひとつの手ですが、OCX自体もChirs_Elfirdさんが作られてるんですか?
なので、この回答待ちです。とはいってもChirs_ElfirdさんがOCXまで作ってて新規に全部作れる場合の案を下に書いておきますが。
>私もtaka_tetsuさんがそれほどのツッコミを入れるなら、どのような手段をとるのか見てみたいと思っております。
なんかツッコミいれた場所の観点がずれちゃいましたね(^^;;;
ReadProcessMemory()等を使った共有メモリ、OKだと思いますよ。
ただ、2chさんの今回#5にかかれたサンプル、
http://oshiete1.goo.ne.jp/kotaeru.php3?q=817941
をもとに、
>正直、無視されていると思っているので、腹が立っています。
という気分で無理やり作ったんだろうなぁというのが見て取れるようなソースだったんで。
おそらく完璧と思って提示されたんだろうなとは思って突っ込んでみたのが火に油を注いでしまったようですね。
確かに「無茶苦茶」はちょっと書きすぎでしたね。失礼しました。ちゃんと理解した上で突っ込んでるんでお間違えなく。
>ほかに共有メモリを利用したやり取りする手法をお持ちなのですか?
で、これなんですが、今回の事例ではファイルマッピング+MapViewOfFileExを使うのがベストかと思っています。
・実装個所がOCXである。
・・・共有メモリを保持するプロセスが特定できない可能性がある。WriteProcessMemoryで書き込むには書き込み対象のプロセスが一意に特定できる状態であることが必要です。しかし、OCXという実装を取っていることから考えると、特定の共有メモリ管理用のプロセスが存在しない可能性もある。
MapViewOfFileやMapViewOfFileExであれば、起動されたプロセスのうちどれか1つハンドルを開いていればオブジェクトは消滅しないため、管理用プロセスが不要となる。
管理用プロセスが要るというのであれば、OCXではなくActiveX EXEにして共有メモリなんて使わないのがベスト。
・Cue構造にしたいため、共有メモリ中のアドレスを必要とする。
・・・MapViewOfFileでは割当ての先頭アドレスがプロセスごとに同じとは限らないのでアドレスを格納しても無意味。MapViewOfFileExなら先頭アドレスを指定できるのでアドレスが有効になる。まぁ、こちらはWriteProcessMemoryでも出来るかとは思いますが。
といったところですかね。
メモリマップドファイルだとサイズ拡張できないというのがありますが、そしたら複数個作っちゃえばいいだけですし。
でも、やっぱり、
>なぜOCX?ActiveX EXEという選択肢はNGだったんですか?
>これならプロセス空間を意識しないで情報のやり取りできますが。
なんですけどね。VBですから。
納得していただけますか?
この回答への補足
すいません、理解力がまったく追いつかず完全に亀レスになってしまいました。個人的にはサンプルソースをそのままコピペしてはい解決とは言いたく無い物で…2chさんを怒らせてしまったのは単に私の理解力不足です。申し訳ありませんでした。
> 現在Chirs_Elfirdさんが使われているOCX中での共有メモリの実装にもとづいた対応策です。
> OCXを選択している時点で他のプロセスでも使用していると考えるのが当然でしょう。
> つまり、処理が既に出来上がっていると考えるべきです。
つまりはその通りです。共有メモリを扱う事自体はできているので、問題はOCX内で共有メモリを使う事にあるのです。
ついでを言えば、共有メモリを扱うクラスもあります。こんな感じです。
Private Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" _
(ByVal hFile As Long, _
lpFileMappigAttributes As SECURITY_ATTRIBUTES, _
ByVal flProtect As Long, _
ByVal dwMaximumSizeHigh As Long, _
ByVal dwMaximumSizeLow As Long, _
ByVal lpName As String) As Long
Private Declare Function OpenFileMapping Lib "kernel32" Alias "OpenFileMappingA" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal lpName As String) As Long
Private Declare Function MapViewOfFile Lib "kernel32" _
(ByVal hFileMappingObject As Long, _
ByVal dwDesiredAccess As Long, _
ByVal dwFileOffsetHigh As Long, _
ByVal dwFileOffsetLow As Long, _
ByVal dwNumberOfBytesToMap As Long) As Long
Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
(ByVal Destination As Long, _
ByVal Source As Long, _
ByVal Length As Long)
Private Declare Sub ZeroMemory Lib "kernel32" Alias "RtlZeroMemory" _
(ByVal Destination As Any, _
ByVal Length As Long)
No.13
- 回答日時:
通りすがりの間違いサンプル提示したものです。
すいません。私のLenサンプルが間違っていたようですね。
ご迷惑おかけしました。m(_ _)m
私自身、結構サンプルを適当に書いているので、私のサンプルを見るときは、「手抜き」で「間違いがある」と思っておいてくださいませ。m(_ _)m
------------------------------------------------
久々発言ついでですが、確かにツッコミどころが気になるのですが、taka_tetsuさんはどうお思いですか?
題意から外れている内容にこだわり過ぎに思うのは私だけ?
2chさんも熱くなり過ぎ。
私個人的にには、「共有メモリ」に関しては、2chさんのサンプル以外は考えられないように思いますが、taka_tetsuさんはどうお思いですか?
「どっちが書く」なんてことは、確かに全然重要ではないように思いますがいかがですか?
見ていて、ちょっと見苦しい言い回しが多いように感じたので、私も個人的ツッコミ入れさせていただきました。
前後の文言が無く「滅茶苦茶」と言われたら、誰だって熱くなると思います。
でも私には、全然滅茶苦茶と思えません。
それ以外に考えられないと思っております。
>そこは一緒なんですけど(^^;;;
>この手法が使えないとは書いてません。
ほかに共有メモリを利用したやり取りする手法をお持ちなのですか?
私もtaka_tetsuさんがそれほどのツッコミを入れるなら、どのような手段をとるのか見てみたいと思っております。
この回答への補足
すいません、入らないのでこっちにわけます。
Public Function SetBuffName(ByVal vstrBufferName As String, _
Optional ByVal vblnOwner As Boolean = False) As Boolean
Dim blnResult As Boolean
Dim lngpBuff As Long
Dim bytBuff(2049012 - 1) As Byte
Dim udtSA As SECURITY_ATTRIBUTES
blnResult = False
udtSA.nLength = Len(udtSA)
'// オーナーモードならファイル作成。使用者モードならファイルオープン
' If (vblnOwner = True Or True) Then
If (vblnOwner = True) Then
'// メモリマップトファイル作成
m_lnghMap = CreateFileMapping(INVALID_HANDLE_VALUE, _
udtSA, _
PAGE_READWRITE, _
0&, _
m_lngTableSize, _
vstrBufferName)
Else
'// メモリマップトファイルオープン
m_lnghMap = OpenFileMapping(FILE_MAP_ALL_ACCESS, _
0&, _
vstrBufferName)
End If
If (m_lnghMap = 0) Then
Beep
Debug.Print Err.LastDllError
Else
'// マッピング
lngpBuff = MapViewOfFile(m_lnghMap, _
FILE_MAP_WRITE Or FILE_MAP_READ, _
0, _
0, _
0)
If (lngpBuff <> 0) Then
'// オーナーモードなら、バッファ内容初期化
m_lngpBuff = lngpBuff
If (vblnOwner = True) Then
Call ZeroMemory(m_lngpBuff, m_lngTableSize)
End If
'// 排他用セマフォ名生成
m_strSema = Format$(vstrBufferName, m_FORMAT_SEMA_NAME)
blnResult = True
Else
Beep
Debug.Print Err.LastDllError
End If
End If
SetBuffName = blnResult
End Function
'// バッファ取得
Public Function GetBuffer(ByVal vlngPtr As Long) As Boolean
Dim blnResult As Boolean
Dim lngSema As Long
If m_lngpBuff <> 0 Then
'// MoveMemoryは#1,#2ともByValのLong宣言してるので、ロングポインタ以外
'// 使えないようになってます。
Call MoveMemory(vlngPtr, m_lngpBuff, m_lngTableSize)
blnResult = True
Else
'// Not Open
End If
GetBuffer = blnResult
End Function
'// バッファ更新
Public Function SetBuffer(ByVal vlngPtr As Long) As Long
Dim lnghSema As Long
Dim blnResult As Boolean
If m_lngpBuff <> 0 Then
'// セマフォでの排他処理
lnghSema = CreateBuffSemaphore()
If (0 <> lnghSema) Then
Call MoveMemory(m_lngpBuff, vlngPtr, m_lngTableSize)
blnResult = True
End If
Call ReleaseBuffSemaphore(lnghSema)
Else
'// Not Open
End If
SetBuffer = blnResult
End Function
会社のだからもしかしたらマズいかなーと思い今まで出すに出せなかったんですが、この際なので出してしまいます。これを使ってました。
元々は別なフォームにあったこのクラスをOCXで呼び出しCue構造にして構造体でも扱えるようにする、と言うのが最終的な目標だった訳です。
このクラスを使うことに絶対性は無いんですが、OCXとCue構造は外せ無い条件なので…
先輩のサンプルソースを元に二月ほどの付け焼刃な知識のため、理解力が追いつかないので…ってまあ、完全にいい訳になってますが…少し、じっくりと読む時間をください。熱くなられるとこちらとしても焦ってしまいますので…
No.12
- 回答日時:
もひとつおまけ。
Type AAA
AAA_int As Integer
AAA_long As Long
End Type
Sub main()
Dim a As AAA
MsgBox VarPtr(a.AAA_long) - VarPtr(a.AAA_int)
End Sub
表示されるのは2ですか?4ですか?
>LenBでやってみてください。メモリを破壊します。
これの根拠は?経験則?
No.11
- 回答日時:
まず最初にLen問題
私の間違いのようです。
すいません。
私もかなりあつくなっておりましたので、言い過ぎもありました。
>当然こういうサンプル出されるんでしたらOCXに置く必要があるんじゃないんですか?
>OCX自体はそれぞれ別のプロセスでコールされるので、OCX側に領域を置くのが筋だと思いますけど、違いますか?
これは決して大事ではありません。
それは設計がどのようになっていて、何をしたいかにより異なると思います。
大事なのは、
構造体の値をが別プロセスでも、容易に構造体として渡す
ということでは?
共有メモリに書き込むのが逆であれば、
書くと読むを逆に行えばいいだけっしょ。
No.10
- 回答日時:
おまけ。
Type AAA
AAA_int As Integer
AAA_long As Long
End Type
Sub main()
Dim a(0 To 1) As AAA
MsgBox VarPtr(a(1)) - VarPtr(a(0))
End Sub
表示されるのは6ですか?8ですか?
No.9
- 回答日時:
>EXEであろうとActiveXであろうと、メモリ共有に関しての手段は一緒です。
そこは一緒なんですけど(^^;;;
この手法が使えないとは書いてません。
1.複数プロセスが立ち上がった場合、どのようにして共有情報が書かれている領域のアドレスをこのサンプルで別プロセスに渡すんですか?
すべてのプロセスが、EXE+OCXという構成で起動するんですよ。
> 3で別なウインドウになるので別プロセスになると思いますが…う、駄目ですか。
とChirs_Elfirdさんが書かれているのですから、当然別プロセスを意識したサンプルを提示してあげないとまずいですよね?
2.このサンプル、共有メモリを保持しているモジュール、どこという想定ですか?私にはEXEにしか見えないんですけど。
>共有メモリを扱うOCXを作る必要がありまして、
当然こういうサンプル出されるんでしたらOCXに置く必要があるんじゃないんですか?
OCX自体はそれぞれ別のプロセスでコールされるので、OCX側に領域を置くのが筋だと思いますけど、違いますか?
まぁ、同一プロセスなんだからどっちに置いてもいいのはわかりますけどね。
>実際にやってみました?構造体のサイズ取得方法を理解してます?
>LenBでやってみてください。メモリを破壊します。
Type AAA
AAA_int As Integer
AAA_long As Long
End Type
Sub main()
Dim a As AAA
MsgBox Len(a)
MsgBox LenB(a)
End Sub
Lenは6、LenBは8です。
なぜLenだとまずいか理解されてますか?
6だとAAA_longの後半2バイト欠けますよ。
欠けても問題ないとお思いですか?
No.8
- 回答日時:
追記
以前のサンプルはこちらの勘違いでActiveXExeで作ってしまったんだけど、
OCX化指令を出している先輩社員もいるのだから、読み替えてくれると思って
わざわざ再投稿しなかったんだけど、なんかうるさいので、作り直し。
でもほとんど差はなし
っていうか、ActiveX.DLLで通るならそれからOCXなんて、当たり前にできます。
「AcitveXDLLのインターフェイスに肉付けしたのがOCX」
だから、AcitveXDLLにできて、OCXにできないなんてこたぁありえません。
AcitveXEXEも同じこと。
↓↓↓↓↓↓↓↓ 重要ここから ↓↓↓↓↓↓↓↓
「反論するなら、意味も無く『無茶苦茶』発言はご勘弁」
「もしあるなら、調査・結果を書いた上でお願いします」
↑↑↑↑↑↑↑↑ 重要ここまで ↑↑↑↑↑↑↑↑↑
Project1(EXE)
├Form1
│└UserControl1(Project2を参照し、コントロールを貼り付け)
└Module1(EXEとOCX兼用)
Project2(OCX)
├UserControl1
└Module1(EXEとOCX兼用)
'''---------------------------------------------
'''---------- Project1.Form1 ここから ----------
'''---------------------------------------------
Option Explicit
Private pProcID As Long
Private hProcess As Long
Private pShared As Long
Private pSharedLen As Long
Private Type typData
a As Long
b As Long
c As Long
End Type
Private pDat As typData
'別アプリ起動
Private Sub Command1_Click()
On Error GoTo PGMERR
Dim strWk As String
'共有メモリに値を書き込む
If Not memWrite(hProcess, pShared, VarPtr(pDat), pSharedLen) Then
Call MsgBox("共有メモリへの書き込み失敗")
GoTo PGMEND
End If
'ActiveXをたたく
'プロセスID/配列要素数/共有メモリ先頭ポインタ
If Not Me.UserControl11.RunExec(pProcID, pShared, strWk) Then
GoTo PGMEND
End If
MsgBox strWk
PGMEND:
Exit Sub
PGMERR:
Call MsgBox(Err.Description, vbCritical)
GoTo PGMEND
End Sub
'ロード
Private Sub Form_Load()
Me.Command1.Caption = "ActiveX起動"
Me.Command1.Enabled = False
'プロセスIDを取得する
If Not GetThreadProcessId(Me.hwnd, pProcID) Then
Call MsgBox("プロセス情報取得失敗")
GoTo PGMEND
End If
'共有メモリオープン
pSharedLen = Len(pDat)
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()
With pDat
.a = 2
.b = 4
.c = 6
End With
End Sub
'''---------------------------------------------
'''---------- Project1.Form1 ここまで ----------
'''---------------------------------------------
'''---------------------------------------------
'''---------- Project2.UserControl1 ここから ---
'''---------------------------------------------
Option Explicit
Private Type typData
a As Long
b As Long
c As Long
End Type
Private pDat As typData
'メイン部
Public Function RunExec(ByVal inProcID As Long, ByVal inShared As Long, ByRef otBuff As String) As Boolean
On Error GoTo PGMERR
If Not memDataRead(inProcID, inShared, otBuff) Then
GoTo PGMEND
End If
RunExec = True
PGMEND:
Exit Function
PGMERR:
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpContext, Err.HelpFile
GoTo PGMEND
End Function
'読み取りと画面反映
Private Function memDataRead(ByVal inAppID As Long, ByVal lngMemPointer As Long, ByRef otBuff As String) As Boolean
On Error GoTo PGMEND
Dim hProcess As Long
Dim dwSize As Long
Dim strBuff As String
otBuff = ""
'メモリサイズを取得
dwSize = Len(pDat)
'共有メモリ確保
If Not procOpen(inAppID, hProcess) Then
Call MsgBox("共有メモリ確保失敗")
GoTo PGMEND
End If
'共有メモリから値を読み込む
If Not memRead(hProcess, lngMemPointer, VarPtr(pDat), dwSize) Then
Call MsgBox("共有メモリからの読み込む失敗")
GoTo PGMEND
End If
'デバッグ用
With pDat
strBuff = ""
strBuff = strBuff & "受けデータ" & vbCrLf
strBuff = strBuff & " A:" & .a & vbCrLf
strBuff = strBuff & " B:" & .b & vbCrLf
strBuff = strBuff & " C:" & .c & vbCrLf
End With
otBuff = strBuff
memDataRead = True
PGMEND:
Call procFree(hProcess)
Exit Function
PGMERR:
Call procFree(hProcess)
Err.Raise Err.Number, Err.Source, Err.Description, Err.HelpContext, Err.HelpFile
GoTo PGMEND
End Function
'''---------------------------------------------
'''---------- Project2.UserControl1 ここまで ---
'''---------------------------------------------
'''-----------------------------------------------
'''---------- 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 ここまで ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
No.7
- 回答日時:
まず反論の前に実行してみてください。
ReadProcessMemoryを利用することにより、プロセスを意識しないでいいことになります。
>いくらなんでもexeとexeのサンプルを、無理矢理exeとOCXを想定したActiveXDLLのサンプルにするのは無茶苦茶かと。
EXEであろうとActiveXであろうと、メモリ共有に関しての手段は一緒です。
>>メモリサイズを取得
>> dwSize = Len(pDat)
>これ、LenBにしないとアライメントずれてサイズたんないかも知れないし。
実際にやってみました?構造体のサイズ取得方法を理解してます?
LenBでやってみてください。メモリを破壊します。
参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=317246
No.6
- 回答日時:
>もしくは共有メモリ上にこの構造体の内容をそのままCopyMemoryしてますか?
>(そしたら、別の構造体に入れるアドレスは共有メモリ上をさしますよね)
大事なことを忘れてました。
OCXでの共有メモリのアドレスのマッピングの方法でMapViewOfFileを使用している場合、
プロセスごとに異なるアドレス空間に割り当てられるので、共有メモリにアドレス値を
書き込んでいても別プロセスでは無効なアドレスを指してしまっています。
これを回避するには、OCX側で共有メモリの領域をどのように確保しているか、複数回確保の要求があった場合、どのように割り当てているかの実装方法に依存してくるため、ここでは記述できません。
#2の方の参考urlのようにOCXでReadProcessMemory()もひとつの手ですが、OCX自体もChirs_Elfirdさんが作られてるんですか?
> 3で別なウインドウになるので別プロセスになると思いますが…う、駄
>目ですか。
これなんですけど、とーーーーーっても気になってるんですが(^^;;;;
本当に別プロセスなんですか?
「プロセス」って単位わかってますか?ウィンドウが違ってもプロセス一緒なんてごく当たり前ですが。
前回の質問
http://oshiete1.goo.ne.jp/kotaeru.php3?q=1087139
で、
>VALIANTだとサイズが大きすぎて実用性がありませんし、
という???なことを書かれているのがかなり気になります。
Variantなら簡単に扱えるような仕様の共有メモリなのですか?
で、ツッこんでいいのかなぁ・・・
元はちゃんとしてるように見えるんだけど。
いくらなんでもexeとexeのサンプルを、無理矢理exeとOCXを想定したActiveXDLLのサンプルにするのは無茶苦茶かと。
元のサンプルはコマンドラインで別exeに共有させるメモリの先頭アドレス渡してますけど、
これじゃだめですよねぇ・・・
> 'プロセスID/配列要素数/共有メモリ先頭ポインタ
> If Not objPro2.RunExec(pProcID, pShared, strWk) Then
OCXの想定だったらアドレス空間一緒ですよね。
あと、構造体なんだから
> '共有メモリオープン
> pSharedLen = Len(pDat)
と、
>メモリサイズを取得
> dwSize = Len(pDat)
これ、LenBにしないとアライメントずれてサイズたんないかも知れないし。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# C言語で構造体の参照渡しができません 2 2022/12/18 21:22
- C言語・C++・C# c言語の問題です 2 2023/07/21 10:51
- Excel(エクセル) エクセルの数式で教えてください。 1 2023/02/15 08:30
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Visual Basic(VBA) VBAでのMATCH関数 3 2022/10/17 19:06
- C言語・C++・C# C言語 2 2022/07/21 00:02
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- 建設業・製造業 別棟増築について質問です。 鉄骨造二階建て約250m2の建物に住宅用エレベーターを設置する計画をして 2 2022/04/02 13:44
- C言語・C++・C# いまc言語を独学で勉強しているのですがいまいちわかりません。 https://monozukuri- 3 2023/07/06 18:59
- Visual Basic(VBA) Excel VBA キーワードから列を取得して、さらに空欄行を非表示にする 3 2022/10/21 22:49
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
API関数 GetExitCodeProcess
-
プロセスのアタッチ・デタッチ...
-
プロセスIDからウィンドウハ...
-
ADOでアクセスのレコードに...
-
explorer.exeが異様にメモリを食う
-
他のコンピュータのプロセスを取得
-
タスクマネージャーのプロセス...
-
ShellExecuteが起動したプロセ...
-
他のアプリケーションをクリッ...
-
怪しいプロセス教えてください。
-
IISがフリーズ
-
VB6.0 SHELLで起動...
-
WebBrowserでPDF表示でのトラブル
-
セマフォとmutexの違いは?
-
プロセスIDの取得方法について
-
誤ってプロセスの終了をしてし...
-
非表示になったエクセルは?
-
デスクトップ上のアイコン名の...
-
バイナリ→構造体
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
バックグラウンドのプロセスの...
-
explorer.exeが異様にメモリを食う
-
タスクマネージャーのプロセス...
-
プロセスのアタッチ・デタッチ...
-
C#でのbatファイル実行結果取得
-
VB6.0 SHELLで起動...
-
ADOでアクセスのレコードに...
-
Windowsでのfork方法
-
非表示になったエクセルは?
-
共有メモリの同時アクセスにつ...
-
プロセスIDからウィンドウハ...
-
プロセスIDの取得方法について
-
C++のプログラムをバックグラウ...
-
C++でシェルを起動
-
Linuxでのスレッド間メッセージ...
-
OSPFでプロセスを分ける意義に...
-
怪しいプロセス教えてください。
-
Process.Startの戻り値を後で取得
-
SendMessageが失敗するときがある
-
ウィンドウのタイトルからプロ...
おすすめ情報