はじめての親子ハイキングに挑戦!! >>

開発環境:Win2000 SP4 VB6.0 SP5

共有メモリを使用して、別プロセスとデータの受け渡しを
したいと思っております。
色々調べた結果、CreateFileMappingを使用するまでは、
理解できたのですが、受け渡すデータについて困っています。

受け取る際のデータの形式が
Public Type typXYData
xx(20000) As Long
yy(20000) As Long
End Type

のユーザー定義型なっていて、64KBを越える為に宣言が
できません。
このような場合はどうやって共有メモリからデータを
受け取ったらよいのでしょうか?

解かる方ご教授お願い致します。

このQ&Aに関連する最新のQ&A

A 回答 (3件)

まずここ読む


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/
    • good
    • 0
この回答へのお礼

ご回答本当にありがとうございます。
HPからサンプルまで、本当に助かります。
教えていただいたHPとサンプルを使わせて頂き、
プログラムを作成していきます。
その後、また改めて↑返事にお礼を書かせて頂きます。

ありがとうございました。

お礼日時:2004/03/30 22:13

追記



http://oshiete1.goo.ne.jp/kotaeru.php3?q=317246
の#4でZeroMemoryについて述べられている。

「その型で、文字列以外は領域が決まっている。ただし、固定長文字列は可。」
という意の言葉が、最初の方である。


同様にサンプルも、先頭アドレスと領域サイズさえあれば可。
仕様的には全く一緒。
さらに当たり前ですが、その領域が連続していることが前提条件。

それに添っているのであれば、ユーザ型であろうとなかろうと、関係なく可能です。


でも、宣言できないような型は、共有領域以前の問題。
サイズオーバーなら、型・インターフェースを見直す必要があると思うけど、どうだろう。。。

限界まで共有領域を確保するのは、負荷としても問題ありでは?
    • good
    • 0

xx(20000) As Long


yy(20000) As Long

ユーザー定義型ではなく、配列として受ければよいのでは?
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。
>ユーザー定義型ではなく、配列として受ければよいのでは?
勉強不足で、このような形を取ってしまいました。
OpenFileMapping,CreateFileMappingなどを
使用して共有メモリのプログラムを組んでいるのですが、
一括でデータを取得する方法(ユーザー定義)しかわからなかったので・・・

配列で受け取る時はループして取得するのでしょうか?
それとも、Cのようにポインタとか使用するのでしょうか?

再度質問するようですが、宜しくお願い致します。

お礼日時:2004/03/29 19:10

このQ&Aに関連する人気のQ&A

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

このQ&Aを見た人はこんなQ&Aも見ています

このQ&Aを見た人が検索しているワード

このQ&Aと関連する良く見られている質問

Q既存のアプリのsyslistview32から文字列取得

既存のアプリケーションにあるコンポーネント「syslistview32」から文字列取得を取得したいのです。
自分なりに調べてみましたが、SendMessageを使用するのだと思いますが、具体的な記述(流れ)の方法をどうしていいのか分かりません。
解る方いましたら、ご教授ください。

Aベストアンサー

>SendMessageを使用するのだと思いますが
SendMessageを利用するのであれば、共有メモリを利用します。

最初に
http://oshiete1.goo.ne.jp/kotaeru.php3?q=817941
の#2の参考URLを見てから#2の回答を見てください。
CをVB化しています。
(実を言うと、これ私が別のメーリングリストで公開したのに非常に似ているのですが^^;)
あとはLVM_GETITEMを確保した共有メモリ部に、書き込む処理を行っていきます。


共有メモリを利用するには、OS別の方法を考慮しなければならないのです。
SendMessage以外の別方法が手元にあるので、それを張ってきますね^^

デスクトップもsyslistview32でできてますので、それを捕らえる方法です。

要参照設定
oleacc.dll
(NT4ならばService Pack 6a)
(Win98ならば `ユーザ補助`をインストール)

んでもってサンプル
Option Explicit

