• ベストアンサー

「FindWindow」、ウィンドウハンドルについて

知恵を貸してください。 VB6.0にて作業しています。 コモンダイアログからExcelファイルを指定して開く際、 現在起動中のものを二重起動しないために「FindWindow」 を用いました。 最初は正常に動作したのですが、何度か操作しているうちに、 Excelを起動していない(ctrl+Alt+Delで確認し、何度も再起動しました)のに 起動中の処理(ハンドルを表示)をするようになってしまいました。 (1)ソースの正否 (2)ウィンドウハンドルからウィンドウを特定する方法  ハンドル(3409196)が表示されるため、この番号から  指定されたウィンドウを特定できれば  原因特定にいたるのではないかと考えました。 についてアドバイスいただけないでしょうか? 以下にコードを記述します。 *モジュール側の記述は省略しました。 Private Sub Command1_Click() Dim hwindow As Long Dim Fname As String Dim XLSApp As Object (前述分省略) cdl.ShowOpen Fname = cdl.FileName   hwindow = FindWindow("XLMAIN", vbNullString) If hwindow = 0 Then Set XLSApp = GetObject(Fname)    (以下指定ファイルを開く処理) Else   MsgBox hwindow  End If End Sub 以上です、よろしくお願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • BellBell
  • ベストアンサー率54% (327/598)
回答No.3

まったく別のアプローチですが、以下の方法を当方はよく利用します '------------------------------------------------ Dim XLSApp As Object On Error Resume Next 'エクセルが起動していない場合エラーになるためエラーを抑止 Set XLSApp = GetObject(, "Excel.Application") '開いているエクセルを取得 On Error GoTo 0 'エラー抑止を解除 If XLSApp Is Nothing Then MsgBox "エクセルは起動していません" Else MsgBox "エクセルは起動中です" End If '------------------------------------------------ また、以下の様に関数化して使用する方がよりお勧めです '------------------------------------------------ 'ActiveXExeが起動中か否かを返す '起動中=True/起動していない=False Public Function ExistActiveXExe(Byref argActiveXClassName As String)As Boolean Dim ObjExistCheck As Object On Error Resume Next Set ObjExistCheck = GetObject(, argActiveXClassName) On Error GoTo 0 ExistActiveXExe = Not (ObjExistCheck Is Nothing) Set ObjExistCheck = Nothing End Function '------------------------------------------------ 業務などで、"On Error Resume Next"使用禁止などの(頑迷な)ルールがある場合等、また"On Error Go To [ラベル]"が使用できる場合は関数化の方法なら簡単に書き換えられます。 On Error禁止の場合は、上記方法はあきらめてください。

achi1111
質問者

お礼

BellBell様、回答ありがとうございます。 なるほど、こういうアプローチ方法もあるのですね。 "On Error Resume Next"使用禁止はありませんので参考にさせてください。 なお、じゃんぬねっと様へのお礼の欄にも書きましたが、 プログラムが動くようになりました。 マクロを起動させたために、ずっとExcelが開放されなかった(表現が違っていたらすみません) のかと思っています。 もし、マクロが原因ならば、マクロを含むEXCELは、はじく処理もいれないと。。。ですね。

achi1111
質問者

補足

頂いた回答で教えていただきたいのですが、 関数化の方は、'ActiveXExeが起動中か否かを返す' なので、Excelが起動中かどうかを調べるためには Function ExistActiveXExe の所をExcelに変えればよいのでしょうか? ExistActiveXExe argActiveXClassName ObjExistCheck は単なる文字列だと解釈していたので、宣言部分をそのまま使い、 下記のように記述したところ If ExistActiveXExe("XLMAIN") = False Then Excelを起動中でも起動していなくても同じ結果を返してきました。(どちらの回答も起動中) せっかく教えていただいたので、関数化の方も使いたいと考えています。 大変お手数ですが、使い方を教えてください。 申し訳ありません。

その他の回答 (4)

  • JeanneNet
  • ベストアンサー率48% (100/208)
回答No.5

こんにちは、じゃんぬねっと です。 ひとつ気になったのが、 > Excelを起動していない(ctrl+Alt+Delで確認し、何度も再起動しました)のに これは、アプリケーション タブではなく、 プロセス タブに EXCEL がないことまで確認したんですよね? もし、マクロによって何らかのファイルを掴んでいたとしても、 ここに表示されると思いますので...

