[Tips]一定時間経過後にスクリプトを実行する

PowerShellで一定時間経過した後にスクリプトを実行させたくて、下記のような関数を作ってみました。

function Execute-Script([int]$Time, [ScriptBlock]$ScriptBlock, [String]$ComputerName = ".")
{
    [System.Threading.Thread]::Sleep($Time)
    Invoke-Command -ComputerName $ComputerName -ScriptBlock $ScriptBlock
}

この関数を使用する際の書式は

Execute-Script スクリプトを実行させるまでの待機時間(mSec), 実行させるスクリプト, [スクリプトを実行するリモートコンピュータ名]

です。

[スクリプトを実行するリモートコンピュータ名]は省略可能で、省略した場合にはローカルコンピュータでスクリプトを実行します。

関数の中身ですが、一定時間待機するのにSleepメソッドを使用しています。

Sleepメソッドの引数には、待機する時間を単位:mSecで指定します。1秒なら1000ということです。

そしてスクリプトの実行はInvoke-Commandを使用しています。このコマンドレットにより、リモートコンピュータ上でもスクリプトを実行させることが可能です。

Invoke-Commandの使い方はWindows PowerShell によるリモート制御 ~その3 永続的なセッション編 ~ を参照ください。

 

実際の使用例を下記に示します。これは3秒経過したらローカルコンピューター上でGet-Dateコマンドレットを実行します。

PS> Execute-Script 3000 {Get-Date}

次のコマンドは、3秒後にリモートコンピューターMyServ01でGet-Dateコマンドレットを実行します。

PS> Execute-Script 3000 {Get-Date} MyServ01

[Tips]エクスプローラの新規作成メニューからPowerShellのスクリプトファイルを作成するには?

この記事には、レジストリ操作が含まれます。
必ず自己責任のもとで行ってください。
PowerShell from Japan!!ではいかなる責任も負わないものとします。


では本題です。

今回は、エクスプローラの新規作成メニューにPowerShellのスクリプトファイルを新規作成する項目を追加してみたいと思います。

本記事で紹介するコマンドを実行すると、下記のようになります(クリックで拡大します)。

エクスプローラの新規作成メニューに項目を追加するには

レジストリの、HKEY_CLASSES_ROOT にある拡張子にShellNewというキーを作成し、名前が”NullFile”でデータが空の値を作成します。

PowerShellのスクリプトファイル(ps1)を新規作成できるようにするには

HKEY_CLASSES_ROOT\.ps1\ShellNew

というキーを作成し、名前が”NullFile”でデータが空の値を作成します。


はじめに、[Tips]HKEY_CLASSES_ROOTを操作するには? の記事を参照して、HKEY_CLASSES_ROOTをHKCR:としてアクセスできるようにしてください。

次に、パス HKCR:.ps1 に、ShellNew を作成します

PS> New-Item -Path HKCR:\.ps1\ShellNew

最後に、名前が”NullFile”でデータが空の値を作成します。

PS> New-ItemProperty -Path HKCR:\.ps1\ShellNew -Name "NullFile"

これで、次回エクスプローラを起動したときから、新規作成メニューに「Windows PowerShellスクリプト」が追加されます。

[Tips]HKEY_CLASSES_ROOTを操作するには?

通常PowerShellで操作できるレジストリは、HKEY_CURRENT_USER と HKEY_LOCAL_MACHINE です。

HKEY_CURRENT_USERはHKCU、HKEY_LOCAL_MACHINEはHKLMとしてあらかじめ登録されており

PS> cd HKCU:

PS>cd HKLM:

などとしてアクセスできます。

しかし、HKEY_CLASSES_ROOTは登録されていないので、

PS> cd HKCR:

のようにしてアクセスすることができません。

これを実現するために下記コマンドでPowerShell ドライブとして登録します。

PS>New-PSDrive -Name HKCR -PSProvider Registry -Root HKEY_CLASSES_ROOT

上のコマンドは HKEY_CLASSES_ROOT を HKCRとして扱えるように、New-PSDriveコマンドレットを使用しWindows PowerShell ドライブとして登録しています。

登録が完了すれば、下記のように HKEY_CLASSES_ROOT にアクセスすることが可能になります。

PS C:\Work> cd HKCR:
PS HKCR:\> ls


    Hive: HKEY_CLASSES_ROOT


SKC  VC Name                           Property
---  -- ----                           --------
  3   4 *                              {QuickTip, InfoTip, AlwaysShowExt, TileInfo}
  0   1 .$aw                           {(default)}
  0   1 .$bw                           {(default)}
  0   1 .$fw                           {(default)}
  0   1 .$sw                           {(default)}
  0   1 .$td                           {(default)}
  0   1 .$tdc                          {(default)}
  0   1 .$tdr                          {(default)}
:
:

Windows PowerShell でのバックグラウンドジョブ ~ その4 親ジョブと子ジョブ~

PowerShellで実行されるジョブには親子関係があります。

今回は

について説明します



親ジョブと子ジョブの確認

親子関係を確認する為に 、最初に次のコマンドを実行してみます。

このコマンドはローカルコンピュータとリモートコンピュータMyServ01に対し、Get-Serviceコマンドレットを実行します。

PS> $job = Invoke-Command localhost, MyServ01 -Command {Get-Service} -AsJob

この時点で次のようにGet-Jobコマンドレットを実行すると、1つのジョブが返されます。

1つのジョブでlocalhostとMyServ01に対して、コマンドが実行されていることがわかります。

PS> Get-Job
Id Name State HasMoreData Location Command
-- ---- ----- ----------- -------- -------
1 Job1 Completed True localhost,MyServ01 Get-Service

次に、下記のようにGet-Jobコマンドレットを使用して、もう少し詳しい情報を見てみましょう。(この確認方法はヘルプに載っています)

PS> Get-Job | Format-List -Property Name, ChildJobs 
Name      : Job1
ChildJobs : {Job2, Job3}

実行結果を見るとNameにJob1が、ChildJobsにJob2とJob3が記述されています。

これは、実際のジョブはJob2とJob3で実行されており、親ジョブであるJob1の管理下にあることを示しています。

次のように入力すれば、各子ジョブについて確認することができます。

PS> Get-Job Job2, Job3

Id              Name            State      HasMoreData     Location             Command
-- ---- ----- ----------- -------- -------
2 Job2 Completed True localhost Get-Service
3 Job3 Completed True MyServ01 Get-Service

 


子ジョブの管理

ジョブの親子関係がわかると、特定の子ジョブの実行結果を取得することが可能になります。

たとえば、先ほどの子ジョブであるJob2の実行結果を取得するのであれば

PS> Receive-Job -Id 2 -Keep

のように子ジョブのIDを指定することができます。

また、子ジョブは親ジョブに管理されていることから、次のようにRemeve-Jobコマンドレットを使用して親ジョブを削除すると、ぶら下がっているすべての子ジョブも削除されますので覚えておきましょう。

PS> Remove-Job -Id 1

Windows PowerShell でのバックグラウンドジョブ ~ その3 リモートコンピュータでのバックグラウンドジョブ~

これまでの記事

では、ローカルコンピュータにおけるバックグラウンドジョブについて説明しました。

今回は

について説明します。



対話型セッションでのバックグラウンドジョブ

PowerShellにおける対話型セッションでも、バックグラウンドジョブを実行することができます。

対話型セッションの方法については、Windows PowerShell によるリモート制御 ~その1 準備編~ を参照ください。

まずは、リモートコンピュータ(ここでは例として MyServ01 とします)に対話型接続をします。

PS> Enter-PSSesion MyServ01
[MyServ01]: PS C:\Work>

あとは、Start-Jobコマンドレットを使用すれば、対話型セッションの中でもローカルコンピュータ同様にバックグラウンドジョブを実行できます。

[MyServ01]: PS C:\Work> $job = Start-Job -ScriptBlock { Get-Service }

Start-Jobコマンドレットの使用方法については

Windows PowerShell でのバックグラウンドジョブ ~ その1 ローカルコンピュータでのバックグラウンドジョブ~

を参照ください。


永続的なセッションでのバックグラウンドジョブ

今度は、対話型セッションではなく、永続的なセッションでのバックグラウンドジョブについてです。

永続的なセッションについては、Windows PowerShell によるリモート制御 ~その3 永続的なセッション編 ~ を参照ください。

 

まずは、New-PSSessionコマンドレットでリモートコンピュータへのセッションを作成します。

PS >$sess = New-PSSession -ComputerName MyServ01

作成したセッションを使用してバックグラウンドジョブを実行するにはInvoke-Commandコマンドレットと-AsJobパラメータを使用します。

PS C:\Work>Invoke-Command -Session $sess -ScriptBlock { Get-Service } -AsJob

Id              Name            State      HasMoreData     Location             Command
--              ----            -----      -----------     --------             -------
1               Job1            Running    True            htaka2                Get-Service

たったこれだけで、リモートコンピュータでもバックグラウンドジョブを実行することができます。


参考記事

リモート制御については、下記の記事を参照ください

  • Windows PowerShell によるリモート制御 ~その1 準備編~
  • Windows PowerShell によるリモート制御 ~その2 セッション編(基礎)~
  • Windows PowerShell によるリモート制御 ~その3 永続的なセッション編 ~
  • Windows PowerShell によるリモート制御 ~その4 複数セッションの作成と使用 ~
  • Windows PowerShell によるリモート制御 ~その5 ComputerNameパラメータを持つコマンドレット ~