Private Type UUID
  Data1 As Long
  Data2 As Integer
  Data3 As Integer
  Data4(7) As Byte
End Type

Private Const CHILDID_SELF = 0&
Private Const OBJID_CLIENT = &HFFFFFFFC

Private Declare Function AccessibleObjectFromWindow Lib "oleacc" _
  (ByVal hWnd As Long, _
  ByVal dwObjectID As Long, _
  ByRef riid As UUID, _
  ByRef ppvObject As Any) As Long

Private IID_IAccessible As UUID

Private Enum NVADIRConstants
  NAVDIR_MIN
  NAVDIR_UP
  NAVDIR_DOWN
  NAVDIR_LEFT
  NAVDIR_RIGHT
  NAVDIR_NEXT
  NAVDIR_PREVIOUS
  NAVDIR_FIRSTCHILD
  NAVDIR_LASTCHILD
  NAVDIR_MAX
End Enum

Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWndParent As Long, ByVal hWndChildAfter As Long, ByVal lpClassName As String, ByVal lpWindowName As String) As Long

Sub Main()
  Dim lngWnd As Long
  Dim colWk  As Collection
  Dim i    As Integer
  
  Call UUID_Init
  
  lngWnd = GetSysLVHwnd
  If Not GetListViewItems(lngWnd, colWk) Then
    MsgBox "失敗"
  End If
  
  For i = 1 To colWk.Count
    Debug.Print colWk(i)
  Next i
  
End Sub

Private Sub UUID_Init()
  With IID_IAccessible
    .Data1 = &H618736E0
    .Data2 = &H3C3D
    .Data3 = &H11CF
    .Data4(0) = &H81
    .Data4(1) = &HC
    .Data4(2) = &H0
    .Data4(3) = &HAA
    .Data4(4) = &H0
    .Data4(5) = &H38
    .Data4(6) = &H9B
    .Data4(7) = &H71
  End With
End Sub

Private Function GetSysLVHwnd() As Long
  Dim h As Long
  h = FindWindow("Progman", vbNullString)
  h = FindWindowEx(h, 0, "SHELLDLL_defVIEW", vbNullString)
  GetSysLVHwnd = FindWindowEx(h, 0, "SysListView32", vbNullString)
End Function

Private Function GetListViewItems(ByVal inWnd As Long, Optional otCol As Collection) As Boolean
  Dim objAcc   As IAccessible
  Dim varChild  As Variant
  
  Set otCol = Nothing

  Call AccessibleObjectFromWindow(inWnd, OBJID_CLIENT, IID_IAccessible, objAcc)

  If objAcc Is Nothing Then
    Exit Function
  End If
  
  Set otCol = New Collection
  
  varChild = objAcc.accNavigate(NAVDIR_FIRSTCHILD, CHILDID_SELF)
  Do Until IsEmpty(varChild)
    otCol.Add objAcc.accName(varChild)
    varChild = objAcc.accNavigate(NAVDIR_NEXT, varChild)
  Loop
  Set objAcc = Nothing
  GetListViewItems = True
End Function

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

>SendMessageを使用するのだと思いますが
SendMessageを利用するのであれば、共有メモリを利用します。

最初に
http://oshiete1.goo.ne.jp/kotaeru.php3?q=817941
の#2の参考URLを見てから#2の回答を見てください。
CをVB化しています。
(実を言うと、これ私が別のメーリングリストで公開したのに非常に似ているのですが^^;)
あとはLVM_GETITEMを確保した共有メモリ部に、書き込む処理を行っていきます。


共有メモリを利用するには、OS別の方法を考慮しなければならないのです。
SendMessage以外...続きを読む

Qvb6で異なるのプロジェクト間で、値を渡したい

VB6で、以下1~3のような画面を作成したとします。
1.プロジェクトA・ログイン画面フォーム
2.プロジェクトB・照会画面フォーム
3.プロジェクトC・登録画面フォーム

