2012年3月30日金曜日

◆出力を変数に代入しつつコンソールへ

以下のようなTipsを見かけたのでメモしておく。

通常、「出力結果を変数に代入しつつコンソールに出力する」というと「Tee-Object」を思い浮かべるのだが、

PS>ps | tee  -Variable  a

代わりにこんな感じでもよろしいのだと。

PS>($a = ps)

「へぇー」

 

共通パラメータ(OutVariable)でも。

PS>ps  -OutVariable  a

2012年3月22日木曜日

◆Active Directory 直属の部下たちのメールアドレスを取得

前回に引き続き、残業時間をチェックし警告メールを送信するスクリプトを作っている。

サブリーダーに「Cc」でメールすることにしたのだが、リーダーとサブリーダーの関係をどこに持つか・・・。
今のところ「上司」-「直属の部下」プロパティは使われていないので、簡便的にこのプロパティを使うこととした。
リーダーが上司、サブリーダー達がその部下という扱いだ。

「直属の部下」プロパティが見つかればなんてことはないと思ったのだが、そのプロパティが「属性エディタ」で見つからない。
実は、「上司」プロパティと「直属の部下」プロパティは一体管理されており、通常はメンバー側から見た「上司」プロパティとして表示されているようだ。

「直属の部下」プロパティを「属性エディタ」で表示するには、「フィルター」ボタンをクリックして「後方リンク」をチェックしてあげればよい。
image
image

プロパティを確認していくと、「直属の部下」は「directReports」だと判る。
image

直属の部下からメールアドレスを取得するのはこんな感じ。

001
002

(Get-ADUser hara_tatsunori -Properties DirectReports).DirectReports | 
 
%{Get-ADUser $_ -Properties mail} | select -expand mail

あとはこれをこのまま「Cc」に指定すればよい。

2012年3月21日水曜日

◆データによってパラメータの組合せを切り替える

残業時間をチェックして、しきい値を超えたらリーダーにメールを送るなんて処理を作っている。
サブリーダーが存在するグループには「Cc」でサブリーダーにも送信する。

データによって、「Cc」パラメータがあったりなかったりするので、それぞれのパターンのコマンドを用意しておけば良いのだが、「Bcc」も追加なんてことになるとパターンが増えて面倒だ。

こんな時はどうするのがベストなのでしょうね。

さしあたって(以前もどこかで使った気がするが)、分配演算子を使って以下のようにすることとした。

001
002
003
004
005
006
007

$names = "a*","c*",""

$names | %
{
 
$optParam =
 @{}
 
if($_){$optParam.name = $_
}
 
ps -ComputerName (hostname) @optParam | Out-String
}

image

2012年3月15日木曜日

◆パイプライン中の処理かどうかを判定する

以前、以下の記事で調査したのだが、同じ目的の記事が有ったので紹介しておく。

PowerShell: ◆パイプライン中の処理かどうかを判定する(挫折)

--

Pipeline Used Or Not? - Power Tips - Powershell.com Powershell Scripts, Tips and Resources

--

前回調査してからちょっと間が空いたのと、前回なんとなく紆余曲折していたのでもう一度確認。

結局のところ「$myinvocation.ExpectingInput」を使うのがベスト?

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018

function test {
 
[CmdletBinding(DefaultParameterSetName='NonPipeline')]
  param
(
   
[Parameter(ValueFromPipeline=$true)]
    $Data
  )
 
 
begin { $myinvocation.
ExpectingInput }

 
process {$myinvocation.
ExpectingInput}
 
 
end { $myinvocation.
ExpectingInput }
}


"パイプライン"
1,2 | test
"ダイレクト"
test 1,2

image

2012年3月9日金曜日

◆必ず確認メッセージを表示するコマンド(関数)を作る。(confirm)

自作の関数にて、「confirm」と「whtif」をサポートするためには以下の属性をつければ良さそうだ。

CmdletBinding(SupportsShouldProcess=$true)

 

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017

function CommandWithConfirm {
 
[CmdletBinding(SupportsShouldProcess=$true)]
  param
()

 
$mailAddr = "test1@hoge.co.jp","test2@hoge.co.jp"
 
 
foreach($addr in $mailAddr
)
  {
   
if ($PSCmdlet.ShouldProcess($addr, "メールを送信"
)) {
     
"$($addr)にメールを送信しました。"
    } else
 {
     
"$($addr)へのメール送信をバイパスしました。"
    }
  }
}


CommandWithConfirm -confirm

ここで、confirmを付け忘れるといきなり大量のメールを送信してしまうおそれがある。これを防ぐには必ず確認メッセージを表示するようにしておけば良い。

予めCmdletBindingにそういった機能が用意されていて、以下のようにすれば良い。

[CmdletBinding(SupportsShouldProcess=$true,ConfirmImpact="high")]

要はこの処理は非常に危険だよということで、”high”を指定するという事なのだろう。

2012年3月8日木曜日

◆メール送信をテストする

PowerShellから管理者宛にメールを送ることはよくある。

ある程度の人数に送ったりする場合は、変なメールを大量に送り付けないようテスト方法に気を遣う。

なにか良い方法は無いかと思うのだが、あまりコレといった方法が思いつかない。
とりあえず、関数を作って置き換える事とした。
(本来は関数自体が何らかのパラメータを受けて、実送信とテスト送信を切り替えれば良いのかもしれない)

<
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023

function Send-MailMessageTest
{
 
param($To,$Cc,$From,$Subject,$SmtpServer,$body,$Attachments,$Encoding
)

 
$mailArgs = $PSBoundParameters
  if(!$globalMailTo){Write-Host "GlobaMailTo not found" -f Red;return
}
 

$body = 
@"
*** (Start)メール確認モジュールによる追加メッセージです ***
To:{0}
Cc:{1}
*** (End) 以下、本文です ***

{2}
"@


  $mailArgs.Body =
 
   
$body -f $mailArgs.To,($mailArgs.Cc | Out-String),$mailArgs.
Body
 
$mailArgs.To = $globalMailTo
  $mailArgs.Remove("Cc"
)
 
 
Send-MailMessage    @mailArgs
}

とりあえず、テスト用のメール送信先を「$globalMailTo」として外から与えることとした。

あとは本来の送信先とCcを本文に追記して送信する。

その他のパラメータは、そのままフォワード。

これでもメールアドレスの形式チェックや存在チェックはできないが、いくらか本番らしくテストできるかも・・・。

◆ディスクコントローラのエラーを検出する

以下にイベントログからディスクコントローラのエラーを拾う方法(というかインスタンスID)が載っていたのでメモしておく。
Finding Disk Controller Errors - Power Tips - Powershell.com – Powershell Scripts, Tips and Resources

私は特別ハードに詳しいわけではないので、このエラーが出たらどうするかといった事は判らないが、頻繁に出るようであればHDDに何かしらの不具合がある可能性が高いと思うので、それなりの対策が必要かも。
(1回2回出たからといって必ずしもハード障害というわけ無いみたいだが・・・)

PS>Get-EventLog -LogName System -InstanceId 3221487627 -ea 0 | ft TimeWritten,Message -auto

TimeWritten         Message
-----------         -------
2012/02/28 11:51:07 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。
2012/02/28 11:51:06 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。
2012/02/28 11:51:06 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。
2012/02/28 11:51:05 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。
2011/06/20 11:29:39 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。
2011/06/20 11:29:38 ドライバーは \Device\Harddisk2\DR2 でコントローラー エラーを検出しました。