[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2006/06/27(Tue) 11:25
投稿者名:かずちん
Eメール:
URL :
タイトル:
他ハンドルの取得方法
いつもお世話になっています。
開発環境:Windows2000/XP,VB6.0(SP6)

http://www.bcap.co.jp/hanafusa/VBHLP/tap_kanren.htm
http://www.bcap.co.jp/hanafusa/VBHLP/tap_PrgEnd.htm

上記などを一通り目をとおしたのですが、上手く取得できていません。

===============================================================
'既存のプロセスオブジェクトのハンドルを取得(P665)
Private Declare Function OpenProcess Lib "kernel32" _
    (ByVal dwDesiredAccess As Long, ByVal bInheritHandle As Long, _
     ByVal dwProcessId As Long) As Long
'指定のプロセスの終了コードを取得(P660)
Private Declare Function GetExitCodeProcess Lib "kernel32" _
    (ByVal hProcess As Long, lpExitCode As Long) As Long
'開かれているオブジェクトのハンドルを解放する(P1252)
Private Declare Function CloseHandle Lib "kernel32" _
    (ByVal hObject As Long) As Long

Private Const PROCESS_QUERY_INFORMATION = &H400&
Private Const STILL_ACTIVE = &H103&

Public Sub ShellEnd(ProcessID As Long)
    Dim hProcess As Long
    Dim EndCode As Long
    Dim EndRet   As Long
    'ハンドルを取得する
     hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, 1, ProcessID)
     MsgBox hProcess
    '終わるまで待つ
    Do
        EndRet = GetExitCodeProcess(hProcess, EndCode)
        DoEvents
    Loop While (EndCode = STILL_ACTIVE)
    'ハンドルを閉じる
     EndRet = CloseHandle(hProcess)
End Sub

Sub Main
    Dim ret1   As Long
    
    ret1 = Shell(Environ("ComSpec") & " /c start C:\Test.xls")
    
    ShellEnd (ret1)
    
    MsgBox "Test", vbOKOnly

End Sub
===============================================================

上記だと上手くハンドルが取れずにExcelファイルを閉じる前にMsgboxが表示されてしまいました。
やりたい事は開いたExcelファイルを修正などをして閉じた後に、処理を引き続き行いたいのです。

開いたExcelファイルのハンドルを上手く取る方法はありますでしょうか?
又ネットワークドライブ先のExcelファイルでも正常にハンドルを取得できますでしょうか?
宜しくお願い致します。

投稿時間:2006/06/27(Tue) 17:07
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re: 他ハンドルの取得方法
>     ret1 = Shell(Environ("ComSpec") & " /c start C:\Test.xls")

うわ。これで取れるプロセスIDはシェルプログラム(Command.com等)のものですね。
シェルプログラムはEXCEL(別プロセス)を起動してすぐ終了するから話が合っています。

ret1 = Shell("EXCEL C:\Test.xls", vbNormalFocus)

という感じでEXCELそのものを起動すればOK。手打ちなので第1引数は試行錯誤が必要かも。

投稿時間:2006/06/28(Wed) 14:44
投稿者名:かずちん
Eメール:
URL :
タイトル:
Re^2: 他ハンドルの取得方法
ダンボさん、ご返答ありがとうございます。

> うわ。これで取れるプロセスIDはシェルプログラム(Command.com等)のものですね。
> シェルプログラムはEXCEL(別プロセス)を起動してすぐ終了するから話が合っています。
>
> ret1 = Shell("EXCEL C:\Test.xls", vbNormalFocus)
>
> という感じでEXCELそのものを起動すればOK。手打ちなので第1引数は試行錯誤が必要かも。

上記の方法で実行した所
「実行時エラー:53 ファイルが見つかりません。」のエラーが表示されてしまいました。
何か設定が必要なのでしょうか?

投稿時間:2006/06/29(Thu) 06:28
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re^3: 他ハンドルの取得方法
> > ret1 = Shell("EXCEL C:\Test.xls", vbNormalFocus)
> > という感じでEXCELそのものを起動すればOK。手打ちなので第1引数は試行錯誤が必要かも。

> 何か設定が必要なのでしょうか?
必要なものは「試行錯誤」ですわね。ここで使うファイルは2つ。
C:\Test.xlsはEXCEL起動後にEXCELが自力で読み出すことを期待しています。
後はShell関数の仕様を勉強すれば、前に進めるでしょう。
http://www.bcap.co.jp/hanafusa/VBHLP/tap_shell.htm

投稿時間:2006/06/30(Fri) 15:33
投稿者名:かずちん
Eメール:
URL :
タイトル:
他ハンドルの取得方法【解決】
> > > ret1 = Shell("EXCEL C:\Test.xls", vbNormalFocus)
> > > という感じでEXCELそのものを起動すればOK。手打ちなので第1引数は試行錯誤が必要
かも。
>
> > 何か設定が必要なのでしょうか?
> 必要なものは「試行錯誤」ですわね。ここで使うファイルは2つ。
> C:\Test.xlsはEXCEL起動後にEXCELが自力で読み出すことを期待しています。
> 後はShell関数の仕様を勉強すれば、前に進めるでしょう。
> http://www.bcap.co.jp/hanafusa/VBHLP/tap_shell.htm

fname = Excelがインストールされているフォルダ & "\EXCEL.EXE"
ret1 = Shell(fname & " C:\Test.xls", vbNormalFocus)

使用するパソコンは全て同一の環境にOFFICEがインストールされている為
あまり良くはありませんが、力技で解決いたしました。

ダンボさん、ありがとうございました。