まず、1を表示して、ログインして、
次に2や3の画面に、ログイン情報を渡してやりたいのですが、
どうすればよいでしょうか?
異なるプロジェクト間で値を渡せません。

Aベストアンサー

プロジェクトA,B,CをActiveX DLLとして作成すればメイン
モジュールからそれらのコンポーネントを呼ぶだけですみ
ます。
#変数の受渡しもプロパティを使用すれば可能。
プロジェクトグループにすれば、モジュール間のデータの
受渡し等の動作確認もできます。

Qファイルマッピングについて

ファイルマッピングについての質問です。
現在CreatFileMapping、OpenFileMapping、MapViewOfFileをつかって
EXE間のデータのやり取りをしているのですが、
このファイルマッピングを利用して構造体を
やりとりする事は出来ないものでしょうか?
開発環境はWinNT4とVB6です。よろしくお願いします。

Aベストアンサー

試してみました。

gOpenFileMappingMapViewOfFileFileMapReadFileMapWrite.vbpの変更点
---
Private Declare Sub MoveMemory Lib "kernel32.dll" _
Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)

Private Type tyData
x As Long
y As Long
b(9999) As Byte
s As String * 1024
End Type
Private Data As tyData

Command1_Click()
Data.s = Text1.Text
' 文字列をコピー
Call MoveMemory(ByVal lngFileMapViewAddress, Data, Len(Data))

Command2_Click()
Data.s = ""
Call MoveMemory(Data, ByVal lngFileMapViewAddress, Len(Data))
Label3.Caption = RTrim(Data.s)

Command3_Click()
lngFileMapSizeLow = Len(Data)
---
普段はEXE間のデータはファイルで渡していますが、ファイルマッピングも
結構いいですね。今後、挑戦したいです。

試してみました。

gOpenFileMappingMapViewOfFileFileMapReadFileMapWrite.vbpの変更点
---
Private Declare Sub MoveMemory Lib "kernel32.dll" _
Alias "RtlMoveMemory" _
(Destination As Any, _
Source As Any, _
ByVal Length As Long)

Private Type tyData
x As Long
y As Long
b(9999) As Byte
s As String * 1024
End Type
Private Data As tyData

Command1_Click()
Data.s = Text1.Text
' 文字列を...続きを読む

QCで作成したDLL関数をVBから呼び 引数渡し方法

/**** Cプログラム *****/
int testAP( char* a)
aのポインタにアドレスを返します。

/**** VB プログラム****/
Public Declare Function testAP Lib "test.dll" (ByRef a As String) As Integer


Dim keydata As String * 128

lngRc = testAP(keydata)

上記VBのAPを実行するとアプリケーションエラーになります。
Cプログラムのデバックをすると入口ではaのポインタにはアドレスがセットされていて
、値を設定出来、最後まで正常動作して、VBとのインタフェースで落ちています。
VB6.exeでアプリケーションエラーになっています。

恐らく、VBにはポインタという概念が無いと聞いていてCのAPとの受け渡しに失敗して
そうなのですが、VBでの引き渡し方法が分かりません。
よろしくお願い致します。

Aベストアンサー

