Monday, June 30, 2008

前回はErrorRecordオブジェクトについて説明しました。

PowerShellではエラーが発生するごとに、そのエラー内容(ErrorRecord)を保存している変数があります。

この変数は、"Error"という名前がついた自動変数でSystem.ArrayList型となっています。

また、この変数に格納できる最大要素数は自動変数 MaximumErrorCount で決められておりデフォルト値は256となっています。

では、実際にエラーを発生させてError変数がどのように変わっていくのかをみてみたいと思います。(PowerShellを立ち上げていた方は、念のため起動し直してから始めてください)

まずは、現在のError変数の内容を確認しておきましょう。

PS C:\Work> $Error
PS C:\Work>

この時点ではエラーは発生していないので、何も格納されていません。

 

次に前回同様、下記のように入力してエラーを発生させます。

PS C:\Work> dir HIRO.txt
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt

エラーを発生させた後のError変数はどうなったでしょうか?

PS C:\Work> $Error
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt

上記のように、先ほど発生した内容が格納されていることがわかります。

要素数はどうなったでしょうか?

PS C:\Work> $Error.Count
1

エラーは1つしか発生していないので、当然"1"となります。

では、このError変数が本当にErrorRecordオブジェクトを格納しているのかGetType()メソッドで確かめてみましょう。

(ここでは要素番号0の型をGetType()メソッドで確認しています。)

PS C:\Work> $Error[0].GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ErrorRecord                              System.Object

次に、もう1つエラーを発生させてみましょう。

PS C:\Work> mkdir HIRO*2.txt
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item  <<<< -type directory -path $paths

この状態でError変数の内容を確認してみると

PS C:\Work> $Error
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item  <<<< -type directory -path $paths
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt

少し見づらいですが、2つのエラーが格納されていることがわかります。

Error[0]には何が格納されているか確認してみましょう。

PS C:\Work> $Error[0]
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item  <<<< -type directory -path $paths

ご覧の通りインデックス0には、常に最後に発生したエラーが格納されます。

このように、Error変数はエラーの履歴をMaximumErrorCount変数で定められた数だけ保持しますので、過去にさかのぼってエラーを追跡することが可能です。

Monday, June 30, 2008 10:12:25 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Sunday, June 29, 2008

前回「エラーをファイルにリダイレクトする(PowerShell 入門) 」で2>&1演算子を使用してエラーの内容を変数に保存しました。

このようにしてエラーを格納すると、その変数はErrorRecordオブジェクトとなります。

ではErrorRecordオブジェクトにはどのようなメンバーが備わっているかを確認したいと思います。

まずは、前回同様下記のようにしてErrorRecord型の変数を作成しましょう。

$err = mkdir HIRO*2.txt 2>&1

次に、Get-Memberコマンドレットでどのようなメンバーがあるかを確認します。

PS C:\Work> $err | Get-Member


   TypeName: System.Management.Automation.ErrorRecord

Name                      MemberType   Definition
----                      ----------   ----------
Equals                    Method       System.Boolean Equals(Object obj)
GetHashCode               Method       System.Int32 GetHashCode()
GetObjectData             Method       System.Void GetObjectData(SerializationInfo info, StreamingContext context)
GetType                   Method       System.Type GetType()
get_CategoryInfo          Method       System.Management.Automation.ErrorCategoryInfo get_CategoryInfo()
get_ErrorDetails          Method       System.Management.Automation.ErrorDetails get_ErrorDetails()
get_Exception             Method       System.Exception get_Exception()
get_FullyQualifiedErrorId Method       System.String get_FullyQualifiedErrorId()
get_InvocationInfo        Method       System.Management.Automation.InvocationInfo get_InvocationInfo()
get_TargetObject          Method       System.Object get_TargetObject()
set_ErrorDetails          Method       System.Void set_ErrorDetails(ErrorDetails value)
ToString                  Method       System.String ToString()
writeErrorStream          NoteProperty System.Boolean writeErrorStream=True
CategoryInfo              Property     System.Management.Automation.ErrorCategoryInfo CategoryInfo {get;}
ErrorDetails              Property     System.Management.Automation.ErrorDetails ErrorDetails {get;set;}
Exception                 Property     System.Exception Exception {get;}
FullyQualifiedErrorId     Property     System.String FullyQualifiedErrorId {get;}
InvocationInfo            Property     System.Management.Automation.InvocationInfo InvocationInfo {get;}
TargetObject              Property     System.Object TargetObject {get;}

これらの中から、主要なメンバーについて説明したいと思います。

CategoryInfoプロパティ

このプロパティは文字通りエラーの種類についての情報が格納されています。

PS C:\Work> $err.CategoryInfo

Category   : InvalidArgument
Activity   : New-Item
Reason     : ArgumentException
TargetName : C:\Work\HIRO*2.txt
TargetType : String

CategoryでInvalidArgumentとなっていることがわかります。これはdirコマンドに対して、無効な文字が含まれたパスを指定しているためです。

さらにReasonをみるとこのArgumentExceptionという例外が発生したことがわかります。

Exceptionプロパティ

Exceptionプロパティ自体も様々なメンバーを持っていますが、規定のプロパティはMessageとなっており、エラーの内容を確認することができます。

PS C:\Work> $err.Exception
パスに無効な文字が含まれています。

InvocationInfoプロパティ

このプロパティはエラーの発生場所に関する情報が格納されます。

PS C:\Work> $err.InvocationInfo


MyCommand        : New-Item
ScriptLineNumber : 1
OffsetInLine     : -2147483648
ScriptName       :
Line             : param([string[]]$paths); New-Item -type directory -path $paths
PositionMessage  :
                   発生場所 行:1 文字:34
                   + param([string[]]$paths); New-Item  <<<< -type directory -path $paths
