その他

タスクスケジューラで「最上位の特権で実行する」を選択せずに、ExcelVBAのuser32の関数を利用する方法[No35]

スポンサーリンク

「マウスのクリック」も含まれるWebブラウザを自動操作するマクロExcelを作成しました。また、Excelを起動せずともマクロExcel内の関数が実行できるように「外部ファイルから起動するためのVBSファイル」も用意しました。

タスクスケジューラからの実行では、そのマクロExcelの処理をさせるように、「外部ファイルから起動するためのVBSファイル」を実行するようにしていました。

そのマクロExcelは、タスクスケジューラの「全般」タブの「最上位の特権で実行する」をチェックした(または、チェックを入れた・選択した・最上位の権限に昇格させた・ONの)状態では、全体的に上手く実行されない作りになっていました。・・・事象1

そのマクロExcelを「最上位の特権で実行する」をチェックしない(または、チェックを入れない・チェックをはずしておく・未選択の・最上位の権限に昇格させない・OFFの)状態でタスクを登録すれば良いと思っていましたが、登録し実行すると大枠の処理は動作しても、処理内で「マウスのクリック」だけが行われませんでした。・・・事象2
※「マウスのクリック」はWindowsAPIのuser32.dllの関数のmouse_eventが動作することにより行われます。

まとめると次のようになっていました。

「「マウスのクリック」も含まれるWebブラウザを自動操作するマクロExcel」の処理をタスクスケジューラで実行したいと思い、「外部ファイルから起動するためのVBSファイル」から間接的に実行するようにしたが、タスクの設定の「最上位の特権で実行する」のON、OFFの状態によって次のようになってしまう。
ONの時には、全体的に上手く実行されなく、…事象1
OFFの時には、「マウスのクリック」だけが行われない。…事象2

基本的には、「最上位の特権で実行する」をONの状態で実行させれば、正常に動作するプログラムがほとんどと思いますが、今回は正常に動作しなかったため、この記事では事象1と事象2が起きたこのプログラムを「特別の事情を抱えているプログラム」とします。

繰り返しになりますが、選択できない特別な事情がない限り、「最上位の特権で実行する」をONの状態で実行すれば問題ありません。

これはどう対処したら良いか悪戦苦闘し、何とか解決できました。解決までに行った調査についてや、解決したその方法を紹介します。

動作環境

動作環境は次の通りです。

  • Windows PC、Windows 10 Pro
  • PCにはアカウントは1つのみ。そのユーザーは管理者。
  • 今回、そのユーザーでログオンし処理を行う。
  • PCに電源アダプタは接続している。

調査内容

問題の起きたファイル内容を簡略化させたファイル(記事内の呼び名:「自動化マクロExcel」)を用意します。「自動化マクロExcel」には「マウスを目的の場所に移動させて、クリックする」処理が登録されているマクロ(記事内の呼び名:「クリック処理」マクロ)を登録しておきます。調査ではこの「自動化マクロExcel」を用いました。

「手動実行」「タスクスケジューラによる実行」での挙動はそれぞれ次のようになっていました。

手動実行の場合

  • 「自動化マクロExcel」を起動して直接「クリック処理」マクロを実行すると、正常に処理された。
    ※詳細:「自動化マクロExcel」を起動し、「クリック処理」マクロを実行すると、マウスが目的の座標に移動しクリックすることができる。
  • 「外部ファイルから起動するためのVBSファイル」の実行から「自動化マクロExcel」内の「クリック処理」マクロを実行すると、正常に処理された。
    ※詳細:「外部ファイルから起動するためのVBSファイル」をダブルクリックすることで、「自動化マクロExcel」の「クリック処理」マクロが動作し、マウスが目的の座標に移動しクリックすることができる。