>__declspec(dllexport) int testAP(BSTR* cp_KeyData){
>
>→char*からBSTR*に変更しました。

だめです。そんな強引なことをしないでください。
char *でかまいません。
BSTR*にするとメモリ破壊が起きます。
__stdcallはどうしたんですか?
(ごめんなさい、アンダースコア2つですね)

>只、VCのデバックを行うと実行時エラー'49'
>DLLが正しく呼び出せません。が出力される。
>(DLL関数を呼んで処理が終了してVBに戻る所で出力されます。

VBのDeclareステートメントと、Cの処理があっていません。メモリを破壊しているのでしょう。
EXEにして動くのはたまたまでしょう。

Qプロセス間通信について

VisualBasic2005にてプログラムを作ったのですが、作ったあとに別のPCにインストールして実行してみると動作しないことに気づきました。
プログラムの内容は、Aというプログラムに引数をつけて実行すると常駐プログラムBに引数の値を渡すというシンプルなものです。AとBは同じクライアントPCにて実行します。
「VB2005逆引き大全500の極意」という書籍のプロセス間通信という産プルを参考に作ったのですが、どうもHTTPでデータを渡しているらしくWEBサーバが動作していないと動作しないんです。
私のPCはPHPなども使う為Apacheが動作中です。
通常のクライアントにHTTPでの通信を受信する方法はないのでしょうか?(ApacheなどのWEBサーバをインストールしないで)
クライアントPCには.net Framework2.0がインストール済みです。
OSはWindowsXP(Home,Pro双方)
どなたか分かる方、ご教授お願いします。

Aベストアンサー

Windowsの場合、プロセス間通信としては
・ファイル
・Windowsメッセージ
・OLE
・名前付パイプ
・メールスロット
・共有メモリ
・メモリマップドファイル
・ソケット(通信)
・メッセージキュー
・イベント
・リモート処理
これで全部ではないですが、いくつもあります。
通信でどのようなデータ(サイズ、データ量、応答速度…)のやり取りを行い、2つのプロセスが同じPC、異なるPCか、更には質問とは関係ないですが、1:N、N:Nの通信、…等の条件でどの方式にするか決めます。

参考URL:http://oshiete1.goo.ne.jp/qa3173481.html,http://oshiete1.goo.ne.jp/qa1924882.html

QプロセスIDの取得方法について

下に同様の質問をしたのですが、削除方法分からない為、再度質問させていただきまし。

VB5.0を利用しています。
VBで書いたexeを実行した際に、そのプロセスID(自分の)は、GetCurrentProcessIdを利用すれば取得できると分かりました。
が、プログラム内でExcelを下記の様にオブジェクトを作成した場合、そのプロセスIDをどうやって取得すればいいのでしょうか?
ご存知の方居ましたら、教えて下さい。

Set ExcelObj = CreateObject("Excel.Application")
ここで起動?されたExcelのプロセスIDを取得したいのですが。

Aベストアンサー

FindWindowなどのキャプションか、クラス名で対象オブジェクトハンドルを取得し、
GetCurrentProcessId関数で、プロセスIDとスレッドIDを取得する方法が一般的。
過去スレにいっぱいサンプルがあります。

スクリプトを使用するなら、以下の方法もあったりする。

でもどちらも複数EXCEL起動時は、考えなければいけない部分多し。

Sub Main()
  Dim ExcelObj As Excel.Application
  
  Set ExcelObj = CreateObject("Excel.Application")
  ExcelObj.Visible = True
  Call DebugHandle
  ExcelObj.Quit
  Set ExcelObj = Nothing
End Sub

Public Function DebugHandle()
  Dim strSQL   As String
  Dim objWk    As Object
  Dim objXlsProc As Object
  strSQL = "SELECT Handle FROM Win32_Process WHERE Name = 'EXCEL.EXE'"
  Set objWk = GetObject("winmgmts:").ExecQuery(strSQL)
  For Each objXlsProc In objWk
    Debug.Print objXlsProc.Handle
  Next
End Function

FindWindowなどのキャプションか、クラス名で対象オブジェクトハンドルを取得し、
GetCurrentProcessId関数で、プロセスIDとスレッドIDを取得する方法が一般的。
過去スレにいっぱいサンプルがあります。

スクリプトを使用するなら、以下の方法もあったりする。

でもどちらも複数EXCEL起動時は、考えなければいけない部分多し。

Sub Main()
  Dim ExcelObj As Excel.Application
  
  Set ExcelObj = CreateObject("Excel.Application")
  ExcelObj.Visible = True
  Call DebugH...続きを読む

Qオブジェクト(dll)のレジストリ登録について

いつもお世話になっております。

dllの使い方について教えてください。

vb5.0で開発を進めているのですが、
dllを呼び出す際に、レジストリ登録を
しなければいけないのでしょうか?

いくつかのサイトでは、参照設定際すれば、
実行できているようです。。

実行環境では、レジストリ登録しないと
動かない場合があるということでしょうか?

ご教授、よろしくお願いします。

Aベストアンサー

何のDLLか、によるが。

・あなたがVB5.0で作成したDLLを、開発に使ったマシン以外で使う。
→該当するマシンでレジストリに登録する必要があります。

・あなたがVB5.0で開発を行うにあたり使用するDLLを開発に使ったマシン以外で使う。
→VB5.0で参照設定できるのであれば、それと同じ方法で該当するマシンにDLLをインストールすれば同様にレジストリに登録済みとなる事でしょう。

よくわかんなければ次のようにしてみれば良いだろう。コマンドプロンプトを開いて
C:\>regsvr32 hogehoge.dll
これで「Successful」と出ればActiveX DLLだ。エントリポイントが見つかりません云々と言われたらそれはWin32ネイティブDLLという事。登録に失敗して環境を壊すという事はないのでとりあえず登録を試みてみれば良いのではないかな。

現在では大きく分けてDLLは3つある。
・Win32ネイティブDLL:レジストリ登録不要。パスの通った所に配置する。
・ActiveX DLL:レジストリ情報によって呼び出すDLL。レジストリに登録する。インプロセスCOMサーバと言っても差し支えないかもしれないがあるかもしれない。
・Microsoft .Net アセンブリ:レジストリの登録は不要。単純に実行ファイルと同じパスに配置するか、.Netにおけるレジストリといえるグローバルアセンブリキャッシュに登録する。

何のDLLか、によるが。

・あなたがVB5.0で作成したDLLを、開発に使ったマシン以外で使う。
→該当するマシンでレジストリに登録する必要があります。

・あなたがVB5.0で開発を行うにあたり使用するDLLを開発に使ったマシン以外で使う。
→VB5.0で参照設定できるのであれば、それと同じ方法で該当するマシンにDLLをインストールすれば同様にレジストリに登録済みとなる事でしょう。

よくわかんなければ次のようにしてみれば良いだろう。コマンドプロンプトを開いて
C:\>regsvr32 hogehoge.dll
これで「S...続きを読む

QVB6 配列を初期化したい

VB6でループさせて配列に値を入れて、計算させて最終的に求めたい値をRとします。そのときループで繰り返すためか同じ配列に値を入れてどんどん値がでかくなりRの値がおかしくなってしまいます;
おそらく問題は一回前に入れた配列がそのままのこってしまってるからなのだと思うのですが;
配列の中の値をクリアする方法はないものでしょうか?
一応、配列=0として初期化しようとしても値は変わらず前のが残ったままになってしまっています;
どなたかわかる方いらっしゃいましたらご回答宜しくお願いします

その他何かいい方法があればそれも教えていただけたらと思います

Aベストアンサー

Eraceステートメントを使用

  Dim a() as Long
  Dim s(100) as String
  Dim x() as Long

  Erase a     ’要素が0になる
  Erase s     ’要素が""になる

  Redim x(100) as Long

  Erase x      ’メモリを解放

注)VB2005の場合は動作が異なるので注意して下さい。

Q他アプリの操作(メニューバー)

市販されているアプリケーションを自分で作成しているソフトで操作したいのですが、どの様に制御したらいいのか判りません。プログラムはVB6.0で作成しております。
したい事は他のアプリケーションでメニューバーの中の項目の
印刷項目を選択したいのですが、メニューバーのハンドルを取得
出来ず困っております。
そもそもメニューバーのハンドルって取得できるのでしょうか?

Aベストアンサー

ウィンドウハンドルの取得については割愛します。

Option Explicit

Private Declare Function GetMenu Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Long, lpMenuItemInfo As MENUITEMINFO) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hWnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_COMMAND = &H111