InvocationName   : New-Item
PipelineLength   : 1
PipelinePosition : 1

TargetObjectプロパティ

このプロパティにはエラー発生時の操作対象オブジェクトが格納されます。ただし、すべてのエラーがこのフィールドを設定する訳ではないため、Nullの場合もあります。

PS C:\Work> $err.TargetObject C:\Work\HIRO*2.txt

 

このようにErrorRecordオブジェクトにはエラーの原因を解明する上で役立つ情報が格納されています。

ぜひ、ErrorRecordオブジェクトの利用方法を理解し、スクリプトのデバッグに活用してください。

Sunday, June 29, 2008 10:56:02 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Saturday, June 28, 2008

今回から、PowerShellにおける、エラー/例外処理/デバッグ手法について説明していきたいと思います。

今回はエラーをファイルにリダイレクトする方法についてです。

まずは、「リダイレクトとは何か?」ですが、処理を行った結果の出力先を別な場所へ変更することを意味します。

通常PowerShell上で、あるコマンドを実行してエラーが発生した場合は、コンソールウィンドウにエラーメッセージが表示されます。

ここでは、このエラーをファイルに出力することをリダイレクトすると呼んでいます。

PowerShellでエラーをファイルにリダイレクトする方法にはリダイレクト演算子を使用し、3種類あります。1つずつみていきましょう。

2> 演算子

この演算子はエラーの内容をファイルに出力します。出力先のファイいるがすでに存在する場合には上書きをします。

下記は、dirコマンドで存在しないファイルを指定した場合の例です。

PS C:\Work> dir HIRO.txt
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt

では、このエラーをファイルにリダイレクトしてみましょう。

PS C:\Work> dir HIRO.txt 2>err.txt

上記のように、2>演算子の後ろに、エラーメッセージを書き込むファイル名を記述します。

ファイル名だけを記述した場合は、カレントディレクトリに出力します。

では Get-Contentコマンドレットを使用して実際にファイルの中身をみてみましょう。

PS C:\Work> Get-Content err.txt
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt 2>err.txt

エラーの内容がerr.txtに書き出されていることがおわかりいただけたかと思います。

2>> 演算子

先ほどの演算子と非常に良く似ていますが>が1つ多いですね。

この演算子は、エラーの出力先のファイルがすでに存在する場合は、追記書き込みを行います。

実験してみましょう。

追記されていることを確認するために、出力先のファイルは先ほどと同じerr.txtとします。また異なるエラーメッセージが記述されるようmkdirコマンドに変更しました。

PS C:\Work> mkdir HIRO*2.txt 2>>err.txt

実行したら、先ほど同様Get-Contentコマンドレットで確認してみましょう。

PS C:\Work> Get-Content err.txt
Get-ChildItem : パス 'C:\Work\HIRO.txt' が存在しないため検出できません。
発生場所 行:1 文字:4
+ dir  <<<< HIRO.txt 2>err.txt
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item  <<<< -type directory -path $paths

エラーメッセージが追記されていることがわかりますね。

2>&1 演算子

最後に2>&1演算子ですが、この演算子を使用するとエラーの内容を変数に書き込むことができます。

使用方法は下記の通りです。

$err = mkdir HIRO*2.txt 2>&1

では、エラーの内容が変数に代入されているかを確認してみましょう。

PS C:\Work> $err
New-Item : パスに無効な文字が含まれています。
発生場所 行:1 文字:34
+ param([string[]]$paths); New-Item  <<<< -type directory -path $paths

通常、変数の内容を確認してもメッセージに色がつかないのですが、2>&1演算子を使用して代入された値は赤色で表示されていることがわかります。

これは、変数の型がErrorRecordであり、PowerShellがエラーと認識しているからです。

PS C:\Work> $err.GetType()

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     ErrorRecord                              System.Object

次回は、このエラーを保持する変数について説明したいと思います。

Saturday, June 28, 2008 10:32:42 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [1]  |  Trackback
Wednesday, June 25, 2008

Windows Formアプリケーションを作成する その1(PowerShell Tips)
Windows Formアプリケーションを作成する その2(PowerShell Tips)
Windows Formアプリケーションを作成する その3(PowerShell Tips)

の続きです。

今回は、[閉じる]ボタンを追加することで、前回同様コントロールの追加方法、そしてイベントの作成方法についてみていきたいと思います。

1.パネルを追加する

 今回追加する[閉じる]ボタンはパネルに追加したいと思います。

 ということで、まずは下記のようにしてフォームにパネルを追加します。

#===== Panelの作成 =====
$panel1 = New-Object System.Windows.Forms.Panel
$form.Controls.Add($panel1)
$panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
$panel1.Height = 30

 まずは、New-Objectコマンドレットを使用して、パネルのインスタンスを作成します。

 そしてフォーム($form)のControls.Addメソッドを使用して、パネルを追加します。

 パネルはフォームの最下部に設置したいので、Bottomを指定し、高さを30としています。

2.ボタンを追加する

 ボタンもNew-Objectコマンドレットを使用して、インスタンスを作成します。

 また、Locationプロパティを使用して、ボタンの配置位置を指定します。ボタンはパネルに追加するので基点はパネルの左上となります。

#===== [閉じる]ボタンの作成 =====
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Location = New-Object System.Drawing.Point(405, 4)

3.ボタンテキストの設定

 [閉じる]ボタンなので、Textプロパティに「閉じる」を指定します。

$btnClose.Text = "閉じる"

4.Anchorの設定

 Anchorはそのコントロールの親(ここではPanel)が伸縮したときに、配置位置をどのようにするかを指定するものです。

 今回は、パネルの右上からの位置をキープし続けるようにしたいためTopとRightを指定しています。 この組み合わせは-bor演算子を使用して設定します。

