電子書籍の厳選無料作品が豊富!

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件中11~15件)

#2で挙げたサンプル見てます?


そのまんま使えるはずです。


Project1(EXE)
├Form1
└Module1(EXEとOCX兼用)

Project2(OCX)
├Class1
└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 strParam  As String
  Dim objPro2   As Object
  Dim strWk    As String
 
  '共有メモリに値を書き込む
  If Not memWrite(hProcess, pShared, VarPtr(pDat), pSharedLen) Then
    Call MsgBox("共有メモリへの書き込み失敗")
    GoTo PGMEND
  End If

  'ActiveXをたたく
  Set objPro2 = CreateObject("Project2.Class1")
  'プロセスID/配列要素数/共有メモリ先頭ポインタ
  If Not objPro2.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.Class1 ここから ---------
'''---------------------------------------------
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.Class1 ここまで ---------
'''---------------------------------------------

'''-----------------------------------------------
'''---------- Project1.Module1 ここから ----------
'''---------- Project2.Class1 ここから ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
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.Class1 ここまで ----------
'''---------- 二つのプロジェクトで必要 ----------
'''-----------------------------------------------
    • good
    • 0

>そういう事ですか…しかし、何もVBごと落ちなくてもいいじゃないかと思うんですがそこの所どうなんでしょう某MS社の偉い人。



WinAPIの使い方間違ってればしょうがないです。VBそのもののプロセスのメモリを破壊してるんですから。


>…と思って二回CopyMemoryを(管理用構造体、内部データの二回)して見たんですが…やはりVBごと落ちてしまいます。


2回するのはいいんですが、

>1、VarPtrを使ってLong型のポインタに変換(してると思ってます)

これそのままにしてません?

VarPtrで取得できるのはあくまでも呼び元のプロセスで確保している領域のアドレスです。

>2、それを別の構造体に格納、その構造体を共有メモリに移す。
つまり、ここで本来格納しないといけないアドレスは、
1回目のCopyMemoryのコピー先アドレスですよね。
    • good
    • 0

>CopyMemoryは試したんですが、VBごと落ちてしまいます。


> …構造体のサイズが大きすぎて使えない…とか?

プロセスが違うから、Longに格納したアドレスが無効なんで落ちるんじゃなくて?


> 64Byteの構造体(ユーザー定義型)です。
> 中身はstring型とLong型が計16個です。

この構造体の領域自体、共有メモリ上にないとだめなのは理解されてますか?
もしくは共有メモリ上にこの構造体の内容をそのままCopyMemoryしてますか?(そしたら、別の構造体に入れるアドレスは共有メモリ上をさしますよね)

この回答への補足

>>CopyMemoryは試したんですが、VBごと落ちてしまいます。
>> …構造体のサイズが大きすぎて使えない…とか?
>プロセスが違うから、Longに格納したアドレスが無効なんで落ちるんじゃなくて?
 そういう事ですか…しかし、何もVBごと落ちなくてもいいじゃないかと思うんですがそこの所どうなんでしょう某MS社の偉い人。

>> 64Byteの構造体(ユーザー定義型)です。
>> 中身はstring型とLong型が計16個です。
>この構造体の領域自体、共有メモリ上にないとだめなのは理解されてますか?
>もしくは共有メモリ上にこの構造体の内容をそのままCopyMemoryしてますか?(そしたら、別の構造体に入れるアドレスは共有メモリ上をさしますよね)
 理解していませんでした(ぉぃ)サイズ以前の問題ですか…こちらもCopyMemoryして共有メモリ上に上げておく必要がある…つまり、二回CopyMemoryをする必要があるんですね。
 …と思って二回CopyMemoryを(管理用構造体、内部データの二回)して見たんですが…やはりVBごと落ちてしまいます。
 一応、classを使って共有メモリに構造体を渡す事はできているんですが、OCXと言う壁があるとどうにもうまく行かない物なんでしょうか…出来る気がしてなら無いんですが。

補足日時:2004/11/19 17:22
    • good
    • 0

一応共有メモリに関して、サンプルを書いた事があるので


http://oshiete1.goo.ne.jp/kotaeru.php3?q=817941


それと
>CopyMemoryは試したんですが、VBごと落ちてしまいます。
CopyMemoryの宣言や、その引数がわからないことには、誰もこのことには発言不可能

APIビューア通りの
Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)
としているなら、ポインタの値渡しが鉄則

call copymemory(ByVal [先頭アドレス],ByVal [先頭アドレス],[長さ])
『ByVal』 付けてます?

参考URL:http://oshiete1.goo.ne.jp/kotaeru.php3?q=817941
    • good
    • 0
この回答へのお礼

Private Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" _
(cStr1 As Any, cStr2 As Any, ByVal iLen As Long)
 CopyMemoryの宣言はこれです…同じ物ですよね?
 ByVal はきちんと使って渡しているんですが…

 とりあえず、参考URL熟読して次の案を出してみます。ありがとうございました。

お礼日時:2004/11/19 17:25

>1、VarPtrを使ってLong型のポインタに変換(してると思ってます)



できるはずですが、何の変数のアドレスをVarPtr使ってLongの数値にしてるんですか?質問文から読み取れないんですが。


>2、それを別の構造体に格納、その構造体を共有メモリに移す。
>
>3、別ウインドウから取り出し、最初のLongのポインタを引き抜く

これって別プロセスですか?
プロセス違う時点でポインタは無効になりますけど。

>4、Long型ポインタから構造体に戻す
CopyMemoryでしょ、ここで。


ということで、根本的なところがまずいような。
>1と4はOCXを扱う側、2と3はOCX内で行ってます。

1を扱う側でやっちゃまずいでしょ。共有メモリ内のアドレスでなければいけないんですから、扱う側で使い始める前にアドレスはわかってないといけないはずですよね。



>共有メモリを扱うOCXを作る必要がありまして、

なぜOCX?ActiveX EXEという選択肢はNGだったんですか?
これならプロセス空間を意識しないで情報のやり取りできますが。

この回答への補足

>> 1、VarPtrを使ってLong型のポインタに変換(してると思ってます)
> できるはずですが、何の変数のアドレスをVarPtr使ってLongの数値にし
> てるんですか?質問文から読み取れないんですが。
 64Byteの構造体(ユーザー定義型)です。
 中身はstring型とLong型が計16個です。

>> 2、それを別の構造体に格納、その構造体を共有メモリに移す。
>> 3、別ウインドウから取り出し、最初のLongのポインタを引き抜く
> これって別プロセスですか?
> プロセス違う時点でポインタは無効になりますけど。
 3で別なウインドウになるので別プロセスになると思いますが…う、駄
目ですか。

>> 4、Long型ポインタから構造体に戻す
> CopyMemoryでしょ、ここで。
 CopyMemoryは試したんですが、VBごと落ちてしまいます。
 …構造体のサイズが大きすぎて使えない…とか?

>> 共有メモリを扱うOCXを作る必要がありまして、
> なぜOCX?ActiveX EXEという選択肢はNGだったんですか?
> これならプロセス空間を意識しないで情報のやり取りできますが。
 そこは上司にOCXで作れといわれまして…
 ActiveX EXEと言う物があるんですか。調べてみましたが確かにこちらの方が適任かも…

補足日時:2004/11/18 09:01
    • good
    • 0

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