Private Type MENUITEMINFO
cbSize As Long
fMask As Long
fType As Long
fState As Long
wID As Long
hSubMenu As Long
hbmpChecked As Long
hbmpUnchecked As Long
dwItemData As Long
dwTypeData As String
cch As Long
End Type

' hWndに指定したウィンドウのメニュークリックをエミュレート
' Menusには、メニューを辿る順序を文字列配列で定義
' ファイル -> 印刷 であれば Menus() = {"ファイル", "印刷"}
Private Sub EmulateMenuClick(ByVal hWnd As Long, Menus() As String)
Dim hMenu As Long, lngID As Long, intMenuIndex As Integer
hMenu = GetMenu(hWnd)

' メニュー階層をたどる
For intMenuIndex = 0 To UBound(Menus)

If ContainMenu(hMenu, Menus(intMenuIndex), lngID) = False Then
Call MsgBox("一致するメニューはありません。")
Exit Sub
End If

Next

' 最終的に見つかったメニューのIDをWM_COMMANDでPostMessage
Call PostMessage(hWnd, WM_COMMAND, lngID, 0&)
End Sub

' hMenuのメニューハンドル内でTextの文字列と一致するメニューがあるかどうかを返す
' 見つかればTrue。このとき、hMenuにはサブメニューのハンドル、IDにはメニューのIDが返される
' 見つからなければFalse
Private Function ContainMenu(hMenu As Long, ByVal Text As String, ID As Long) As Boolean
Dim lngCount As Long, lngPos As Long
Dim typMenuItem As MENUITEMINFO
lngCount = GetMenuItemCount(hMenu)