5.イベントの追加

 イベントを追加するには、そのオブジェクトの 変数.Add_イベント名 のように記述します。 今回はクリック時にフォームを閉じたいので

$btnClose.Add_Click({$form.Close()})

 とします。

6.パネルへボタンを追加する

 パネルへボタンを追加するには、Controls.Addを使用します。

$panel1.Controls.AddRange($btnClose)

7.フォームを表示する

フォームを表示するにはShowDialogメソッドを使用します。Showメソッドを使用すると一瞬でフォームが閉じてしまうので、PowerShellで使用するときはShowDialogメソッドを使用するようにしてください。

#===== Formを表示 =====
$form.ShowDialog()
Wednesday, June 25, 2008 10:22:55 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [2]  |  Trackback
Tuesday, June 24, 2008

ご無沙汰しております。おととい中国から帰国しました。

ということで、再開していきたいと思います。

Windows Formアプリケーションを作成する その1(PowerShell Tips)

Windows Formアプリケーションを作成する その2(PowerShell Tips)

の続きです。

前回までは、最初に空の関数を作成して、その中に

・受け取ったパラメータの確認
・パスの存在確認
・XMLファイルの読み込み処理

を追加しました。

今回は、データグリッドビューをフォームに追加してデータを表示する方法について説明します。

1.データグリッドビューの作成

まずデータグリッドビューですが

$dgvXML = New-Object System.Windows.Forms.DataGridView

のようにNew-Objectコマンドレットを使用してインスタンスを作成します。

2.DockStyleの設定

次に、DockStyleをFillに設定します。

$dgvXML.Dock = [System.Windows.Forms.DockStyle]::Fill

以前にも説明したのですが、列挙体を表す値を使用する場合は[]の中には列挙体名を::の右側へは列挙体値を指定します。

3.データをデータグリッドビューに表示する

次にデータの表示ですが、あらかじめ作成しておいたデータセットをDataSourceプロパティに指定します。

このとき、データはDataSetのTable[0]に入っていますので、それを指定します。

$dgvXML.DataSource = $dtSet.Tables[0]

4.データグリッドビューをフォームに追加する

最後に、データグリッドビューをフォームに追加します。

フォームに追加するにはControls.Addを使用します。

$form.Controls.Add($dgvXML)

次回はフォームを閉じるボタンの追加について説明します。

Tuesday, June 24, 2008 10:16:33 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Friday, June 13, 2008

私事ですが、6/15(日)~6/22(日)、中国の上海で出張へ行くことになりました。

食事と買い物 仕事が忙しいためブログの更新ができないかもしれませんが、決してサボっているわけではありませんのご了承ください。

ノートパソコンは持って行くので、時間と環境があれば更新したいと思います。

HIRO

Friday, June 13, 2008 11:03:00 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

Windows Formアプリケーションを作成する その1(PowerShell Tips) の続きです。

今回はデータセットにXMLファイルを読み込みたいと思います。

データセットですが、個人的にすごく好きです。

データベースからのデータをセットして使用するコントロールですが、何よりもXMLファイルを簡単に読み書きできる点がすばらしいと思います。

まずは、PowerShell上でデータセットオブジェクトを作成する方法ですが、New-Objectコマンドレットを使用します。

VB.NETやC#で開発経験のある方にとってはNew(new)演算子と思っていただければ良いでしょう。

$dtSet = New-Object System.Data.DataSet

これでデータセットを使用する準備ができました。

あとはXMLファイルをデータセットに読み込みます。XMLファイルを読み込むには、ReadXmlメソッドを使用します。

$dtSet.ReadXml($XmlFile)

上記のようにすると、$dtSetにはDataTableが1つ作成されます。

$dtSetには複数のDataTableを格納することができるため、アクセスするには

$dtSet.Tables[0] のように記述します。この場合は格納されているテーブルの1つめにアクセスすることを意味します。

この続きはまた次回..

Friday, June 13, 2008 10:41:35 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Thursday, June 12, 2008

Windows Formを表示する(PowerShell Tips)

コントロールを追加する(PowerShell Tips)

でWindows Formアプリケーションの作成方法をみてきました。

今回から何回かに分けて、過去に紹介した簡易XMLビューアを作る(PowerShell Tips) を題材に、実際の開発例についてみていきたいと思います。

まずは簡易XMLビューアのソースです。

#===============================================================================
# View-Xml: XMLファイルを読み込んで表示する(簡易XMLViewer)
#
# 使用例
#   PS > View-Xml XMLファイルパス
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:View-Xml([string]$XmlFile)
{

  #パスが指定されているか?
  if ( $XmlFile.Length -eq $null )
  {
    Write-Host "XMLファイルを指定してください"
    return
  }
  
  #存在するパスか?
  if ( -not $(Test-Path $XmlFile) )
  {
    Write-Host $XmlFile + "は存在しません"
    return
  }
  
  #データセットを作成し、XMLファイルを読み込む
  $dtSet = New-Object System.Data.DataSet
  $dtSet.ReadXml($XmlFile)
  
  #===== Formの作成 =====
  [reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
  $form = New-Object System.Windows.Forms.Form
  $form.Text = $XmlFile
  $form.Width = 500
  $form.Height = 400
  
  #===== DataGridViewの作成 =====
  $dgvXML = New-Object System.Windows.Forms.DataGridView
  $dgvXML.Dock = [System.Windows.Forms.DockStyle]::Fill
  $dgvXML.DataSource = $dtSet.Tables[0]
  $form.Controls.Add($dgvXML)
  
  #===== Panelの作成 =====
  $panel1 = New-Object System.Windows.Forms.Panel
  $form.Controls.Add($panel1)
  $panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
  $panel1.Height = 30
  
  #===== [閉じる]ボタンの作成 =====
  $btnClose = New-Object System.Windows.Forms.Button
  $btnClose.Location = New-Object System.Drawing.Point(405, 4)
  $btnClose.Text = "閉じる"
  $btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
  $btnClose.Add_Click({$form.Close()})
  $panel1.Controls.AddRange($btnClose)
  
  #===== Formを表示 =====
  $form.ShowDialog()
}

1)関数の仕様