タスクスケジューラによる実行の場合

  • 「最上位の特権で実行する」がOFFの時には、「クリック処理」マクロの処理が、動作しない。
    ※詳細:「外部ファイルから起動するためのVBSファイル」をタスクスケジューラ(「最上位の特権で実行する」をOFFの状態)で実行すると、マウスが目的の座標に移動せずクリックもされない。
  • 「最上位の特権で実行する」がONの時には、「クリック処理」マクロの処理が、正常に処理された。
    ※詳細:「外部ファイルから起動するためのVBSファイル」をタスクスケジューラ(「最上位の特権で実行する」をONの状態)で実行すると、マウスが目的の座標に移動しクリックすることができる。

同事象が発生するプログラム

次のマクロを、Dドライブ直下に「MouseClickTest.xlsm」という名前で作成します。
※「調査内容」で記載している「自動化マクロExcel」はこの「MouseClickTest.xlsm」のことです。


Declare Sub mouse_event Lib "user32" ( _
    ByVal dwFlags As Long, _
    Optional ByVal dx As Long, _
    Optional ByVal dy As Long, _
    Optional ByVal dwDate As Long, _
    Optional ByVal dwExtraInfo As Long)
Declare Function SetCursorPos Lib "user32" (ByVal x As Long, ByVal y As Long) As Long

Public Const MOUSE_LEFTDOWN     As Integer = 2
Public Const MOUSE_LEFTUP       As Integer = 4
Public Const MOUSE_RIGHTDOWN    As Integer = 8
Public Const MOUSE_RIGHTUP      As Integer = 16

Public Sub mouseClickR(ByVal psX As Integer, ByVal psY As Integer)
    SetCursorPos psX, psY
    mouse_event MOUSE_RIGHTDOWN, 0, 0, 0, 0
    mouse_event MOUSE_RIGHTUP, 0, 0, 0, 0
    timeWait ("00:00:01")
End Sub

Public Sub mouseClickL(ByVal psX As Integer, ByVal psY As Integer)
    SetCursorPos psX, psY
    mouse_event MOUSE_LEFTDOWN, 0, 0, 0, 0
    mouse_event MOUSE_LEFTUP, 0, 0, 0, 0
    timeWait ("00:00:01")
End Sub

Public Sub test_mouseClickR()
    Call mouseClickR(700, 525)
    MsgBox "クリック処理実行しました。"
End Sub

Public Sub test_mouseClickL()
    Call mouseClickL(700, 525)
    MsgBox "クリック処理実行しました。"
End Sub

Public Sub timeWait(ByVal lengthOfTime As String)
    Application.Wait Now() + TimeValue(lengthOfTime)
End Sub

「test_mouseClickR」をこのエクセルから実行すると、マウスがモニターのX座標700(横700px)、Y座標525(縦525px)に移動して右クリックし、「クリック処理実行しました。」のメッセージボックスが表示されます。
※「調査内容」で記載している「クリック処理」マクロはこの「test_mouseClickR」のことです。
※「調査内容」の「手動実行の場合」に記載した1つ目の内容のことです。

そして、同じくDドライブ直下に「MouseClickTest_Kicker.vbs」を作成し、ダブルクリックで実行すると、同様の動作が得られます。
※「調査内容」の「手動実行の場合」に記載した2つ目の内容のことです。


Option Explicit

'-----
Dim FilePath
FilePath = "D:\MouseClickTest.xlsm"

Dim MacroName
MacroName = "test_mouseClickR"
'-----

Dim ObjExcelApp
Set ObjExcelApp = WScript.CreateObject("Excel.Application")
ObjExcelApp.Visible = True

ObjExcelApp.Workbooks.Open FilePath
ObjExcelApp.Application.Run MacroName

Set ObjExcelApp = Nothing

しかし、作成したMouseClickTest_Kicker.vbsをタスクスケジューラで「最上位の特権で実行する」をOFFの状態で実行すると、マウス移動やクリックは行われず、「クリック処理実行しました。」というメッセージボックスが表示されます。
※「調査内容」の「タスクスケジューラによる実行の場合」に記載した1つ目の内容のことです。

そして、「最上位の特権で実行する」をONの状態で実行すると、正常な動作が得られます。
※「調査内容」の「タスクスケジューラによる実行の場合」に記載した2つ目の内容のことです。

スポンサーリンク

このことからわかること

