音速のエンジニア

やったことを音速で忘れてしまう?とあるエンジニアの備忘録

タスクスケジューラでプログラムを自動実行する(トラブル事例②)

引き続き、タスクスケジューラでプログラムを自動実行する方法。

前回は「作業フォルダ」に関するトラブル事例を紹介しました。

onsoku-engineer.hatenablog.com

今回もトラブル事例のお話(二回目)。

自動実行するプログラムについて

自動実行するプログラムは、所謂ファイル転送系のツールで

指定したフォルダ内にあるファイルを、階層構造を保ちながら指定先のフォルダにコピーする的なやつです。

タスクを作成してテスト実行

前回、前々回の手順を参考に、タスクを作成します。
作成が完了したら、正常に動作するかテスト実行します。

f:id:suz1955wb:20200629003912j:plain:w300

トリガー:
毎日、00:00

プログラム/スクリプト:
C:\Users\XXXXX\Documents\Hatena\hoge.exe

開始(オプション):
C:\Users\XXXXX\Documents\Hatena

セキュリティオプション:
☑ユーザーがログオンしているかどうかにかかわらず実行する

指定したフォルダ内にあるファイルを、夜な夜なNASにバックアップさせます。

NASは、ネットワークドライブとして「Z:\」にマウント済み。

今回このタスクを実行するPCには、複数のユーザーアカウントがあり、「いつ」「どのユーザー」がログオンしているか分かりませんので、セキュリティオプションのユーザーがログオンしているかどうかにかかわらず実行するにチェックを入れています。

尚、デフォルトはユーザーがログオンしているときのみ実行するです。

この設定が問題を引き起こすことになろうとは、、、この時点では知る由もない。。。

さて、今回は何がアカンのか、、、

前回の失敗を踏まえて、作業フォルダはちゃんと指定しています。

ファイルの「コピー元」「コピー先」も正しく指定出来ているのに、コピーに失敗してしまいます。

試したこと

前回同様、適当にログ仕込んで、色々試してみる。

  1. プログラムを直接実行
  2. タスクスケジューラからテスト実行
  3. タスクスケジューラから自動実行

またしても期待通り動いたのは「1」だけ。

やはりタスクスケジューラが絡むと期待通り動かない。

コピー先の「Z:\」が無いと言われる。

いや、ちゃんとあるし。

上述した通り、今回はセットアップするPCの都合でセキュリティオプションを変更しているので、これを疑ってみる。

  1. ユーザーがログオンしているときのみ実行でテスト実行
  2. ユーザーがログオンしてるかどうかにかかわらず実行でテスト実行

お、「1」はうまくいったぞ。「2」は相変わらずアカン。

セキュリティオプションで挙動が変わっているのは確定。

しかし何故コピー先の「Z:\」が見えないんだ...?

ネットワークドライブさん、恥ずかしがらないで

原因を調べてみて分かったこと、ネットワークドライブはログオンしているユーザープロファイル毎に作成されるもので、PC全体に作成されるものではないということ。ユーザーがログオンしているかどうかにかかわらず実行するの場合、ネットワークドライブは無効になるそう。

もう、恥ずかしがりやさんっ。。。

そうと分かれば対策や

まず一つは、ネットワークドライブの代わりに「ネットワーク絶対パスを使用する」という方法。

Z:\XXXXXではなく\\192.168.XXX.XXX\XXXXXね。

どうしてもネットワークドライブを使用する場合は、タスク実行時にネットワークドライブ接続する必要がありそうだ。

プログラムに書いてもよし、バッチファイルに書いてもよし。

例えば、こんなバッチファイル。

net use Z:\ \\192.168.XXX.XXX\XXXXX
cd C:\Users\XXXXX\Documents\Hatena
hoge.exe
  1. net useコマンドで、Z:\にネットワークドライブ接続

  2. カレントディレクトリをC:\Users\XXXXX\Documents\Hatenaへ移動

  3. hoge.exeを実行

という流れだ。

ほいで、タスクスケジューラには、このバッチファイルを指定実行するようにする。

f:id:suz1955wb:20200629003916j:plain:w300

ほな、タスクを作成してテスト実行