投稿時間:2006/07/03(Mon) 10:03
投稿者名:ダンボ
Eメール:
URL :
タイトル:
FindExecutable
> 使用するパソコンは全て同一の環境にOFFICEがインストールされている為
> あまり良くはありませんが、力技で解決いたしました。

それが嫌だったら、FindExecutable を使ったらどうかな。

Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" _
    (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As Long
Dim rc As Long, Buf As String * 1024
rc = FindExecutable("Dummy.xls", "", Buf)

で、BufにExcel.exeのフルパスが得られる。
#(Dummy.xlsは実在していないと駄目なのか?)

投稿時間:2006/07/03(Mon) 11:58
投稿者名:かずちん
Eメール:
URL :
タイトル:
ありがとうございました
> > 使用するパソコンは全て同一の環境にOFFICEがインストールされている為
> > あまり良くはありませんが、力技で解決いたしました。
>
> それが嫌だったら、FindExecutable を使ったらどうかな。
>
> Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExec
utableA" _
>     (ByVal lpFile As String, ByVal lpDirectory As String, ByVal lpResult As String) As L
ong
> Dim rc As Long, Buf As String * 1024
> rc = FindExecutable("Dummy.xls", "", Buf)
>
> で、BufにExcel.exeのフルパスが得られる。
> #(Dummy.xlsは実在していないと駄目なのか?)

こんなAPIがあるとは知りませんでした。
早速使ってみましたが、最初の引数はファイルが存在しないと駄目なのでExcel.exeのフルパスを
得る際にダミーのExcelファイルを一時的に作成・削除で対処しました。

又Bufを1024バイトで作成しているので
Left(Buf,Instr(Buf,vbNullChar)-1)でフルパス部分のみ抽出しています。
ダンボさん、色々とありがとうございました。

ただ最初の引数を設定する際にStringのバイト数を設定する必要性がわかっていないのでそこら辺は
自分で調べてみようと思います。
ちなみにバイト数を指定しないで実行するとVB自体が落ちてしまいました。

投稿時間:2006/07/03(Mon) 12:49
投稿者名:ダンボ
Eメール:
URL :
タイトル:
Re: ありがとうございました
> こんなAPIがあるとは知りませんでした。
私だって今朝まで知らなかった。ただ「ある筈」という信念で調べた。
(途中、msi.dllで大分費やした)

> Left(Buf,Instr(Buf,vbNullChar)-1)でフルパス部分のみ抽出しています。
それでいいです。

> ただ最初の引数を設定する際にStringのバイト数を設定する必要性がわかっていないのでそこら辺は
> 自分で調べてみようと思います。
どうぞ。「Visual Basicにおける文字列の扱い、特にメモリ管理」がキーワードかな。
  Dim Buf As String
  Buf = Space(1024)
でもいいですよ。

投稿時間:2006/07/03(Mon) 13:29
投稿者名:Blue
Eメール:
URL :
タイトル:
Re^2: ありがとうございました
パスならばMAX_PATH(260)で良いはず。

ちなみにFindExecutableの利用時には気をつけなければならない問題があるらしいです。
http://support.microsoft.com/?kbid=140724

Excel.Applicationオブジェクトから起動やパスを取得する方法はダメなんでしょうかね?

投稿時間:2006/07/03(Mon) 14:01
投稿者名:Blue
Eメール:
URL :
タイトル:
Re^3: ありがとうございました
> パスならばMAX_PATH(260)で良いはず。
あ〜ダメかも。〜〜〜AのAPIを使うと、どのように変換されるかよくわからないですが、
260バイトの領域である場合、MAX_PATHというのはUnicodeの文字数ですので、〜〜〜Aは
内部でMBCS(Shift_JIS)で処理するため、全て全角文字である場合(はないけど)、その倍必要でした。

ですので、MAX_PATH * 2 の領域があれば大丈夫そう。
(〜〜〜WのAPIであれば、MAX_PATHで大丈夫)

投稿時間:2006/07/03(Mon) 13:44
投稿者名:かずちん
Eメール:
URL :
タイトル:
調べてみました
> > ただ最初の引数を設定する際にStringのバイト数を設定する必要性がわかっていないのでそこ
ら辺

> > 自分で調べてみようと思います。
> どうぞ。「Visual Basicにおける文字列の扱い、特にメモリ管理」がキーワードかな。
>   Dim Buf As String
>   Buf = Space(1024)
> でもいいですよ。

ダンボさんに提示していただいたキーワードを元に調べてみました。

http://www.gogomonkey.2y.net/prog/aboutBSTR.html
http://www.gogomonkey.2y.net/prog/useAPI_fromVB.html

上記サイトから引用====================================================================
Win32API 関数から文字列を受ける場合、VB 側が確保したメモリ領域に API 関数が(機械的に)
文字列を書き込んでいきますが、用意した文字列変数のサイズが小さいと
致命的なエラー(一般保護エラー)になります。十分な領域を確保する必要が有ります。
======================================================================================

これは初めて知りました。文字列の場合は事前にメモリ確保をしないと受け取れないんですね。
今までAPI関数を使用する際は使用方法を確認するだけで、引数や戻り値について細かく調べないで
使っていました。これからはちゃんと確認してから使っていきたいと思います。

投稿時間:2006/12/21(Thu) 22:02
投稿者名:えいー
Eメール:
URL :
タイトル:
Re: 他ハンドルの取得方法【解決】
はじめまして、宜しくお願いします。
下記のコードを実行してみたら上手くいきましたが、シートを指定してアクティブにしたいのですが、これというのを見つけることが出来ません、方法を教えてください。
> fname = Excelがインストールされているフォルダ & "\EXCEL.EXE"
> ret1 = Shell(fname & " C:\Test.xls", vbNormalFocus)