SSブログ
QLOOKアクセス解析

フォーマットストリングと配列 Lengthの副作用? [PowerShell]

実用上困るかというと、そうでもなさそうな細かな話ですが・・・

配列の長さを知るための Length や Count を使うと不思議な副作用があるようなのです。

まず配列を用意します。たとえば文字列の配列。
$a = 'Xx','Yy','Zz'
これを次にようにフォーマットストリングを使って
"{0}" -f $a
"{1}" -f $a
"{2}" -f $a
のように出力してみると、
Xx
Yy
Zz
となります。ここで配列の長さを知るために
$a.Length
とすると、当然
3
と出力されます。さらに先ほどと同じくフォーマットストリングを使って
"{0}" -f $a
"{1}" -f $a
"{2}" -f $a
のように出力してみると、今度は
Xx Yy Zz
Error formatting a string: インデックス (0 ベース) は 0 以上で、引数リストのサイズよりも小さくなければなりません。.
At line:13 char:9
+ "{1}" -f <<<< $a
+ CategoryInfo : InvalidOperation: (Xx Yy Zz:PSObject) [], RuntimeException
+ FullyQualifiedErrorId : FormatError
Error formatting a string: インデックス (0 ベース) は 0 以上で、引数リストのサイズよりも小さくなければなりません。.
At line:14 char:9
+ "{2}" -f <<<< $a
+ CategoryInfo : InvalidOperation: (Xx Yy Zz:PSObject) [], RuntimeException
+ FullyQualifiedErrorId : FormatError
のようにインデックス0番目を指定したところで全要素が出力され、1番目2番目はエラーになってしまいます。
なぜでしょう。
配列ではなくなったかのように見えます。

とはいえ [] での要素へのアクセスは可能で、たとえば
"{0} {1} {2}" -f $a[0],$a[1],$a[2]

"{0}" -f $a[0]
"{0}" -f $a[1]
"{0}" -f $a[2]
のように記述すれば、
Xx Yy Zz
Xx
Yy
Zz
と期待通りの動きをします。

さらに不思議なことにここで
$a += 'Aa'
と追加してやるとまた元に戻って
"{0}" -f $a
"{1}" -f $a
"{2}" -f $a

でアクセスできるようになります。

タグ:powershell

PowerShellのバックグラウンドジョブ [PowerShell]

unix系のシェルだと & (ampersand) で簡単に作れるバックグラウンドジョブですが、
PowerShell v1 ではそれに相当する機能はありません(よね?)

v2 からは実現可能になっています。CTP2 では runspace、CTP3 では PSSession を用いて、こんな感じで書けます。
$session01 = New-PSSession -ComputerName $ComputerName
$job = Invoke-Command `
-AsJob -ScriptBlock $blockTest01 `
-Session $session01
なんだか面倒ですよね。なぜなんでしょう。

さらにこの方法には CTP2 から CTP3 になって、できるようになるかと思っていたけどまだそのままの制限があります。

バックグラウンドジョブを実行しているセッションの中からはたとえば
Get-WmiObject -Class Win32_BIOS -ComputerName $OtherComputer
のように他のコンピュータにアクセスができないのです。

Enter-PSSessionn の二段重ねが出来ないのも同じ理由かもしれません。

認証とか権限とかの問題のような気がするので、クレデンシャルをうまく渡すとかhttpsでつなぐとかすればどうにかなるのかもしれませんが、winrm 周りの設定が複雑でよくわかりません。(^_^;

どうにかならないものですかねえ。。。

というフィードバックをしようと思いつつ英語で書くのが面倒で・・・


タグ:powershell

タイマーを使ってフォームの定期更新 [PowerShell]

PowerShellでWindowsフォームによるGUIを使ってみています。表示内容の定期的な自動更新を行うために、タイマーを利用した例を書いておきます。

PowerShellでのGUIとはいえ独自の世界があるわけではなく、Windowsフォームの知識があれば書けるということになっているようです。

今回試してみたいタイマーについても、MSDNの次のページに説明はあるのですが、残念ながら使用例としては
  • Visual Basic
  • C#
  • J#
  • Visual C++
のものしかありません。(ちゃんと追加してください・・・)
「Windows フォームの Timer コンポーネントを使用して一定間隔でプロシージャを実行する」
http://msdn.microsoft.com/ja-jp/library/3tszykws.aspx

ということで原理についてはわかったつもりでも、実際にPowerShellで書くには、コールバックの書き方などの文法の細かい部分を理解するのに少し試行錯誤が必要でしたので、忘れないためにもここに記録しておきます。いや、わかってしまえば単純なんですけどね。

空っぽのフォームを作って、そのタイトルに現在時刻と更新回数を表示するだけのとても単純化した例です。


[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")

$timerTest = New-Object Windows.Forms.Timer

$counter = 0

$timerTestTick = {
    $formInfo.text = "{0} ({1})" -f (Get-Date), $counter++
}

function ShowInfoMain
{
    #=== タイマーの初期化
    $timerTest.Add_Tick($timerTestTick)
    $timerTest.Interval = 200
    $timerTest.Enabled = $TRUE
    $timerTest.Start()

    #=== フォームを作って表示
    $formInfo = CreateFormInfo
    [void]$formInfo.ShowDialog()
}

function CreateFormInfo
{ # フォームの定義
    $form = New-Object Windows.Forms.Form

    # ここでその他の要素を定義する

    $form
}

. ShowInfoMain

20080101-01.PNG

人気ブログランキングへ
 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。