憶測を含みますが、わかったことは次の8つです。

  • VBAでマウス操作をする「mouse_event」はuser32の関数であること。
  • user32は「C:\Windows\System32」にある「user32.dll」であるということ。
  • user32.dllを右クリックすると、「削除」や「名前の変更」には管理者権限(ユーザーアカウント制御(UAC)関連)が必要であることから、タスクスケジューラから実行する際は、強い権限でVBAを起動することでuser32の関数を利用できるということ。
  • user32.dllのファイルを別のDドライブ直下にコピーし、VBAプログラム内で参照設定先の変更をLoadLibraryの利用など様々な方法で試しても上手く行かないこと。また、「System32」フォルダごとDドライブ直下にコピーし、そこのuser32を利用しようとしても上手く行かないということ。
  • タスクスケジューラにある「セキュリティ オプション」の「タスクの実行時に使うユーザーアカウント」の中で「ユーザーまたはグループの変更」から選択できる全てのオブジェクトで試したところ、正常な動作を得るには「最上位の特権で実行する」をONの状態にする必要があるということ。
  • タスクスケジューラでExcelを実行するには「 "C:\Windows\System32\config\systemprofile" 」「 "C:\Windows\SysWOW64\config\systemprofile" 」のそれぞれに「Desktop」フォルダを作成しておく必要があるということ。
    ※パソコンの構成によっては、片方だけで良い場合もありますが、どちらにも作成すれば間違いありません。
  • 管理者権限に影響を与えそうな特別な設定はしていないということ。
  • マウス操作の処理なので、「ユーザーがログオンしているときのみ実行する(R)」を選択し、「ユーザーがログオンしているかどうかにかかわらず実行する」のOFFの状態にしておく必要があるということ。

行いたいことの再確認

画像1:マウスがここにある状態でVBAプログラムを実行させる。

画像1

画像2:マウスポインタを画面の中心付近に移動させ右クリックさせる。

画像2

画像3:処理したことがわかるように、ポップアップで「クリック処理実行しました。」と表示させる。

画像3

この一連の処理を、タスクスケジューラのタスクで実行させたいです。

スポンサーリンク

「特別の事情を抱えているプログラム」の再確認

再掲となりますが、冒頭で紹介した「特別の事情を抱えているプログラム」は、
「最上位の特権で実行する」がONの状態では全体的に上手く実行されない作りになっていて、
「最上位の特権で実行する」がOFFの状態で実行する必要がありますが、OFFの状態では一部の処理が動作しませんでした。

解決方法

何度も諦めかけましたが、試行錯誤の末、私が導き出した解決方法を次にお話します。

解決のポイント

  • 「VBAファイルを実行させる外部ファイル」を実行するためのバッチファイルを作成すること。
  • バッチファイルでVBAファイルを全面表示にさせ、アクティブにすること。

プログラム

次の4つのファイルを用意して説明します。

  • ファイル1:MouseClickTest.xlsm
    (場所は「 "D:\MouseClickTest.xlsm" 」)
    (「同事象が発生するプログラム」のところで登場したファイル。)
    ※VBAのマウス関連の処理が書かれたメインのファイルです。このファイルを外部ファイルで起動し、ファイル内の「test_mouseClickR」マクロを実行させたいです。
  • ファイル2:MouseClickTest_Kicker.vbs
    (場所は「 "D:\MouseClickTest_Kicker.vbs" 」)
    ※先程とは#####の所が異なります。下図で確認して下さい。
    ※このファイルを「最上位の特権で実行する」をOFFの状態で、このファイルをキックしてファイル1を実行させたいが上手く行きません。
  • ファイル3:MouseClickTest_Kicker_Kicker_VerBat.bat
    (場所は「 "D:\MouseClickTest_Kicker_Kicker_VerBat.bat" 」)
    ※ファイル2を「最上位の特権で実行する」をOFFの状態でキックすると、ファイル1を起動でき、マウスの処理をしてくれます。(バッチファイルのバージョン)
  • ファイル4:MouseClickTest_Kicker_Kicker_VerVbs.vbs
    (場所は「 "D:\MouseClickTest_Kicker_Kicker_VerVbs.vbs" 」)
    ※ファイル3のVBSファイル版です。

