タスクの情報を取得するコマンドレットが " Get-ScheduledTask " なら、タスクを実行するコマンドレットは " Start-ScheduledTask " です。
今年も残すところあと一ヶ月となりましたので、IP アドレスと MAC アドレスを紐付ける「ARP テーブル」に、手動でエントリを追加する方法を整理してみました。
どれも CUI です。
少なくとも Windows の機能としては、GUI で行う方法は無いようです。
◆ ARP コマンド
" ARP -s [宛先 IP アドレス] [宛先 MAC アドレス] [登録する NIC の IP アドレス] "
おそらくもっとも古くからある手法ではないでしょうか。
Windows XP SP3 でも、Windows 8.1 Update1 でも使用できることを確認しています。
三つ目のオプション [登録する NIC の IP アドレス] は必須ではありませんが、NIC が複数あるコンピューターでは、このオプションで指定してやらないとどの NIC に登録されるかわかりません。
(どうやら、ipconfig コマンドで一番上に表示される NIC に登録されるようなのですが、確証はありません。)
なお、このコマンドにより設定したエントリは OS をシャットダウンすることで揮発してしまいます。
エントリを恒久的に使用したい場合は、 スタートアップスクリプトとしてOS 起動時に実行する等の方法があります。
◆ netsh コマンド
" netsh interface ipv4 add neighbors [登録する NIC 名] [宛先 IP アドレス] [宛先 MAC アドレス] "
netsh コマンド自体は Windows XP にもありますが、こうやって APR エントリを追加することができるのは Windows Vista 以降です。
[登録する NIC 名] というのは、ipconfig を実行した時に「イーサネット アダプタ XXX:」として表示される「XXX」の部分です。
「ローカル エリア接続」のようにスペースを含んでいる場合は、ダブルクォーテーション記号「"」で前後を括ります。
arp コマンドと最も違うのは、デフォルトでは OS シャットダウン時に揮発しない点でしょう。
あえて揮発させたい場合は、" sotre=active " というオプションを付与します。
◆ New-NetNeighbor コマンドレット
" New-NetNeighbor -InterfaceAlias [登録する NIC 名] -IPAddress [宛先 IP アドレス] -LinkLayerAddress [宛先 MAC アドレス(ハイフン無し)] "
これだけコマンドではなく PowerShell です。
Windows 8 や Windows Server 2012 以降で使えるようになった、「NetTCPIP」モジュールに含まれています。
前述の二つのコマンドと違って、MAC アドレスを二桁ずつハイフン記号「-」で区切ってはいけません。
デフォルトでは OS シャットダウン時に揮発ないので、あえて揮発させたい場合は、" -PolicySotre ActiveStore " というオプションを付与します。
特定の曜日に実行されるタスクの情報を PowerShell で確認すると、[DaysOfWeek]というプロパティにその曜日が表示されます。
確認のために実行するコマンドレットは " ((Get-ScheduledTask -TaskName ***).Triggers).DaysOfWeek " です。
コマンドレット全体を括弧記号 " () " で括ることにより、そのコマンドレットの実行結果を持つ「オブジェクト」として扱えるようになります。
そして括弧記号の後ろに " .プロパティ名 " を続けて記述することで、そのオブジェクトに含まれる各種プロパティの中から、指定したプロパティの情報だけを抜き出して表示できます。
上記コマンドレットは、それを二重で行っているわけです。
まず、タスク名を指定して特定タスクの情報を取得し、その中からプロパティ [Triggers] の情報を取得し、さらにその中からプロパティ [DaysOfWeek] の情報を取得しているわけです。
タスクスケジューラに登録されているタスクの情報を確認したい場合、普通に " Get-ScheduledTask -TaskName *** " コマンドレットを実行するだけでは、 [Actions] 、[Principal] 、[Triggers] といったプロパティの詳細は確認できません。
どうやらこれらは、単なるタスクのプロパティの一項目ではなく、これら自身がプロパティを持つオブジェクトのようです。
(↑技術的に正しい表現なのか、いまいち自信がありませんが。)
そこで、「これらのプロパティの、さらにプロパティを表示する」という方法を試してみることとします。
決して複雑な手順を踏むわけではありません。
たとえば " (Get-ScheduledTask -TaskName task).Actions " を実行すると、
[Execute] に powershell.exe が、
[Arguments] に E:¥script.ps1 が表示されます。
それぞれ、タスクケジューラでタスクを作成する際に入力したプログラムと引数に該当します。
管理ツール「タスクスケジューラ」(taskschd.msc)を PowerShell で操作するためには、モジュール「ScheduledTasks」のコマンドレットを使用します。
なお、このモジュールは、 Windows Server 2012 や Windows 8 以降の OS でしか使えません。
同じ PowerShell 3.0 を Windows Server 2008、Windows Server 2008 R2 、Windows 7 にインストールしてみましたが、使えませんでした。
PowerShell において、なんらかの設定情報を取得するためには " Get-***** " というコマンドレットを打つのが常道ですから、とりあえず " Get-ScheduledTask " を実行してみます。
すると、タスクの一覧を取得できました。
コマンドプロンプトで " SCHTASKS /Query " コマンドを実行した場合と似ています。
(PowerShell もコマンドプロンプトも、「管理者として実行」していない場合、アクセス権が及ばないタスクの情報は取得できません。)
Windows Server に PowerShell 1.0 が登場したのが、Windows Server 2008 でした。
デフォルトで搭載されてはいましたが、サーバーマネージャーの「機能の追加」でインストールする必要がありました。
(Windows Vista の場合は、KB928439 をインストールします。)
その後、Windows Server 2008 R2 や Windows 7 では、バージョンアップした PowerShell 2.0 が、最初から使えるようになりました。
そして Windows Server 2012 や Windows 8 では PowerShell 3.0 になりました。
この PowerShell 3.0 を、Windows Server 2008 にインストールできるということを今日初めて知りました。
(Windows Server 2008 R2 と同じ PowerShell 2.0 をインストールできることは知っていたのですが。)
あらかじめ Service Pack 2 を適用しておく必要があり、.NET Framework など複数のコンポーネントをインストールする必要がありますが、Installing Windows PowerShell に手順がまとめられています。
さっそくインストールしてみたのですが、決して Windows Server 2012 と全く同じように使えるわけではないようです。
コマンドレットやモジュールの数にだいぶ差があるようなので、両 OS で比較してみました。
※ OS インストール後、「役割」を何も追加していない素の状態です。
まず powershell.exe を起動。
起動した時点で読み込まれているモジュールを比較するため、" Get-Module " を実行。
Windows Server 2008 ---> Microsoft.PowerShell.Management
Windows Server 2012 ----> Microsoft.PowerShell.Management
どちらも一つだけであり、差はありません。
(コマンドプロンプト上で powershell.exe を実行している状態では、どちらもゼロです。)
次に、get-command で利用可能なコマンドレット数を比較します。
実行結果の行数をカウントするために、" (Get-Command).length " を実行。
Windows Server 2008 ---> 349
Windows Server 2012 ---> 1160
なんと、三倍以上の差があります。
同様にして、利用可能なモジュール数を比較します。
" (Get-Module -listAvailable).length " を実行。
Windows Server 2008 ---> 13
Windows Server 2012 ---> 55
こちらは四倍以上の差です。
最後に、利用可能なモジュールを全て読み込んだ状態でコマンドレット数を比較します。
" Get-Module -listAvailable | import-module " を実行してから " (Get-Command).length " を実行。
Windows Server 2008 ---> 349
Windows Server 2012 ---> 1170
読み込む前と大差ありません。
というわけで、Windows Server 2012 と同等の処理は期待できません。
2013 年最後の投稿としては少々残念な内容になりますが・・・
2013年12月24日の記事に書いたスクリプトには、一つ問題があります。
「kijun.txt」・「hikakutaishou.txt」の、いずれかないし両方のテキストファイルの中身が一行だけだった場合、後半の「各行比較」工程において意図しない動作をしてしまうのです。
この問題を引き起こすのは、 " (Get-Content テキストファイル名)[行] " の部分です。
解説・後半 2/2 に書いた通り、この部分はテキストファイルの [$LN] 行目の文字列を抜き出すことが目的です。
しかし、一行しか無いテキストファイルに対してこれを行うと、[$LN] 文字目の一文字だけを抜き出してしまうのです。
これでは、両テキストファイルの内容が一致しているか否かを、正確に判定出来ません。
一行だけのテキストファイルに対し、その一行の文字列(つまりそのテキストファイル全体)を抜き出す場合は、対象行を指定する " [ ] " が不要となります。
適宜スクリプトを書き換えてご利用ください。
※ if 構文を使って、「$NoK」と「$NoH」のいずれかないし両方が「 1 」だった場合の条件分岐を行えばよいのですが、複雑になりそうなので止めておきます。
なお、このスクリプトが「PowerShell 2.0 以降」でしか動かないのは、配列演算子 " -join " が PowerShell 1.0 には無いためです。
" -join " を使わない形に書き換えれば、Windows Vista Enterprise ( Service Pack 2 ) の PowerShell 1.0 でも実行可能であることを確認済みです。
それでは私は年越し蕎麦を食べに行ってきます。
皆様も良いお年をお迎えください。
最後に、判定処理について解説します。
最初に、「 $K 」,「 $H 」という2つの変数を定義しています。
どちらも、その中身には " (Get-Content テキストファイル名)[行] " を格納しているのですが、これは一度テキストファイルの全文を読み込んでから、指定の行の文字列を抜き出すというものです。
これにより、基準となる「kijun.txt の $LN 行目」と、比較対象となる「hikakutaishou.txt の $LN 行目」の文字列を抜き出すことができます。
次はそれらが一致しているか否かを判定するのですが、判定自体は、前半でも使った比較演算子 " -eq " を使えば簡単です。
両文字列が完全に同じものであれば「True」、少しでも違えば「False」という実行結果になります。
各行の実行結果を、そのまんま一行ずつ「kekka.txt」に出力しても良いのですが、何行目が「True」で何行目が「False」なのかが分かりやすいよう、一工夫します。
実行結果がどちらであれ、まずそれを「 $C 」という変数に格納します。
次に、判定対象行を示す変数「 $LN 」に、+1 し、新たな変数「 $LN2 」に格納します。
※ +1 するのは、PowerShell 上で「ゼロ」から始まる行数を、人間にも分かりやすい「1」から始まる行数に直すためです。
最後に、$LN2 と $C を連結して一続きの文字列にします。
こうすれば、何行目が「True (あるいは False ) 」なのかが分かりやすく出力されます。
しかし、連結には注意が必要です。前半でやったように、単純に「+」で並べる事は出来ません。
それをしてしまうと、「True = 1」、「False = 0」と見做して足し算が行われてしまいます。
このような場合は、" -join " という配列演算子を用いて連結ます。
先に「 $R 」という変数を定義し、 $LN2 と $C を「カンマ区切り」で格納します。
これだけだと、$R の中身は「改行された二行のテキスト」になってしまうのですが、次に $R -join " : " を実行することで「コロンによって連結された一行のテキスト」に変換できます。
それを「kekka.txt」に出力することで、「何行目が一致していて、何行目が不一致なのか」が分かるようになります。
以上で、2013年12月24日の記事に書いたスクリプトの解説は終了です。
が、しかし・・・・
ちょっと書き足りないことがあるので補足編に続きます。
引き続き、スクリプト後半の「各行比較」、つまり両テキストファイルの中身を一行ずつ突き合わせて一致 or 不一致を判定する工程について解説します。
後半のスクリプトは、全体が While 構文によって構成されています。
While 構文は何らかの処理を繰り返し実行させたい場合に便利で、CSV 形式で記述された一覧表を元にドメインユーザーを作成する際にも利用しました。
まずは全体の流れから説明します。
PowerShell において先頭の行は「ゼロ」行目として扱われるため、一致/不一致を判定する処理も、最初は「ゼロ」行目を対象にしてスタートします。
そしてその行についての確認が完了したら、次はその「+1」行目に対して同じ処理を行います。
その繰り返しを、基準となるテキストファイル「kijun.txt」の最後の行まで繰り返します。
こういった処理を、While 構文で記述すると以下のようになります。
まず最初の " $LN = 0 " により、処理対象の行を示す「変数 $LN 」に、数値「ゼロ」を格納します。
お次は条件定義です。" while ($LN -le $NoK-1) " は、行の値が「 $NoK-1 」以下であれば処理を続行し、超えたら終了することを意味します。
変数 $NoK 自体は、基準となる「kijun.txt」の全行数を示す変数として前半で定義済みですが、一行目が「ゼロ」としてスタートするため、最終行は「全行数 -1」となります。
-1 が無いと、一回余計に処理が行われてしまうので注意が必要です。
※ 比較演算子として " -le " (以下) ではなく " -lt " (未満) を用い、 " while ($LN -lt $NoK) " と記述しても同じことです。
この条件定義に続く、{ } で括られた部分に、実際に繰り返したい処理が記述されています。
その最後にある " $LN++ " は、変数 $LN に格納された数値に +1 するための記述です。
これにより、次回は「次の行」に対して同様の処理が行われる事となります。
" $LN++ " より前の部分こそが、このスクリプトのキモとなる「判定処理」なのですが、この部分についてはまた次回詳述します。
後半 2/2 へ続く。
前回ご紹介したスクリプトは前半の「総行数比較」と後半の「各行比較」に分かれており、今回は前半を解説します。
まず、「$NoK」と「$NoH」という二つの変数を定義しています。
これらが各テキストファイルの行数を表すのですが、そのためにコマンドレットを二つ使っています。
Get-Content コマンドレットでテキストファイルの全文を読み込み、それをパイプで Mesure-Object コマンドレットに渡す仕組みです。
Mesure-Object というのは統計情報を算出してくれるコマンドレットで、実行結果の「Count」というプロパティにはテキストの行数が出ます。
(その他、得点表のような CSV ファイルを読み込ませて、平均値を出すことなどが可能です。)
Get-Content から始まるコマンドレットの全体を「 ( ) 」で括り、最後に 「.Count」 を付ける事により、実行結果から「Count」というプロパティだけを得ることが出来ます。
その結果として、「$NoK」には「5」、「$NoH」には「4」という値が格納されます。
この二つの変数が一致するか否かを、比較演算子「-eq」により判定します。
今回のケースでは一致しないので実行結果は「False」となりますが、一致すれば「True」となります。
最後に各テキストファイルの行数を出力するのですが、値だけが出力されても分かりにくいので、「基準」「比較対象」といったタイトルと、「行」という単位を付加します。
文字列を連結する場合は、「 " " 」で括って「 + 」で繋げます。
なお、文字列と数値を連結する場合、数値の方は「 " " 」で括らなくてもいいようです。
(ただし、数値と数値を「 + 」で繋げた場合は、足し算が行われるので注意が必要です。)
後半へ続く。