簡単ですが、以下のようにしたいと思います。

関数名:View-Xml

機能:パラメータで受け取ったXMLファイルを、Windows Formに配置されたデータグリッドビューに表示する

2)空の関数を作成する

まずは、関数名はVew-Xmlと決まっていますので、これを元に空の関数を作成しましょう。また、この関数のスコープはglobalとします。これは、ほかのスクリプトファイルやPowerShellコンソールから使用できるようにするためです。

それと、XMLファイルのパスをパラメータとして受け取れるようにしたいので、関数名の後ろに([string]$XmlFile)と記述します。

[string]は変数$XmlFileはstring型として扱うための指定です。

以上を元に作成した空の関数は下記の通りです。

function global:View-Xml([string]$XmlFile)
{

}

テキストエディタを開いて上記のように入力したら、View-Xml.ps1と名前をつけて保存しましょう。

3)受け取ったパラメータをチェックする

この関数を使用する人は、パラメータを渡さないかもしれませんし、指定されたパスが存在しないかもしれません。

そのようなことが起きても問題にならないように最初にチェックしてしまいましょう。

まずは、パラメータが指定されたかどうかをチェックします。

この関数はパラメータ(XMLファイルのパス)が指定されると、$XmlFileに代入します。

しかし、関数呼び出し時にパラメータを指定しなかった場合には$XmlFileはNullがセットされています。

このような場合はif文で$XmlFileがNull(PowerShellにおけるNullは$Nullと表します)かどうかをチェックします。Nullだった場合はメッセージを表示して関数を抜けるようにします。(return)

  #パスが指定されているか?
  if ( $XmlFile.Length -eq $null )
  {
    Write-Host "XMLファイルを指定してください"
    return
  }

次に、受け取ったパスの存在をチェックします。

指定されたパスが存在するかをチェックするにはTest-Pathコマンドレットを使用します。存在する場合はTrueを返してくるので、-notを付けて、falseが返されたとき、つまりパスが存在しなかったときにif文の中を実行するようにします。

  if ( -not $(Test-Path $XmlFile) )
  {
    #存在するパスか?
    Write-Host $XmlFile + "は存在しません"
    return
  }

どうでしょうか? なんとなく作り方が見えてきましたか?

この続きは次回説明したいと思います。

Thursday, June 12, 2008 11:12:55 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Wednesday, June 11, 2008

Windows Formを表示する(PowerShell Tips) の続きです。

前回はWindows Formを表示するだけで終わってしまいました。

前回のスクリプトは下記の通りです。

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$form.Width = 500
$form.Height = 500
$form.Text = "PowerShellからのForm表示"
$form.ShowDialog()

今回は、Windows Formにコントロールを追加する方法について説明します。

前回作成したフォームにボタンを追加してみましょう。

1)ボタンオブジェクトを作成する

ボタンオブジェクトを作成するには、下記のようにします。

$btnClose = New-Object System.Windows.Forms.Button

2)各プロパティの設定

まずはボタンの配置場所を設定しましょう。今回はフォームに直接追加しますので、座標はフォームの左上からの位置となります。配置位置はLocationプロパティを使用して、下記のように設定します。X=400, Y=420 としました。

$btnClose.Location = New-Object System.Drawing.Point(400, 420)

次に、ボタンに表示する文字を設定しましょう。ボタンに表示する文字はTextプロパティを使用します。

$btnClose.Text = "閉じる"

Anchorプロパティも設定してみましょう。Anchorプロパティは、配置したオブジェクト(ここではボタン)の親(ここではForm)がサイズ変更された場合に、それに伴って、どのように移動させるかを表す値を設定するものです。今回はボタンの下端と右端にAnchor設定します。こうするとボタンの右下がフォームの右下からの距離を保ったまま移動します。

$btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right

ここで見慣れない記述 :: が出てきました。列挙体を表す値を使用する場合は[]の中には列挙体名を::の右側へは列挙体値を指定します。またAcnchorプロパティには1つ以上指定できるのですが、2つ以上の値を設定する場合は-bor演算子を使用します。(-or演算子ではなく、ビット演算子である-borを使用しないとうまく設定できませんので注意してください)

3)イベントを追加する

VB.NETやC#では、オブジェクトをダブルクリックしたり、稲妻アイコンのボタンを押してイベントハンドラを作成することが可能ですが、PowerShellでは自分でイベントハンドラを造る必要があります。

たとえば、。今回のボタンがクリックされたときのイベントは

$btnClose.Add_Click({$form.Close()})

のようにします。

PowerShellにおけるイベントハンドラの作成は

イベントを追加するオブジェクト.Add_イベント

のように記述します。斜体にしたところは、自分が指定するところで、色を付けた部分はおきまりのものです。

よって、今回の場合は

$btnClose.Add_Click

となっています。

イベントのところは、今回はClickイベントを作成するのでClickとしていますが、MouseEnterなど自分が作成したいイベントを指定することが可能です。

()の中身ですが、イベントが起きたときに実行するスクリプトを{}の中に記述します。これは複数行にまたがってもかまいません。また1行の中に書くのであれば、実行単位ごとに ; で区切ります。

4)作成したオブジェクトを親に追加する

こうして作成したオブジェクトは、親が必要です。親を指定して追加を行わないと作成したオブジェクトを使用することはできません。

今回の場合は、ボタン $btnClose を $form(これが親になります)に追加する必要があります。