ファイル2


Option Explicit

'-----
Dim FilePath
FilePath = "D:\MouseClickTest.xlsm"

Dim MacroName
MacroName = "test_mouseClickR"
'-----

Dim ObjExcelApp
Set ObjExcelApp = WScript.CreateObject("Excel.Application")
ObjExcelApp.Visible = True
'#####
'WScript.CreateObject("WScript.Shell").AppActivate ObjExcelApp.Caption
Dim ObjWSH
Set ObjWSH = WScript.CreateObject("WScript.Shell")
ObjWSH.AppActivate ObjExcelApp.Caption
'#####
ObjExcelApp.Workbooks.Open FilePath
ObjExcelApp.Application.Run MacroName

Set ObjExcelApp = Nothing
'#####
Set ObjWSH = Nothing
'#####

ファイル3


@echo off
start "" "D:\MouseClickTest_Kicker.vbs"

ファイル4


Set ObjWSH = CreateObject("Wscript.Shell")
ObjWSH.run "cmd /c D:\MouseClickTest_Kicker.vbs", vbhide

スポンサーリンク

タスクスケジューラの設定

画像4:画像のように下記3つのタスクを作成する。
 ・MouseClickTest_Kicker
 ・MouseClickTest_Kicker_Kicker_VerBat
 ・MouseClickTest_Kicker_Kicker_VerVbs

画像4

画像5:3つのタスクで共通。各タスクの「トリガー」はテスト用なので未選択とする。

画像5

画像6:3つのタスクで共通。各タスクの「条件」は初期値のまま変更しない。

スポンサーリンク

画像7:3つのタスクで共通。各タスクの「設定」も初期値のまま変更しない。

画像7

画像8:MouseClickTest_Kickerのタスクの設定。画像8のように選択する。「タスクの実行時に使うユーザーアカウント」はログオンしているユーザー(管理者)にする。※私は初期値でした。

画像8

画像9:MouseClickTest_Kickerのタスクの設定。画像9のように操作の編集を行う。

画像9

画像10:MouseClickTest_Kicker_Kicker_VerBatのタスクの設定。画像10のように選択する。「タスクの実行時に使うユーザーアカウント」は、ログオンしているユーザー(管理者)にする。

画像10

画像11:MouseClickTest_Kicker_Kicker_VerBatのタスクの設定。画像11のように操作の編集を行う。

画像11

画像12:MouseClickTest_Kicker_Kicker_VerVbsのタスクの設定。画像12のように選択する。「タスクの実行時に使うユーザーアカウント」は、ログオンしているユーザー(管理者)にする。

画像12

スポンサーリンク

画像13:MouseClickTest_Kicker_Kicker_VerVbsのタスクの設定。画像13のように操作の編集を行う。

画像13

備考

・ファイル2(MouseClickTest_Kicker.vbs)で、次の画像の箇所が存在しないと上手く動作しない。この処理はExcelをアクティブにし、前面に表示する処理である。


'WScript.CreateObject("WScript.Shell").AppActivate ObjExcelApp.Caption
Dim ObjWSH
Set ObjWSH = WScript.CreateObject("WScript.Shell")
ObjWSH.AppActivate ObjExcelApp.Caption

・ファイル2のように、Visible処理とWorkbooks.Openの間に、最前面に表示する処理を書かないと上手く動作しない。※マクロを実行した後に、最前面に表示する処理を入れると上手く動作しない。

・VBA側で前面表示する処理を行っても上手く行かない。

・次のコードのように、前面表示を関数化しておけば「BrigToFront Obj01」のように使える。


Sub BringToFront(ByVal Obj)
   On Error Resume Next
   WScript.CreateObject("WScript.Shell").AppActivate Obj.Caption
   On Error Goto 0
   Set obj = Nothing
End Sub

参考

Shell 関数 (Visual Basic for Applications)

最後までお付き合いいただきありがとうございます!

この情報が誰かの役にたてれば幸いです。

スポンサーリンク

-その他