バッチファイルでネットワークドライブ接続する方法で、「1~3」全て期待通り動きました!ふぅ(汗

  1. プログラムを直接実行
  2. タスクスケジューラからテスト実行
  3. タスクスケジューラから自動実行

まとめ

  • タスクスケジューラから実行するプログラムでネットワークドライブを使用する場合、セキュリティオプションのユーザーがログオンしているかどうかにかかわらず実行するにチェックを入れていると、期待通り動かない。

    (ネットワークドライブはログオンしているユーザープロファイル毎に作成されるため)

  • その場合、ネットワークドライブの代わりに、ネットワーク絶対パスを使用する。

  • どうしてもネットワークドライブを使用する場合は、タスク実行時にネットワークドライブに接続するような仕組みを入れる。

タスクスケジューラ、もう卒業しよう。

タスクスケジューラでプログラムを自動実行する(トラブル事例①)

前回、タスクスケジューラでプログラムを自動実行する方法を紹介しました。

onsoku-engineer.hatenablog.com

今回は、そんなタスクスケジューラ絡みのトラブルのお話。

自動実行するプログラムについて

自動実行するプログラムは、自作した物で

  • 実行ファイル(exe)
  • 設定ファイル(ini)

の組み合わせになっており、
プログラム実行時に実行ファイル(exe)と同じ階層にある設定ファイル(ini)を読み込んでから
動作するようになっています。

タスクを作成してテスト実行

前回の手順を参考に、タスクを作成します。
作成が完了したら、正常に動作するかテスト実行します。

プログラム/スクリプト:
C:\Users\XXXXX\Documents\Hatena\hoge.exe

なんか動かない、、、

なんだろう、なんか変。
プログラムは実行されるんだけど、肝心の処理が動いてないように見える。

起動は出来るのに動かない、、、ナニソレ汗

試したこと

自作のプログラムだし、適当にログ仕込んで、色々試してみる。

  1. プログラムを直接実行
  2. タスクスケジューラからテスト実行
  3. タスクスケジューラから自動実行

期待通り動いたのは「1」だけ。いやまぁ、そりゃ「1」は動くでしょ。そもそも。
タスクスケジューラが絡むと期待通り動かない、、、
うーん、起動はするんだよな。設定ファイル(ini)が読み込めてないとか?

ズズーっ(珈琲飲む音)。。。

カレントディレクトリ!お前か!!

仕込んだログから、設定ファイル(ini)が読み込めていないのは確定。
設定が無いので肝心の処理が行えずにエラー終了。

では、何故設定ファイル(ini)が読み込めていないのか?

プログラム実行時に実行ファイル(exe)と同じ階層にある設定ファイル(ini)を読み込んでから、動作するようになっています。

ここです、タスクスケジューラが絡むと期待通り動かない理由。

カレントディレクトリ!

作業場所、作業フォルダのことですね。

タスクスケジューラから実行したプログラムの作業フォルダは、デフォルトで「Windowsのシステムフォルダ」になるみたいです。

設定ファイル(ini)は、実行ファイル(exe)と同階層にあるので、これでは読み込むことが出来ませんね、、、

実行方法 作業フォルダ
プログラムを直接実行 実行ファイルのあるフォルダ
C:\Users\XXXXX\Documents\Hatena
タスクスケジューラから実行 Windowsのシステムフォルダ
C:\Windows\System32

タスクスケジューラで実行するプログラムの作業フォルダを指定する

では、タスクスケジューラで実行するプログラムの作業フォルダを指定しましょう。

  1. 対象のタスクを選択 > ダブルクリック(または、右クリック > プロパティ) > プロパティを表示
    f:id:suz1955wb:20200412005248j:plain:w300
  2. 「操作」タブ > 開始するプログラムをリストから選択 > ダブルクリック(または、「編集」をクリック)
    f:id:suz1955wb:20200412232340j:plain:w300
  3. 「開始(オプション)」に、作業フォルダを入力
    f:id:suz1955wb:20200412232336j:plain:w300

編集が終わったら「OK」をクリックして画面を閉じます。

プログラム/スクリプト:
C:\Users\XXXXX\Documents\Hatena\hoge.exe

開始(オプション):
C:\Users\XXXXX\Documents\Hatena

タスクを作成してテスト実行(今度こそ)

さぁ、もう一度テスト実行してみましょう。

自分を信じて!

タスクスケジューラを信じて!!

どぉりゃぁぁぁ(・Д・)ノ

はいっ!「1~3」全て期待通り動きました!!

  1. プログラムを直接実行
  2. タスクスケジューラからテスト実行
  3. タスクスケジューラから自動実行

まとめ

  • タスクスケジューラでプログラムを実行するときは、「作業フォルダ」を指定する
  • 指定しない場合、「Windowsのシステムフォルダ」になる

続いてトラブル事例②へ。

タスクスケジューラって罠がいっぱい、、、

タスクスケジューラでプログラムを自動実行する

仕事をしていると

  • 毎日決まった時間に行う作業がある
  • 面倒くさい、自動化したい

そんなことありますよね?

、、、よね

Windowsに標準装備されているタスクスケジューラを使えば、指定した時間に特定のプラグラムを自動実行することが出来ます。

タスクスケジューラの起動

以下の手順で、タスクスケジューラを起動します。
(色々な方法がありますが、代表的な例で)

  • スタートメニュー > Windows管理ツール > タスクスケジューラ
  • スタートメニュー > Windowsシステムツール > コントロールパネル > システムとセキュリティ > 管理ツール > タスクスケジューラ

タスクの作成

画面左側から「タスクスケジューラライブラリ」を選択、続いて画面右側から「基本タスクの作成」、または「タスクの作成」を選択します。

f:id:suz1955wb:20200410004423j:plain:w300

両者の違いですが、

  • 基本タスクの作成
    →ウィザード形式でタスク作成をアシストしてくれる。

  • タスクの作成
    →詳細な条件まで指定できる中上級者向け。

といった感じでしょうか。

今回はまず「基本タスクの作成」でタスクの作成をしていきます。

  1. 「タスクの名前」を設定します。分かりやすい任意の名前を設定し、次へ進みます。
    f:id:suz1955wb:20200410004432j:plain:w300

  2. 「トリガー」を設定します。タスクを起動する「きっかけ」ですね。
    選択した内容に応じて次画面の内容が多少違います。今回は「毎日」を選択し、次へ進みます。
    f:id:suz1955wb:20200410004436j:plain:w300

    「開始日」と「開始時刻」を入力し、次へ進みます。
    f:id:suz1955wb:20200410004440j:plain:w300

  3. 実行する「操作」を設定します。今回は「プログラムの開始」を選択し、次へ進みます。
    f:id:suz1955wb:20200410004444j:plain:w300

    実行したいプログラムやスクリプトを入力、または参照先から選択します。
    今回は「参照」からC:\Windows\notepad.exeを選択し、次へ進みます。
    ってメモ帳かよ(笑)
    f:id:suz1955wb:20200410004447j:plain:w300

  4. 内容を確認しウィザードを「完了」します。
    f:id:suz1955wb:20200410004450j:plain:w300

作成したタスクのテスト実行

作成したタスクは、先ほど指定した「トリガー」の条件を満たしたときに実行されます。それまで実行されません。
そのため、作成したタスクが正常に動作するかどうか、予め確認しておくことをお勧めします。

  • 先ほど作成したタスクを選択 > 右クリック > 実行する
    f:id:suz1955wb:20200410004428j:plain:w300

ちゃんと動きましたか?

、、、メモ帳(笑)

まとめ

  • Windowsのタスクスケジューラを使うと、指定した時間に特定のプログラムを自動実行できる。
  • 作成したタスクが正常に動作するか、予め確認しておこう。

さて、そんなタスクスケジューラにまつわるトラブル事例を次回紹介していこうと思います。

続報、寝て待て!

シリアル通信でCOM10以上のポートを使用する

最近はあまり使う機会ないのですが、シリアル通信で指定するCOMポート、以前これで嵌ったことがありまして。

COMポートとは?

シリアル通信でデータ伝送を行うインターフェースのことですね。検索すればすぐに出てくると思います。

参考: COMポートとは | IT用語辞典 e-Words

ポートのオープンでエラーになる

シリアル通信をする際は、まずCOMポートのオープンを行うのですが、いきなりエラーになってしまう。

Win32APIのCreateFile()がINVALID_HANDLE_VALUEで返ってくる。

んー、ボードのマニュアルではCOM10を指定しろと書いてあるのだが、、、

HANDLE h = CreateFile("COM10", ... ); // h = INVALID_HANDLE_VALUE.

いろいろ調べていると、以下のような情報が出てきた!

COM10以上を指定する場合、書式が違う

はい、書き方が違うんですって。
MSDNにも書いてありました。

参考: COM10 以上のシリアル ポートを指定する方法 | MSDN

COM1〜COM9までは、"COM1"という書き方で問題ないのだが
COM10以上は、"\\.\COM10"という書き方になるそうです。

プログラムで書くときは、ちゃんとエスケープしてくださいね。

HANDLE h = CreateFile("\\\\.\\COM10", ... );

これで無事オープン出来ました!

尚、この書き方はCOM1~COM9でも有効ということだそうです。

まとめ

COM1〜COM9までは、"COM1"という書き方でOK。
COM10以上は、"\\.\COM10"という書き方になる。

最後に、、、

リファレンスはちゃんと読まないとですね、、、(汗

もうやめます。

会社のナレッジベースにノウハウを蓄積するのは、もうやめます

こんにちは。こんばんわ。はじめまして。

今更理由を解く必要もないと思いますが、会社のナレッジベースにノウハウを蓄積しても、会社を辞めたり現場を離れたりすれば何も残りません。

客先常駐の案件が多かった私は、案件が終了する度に業務用パソコンとノウハウを置き去りにしてきた気がします。

残りのエンジニア人生、自分のために自分の生きた証を残していこうと思います。


なーんて今更一念発起した中年エンジニアですが、どうぞお付き合いください。