追加を行うには

親オブジェクト.Controls.Add(追加するオブジェクト)

のようにします。

よって

$form.Controls.Add($btnClose)

とします。

5)まとめ

以上をまとめると、スクリプトは下記のようになります。

#アセンブリのロード
[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")

#フォームオブジェクトの作成
$form = New-Object System.Windows.Forms.Form
$form.Width = 500
$form.Height = 500
$form.Text = "PowerShellからのForm表示"

#ボタンオブジェクトの作成
$btnClose = New-Object System.Windows.Forms.Button
$btnClose.Location = New-Object System.Drawing.Point(400, 420)
$btnClose.Text = "閉じる"
$btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Bottom -bor [System.Windows.Forms.AnchorStyles]::Right
#Clickイベントの追加
$btnClose.Add_Click({$form.Close()})

#フォームオブジェクトへボタンを追加
$form.Controls.Add($btnClose)

#フォームオブジェクトの表示
$form.ShowDialog()

実行結果は下記のようになります。[閉じる]ボタンを押すとフォームが閉じられることを確認してください。

Wednesday, June 11, 2008 10:20:36 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Tuesday, June 10, 2008

このブログでも何度か取り上げているWindows Formですが、きちんと説明したことがなかったので、何回かに分けて説明したいと思います。

PowerShellは.NET Frameworkを基盤としているので、Windowsフォームを扱うことが可能です。

通常、.NET Frameworkを利用したWindows FormアプリケーションはVB.NETやC#を使用して作成し、コンパイルして実行というのがスタンダードな方法かと思います。

PowerShellでのWindows Formアプリケーションはコンパイルする必要がありません。(IronPythonなどもそうですね) しかし、デザイナがないのでサイズの決定やコントロールの配置、イベント追加などは慣れないと大変です。

しかし、PowerShellで「一部はGUIを取り入れたい」なんて時には威力を発揮しますので、覚えておいて損はないかと思います。

前置きが長くなりましたが、今回はフォームを表示する方法について説明します。

1)フォームを使う準備をする

フォームを使用するにはSystem.Windows.Formsが必要です。これはVB.NETやC#でいうところの参照設定に該当します。

PowerShellを起動した時点ではSystem.Windows.Formsは使用できないので最初に登録する必要があります。

下記一文で登録することが可能です。

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

ちなみに、現在使用可能なアセンブリを確認するには

PS > ([AppDomain]::CurrentDomain).GetAssemblies()

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\Windows\Microsoft.NET\Framework\v2.0.50727\mscorlib.dll
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\Microsoft.PowerShell.ConsoleHost\1.0.0.0__31bf3856ad364e35\Micros...
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System\2.0.0.0__b77a5c561934e089\System.dll
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System.Management.Automation\1.0.0.0__31bf3856ad364e35\System.Man...
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\System.Configuration.Install\2.0.0.0__b03f5f7f11d50a3a\System.Con...
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.Management\1.0.0.0__31bf3856ad364e3...
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\Microsoft.PowerShell.Security\1.0.0.0__31bf3856ad364e35\Microsoft...
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\Microsoft.PowerShell.Commands.Utility\1.0.0.0__31bf3856ad364e35\M...
True   v2.0           C:\Windows\assembly\GAC_MSIL\Microsoft.PowerShell.ConsoleHost.resources\1.0.0.0_ja_31bf3856ad3...

([AppDomain]::CurrentDomain).GetAssemblies() の一文は下記のようにしてプロファイルに登録しておくと、次回起動時よりGet-Assemblyで確認することができるようになります。

function Get-Assembly { ([AppDomain]::CurrentDomain).GetAssemblies()}

2)フォームをデザインする

Windowsフォームを使用するためには、最低でも

  • Formオブジェクトの作成
  • Form幅の設定
  • Form高さの設定

をする必要があります。 

Formオブジェクトを作成するには

$form = New-Object System.Windows.Forms.Form

のようにします。そして作成したFormオブジェクト($form)に幅と高さを指定します。

下記は幅500と高さ500に設定しています

$form.Width = 500
$form.Height = 500

できれば下記のようにして、タイトルバーに表示するテキストも設定してしまいましょう。

$form.Text = "PowerShellからのForm表示"

3)フォームを表示する

デザインが完了した後は、実際にフォームを表示します。

フォームの表示は ShowDialogメソッドを使用します。

$form.Width = 500
$form.ShowDialog()

ここまでをまとめると下記のようになります。

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
$form = New-Object System.Windows.Forms.Form
$form.Width = 500
$form.Height = 500
$form.Text = "PowerShellからのForm表示"
$form.ShowDialog()

実行結果は下記のようになります。

Tuesday, June 10, 2008 10:49:34 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Monday, June 09, 2008

いろいろな形を描画する(Silverlight 入門) の続きです。

今回はPolylineとPolygonについて説明します。

Polyline

点と点とを直線でつないで描く図形をPolylineと呼びます。

PolylineのXAMLは下記のようになります。

<Polyline Points="100,100 100,250 250,250 250,100"
    Stroke="Black" StrokeThickness="10"/>

このXAMLを使用した実行結果はこちらです。

Pointsのところで各点の座標を指定します。

各点の指定方法は X1,Y1 X2,Y2 X3,Y3 Xn,Yn のように指定します。 各座標間はスペースで区切ります。

上記XAMLはX1,Y1は100,100、X2,Y2は100,250となります。

要素 Strokeは線の色を表し、StrokeThicknessは線の太さを表します。

Polylineは始点と終点を結んでも塗りつぶすことができないので注意してください。

Polygon

Polygonは、円でも矩形でもない多角形を記述する場合に使用します。(矩形を描くこともできますが、Rectangleを使用するのが一般的です)

PolygonのXAMLは下記のようになります。