' メニューの個数でループ
For lngPos = 0 To lngCount - 1
typMenuItem.fMask = &H3F&

typMenuItem.dwTypeData = vbNullChar
typMenuItem.cch = 0
typMenuItem.cbSize = Len(typMenuItem)
Call GetMenuItemInfo(hMenu, lngPos, 1, typMenuItem)

typMenuItem.dwTypeData = String(typMenuItem.cch, " ")
typMenuItem.cch = typMenuItem.cch + 1
typMenuItem.cbSize = Len(typMenuItem)
Call GetMenuItemInfo(hMenu, lngPos, 1, typMenuItem)

Debug.Print typMenuItem.dwTypeData

' メニューの文字列を比較(比較方法はどちらでも)
'If typMenuItem.dwTypeData = Text Then
If typMenuItem.dwTypeData Like Text Then

' 一致したらIDとサブメニューハンドルを返す
ID = typMenuItem.wID
hMenu = typMenuItem.hSubMenu
ContainMenu = True
Exit Function
End If
Next

ContainMenu = False
End Function

EmulateMenuClickにウィンドウハンドルと実行したいメニューを辿る文字列配列を渡してください。
画像は、このコードを利用してAPIビューアのバージョン情報をForm1から実行して表示させたものです。

ウィンドウハンドルの取得については割愛します。

Option Explicit

Private Declare Function GetMenu Lib "user32" (ByVal hWnd As Long) As Long
Private Declare Function GetMenuItemCount Lib "user32" (ByVal hMenu As Long) As Long
Private Declare Function GetMenuItemInfo Lib "user32" Alias "GetMenuItemInfoA" (ByVal hMenu As Long, ByVal un As Long, ByVal b As Long, lpMenuItemInfo As MENUITEMINFO) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA...続きを読む

Qファイルやディレクトリの存在確認を行う方法

ファイルをオープンするのはfopenでOKですが、ファイルやディレクトリの存在確認を行う方法が知りたいです。

何か組み合わせて作るものなのでしょうか?
perlとか便利な演算子があるのですが、C/C++って器用ではないですね。
これは処理系?依存の内容ですか?

私の環境は VC6, VC2005 Windows2000です。

Aベストアンサー

int access(const char* path, int mode);
int stat(const char* path, struct stat* sb);

かな?
MSDN を引くと _access_s() を使えとか書いてあるけど。


このQ&Aを見た人がよく見るQ&A

人気Q&Aランキング