achi1111
質問者

補足

じゃんぬねっと様 返信ありがとうございます。 私が見たのはアプリケーションタブの方です。 プロセスタブの方も確認し、確かにExcelの「.Exe」の表示はあったと記憶しています。 果たして終了させていいものか。。。と思いその箇所は触らずにいました。 確認するのはアプリケーションだけではないんですね。 ありがとうございます。m(_ _)m

  • BellBell
  • ベストアンサー率54% (327/598)
回答No.4

関数化の場合の使用方法を割愛したせいで混乱を招いたみたいですみません。 >If ExistActiveXExe("XLMAIN") = False Then の、"XLMAIN"部分ですが、エクセルの判定を行う場合に渡す文字列(ActiveXオブジェクト名)は"Excel.Application"です。 全文を書くと If ExistActiveXExe("Excel.Application") = False Then です。

achi1111
質問者

お礼

BellBell様 ご説明ありがとうございます。 >関数化の場合の使用方法を割愛したせいで混乱を招いたみたいですみません。 ⇒とんでもありません。こちらこそ知識が足りずお手数おかけしました。当然ですが、無事動作しました^^; 無知は免罪符になりませんが、頂いたアドバイスを自分のものにできるよう精進したいと思います。 ありがとうございました。m(__)m

  • JeanneNet
  • ベストアンサー率48% (100/208)
回答No.2

あ、間違えた、Excel 自身の話だったのね... orz 試して見ましたが、何度やっても正しく動きます。 プロセスも死んでいたんですよね?

achi1111
質問者

お礼

No.1にあわせてお礼いたしました。 遅くなりすみません。起動確認しておりました。

  • JeanneNet
  • ベストアンサー率48% (100/208)
回答No.1

こんにちは、じゃんぬねっと です。 二重起動防止ならば、Mutex を使う方法の方が確実だと思います。 こんなワードで検索してみてください。 http://www.google.co.jp/search?hl=ja&q=%E4%BA%8C%E9%87%8D%E8%B5%B7%E5%8B%95+%E7%A6%81%E6%AD%A2+Mutex&lr=

achi1111
質問者

お礼

じゃんぬねっと様、回答ありがとうございます。 実はPCを数時間ほおっておいたところ、障害無く起動できるようになりました。 もしかして、マクロ入りのExcelを開いたことが原因でしょうか?(できるのかな、と思い昨日何度か試してました)