<Polygon Points="100,100 100,250 250,250 250,100"
    Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>

このXAMLを使用した実行結果はこちらです。

各点の指定方法はPolylineと同様に、X1,Y1 X2,Y2 X3,Y3 Xn,Yn のように指定します。 各座標間はスペースで区切ります。

上記XAMLはX1,Y1は100,100、X2,Y2は100,250となります。

要素 Strokeは線の色を表し、StrokeThicknessは線の太さを表します。またFillで作成した多角形の内部を塗りつぶします。

実は上記に示した、PolylineとPolygonの座標が全く同じであることに気づいたでしょうか?

PolylineとPolygonの違いは、始点と終点をつなぐかどうかという点にあります。

Polygonは自動で始点と終点を結ぶ線が作成され色を塗ることが可能という特徴があります。

Monday, June 09, 2008 10:36:00 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

スクリプトブロック(PowerShell 入門) の続きです。

スクリプトブロックではparamによる引数の受け取りが可能です。

PS > $script = { param($a); $a * 3 }

上記は、paramで引数を1つ受け取ります。

このスクリプトブロックは、引数を3倍します。

実行方法は、前回説明したように&演算子を使用して変数名を指定し、その後に引数として渡す値を記述します。

PS > & $script 5
15

もう1つ、$argsによる値の受け取りも可能です。

先ほどのスクリプトブロックを$argsで書き換えてみたのが下記です。

PS > $script = { $args[0] * 3 }

実行方法は、paramのときと同じで

PS > & $script 5
15

とします。

Monday, June 09, 2008 10:06:10 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Sunday, June 08, 2008

Silverlightで描画可能な図形には、Ellipse, Line, Path, Polygon, Polyline, Rectangleがあります。

今回はEllipse, Line, Rectangleそれぞれについて説明したいと思います。

Ellipse

これは、このBlogでも何度も取り上げているのですが、改めて説明したいと思います。

EllipseのXAMLは下記のようになります。

<Ellipse Canvas.Left="30" Canvas.Top="30"
    Height="200" Width="200"
    Stroke="Black" StrokeThickness="10" Fill="Blue"/>

このXAMLを使用した実行結果はこちらです。

Ellipse は Width と Heightで指定した矩形に内接する円を描画します。このときWidthとHeightの比率が1:1の時に円、それ以外の比率で楕円となります。

Strokeは、円を縁取る線の色を表し、StrokeThicknessは線の太さ、Fillは円を塗りつぶす色となります。

Line

Lineは文字通り線を描画します。

LineのXAMLは下記のようになります。

<Line Canvas.Left="30" Canvas.Top="30"
  X1="50" Y1="50" X2="150" Y2="150"
  Stroke="Blue" StrokeThickness="5"/>

このXAMLを使用した実行結果はこちらです。

Lineは線ですので、始点(X1,Y1)から終点(X2,Y2)を指定することで描画することができます。

Strokeは線の色を表し、StrokeThiknessが線の太さを表します。

Rectangle

Retangleは矩形を描画します。

RectangleのXAMLは下記のようになります。

<Rectangle Canvas.Top="20" Canvas.Left="20"
    Width="100" Height="100" 
    Fill="Blue" Stroke="Red" StrokeThickness="3" />

このXAMLを使用した実行結果はこちらです。

Widthと(幅)とHeight(高さ)を指定して描画します。WidthとHeightの比率を1:1にすることで正方形を、それ以外の比率で長方形を描画することができます。

Fillで塗りつぶしの色、Strokeで線の色、StrokeThicknessで線の太さを表します。

Sunday, June 08, 2008 10:34:54 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

PowerShellでスクリプトブロックを作成して実行する方法について紹介したいと思います。

スクリプトブロックとは?

まず、スクリプトブロックとは何か? ですが、ほかの言語で言うと匿名関数やラムダ式に相当するものです。

名前のない関数ともいえるでしょうか。

PowerShellにおいては中括弧 {} で囲まれたスクリプトコードに過ぎません。

たとえば

PS > 1..10 | foreach { Write-Host $_ }

と記述したときの、{ Write-Host $_ } はスクリプトブロックです。

スクリプトブロックを変数に代入する

スクリプトブロックは、変数に代入することもできます。

たとえば

PS > $s = { $a * 3 }

上記は、変数$aを3倍するというスクリプトブロックを変数$sに代入したことになります。

スクリプトブロックを実行する

では、スクリプトブロックを実行するにはどうすれば良いでしょうか?

PS > $s

上記のように変数名を入力して[Enter]を押すだけでは実行数することができません。

スクリプトブロックを実行するには、下記のように &演算子を使用します。(&とスクリプトブロックが代入された変数との間にはスペースが必要です)

PS > $a =2
PS > & $s
6

次回、スクリプトブロックでのパラメータの受け取り方法について説明したいと思います。

Sunday, June 08, 2008 9:49:04 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Saturday, June 07, 2008

通常Silverlight表示エリアには、キャンバスを1つ用意します。

実は、このキャンバスオブジェクトは入れ子にして使用することが可能です。

下記は Canvasオブジェクトを入れ子にした例です。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="300" Height="300" Background="Gray">
    
    <Canvas
        Canvas.Left="50" Canvas.Top="50"
        Width="50" Height="50" Background="Red" />

    <Canvas
        Canvas.Left="150" Canvas.Top="50"
        Width="50" Height="50" Background="Red" />
</Canvas>

上記の場合は300x300のキャンバスオブジェクトの中に、50x50のキャンバスオブジェクトが2個配置してあります。実行結果はこちら

子のキャンバスオブジェクトの中でCanvas.LeftやCanvas.Topを使用していますが、これは親のキャンバスオブジェクトからの位置を表しています。

