dポイントプレゼントキャンペーン実施中!

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内で出来るといいなーとは思ってますが…すいません、本当に蛇足でした。

A 回答 (15件中1~10件)

> ついでを言えば、共有メモリを扱うクラスもあります。

こんな感じです。

ということでどんな実装になっているかがわかったので、
対応策を。


対応策1
Cue構造の要素1つずつに個別の領域をSetBuffName()を使って割り当てて行き、要素の位置はアドレスではなく領域名を導き出せる数字等(たとえば"Cue1"だったら1)を別の構造体に格納して連結していく


対応策2
要素1つずつに個別の共有メモリを割り当てるのではなく一括にしか取得できない場合は、VarPtr()で取得されるローカルの変数のアドレスを入れるのではなく、共有メモリに書き込む大きな領域の先頭からのオフセットを入れておく。


みたいな感じでできそうですね。
やっぱり対応策1が楽かな。
    • good
    • 0
この回答へのお礼

 つまり…BufNameをバッファ名として渡された場合、BufName_1、BufName_2、みたいな感じでOCX内で定義してバッファを並べればいい訳ですね?で、それを管理する構造体を作り、読み込む構造体の名前を格納しておく…ってなんだか分かったような分かって無いような言い方してますが、出来てるので分かったんだと思います。まあ、アドレスにこだわったのがそもそもの間違いだと…
 お二人には大変ご迷惑をおかけいたしました。おかげさまで足りない頭でも何とか完成には至れました…分かってみれば単純な理屈でしたけど。何故これが思いつかなかったのかと…
 初めからこの実装を出していれば話もこじれずに済んだのかもしれませんが…色々と勉強させていただいただきました。Lenやポインタの事もどこかでそのうち参考にさせていただきます。
 本当にありがとうございました。

お礼日時:2004/11/29 09:43

>「どっちが書く」なんてことは、確かに全然重要ではないように思いますがいかがですか?



単なる「共有メモリのサンプル」でしたら重用ではないですけど、「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)

補足日時:2004/11/25 09:39
    • good
    • 0

通りすがりの間違いサンプル提示したものです。


すいません。私の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構造は外せ無い条件なので…

 先輩のサンプルソースを元に二月ほどの付け焼刃な知識のため、理解力が追いつかないので…ってまあ、完全にいい訳になってますが…少し、じっくりと読む時間をください。熱くなられるとこちらとしても焦ってしまいますので…

補足日時:2004/11/25 09:41
    • good
    • 0

もひとつおまけ。



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でやってみてください。メモリを破壊します。

これの根拠は?経験則?
    • good
    • 0

まず最初にLen問題



私の間違いのようです。
すいません。

私もかなりあつくなっておりましたので、言い過ぎもありました。


>当然こういうサンプル出されるんでしたらOCXに置く必要があるんじゃないんですか?
>OCX自体はそれぞれ別のプロセスでコールされるので、OCX側に領域を置くのが筋だと思いますけど、違いますか?
これは決して大事ではありません。
それは設計がどのようになっていて、何をしたいかにより異なると思います。

大事なのは、
構造体の値をが別プロセスでも、容易に構造体として渡す
ということでは?
共有メモリに書き込むのが逆であれば、
書くと読むを逆に行えばいいだけっしょ。


    • good
    • 0

おまけ。



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ですか?
    • good
    • 0

>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バイト欠けますよ。

欠けても問題ないとお思いですか?
    • good
    • 0

追記



以前のサンプルはこちらの勘違いで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 ここまで ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
    • good
    • 0

まず反論の前に実行してみてください。



ReadProcessMemoryを利用することにより、プロセスを意識しないでいいことになります。

>いくらなんでもexeとexeのサンプルを、無理矢理exeとOCXを想定したActiveXDLLのサンプルにするのは無茶苦茶かと。

EXEであろうとActiveXであろうと、メモリ共有に関しての手段は一緒です。


>>メモリサイズを取得
>>  dwSize = Len(pDat)
>これ、LenBにしないとアライメントずれてサイズたんないかも知れないし。
実際にやってみました?構造体のサイズ取得方法を理解してます?
LenBでやってみてください。メモリを破壊します。


参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=317246
    • good
    • 0

>もしくは共有メモリ上にこの構造体の内容をそのまま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にしないとアライメントずれてサイズたんないかも知れないし。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!