関連するQ&A

  • ウィンドウハンドルの取得方法

    ダイアログの表示されないEXEを起動させて、FindWindowを使用してそのEXEのウィンドウハンドルを取得したいのですが上手くいきません・・。 FindWindowの第一引数は「ウィンドウのクラス名」を指定するようなのですが、「ウィンドウのクラス名」の意味が良くわかりません。第二引数は「ウィンドウ名」を指定するようなのですが、今回のようなアンダーグラウンドで動くEXEには「ウィンドウ名」は無いと思ってよいのでしょうか? ちなみにダイアログのあるEXEならウィンドウハンドルを取得できます。 お分かりの方がいらっしゃれば、ご教授願います。

  • APIを使う時は参照設定は不要?

    例えば Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long Sub test() Dim Handle As Long Handle = FindWindow("IEFrame", vbNullString) Debug.Print Handle End Sub と言うコードでウィンドウハンドルを取得する場合、 参照設定のどこにもチェックを入れませんが、なぜ参照設定しなくても使えるのでしょうか? Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" _ (ByVal lpClassName As String, ByVal lpWindowName As String) As Long が参照設定の代わりになるのですか?

  • VB2010 ウィンドウタイトルを取得

    こんにちはVB学習を始めて2週間になりました。 Webの記事などを参考にしていますがバージョンによって記述が変わって苦戦しています。 今回ご質問したい内容です。 ボタンを押すとメモ帳が起動されているか調べてそのウィンドウタイトルを得る ウィンドウタイトルで検索してハンドルを取得してそのままそのハンドルで逆に ウィンドウタイトルを得ています(無意味な処理ですが学習用という事で) Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer Private Declare Function GetWindowText Lib "user32.dll" Alias "GetWindowTextA" (ByVal hWnd As Integer, ByVal lpString As String, ByVal nMaxCount As Integer) As Integer Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click Dim ECHandle As Integer Dim Titlename As String Titlename = vbNullString ECHandle = FindWindow(vbNullString, "無題 - メモ帳") GetWindowText(ECHandle, Titlename, 255) Label5.Text = Titlename If ECHandle = 0 Then Label4.Text = "取得できない" Else Label4.Text = "取得出来た" & ECHandle & Titlename End If End Sub 結果はというと Titlename が空っぽのままでタイトルが取得できません どのような原因が考えられますでしょうか? よろしくお願いいたします。

  • vbaから他のアプリを終了

    エクセルVBAから他のアプリを終了するマクロを書きたいのですが、途中で行き詰ってます。 Sub test() Dim h As Long h = FindWindow(vbNullString, "タイトル") Call SendMessage(h, 0, 0, "ALT+{F4}") End Sub FindWindowでハンドルを取得してALT+F4を送ればいいじゃないかと思ってますが ALT+F4の送り方がわかりません。どなたか教えてください。 また、ほかに良い方法があれば併せてご提案くださると幸甚です。 よろしくお願いします。 -- エクセル2003

  • オブジェクトが必要です・・・・・

    オブジェクトが必要です・・・・・ すみません、判りません、丸投げです(爆)、申し訳ありませんがどなたか完成していただけませんか?;; また、この辺りをサルでも判るように解説してくれていて勉強し易いサイトがあったら教えてください・・・ Private Sub コマンド1_Click() Dim xlsApp As Excel.Application Dim xlsBook As Excel.Workbook Dim xlsSht As Excel.Worksheet Set xlsApp = CreateObject("Excel.Application") Set xlsBook = xlsApp.Workbooks.Open("■■■■■.xls") Set xlsSht = xlsWkb.Sheets(■■■■) If xlsBook.ReadOnly Then xlsBook.Close MsgBox "そのファイルは既に開かれています。" xlsApp.Quit Else xlsBook.Close End If Set wkb = Nothing: Set xls = Nothing Exit_exOpenEditC: Exit Sub Err_exOpenEditC: MsgBox Err.Number & " - " & Err.Description Resume Exit_exOpenEditC End Sub accessからexcelファイルをシートを指定して開き、重複の場合は開かない様にし、メッセージボックスを表示させたいのです・・・

  • 複数のブックの特定シートを1つのブックにまとめたい

    複数のブックの特定のシートを1つのブックにまとめたいのですが そのマクロは下記のように検索してでてきたのですが Sub test() Dim Fname As String Dim Wbm As Workbook Dim Wbs As Workbook Application.ScreenUpdating = False Set Wbs = ThisWorkbook Fname = Dir(ThisWorkbook.Path & "\*.xlsx*") Do While Fname <> "" If Fname <> ThisWorkbook.Name Then Workbooks.Open ThisWorkbook.Path & "\" & Fname Set Wbm = ActiveWorkbook Wbm.Worksheets("2016.03").Copy after:=Wbs.Worksheets(Wbs.Worksheets.Count) ActiveSheet.Name = Left(Fname, InStr(Fname, ".") - 1) Wbm.Close End If Fname = Dir() Loop Application.ScreenUpdating = True End Sub たとえば、特定のシートというのが毎回変わる場合今回は”2016.03"ですが 次回は”2016.04”という風に変わる時、どこかに入力したセルの値を元にシートを検索してくることなどは可能なのでしょうか? よろしくお願い致します。

  • エクセルのマクロで特定フォルダ内のJPGファイルを検索して開きたいので

    エクセルのマクロで特定フォルダ内のJPGファイルを検索して開きたいのですが、うまくいきません。 検索して開くファイルは、アクティブセルの値で始まります。 (例えばアクティブセルが「0000」だとすると、フォルダ内にある「0000りんご.JPG」というファイルを開く。りんごの部分は特定の文字でないためワイルドカードを使用してみましたがうまくいきません) Sub test() Dim P As String Dim Fname As String Fname = ActiveCell.Value P = "パス名\" & Fname & "*.JPG" Shell "Rundll32.exe" & " Shimgvw.dll,ImageView_Fullscreen" & " " & P, vbNormalFocus End Sub どうぞよろしくお願い致します。

  • Excelにおけるセルの値をVB2005に配列として取り込みたい

    Excelのセルの値をVB2005に配列として取り込みたいのですが、Excel.Rangeと配列の整合性が取れず困っています。 なんらかヒントになるような助言をお願いします。 以下は今までに作成中のコードです。 Public Class Form1 Dim xlsapp As New Excel.Application Dim xlsbook As Excel.Workbook Dim xlssheet As Excel.Worksheet Dim fn As String = "sample.xls" Dim Q(,,) As Double Dim i, j, x, y, z As Integer Dim k As Double Dim w(i), v(i), u(i) As Double Dim As Object Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click xlsbook = xlsapp.Workbooks.Open(fn) xlssheet = xlsbook.Worksheets(1) k = 1 w(i) = xlssheet.Cells(1, 3) v(i) = xlssheet.Cells(1, 2) u(i) = xlssheet.Cells(1, 1) For x = 2 To 11 If w(i) = 1 Then For y = 2 To 11 If v(i) = 1 Then Q(1, 1, k) = u(i) k = k + 1 End If Next End If Next z = k For k = 1 To z TextBox1.Text = Q(1, 1, k) Next End Sub Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click Me.Close() xlsapp.DisplayAlerts = False xlssheet = Nothing xlsbook.Close() xlsbook = Nothing xlsapp.Quit() xlsapp = Nothing End Sub End Class

  • エクセルVBAのウィンドウサイズ変更でエラー

    エクセル2000で、ファイルを二つのウィンドウに表示させて作業を行うのに、Auto_Openのマクロでサイズの調整を行っていましたが、ある日を境にエラーが出て動かなくなってしまいました。エラー発生前に、特別な事を行ったという自覚はありません。 マクロの内容は、次の通りです(抜粋) Dim fname1, fname2, windowname1, windowname2 As Variant Sub Auto_Open() fname1 = ActiveWorkbook.Name windowname1 = fname1 Windows(windowname1).Activate With ActiveWindow .Top = 4 .Left = 4 .Width = 630 .Height = 460 End With (省略、2つ目のファイルを開いて、上と同様にウィンドウ2のサイズ設定) End Sub エラーの内容は次の通りです 実行時エラー1004 Window classのTOPプロパティを設定できません。 TOPの所をコメントにして実行させると、次のLeftでやはりエラーとなります。 この日以降ずっと駄目なので、このマクロの部分は機能しないようにして今日に至っております。 原因と対処の仕方を教えて下さい。

  • Active Basic 他のアプリケーションを終了させる

    Active Basic4.23.00を使用しています。 指定したほかのプロセスを終了させようと思っているのですが、 なかなか上手くいきません。 Dim hWnd As HWND Dim err As Long Dim code As DWord hWnd=FindWindow("notepad",NULL) If hWnd=NULL Then MessageBox(hMainWnd,"FindWindowでエラーが発生!","Error",MB_OK or MB_ICONHAND) Exit Sub End If GetExitCodeProcess(hWnd,code) If code=STILL_ACTIVE Then MessageBox(hMainWnd,"GetExitCodeProcessでSTILL_ACTIVEが返った!","Error",MB_OK or MB_ICONHAND) Exit Sub End If err=TerminateProcess(hWnd,code) If err=0 Then MessageBox(hMainWnd,"TerminateProcessでエラーが発生!","Error",MB_OK or MB_ICONHAND) MessageBox(0,Str$(code),"GetExitCodeProcessで取得したコード",MB_OK or MB_ICONINFORMATION) Exit Sub End If このようなコードを書きました。 すみませんが、間違いの指摘のほうをお願いします。 それと、『FindWindow』関数についてです。 ヘルプに、 >lpClassName >検索するクラス名を指定します。必要のないときは、NULL を指定することができます。 とありますが、クラス名≒プロセス名と考えてもいいのでしょうか。 また、lpClassNameを指定し、lpWindowNameにNULLを指定(今回のコードのような場合)では、ハンドルを取得できないのでしょうか。 すみませんが、ご教授をお願いします。