次に、この2つのキャンバスオブジェクトサイズを少し大きくして円を追加してみたいと思います。左側のキャンバスには青い円、右側には緑の円を追加しました。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="300" Height="300" Background="Gray">
    
    <Canvas
        Canvas.Left="20" Canvas.Top="50"
        Width="100" Height="100" Background="Red">
        
        <Ellipse
        Height="50" Width="50" Canvas.Left="0" Canvas.Top="0"
        Stroke="Black" StrokeThickness="3" Fill="Blue" />
        
    </Canvas>

    <Canvas
        Canvas.Left="140" Canvas.Top="50"
        Width="100" Height="100" Background="Red">
        
        <Ellipse
        Height="50" Width="50" Canvas.Left="0" Canvas.Top="0"
        Stroke="Black" StrokeThickness="3" Fill="Green" />
        
    </Canvas>
</Canvas>

上記を実行すると、各円は子のキャンバスのエリアの左上に表示されていることがわかります。実行結果はこちら

これは、Ellipseの要素Canvas.TopとCanvas.Leftが子のキャンバスを意味しているからです。

このように、各オブジェクトには親子関係があることを覚えておいてください。

一番外側のCanvasがおじいちゃん(おばあちゃん)、その中のCanvasがお父さん(お母さん)、一番内側のEllipseが子供といったところです。 

次に、子供のCanvasオブジェクトに追加した円(Ellipse)の移動についてみてみましょう。

左側に配置したCanvasにある円をキャンバスオブジェクト超えるあたりに配置したXAMLを準備してみました。

<Canvas
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Width="300" Height="300" Background="Gray">
    
    <Canvas
        Canvas.Left="20" Canvas.Top="50"
        Width="100" Height="100" Background="Red">
        
        <Ellipse
        Height="50" Width="50" Canvas.Left="80" Canvas.Top="80"
        Stroke="Black" StrokeThickness="3" Fill="Blue" />
        
    </Canvas>

    <Canvas
        Canvas.Left="140" Canvas.Top="50"
        Width="100" Height="100" Background="Red">
        
        <Ellipse
        Height="50" Width="50" Canvas.Left="0" Canvas.Top="0"
        Stroke="Black" StrokeThickness="3" Fill="Green" />
        
    </Canvas>
</Canvas>

実行結果はこちらです。

これはEllipseの親であるCanvas(お父さん)の左上を起点として、X方向に80, Y方向に80動いており、クリッピングはされていません。

このように、各オブジェクトの移動範囲は、そのオブジェクトが属する親からの絶対移動となることも覚えておくと良いでしょう。

今回のサンプルはこちらからダウンロードできます。

Saturday, June 07, 2008 11:11:58 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は

記事 関数名 説明
SQL*PLUSもどきを作る1 PSOracle SQL*PLUSもどきのメイン関数
SQL*PLUSもどきを作る1の説明 PSOracle SQL*PLUSもどきのメイン関数の説明
SQL*PLUSもどきを作る2 Get-OracleConnectionStirng 接続文字列を作成する
SQL*PLUSもどきを作る3 Execute-QueryString SQLを実行した結果をDataSetに格納して返す
SQL*PLUSもどきを作る4 desc descコマンド
SQL*PLUSもどきを作る5 Read-MultiLine コマンドラインから複数行の入力を受け取る
SQL*PLUSもどきを作る6 Execute-Query SQLを実行して、結果をコンソールウィンドウに表示する
SQL*PLUSもどきを作る5(改訂版) Read-MultiLine コマンドラインから複数行の入力を受け取る。終端判定を1文字以上でも行えるよう見直し。
SQL*PLUSもどきを作る7 Disconnect 切断処理

SQL*PLUSもどきを作る8

Write-SqlHistory SQL実行履歴の保存
SQL*PLUSもどきを作る6(改訂版) Execute-Query SQLを実行して、結果をコンソールウィンドウに表示する。SQL実行履歴作成機能の追加。

SQL*PLUSもどきを作る9

View-History SQL履歴からの実行機能作成

SQL*PLUSもどきを作る6(改訂版2)

Execute-Query その9で作成した機能を組み込み、さらにXMLエクスポート機能を付加。

SQL*PLUSもどきを作る10

View-Table SQL実行結果をデータグリッドビューへ表示する機能の作成

の続きです。

前回は、SQL実行結果をデータグリッドビューに表示する部分を作成しました。

今回は、この関数を実際に使用できるようにExecute-Query関数を改造します。

#=========================================================================================
# Execute-Query: QueryStringを実行する
#
# UPDATE 2008/04/28     Ver.1.0.0
#        2008/05/19     Ver.1.0.1   SQL履歴作成機能の追加
#        2008/06/03     Ver.1.0.2   履歴からの実行機能および取得データエクスポート機能の追加
#        2008/06/07     Ver.1.0.3   取得結果をデータグリッドビューに表示できるようにする
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#=========================================================================================
function global:Execute-Query([string]$ExportXmlFile, [switch]$View, [switch]$History)
{
    if ( $History )
    {
        #履歴からの実行(Ver.1.0.2 )
        $XmlFile = "$([Environment]::GetFolderPath(`"MyDocuments`"))\WindowsPowerShell\Oracle\History.xml"
        $SqlHis = View-History $XmlFile
      
        if ($SqlHis -eq $Null) { return }
    }
    
    if ( $SqlHis.Length -gt 0 )
    {
        $strSQL = $SqlHis
    }
    else
    {
        Write-Host "SQLを入力してください。" -foregroundcolor Yellow
        Write-Host "`";`"で入力を終了し、実行します。" -foregroundcolor Yellow
        
        #複数行のQueryStringを受け取る
        $strSQL = Read-MultiLine
    }
    
    #履歴の作成(Ver.1.0.1)
    Write-SqlHistory $strSQL
    
    #QueryStringを実行する
    $dtSet = Execute-QueryString $strSQL
    if ( $dtSet.Tables.Count -gt 0 )
    {
        #DataGridViewへの表示(Ver.1.0.3)
        if ( $View ) { View-Table $dtSet.Tables[0] }
        else {
            #format-tableコマンドレットでデータを表示
            $dtSet.Tables[0].Rows | format-table
        }
    }
    
    #取得データをXMLにエクスポート(Ver.1.0.2)
    if ( $ExportXmlFile.Length -gt 0 )
    {
        $dtSet.WriteXml($ExportXmlFile);
    }
}

