tech.guitarrapc.cóm

Technical updates

PowerShellの出力内容をバッチで受け取る

多くの方は、PowerShellを直接起動させるのではなくバッチから.ps1スクリプトを起動させているかなと思います。 ご存じの通り、PowerShellにはGet-Dateコマンドレットを利用することでVBSなどより自在に任意の日付を取得できます。 うまく利用すれば、バッチ単独ではうん十行書くような任意の日付取得が楽になります。 先日、ちょっとバッチでPowerShellなどを各種コマンドを順次呼び出して、SQLにPowerShellで取得した日付を渡す処理が必要になりました。 Perlで日付を取得するとかふざけたことになっていたのでツイつぶそうかと(白目) 機会が無くて知らなかったのですが……PowerShell出力結果ってバッチにナカナカ渡せないんですね…… 結局使ったのは原始的なやり方ですが、一例になれば幸いです。

PowerShellの出力結果をバッチで読み込む

たとえば、以下のPowerShellで昨日を取得します。 このGet_Yesterday.ps1をバッチから呼び出し、出力結果をバッチで環境変数にセットすることで、日付を別のコマンドに渡したい…。 以下の3つのパターンを紹介します。
1. PowerShell出力結果をテキストにはき出してバッチで読み込み環境変数へ 2. 出力ごとにPowerShellを分けて、それぞれを環境変数としてバッチでセット 3. PowerShell動作時にスイッチを与えて環境変数としてバッチでセット
どう考えても3しかありえないのですが……参考程度に…

PowerShell出力結果をテキストにはき出してバッチで読み込み環境変数へ

#ファイル名 : Get_Yesterday.ps1

# Get Yesterday
$date = (Get-Date).AddDays(-1)

# Get YYMM
$yyyymm=[string]$date.Year + [string]$date.Month
$yyyymm | Out-File -Encoding default -FilePath .\yyyymm.txt

# Get YYMMDD
$yyyymmdd=$yyyymm + [string]($date.Day)
$yyyymmdd | Out-File -Encoding default -FilePath .\yyyymmdd.txt
初めは、PoerShell標準出力をバッチに渡すのにユーザー環境変数や%ERRORLEVEL%などを探ったのですが当然だめな訳で。 結局PowerShellの出力をファイルに書き出して、Batでファイルを読み込んじゃいました……
powershell .\powershell\Get_Yesterday.ps1
FOR /F %%a IN (YYYYMMDD.txt) DO SET YYYYMMDD=%%a
FOR /F %%a IN (YYYYMM.txt) DO SET YYYYMM=%%a
これで、%YYYYMMDD%や%YYYYMM%で取得出来ます。 少しでも参考になればいいのですが……  

出力ごとにPowershellを分けて、それぞれを環境変数としてバッチでセット

[2012/Dec/19 PM17:00 :追記] 一晩寝たらコレでもかなーと思いますが、出力に応じてPowerShellを分けなきゃいけないっぽい? ※Function化して、paramなどで指定すれば分けなくてもいいです。ただ、単純化させたかったので後はご自由に
#ファイル名 : Get_Yesterday1.ps1

# Get Yesterday
$date = (Get-Date).AddDays(-1)

# Get YYMM
$yyyymm=[string]
$date.Year + [string]$date.Month
$yyyymm
#ファイル名 : Get_Yesterday2.ps1

# Get Yesterday
$date = (Get-Date).AddDays(-1)

# Get YYMMDD
$yyyymmdd=$yyyymm + [string]($date.Day)
$yyyymmdd
後は、バッチでFOR /FにてPowerShell実行、結果を環境変数で受け取る……と。 これならPowerShellでファイル出力は不要になります。
FOR /F "usebackq" %%a IN (`powershell .\powershell\Get_Yesterday1.ps1`) DO SET YYYYMM=%%a
ECHO %YYYYMM%

FOR /F "usebackq" %%a IN (`powershell .\powershell\Get_Yesterday2.ps1`) DO SET YYYYMMDD=%%a
ECHO %YYYYMMDD%
(単純に2つPowerShellで標準出力すると、DO SETで同じ%%aに入ってしまうので.ps1を分けました……%%bに入ればよかったのですが……あれー?)  

PowerShell動作時にスイッチを与えて環境変数としてバッチでセット

[2012/Dec/19 PM18:00 :追記] スクリプト動作時にswitchを与えて、FunctionでYYYYMMDDとYYYYMMのいずれかを選択出来るようにしました。 一時ファイルも利用しないし、.ps1読み込み時のスイッチを変えるだけです。 これでとりあえずやりたいことはできましたね。
#ファイル名 : Get_Yesterday.ps1
#Powershell 2.0

#Select switch for YYYYMMDD or YYYYMM
param(
     [switch]$YYYYMM ,
     [switch]$YYYYMMDD
     )

function Get-YYYYMMDD{

    param
    (
        [string]$dateformat
    )

    # Get Yesterday
    $date = (Get-Date).AddDays(-1)

    switch ($dateformat)
    {
    "YYYYMM"
        {
            # Get YYYYMM date format
            $yyyymm=[string]$date.Year + [string]$date.Month
            return $yyyymm
        }
    "YYYYMMDD"
        {
            # Get YYYYMMDD date format
            $yyyymmdd = [string]$date.Year + [string]$date.Month + [string]($date.Day)
            return $yyyymmdd
        }
    default
        {
            throw "Input -dateformat YYYYMM or -dateforamt YYYYMMDD"
        }
    }
}

if ($yyyymm){Get-YYYYMMDD -dateformat YYYYMM}
if ($yyyymmdd){Get-YYYYMMDD -dateformat YYYYMMDD}
バッチでは、コマンド実行時にスイッチを選択するだけです。 少しは使い易くなったかと。
FOR /F "usebackq" %%a IN (`powershell .\powershell\Get_Yesterday.ps1 -YYYYMMDD`) DO @SET YYYYMMDD=%%a
FOR /F "usebackq" %%a IN (`powershell .\powershell\Get_Yesterday.ps1 -YYYYMM`) DO @SET YYYYMM=%%a