Invoke codeを使って、今windows上に表示されているウィンドウを取得し、
その中から特定のウィンドウをアクティブにする、という仕組みを構築したいと考えています。
表示されているウィンドウの一覧はSystem.Diagnostics.Process.GetProcessで取得できたのですが、
その次の特定のウィンドウをアクティブにする方法が見つからず、困っています。
UiPathアクティビティでGetActiveWindow⇒ShowWindowが使用できれば良いのですが、
取得したいウィンドウが表示されるタイミングがまちまちなので、上記の方法を考えています。
どなたかこのInvokeCodeを使って特定のウィンドウをアクティブにする方法をご教授いただけないでしょうか。
tango
April 11, 2019, 4:55am
2
@RYOKO0306 さん、こんにちは
VB.NETに詳しいわけではありませんが、 System.Diagnostics.Process.GetProcessのProcess.MainWindowTitleプロパティで
AppActivate(Process.MainWindowTitle)
とするのはどうでしょう。以下のdobonにそれでもうまくいかない場合のあれこれもかいてあります。ご参考まで
Yoichi
(Yoichi)
April 11, 2019, 5:49am
3
こんにちは
UiPathアクティビティでGetActiveWindow⇒ShowWindowが使用できれば良いのですが、
取得したいウィンドウが表示されるタイミングがまちまちなので、上記の方法を考えています。
invoke code使わずにUiPathのアクティビティを使う方法を詰めたほうが良いように思えますが...
もしやるとすれば、GetProcessesなりGetProcessesByNameなりで取得したProcessのインスタンスからUiPath.Core.Windowを生成してやり、それを操作するほうが良いと思います。
ウインドウを特定する方法はプロセス名やMainTitle等を使うことになると思います。
戻り値でこのUiPath.Core.Windowの値を外に返してやれば、外でそのまま使えます。例えばAttach WindowアクティビティでAttachできますので、下の例ではBringToForegroundを使ってinvokeCode内で前面に持ってきていますが、外でAttach後Activateアクティビティを使ってアクティブにすることもできます。
以下invoke codeの中身の例
Dim listProcess As List(Of Process)
Dim w As UiPath.Core.Window
Dim listWindow As List(Of UiPath.Core.Window) = New List(Of UiPath.Core.Window)
listProcess=Process.GetProcessesByName("iexplore").ToList
For Each ps As Process In listProcess
Dim p As IntPtr =ps.MainWindowHandle
If (p<>IntPtr.Zero)
w = New UiPath.Core.Window(p)
listWindow.Add(w)
End If
Next
listWindow(0).BringToForeground
ArgWindow=listWindow(0)
Yoichiさま、tangoさま
アドバイスいただき、本当にありがとうございます。
Yoichiさまに教えていただいた手順で
InvokeCode上で特定のウィンドウは取得できたのですが、
その後UiPathのアクティビティに引き渡した後で止まってしまいました。
ですがなぜか、InvokeCode中で取得したウィンドウタイトルをデバック用にMsgboxで表示し、
表示されたMsgboxのOKボタンを押すと、処理が問題なく進みます。
追加したコードはMsgbox()だけです。。
具体的に作りたいフローは、下記の画像のようにMSAccessで作成した帳票を
PDFで印刷(保存)するという単純なものなのですが、
「名前を付けて保存」ダイアログの「保存」ボタンが実行時に検出されず
エラーが出ることが度々発生してしまいます。
セレクターエディタでは問題なく検出されていますが、
実行すると5割の確率で検出できません。
ホットキーも試しましたが同様に安定しません。
MSAccessの動作上、この「名前を付けて保存」の裏に「印刷中」のダイアログが常に表示されるのですが、
この2つのダイアログが表示されるタイミングもアクティブになるタイミングも
まちまちなため、
「名前を付けて保存」を確実にアクティブにする方法を模索していました。
上記の内容についてもしご知見がおありでしたら
再度アドバイスいただけないでしょうか。
Yoichi
(Yoichi)
April 15, 2019, 3:59am
5
こんにちは
現象的には、ボタンが表示される前(機能可能になる前)にクリックを行っているのかもしれません。
とりあえずの対応策としては例えば、
Find Element(要素を探す)で当該ボタンがVisibleまたはActiveになるまで待ってからクリックを行う。(Wait Visible,Wait Activeを利用)必要に応じてクリックの直前にActivateアクティビティで「名前を付けて保存」ダイアログを前面にもってくる。
あるいは、Retry Scopeアクティビティ等で、仮に保存ボタンのクリックに失敗しても何回かはクリックするようにする。
あたりをまずは試すのが良いのではと思います。(おそらくinvoke codeは不要かと)
いかがでしょうか?
Yoichiさま
以前はFind Elementを使っても検出されなかったのですが、
プロパティのWait VisibleとWait Activeを有効にしたところ、
無事検出できました!
お恥ずかしながらこのプロパティの存在に気づきませんでした。
勉強不足でした。。
今のところ30回ほどテストして安定稼働しているので
今回の件は解決したと思われます。
結局Invoke Codeは無用でしたが、
勉強になりましたので今後の参考にさせていただきます。
ご指導いただきありがとうございました!