開発ポイント

Execute-Query関数を呼び出すときに、パラメータ View を指定することで取得結果をデータグリッドビューへ表示することが可能になります。

パラメータViewはスイッチパラメータを使用しており、実行時に View パラメータが指定されると、変数$ViewがTrueになる性質を利用して、前回作成したView-Table関数を呼ぶように作成してあります。

使用方法

PS > Execute-Query -View
select * from emp;

これを実行すると、下記のようになります。

また、この関数は Histroy パラメータと同時に指定可能なので

PS > Execute-Query -View -History
select * from emp;

のように入力とすると

上図が表示され、この画面で[選択]ボタンを押すと

選択したSQLの実行結果が、データグリッドビューにが表示されます。

Saturday, June 07, 2008 10:31:53 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Friday, June 06, 2008

この記事は

記事 関数名 説明
SQL*PLUSもどきを作る1 PSOracle SQL*PLUSもどきのメイン関数
SQL*PLUSもどきを作る1の説明 PSOracle SQL*PLUSもどきのメイン関数の説明
SQL*PLUSもどきを作る2 Get-OracleConnectionStirng 接続文字列を作成する
SQL*PLUSもどきを作る3 Execute-QueryString SQLを実行した結果をDataSetに格納して返す
SQL*PLUSもどきを作る4 desc descコマンド
SQL*PLUSもどきを作る5 Read-MultiLine コマンドラインから複数行の入力を受け取る
SQL*PLUSもどきを作る6 Execute-Query SQLを実行して、結果をコンソールウィンドウに表示する
SQL*PLUSもどきを作る5(改訂版) Read-MultiLine コマンドラインから複数行の入力を受け取る。終端判定を1文字以上でも行えるよう見直し。
SQL*PLUSもどきを作る7 Disconnect 切断処理

SQL*PLUSもどきを作る8

Write-SqlHistory SQL実行履歴の保存
SQL*PLUSもどきを作る6(改訂版) Execute-Query SQLを実行して、結果をコンソールウィンドウに表示する。SQL実行履歴作成機能の追加。

SQL*PLUSもどきを作る9

View-History SQL履歴からの実行機能作成

SQL*PLUSもどきを作る6(改訂版2)

Execute-Query その9で作成した機能を組み込み、さらにXMLエクスポート機能を付加。

の続きです。

SQLを実行する関数 Execute-Queryをさらにカスタマイズして、SQLの実行結果をDataGridViewに表示する機能を追加したいと思います。

これを実現するためにView-Tableという関数を作成しました。

今回はこの関数について説明したい思います。この関数をExecute-Query関数から呼び出す部分は次回説明したいと思います。

この関数の実行結果は下記のようになります。

このようにデータグリッドビューに表示することによって、SQL文を書き直すことなく取得結果をソートすることが可能となります。

今回作成した関数は下記の通りです。

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
#===============================================================================
# View-DataSet: DataTableをデータグリッドへ表示する
#
# UPDATE: 2008-06-04 Ver.1.0.0
# 使用例
#   PS > View-Table [DataTable]
#
# copyright HIRO's.NET(http://hiros-dot.nte/)
#===============================================================================
function global:View-Table
{
    Param([System.Data.DataTable]$dtTbl)

    #===== Formの作成 =====
    $form = New-Object System.Windows.Forms.Form
    $form.Text = "SQL実行結果"
    $form.Width = 500
    $form.Height = 400
    
    #===== DataGridViewの作成 =====
    $dgvXML = New-Object System.Windows.Forms.DataGridView
    $dgvXML.Dock = [System.Windows.Forms.DockStyle]::Fill
    $dgvXML.DataSource = $dtTbl
    $dgvXML.ReadOnly = $True
    $form.Controls.Add($dgvXML)
    
    #===== Panelの作成 =====
    $panel1 = New-Object System.Windows.Forms.Panel
    $form.Controls.Add($panel1)
    $panel1.Dock = [System.Windows.Forms.DockStyle]::Bottom
    $panel1.Height = 30
    
    #===== [閉じる]ボタンの作成 =====
    $btnClose = New-Object System.Windows.Forms.Button
    $btnClose.Location = New-Object System.Drawing.Point(405, 4)
    $btnClose.Text = "閉じる"
    $btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
    $btnClose.Add_Click({$form.Close()})
    $panel1.Controls.AddRange($btnClose)
    
    #===== Formを表示 =====
    $form.ShowDialog()
}

開発ポイント

・パラメータはデータテーブル

呼び出し元のExecute-Query関数は、SQLの実行結果をデータセットに取り出します。

この関数では、そのデータセット内に作成されたデータテーブルを引数として受け取っています。

データグリッドビューはDataSourceプロパティにデータテーブルをセットすると、データテーブルに含まれるデータを自動で表示してくれるのでコードが短く済んでいます。

次回は、Execute-Query関数に、今回作成したData-View-を組み込みます。

 

Friday, June 06, 2008 11:20:36 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Thursday, June 05, 2008

HIRO's.NET に Silverlight コーナー設置しました

このBlogで取り上げた内容をまとめたものです。

一気に読みたい方は是非ご利用ください。