
今までExcel2000のVBAから、以下のようなコードを使ってC++で作ったコマンドプロンプトで動くプログラムを動かすプログラムを作っていましたが、これを64bitのWindows7上で動いているExcel2010で使おうとしたらメッセージが出ました。いろいろ調べてみたところ、たぶんDeclareにPtrSafeを付ければ良いようなのですが、その際、他のコードはそのままで良いのでしょうか。特に、コード中のLongはそのままで良いのか気になるのですが...。ちなみに、下記コードの条件コンパイルはネットで調べて見よう見まねで付けたもので、Excel2000のときには付けていないものでした。ご存じの方がいらっしゃいましたらご教授ください。
'------------------------------------------------------------------------------
' Win32 API関数・定数の宣言
'------------------------------------------------------------------------------
#If VBA7 And Win64 Then '64bit
Declare PtrSafe Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Declare PtrSafe Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare PtrSafe Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
#Else '32bit
Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, _
ByVal dwMilliseconds As Long) As Long
Declare Function OpenProcess Lib "kernel32" (ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, ByVal dwProcessId As Long) As Long
Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
#End If
Private Const PROCESS_ALL_ACCESS As Long = &H1F0FFF
Private Const INFINITE As Long = &HFFFF
'------------------------------------------------------------------------------
' Run
'------------------------------------------------------------------------------
Public Sub Run(ByVal project_name As String)
Dim program As String
Dim task_id As Long
Dim h_proc As Variant
program = mdlFunc.ProgramPath() & mdlFunc.ProgramOption(project_name) 'プログラム名
task_id = Shell(program, vbHide)
h_proc = OpenProcess(PROCESS_ALL_ACCESS, False, task_id)
If OpenProcess(PROCESS_ALL_ACCESS, False, task_id) <> vbNull Then
Call WaitForSingleObject(h_proc, INFINITE)
CloseHandle h_proc
End If
End Sub
No.3ベストアンサー
- 回答日時:
LongPtrの補足ですが、
32bit環境で動かした場合は、LongPtrは32bit、
64bit環境で動かした場合は、LongPtrは64bitとして扱われます。
上記の通りポインタは大きさが変わる物で、他言語ではある程度流動的に変わる仕様なのですが、
VB(VBA)の整数型(int, long)は常に大きさが変わらない仕様であったため、
今回のような事になったのでしょう。
>> OpenProcessの戻り値もアドレスなのでLongPtrにする必要がある
はい、そうです。
>> 1. かつてのVBAではポインタ(32bit)を扱う型が無かったので、同じ32bitであるLongで代用していた。
>> 2. 64bit環境ではアドレスが64bitになるので、32bitのLongに格納するとデータが欠落する。
>> 3. これの対策としてポインタとしてのLongPtrという型が追加された。
>> 4. 今回のプログラムの場合、OpenProcessがプロセスハンドルとしてアドレスを返す。
はい、そうです。
>> 5. これを受け取るデータ型はVariantなので問題ないが(自動で判別するから?)、
>> WaitForSingleObjectの第1引数及びCloseHandleには64bitのポインタを渡す必要がある。
Variantで問題があるかどうかは分かりませんが、
OpenProcess関数はHANDLE型を返しますので、受け側(h_proc)はLongPtrが適切だと思います。
>> 6. 結果、WaitForSingleObjectの第1引数とCloseHandleの引数をLongPtrにする必要がある。
はい、そうです。
参考URL:http://msdn.microsoft.com/ja-jp/library/ee691831 …
丁寧にお教えいただきありがとうございました。詳細なことはこれから勉強しようと思いますが、今回のポインタの件は何となく理解できたような気がします。
No.2
- 回答日時:
こんにちは。
APIの宣言自体は、Win32API_PtrSafe.TXTから持って来ればいいです。
http://www.microsoft.com/download/en/details.asp …
C:\Office 2010 Developer Resources\Documents\Office2010Win32API_PtrSafe\Win32API_PtrSafe.TXT
# それと、コード中のおかしな所は、直しました。
Public Sub Run(ByVal project_name As String)
Dim program As String
Dim task_id As Long
Dim h_proc As LongPtr
program = mdlFunc.ProgramPath() & mdlFunc.ProgramOption(project_name) 'プログラム名
task_id = Shell(program, vbHide)
h_proc = OpenProcess(PROCESS_ALL_ACCESS, 1, task_id)
If h_proc <> 0 Then
Call WaitForSingleObject(h_proc, INFINITE)
CloseHandle h_proc
End If
End Sub
No.1
- 回答日時:
ざっと見ておかしいのは、(*)のLongです。
64bit環境になってからは、これをLongPtrにする必要があるかと。
Declare PtrSafe Function WaitForSingleObject Lib "kernel32"(
ByVal hHandle As Long(*),
ByVal dwMilliseconds As Long) As Long
dwMilliseconds側のLongはそのままです。
他も同様に、数値の値としてのLongはそのままで、ポインタやハンドルとしてのLongはLongPtrにしてみてください。
この回答への補足
追加ですみません。OpenProcessの戻り値もアドレスなのでLongPtrにする必要がある、という理解で間違いないでしょうか。
補足日時:2012/03/27 08:59ご回答いただきありがとうございます。いまいち正しく理解できているか判らないので確認させてください。
1. かつてのVBAではポインタ(32bit)を扱う型が無かったので、同じ32bitであるLongで代用していた。
2. 64bit環境ではアドレスが64bitになるので、32bitのLongに格納するとデータが欠落する。
3. これの対策としてポインタとしてのLongPtrという型が追加された。
4. 今回のプログラムの場合、OpenProcessがプロセスハンドルとしてアドレスを返す。
5. これを受け取るデータ型はVariantなので問題ないが(自動で判別するから?)、WaitForSingleObjectの第1引数及びCloseHandleには64bitのポインタを渡す必要がある。
6. 結果、WaitForSingleObjectの第1引数とCloseHandleの引数をLongPtrにする必要がある。
以上で間違いないでしょうか。お時間があれば確認していただけると幸いです。よろしくお願いいたします。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Access(アクセス) Vba Userformを前面に出すについて 3 2022/04/15 12:29
- Visual Basic(VBA) いつもお世話になっております、VBAで教えて頂きたいのですが 2 2022/05/05 22:20
- Excel(エクセル) 【マクロ】スクショ印刷がうまく動かない件 5 2022/12/06 17:37
- Visual Basic(VBA) 別シートから年齢別の件数をカウントしたいの続き 5 2023/01/24 00:16
- Visual Basic(VBA) VBA 別ブックからの転記の高速化について VBA 別ブックからの転記の高速化についてご教授下さい。 19 2022/07/26 13:07
- Visual Basic(VBA) VBAで質問ですが、皆さんはどの様に導き出しているのでしょうか? 6 2022/05/03 21:53
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る バッチからEXEの結果を受け取りたいのですが、 下記のバッ 1 2023/07/04 15:13
- Visual Basic(VBA) batからexeを実行し戻り値を受け取る EXEの実行内容の結果によって、戻り値を0か1かで返したい 1 2023/07/04 16:40
- Visual Basic(VBA) Vbaで数式をポーランド記法に変換するコードを作って実行しようとするとフリーズします。 1 2022/05/24 17:53
- Excel(エクセル) VBAの指示の内容 昨日こちらでご教示頂いたのですが初心者な為、一つ一つの指示が何をやっているのかわ 2 2022/10/25 18:08
このQ&Aを見た人はこんなQ&Aも見ています
-
VBA kernel32 の意味
マウス・キーボード
-
API関数 GetExitCodeProcess
Visual Basic(VBA)
-
excelのInitializeイベントとActivateイベントについて
Excel(エクセル)
-
-
4
動かなくなってしまった古いVBAを動くようにしたい
Visual Basic(VBA)
-
5
VB6.0 SHELLで起動したプログラムを終了さしたいのですが
Visual Basic(VBA)
-
6
あるプログラムのコマンドライン引数を調べる方法について
その他(コンピューター・テクノロジー)
-
7
メッセージボックスを前面に表示させるには?
Visual Basic(VBA)
-
8
vbaから他のアプリを終了
Visual Basic(VBA)
-
9
対象のアプリケーションが終了するまで起動し続ける
C言語・C++・C#
-
10
64ビットエクセルでのAPI宣言/PtrSafe
Excel(エクセル)
-
11
PowerShellを使って関連付けられたアプリケーションでファイルを開く時のエラー
Excel(エクセル)
-
12
Excel VBAでPDFファイルをMicrosoft Print to PDFで出力したい
Visual Basic(VBA)
-
13
VBAで保存しないで閉じると空のBookが残る
Excel(エクセル)
-
14
【ExcelVBA】各セルをダブルクォーテーションで括ってCSV保存したい
Visual Basic(VBA)
-
15
Vba LongPtrについて教えてください
Visual Basic(VBA)
-
16
VBAでfunctionを利用しようとしたときに「引数は省略できません」というエラーが出ます
Visual Basic(VBA)
-
17
Excel-VBAの「しばらくお待ちください」のダイアログが自動的に閉じない
Excel(エクセル)
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
ExcelVBAでのkernel32(64bit)
-
戻り値で構造体を返すことは可...
-
セグメントエラー
-
デバイスハンドルとは?
-
アプリを32bitから64bit移行
-
#define NULL ((void *)0) の弊害
-
Cで作成したDLL関数をVBから呼...
-
fopne で失敗する原因
-
NULLポインタが0でない処理系と...
-
メモリのアドレスからの値の取...
-
不適切なポインタ
-
TCHAR文字列内の検索について
-
参照型で受け取った引数をポイ...
-
ハンドル、アドレス、ポインタ...
-
str[i] は *(str + i) と同義で...
-
構造体のアドレス渡し
-
関数ポインタの高速化のメリット
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
セグメントエラー
-
C言語のポインタに直接アドレス...
-
init関数の意味
-
Run-Time Check Failure #3とい...
-
戻り値で構造体を返すことは可...
-
ExcelVBAでのkernel32(64bit)
-
アプリを32bitから64bit移行
-
参照型で受け取った引数をポイ...
-
fopne で失敗する原因
-
PASCALとFARの意味
-
LPSTR型の初期化について
-
CWnd::EnableWindow()の扱い方
-
ポインタについて
-
プーさんのマウスポインタを教...
-
連結リスト 要素の入れ替え
-
ハンドルはポインタか
-
C++で関数ポインタから関数名を...
-
自作DLLの引数について、ポイン...
-
NULLポインタが0でない処理系と...
-
TCHAR文字列内の検索について
おすすめ情報