Monday, March 31, 2008

この記事は2008/03/20にわんくまブログで書いたものです。

Windows Server 2008 の評価版がダウンロード可能になったことを受けて、Standardエディションをインストールしてみました。

デフォルトではPowerShellはインストールされていません。

今回はWindows Server 2008 ServerにPowerShellをインストールする手順を紹介します。

まずはWindows Server 2008のインストールが完了したらWindows Updateを実行し、必ず最新の状態にしてから進めてください。

ここから先はWindows Updateが完了したWindows Server 2008でのPowerShellのインストール手順です。

 

1)「初期構成タスク」を起動し、「このサーバーのカスタマイズ」から「機能の追加」をクリックします。

 

 

2)「機能の追加ウィザード」が表示されるので、一覧から「Windows PowerShell」にチェックを付け[次へ(N)]をクリックします。

3)あとはインストールが完了するのを待ちます

4)インストールが完了すると、[スタート]-[すべてのプログラム]-[Windows PowerShell 1.0] から Windows PowerShell を起動することができるようになります。

Monday, March 31, 2008 5:24:13 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/11にわんくまブログで書いたものです。

PowerShell を使用して一からXmlDocumentを作成する手順を紹介します。

Step1
はじめにXmlDocumentを作成します

PS C:\Work> $XmlDoc = New-Object System.Xml.XmlDocument
PS C:\Work> $XmlDoc.GetType()

Step2
XML宣言ノード を作成するにはXmlDeclaretionクラスを使用します。

PS C:\Work> [System.Xml.XmlDeclaration]$XmlDecl = $XmlDoc.CreateXmlDeclaration("1.0","UTF-8",$Null) 

Step3
ルート要素を追加する

PS C:\Work> $rootElement = $XmlDoc.CreateElement("personal_data")

Step4
子要素を追加する
まず、子要素を作成する

PS C:\Work> $zipElement = $XmlDoc.CreateElement("zip")

Step5
子要素の値を設定する

PS C:\Work> $zipValue = $xmlDoc.CreateTextNode("012-3456")
PS C:\Work> $zipElement.AppendChild($zipValue)

Step6
子要素をルート要素に追加する

PS C:\Work> $rootElement.AppendChild($zipElement)
#text
-----
012-3456 

Step7
必要な子要素分だけStep4~Step6を繰り返します。

Step8
ルート要素をDOMドキュメントに追加する

PS C:\Work> $xmlDoc.AppendChild($rootElement) 
zip
---
012-3456 

Step9
作成したドキュメントをファイルに保存する

PS C:\Work> $XmlDoc.Save("C:\Work\Test.xml")

PowerShellでXmlDocumentを作成したくなったら参考にしてください。

Monday, March 31, 2008 5:20:23 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/06にわんくまブログで書いたものです。

Encodingを指定してXMLファイルを作成する(PowerShell Tips) で紹介した方法で、文字列からXMLファイルを作成すると、インデントと改行がされないことをお伝えしました。

ということで、今回は前回の手順に+αすることで、改行とインデントがされるようにしてみたいと思います。

まずは前回の手順どおりにXmlTextWriterまで作成します。

PS C:\Work> $SaveFile = "C:\Work\UTF8.xml"
PS C:\Work> $Encoding = [System.Text.Encoding]::UTF8
PS C:\Work> $strXml = @"
>> <?xml version='1.0' encoding='utf-8' ?>
>> <personal_data>
>> <zip_code>012-3456</zip_code>
>> <address>1-1,Tokyo,Japan</address>
>> <name>HIRO</name>
>> </personal_data>
>> "@
>> PS C:\Work> $xmlDoc = [xml]$strXml PS C:\Work> $XmlWriter = New-Object System.Xml.XmlTextWriter($SaveFile, $Encoding)

で、今回のポイントはここからです

PS C:\Work> $XmlWriter.Formatting = [System.Xml.Formatting]::Indented
PS C:\Work> $XmlWriter.Indentation = 4

XmlTextWriter のFormattingプロパティに Indentedを指定することで、作成するXmlドキュメントでインデントがされるようになります。

また、XmlTextWriter の Indentation プロパティを使用することでインデント幅を指定することができます。

上記の場合はインデント幅は空白4つ分です。

あとは、ドキュメントを保存して、XmlTextWriterを閉じておしまいです。

PS C:\Work> $xmlDoc.Save($xmlWriter)
PS C:\Work> $XmlWriter.Close()

作成されたドキュメントは下記のように改行とインデントがされています。

<xml version='1.0' encoding='utf-8'?>
<personal_data>
    <zip_code>012-3456</zip_code>
    <address>1-1,Tokyo,Japan</address>
    <name>HIRO</name>
</personal_data>

Monday, March 31, 2008 5:05:53 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/05にわんくまブログで書いたものです。

インストールされているアプリの一覧を取得するにはWMIオブジェクトの win32_product を使用します。

Get-WmiObject win32_product

リモートコンピュータのインストール済みアプリ一覧の取得は -computerName パラメータを使用して

Get-WmiObject -computerName リモートコンピュータ名 win32_product 

とします。

ただし、 win32_productは Windows VistaとWindows 2003 Server にはありません。

正確にはWindows 2003 ServerはWMIプロバイダを追加することで使用できるようになるらしいです。

OSごとに、使用可能なWMIオブジェクトが異なるのは、進化していく上で必要なことなんでしょうが.....

んー、Vistaや2003 Serverでwin32_productに代わるものってなんでしょう?

Monday, March 31, 2008 5:02:51 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/04にわんくまブログで書いたものです

文字列からXmlDocumentを作成する(PowerShell Tips)

での Xmlファイルの作成はEncodingの指定をせずに保存しました。

今回はEncodingを指定して、保存する方法を紹介します。

 

まずは保存先ファイル名とEncodingを変数に代入します。

PS C:\Work> $SaveFile = "C:\Work\UTF8.xml"
PS C:\Work> $Encoding = [System.Text.Encoding]::UTF8

次に、前回同様ヒア文字列を使用してXML文字列を作成

PS C:\Work> $strXml = @"
>> <?xml version='1.0' encoding='utf-8' ?>
>> <personal_data>
>> <zip_code>012-3456</zip_code>
>> <address>1-1,Tokyo,Japan</address>
>> <name>HIRO</name>
>> </personal_data>
>> "@
>>

で、これをXmlDocument型にキャストしておきます。

PS C:\Work> $xmlDoc = [xml]$strXml

で、前回はここで$XmlDoc.Save()メソッドを実行したのですが、ここでXmlTextWriterを作成します。

こうすることでEncodingを指定できます。

PS C:\Work> $XmlWriter = New-Object System.Xml.XmlTextWriter($SaveFile, $Encoding)

で、保存して、XmlTextWriterを閉じます。

PS C:\Work> $xmlDoc.Save($xmlWriter)
PS C:\Work> $xmlWriter.Close()

実際にファイルを開いてみると、utf-8で有ることが確認できます。(下図はサクラエディタで開いたものです)

 

 

最後に、上記を応用して、Shift_Jisで保存してみたいと思います。

PS C:\Work> $SaveFile = " ps c:\Work\Shift_Jis.xml? c:\Work>$encoding = [System.Text.Encoding]::GetEncoding("Shift_Jis")
PS C:\Work> $xmlDoc = [xml]$strXml
PS C:\Work> $XmlWriter = New-Object System.Xml.XmlTextWriter($SaveFile, $Encoding)
PS C:\Work> $xmlDoc.Save($xmlWriter)
PS C:\Work> $xmlWriter.Close()

作成したXmlファイルはShift_Jisであることが確認できます。

 

注意事項が2点あります。

1つ目はEncodingです。

UTF8のときと違って、Shift_Jistは

$encoding = [System.Text.Encoding]::Shift_Jis

とすることができません。

GetEncodingメソッドを使用して

[System.Text.Encoding]::GetEncoding("Shift_Jis")

とする必要があります。

2つ目は、Xmlファイルが改行されずに1行になってしまっていることです。

前回の方法で保存したものは改行および自動インデントがされました)

これについては、次回以降で説明したいと思います。

Monday, March 31, 2008 4:46:49 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/03にわんくまブログで書いたものです。

指定した年月のカレンダーを表示する の色つき版を作ってみました。

実行結果は下記の下段のほうです。

下図の上段のほうは、前回の実行結果です。

 

以下ソース

Get-Calendar2.ps1

#===============================================================================
# Get-Calendar2: 指定した年月のカレンダーを表示する(色つき版)
#
# パラメータ:
#       $Year: 年(省略した場合は現在の年)
#      $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
#   PS > Get-Calendar2 2008 2
#
# 使用例2(年月省略)
#   PS > Get-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net//)
#===============================================================================
function global:Get-Calendar2
{
  Param ([int]$Year = $(Get-Date).Year, [int]$Month =  $(Get-Date).Month)
  
  #表示用年月作成
  $DispMonth = New-Object DateTime($Year, $Month, 1)
  $strDispMonth = ($DispMonth.ToString("MMMM",[System.Globalization.CultureInfo]'en-US') + " " + $Year)
  #横幅35文字の中間に表示されるようにする
  Write-Host ""
  Write-Host $strDispMonth.PadLeft([int](35 - (35 - $strDispMonth.Length) / 2))
  
  $firstSunday = Get-FirstSunday $Year $Month
  $lastDay = Get-LastDay $Year $Month
  Write-Host "Sun." -foregroundcolor Red -noNewline
  Write-Host " Mon. Tue. Wed. Thu. Fri. " -noNewline
  Write-Host "Sat." -foregroundcolor Cyan
  
  # 第1日曜日が"1日"以外の第1週を表示
  if ( $firstSunday -ne 1 )
  {
    for ( $i = 1; $i -lt $firstSunday - 1; $i++ )
    {
      $week += $i.ToString("  #  ")
    }
    $spc = "     "
    $spc *= [int](7 - ( $firstSunday - 1 ))
    Write-Host ($spc + $week) -noNewline
    #土曜日をCyanにする
    Write-Host ($firstSunday - 1).ToString("  #  ") -foregroundcolor Cyan
  }
  
  #中間週を表示
  $loopWeek = [Math]::floor(($LastDay - $firstSunday) / 7)
  $Day = $firstSunday
  for ( $weekCnt = 0; $weekCnt -lt $loopWeek; $weekCnt++ )
  {
    for ( $iDay = 0; $iDay -lt 7; $iDay++ )
    {
      if ( $Day -lt 10 ) { $strDay = $Day.ToString("  #  ") }
      else               { $strDay = $Day.ToString(" ##  ") }
      
      #日曜日はRed, 土曜日はCyanにする
      if ($iDay -eq 0 )     { Write-Host $strDay -foregroundcolor Red -noNewline }
      elseif ($iDay -eq 6 ) { Write-Host $strDay -foregroundcolor Cyan}
      else                  { Write-Host $strDay -noNewline }
      $Day += 1
    }
    #Write-Host ($week)
  }
  
  #最終週を表示
  if ( $Day -le $LastDay )
  {
    $week = ""
    $LastSunday = $Day
    $Day += 1
    for ( $iDay = $Day; $iDay -le $LastDay - 1; $iDay++ )
    {
      $week += $Day.ToString(" ##  ")
      $Day += 1
    }
    
    #最終週の日曜日の色をRedにする
    Write-Host $LastSunday.ToString(" ##  ") -foregroundcolor Red -noNewline
    Write-Host $week -noNewline
    
    #最終日が土曜日の場合は色をCyanにする
    if ($LastDay - $LastSunday -eq 6) { Write-Host $LastDay.ToString(" ##  ") -foregroundcolor Cyan }
    else                              { Write-Host $LastDay.ToString(" ##  ") }
  }
}

 

ポイントは

Write-Hostコマンドレットで色を付けているということです。

前景色(文字色)はパラメータ -foregroundcolor で指定することができます。

指定可能な色は

  • Black
  • DarkBlue
  • DarkGreen
  • DarkCyan
  • DarkRed
  • DarkMagenta
  • DarkYellow
  • Gray
  • DarkGray
  • Blue
  • Green
  • Cyan
  • Red
  • Magenta
  • Yellow
  • White

です。

あとは むたぐちさんに Write-Hostコマンドレットは、-noNewlineパラメータを使用すれば改行しないで文字を出力できることを教えていただきましたので、それを使用しました。

Monday, March 31, 2008 4:35:58 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/03にわんくまブログで書いたものです。

今回は文字列からXmlDocumentを作成して、ファイルに保存する方法を紹介します。

まずは、以下のようにしてXML文字列を作成します。

PowerShellでは複数行にわたる文字列は ヒア文字列を使用することであらわすことができます。

ヒア文字列は@" ~ "@ で表します。

PS C:\Work> $strXml = @"
>> <?xml version='1.0' ?>
>> <personal_data>
>> <zipcode>012-3456</zipcode>
>> <address>1-1, Tokyo, Japan</address>
>> <name>HIRO</name>
>> </personal_data>
>> "@
>>

 

どのような文字列が代入されたのかを確認してみると

PS C:\Work> $strXML

<?xml version='1.0' ?>
<personal_data>
<zipcode>012-3456</zipcode>
<address>1-1, Tokyo, Japan</address>
<name>HIRO</name>
</personal_data>

きちんと改行されて代入されていることがわかります

次にこの文字列をXmlDocument型にキャストします。

PS C:\Work> $xmlDoc = [xml]$strXml

最後に、ファイルへ出力する方法ですが、Saveメソッドを使用して下記のように記述します。

PS C:\Work> $xmlDoc.Save("C:\Work\Test.xml")

で、ファイルに出力できたら、メモ帳などで内容を確認してみてください。

下記のようになっているかと思います。

Test.xml

<?xml version="1.0"?>
<personal_data>
  <zipcode>012-3456</zipcode>
  <address>1-1, Tokyo, Japan</address>
  <name>HIRO</name>
</personal_data>

インデントまで自動でしてくれます。

すばらしいですね。

Monday, March 31, 2008 4:11:51 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/03/03にわんくまブログで書いたものです。

今週は、PowerShellでのXMLの取り扱いについてまとめていこうかと思います。

まずはXMLファイルの読み込みから。

VB.NETだとXmlDocumentは

Dim xmlDoc As New System.Xml.XmlDocument
xmlDoc.Load("C:\Work\Test.xml")

みたいに記述します。

 

PowerShellでは

[xml]$doc = Get-Content "C:\Work\Test.xml"

と書くと、変数$docにXMLファイルが読み込まれます。

これで読み込むことができるのですが、エンコーディングはきちんと指定することをお勧めします。

エンコーディングを指定する場合は、-encodingパラメータを使用します。

-encodingパラメータには、

  • Unicode
  • UTF7
  • UTF8
  • UTF32
  • ASCII
  • BigEndianUnicode
  • Default
  • OEM

を指定することができます。

UTF8で読み込む場合は

[xml]$doc = Get-Content "C:\Work\Test.xml" -encoding UTF8

のように記述します。

で、[xml]でキャストした$docのデータ型はどうなっているかというと(GetType()メソッドで確認)

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

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     False    XmlDocument                              System.Xml.XmlNode

XmlDocumentとなっていることが確認できます。

で、使用可能なメンバーは(Get-Memberコマンドレットで確認)

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


   TypeName: System.Xml.XmlDocument

Name                        MemberType            Definition
----                        ----------            ----------
ToString                    CodeMethod            static System.String XmlNode(PSObject instance)
add_NodeChanged             Method                System.Void add_NodeChanged(XmlNodeChangedEventHandler value)
add_NodeChanging            Method                System.Void add_NodeChanging(XmlNodeChangedEventHandler value)
add_NodeInserted            Method                System.Void add_NodeInserted(XmlNodeChangedEventHandler value)
add_NodeInserting           Method                System.Void add_NodeInserting(XmlNodeChangedEventHandler value)
add_NodeRemoved             Method                System.Void add_NodeRemoved(XmlNodeChangedEventHandler value)
add_NodeRemoving            Method                System.Void add_NodeRemoving(XmlNodeChangedEventHandler value)
AppendChild                 Method                System.Xml.XmlNode AppendChild(XmlNode newChild)
Clone                       Method                System.Xml.XmlNode Clone()
CloneNode                   Method                System.Xml.XmlNode CloneNode(Boolean deep)
:
たくさんあるので省略
:

このようにPowerShellでは簡単にXMLを取り扱うことが可能です。

Monday, March 31, 2008 4:09:19 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/22にわんくまブログで書いたものです。

前回はキャラクタベースのカレンダー表示を紹介しました。

今回は、GUI版を作成したので紹介します。

 

実行イメージは下記の通りです。

 

 

View-Calendar.ps1

[void][reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
#===============================================================================
# View-Calendar: 指定した年月のカレンダーを表示する(GUI版)
#
# パラメータ:
#       $Year: 年(省略した場合は現在の年)
#      $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
#   PS > View-Calendar 2008 2
#
# 使用例2(年月省略)
#   PS > View-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:View-Calendar
{
  Param ([int]$Year = $(Get-Date).Year, [int]$Month =  $(Get-Date).Month)
  
  #===== Formの作成 =====
  $form = New-Object System.Windows.Forms.Form
  $form.Text = "Calendar"
  $form.Width = 147
  $form.Height = 210
  $form.FormBorderStyle = [Windows.Forms.FormBorderStyle]::FixedToolWindow

  #===== MonthCalendarの作成 =====
  $cal = New-Object System.Windows.Forms.MonthCalendar
  $cal.Dock = [System.Windows.Forms.DockStyle]::Fill
  $cal.SelectionStart = New-Object DateTime($Year, $Month, 1)
  $cal.SelectionEnd = New-Object DateTime($Year, $Month, 1)
  $form.Controls.Add($cal)
  
  #===== 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(61, 4)
  $btnClose.Text = "閉じる"
  $btnClose.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
  $btnClose.Add_Click({$form.Close()})
  $panel1.Controls.Add($btnClose)
  
  [void]$form.ShowDialog()
}

ポイント

見てのとおり、今回はMonthCalendarコントロールを使用しました。

MonthCalendarコントロールは、日にちをマウスで選択可能なので、フォームが閉じられる時に選択されている日を返すようにしてもよいかもしれませんね。

その場合は

[閉じる]ボタンが押される時の処理を

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

から

$btnClose.Add_Click({$form.DialogResult = "OK"; $form.Close()})

として、フォームのShowDialog()を

if ( $form.ShowDialog() -eq "OK" )
{
  retrurn $cal.SelectionStart.ToString()
}

とすればよいと思います。

Monday, March 31, 2008 4:00:06 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/21にわんくまブログで書いたものです。

PowerShellでは、カレンダーを表示するコマンドレットがないので自作してみました。

紹介する関数(Get-Calendar)は

指定した年月の最終日を取得する(PowerShell Tips)

指定した年月の第1日曜日を取得する(PowerShell Tips)

が必要です。

実行イメージは下記のとおり

Get-Calendar.ps1

#===============================================================================
# Get-Calendar: 指定した年月のカレンダーを表示する
#
# パラメータ:
#       $Year: 年(省略した場合は現在の年)
#      $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
#   PS > Get-Calendar 2008 2
#
# 使用例2(年月省略)
#   PS > Get-Calendar
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-Calendar
{
  Param ([int]$Year = $(Get-Date).Year, [int]$Month =  $(Get-Date).Month)
  
  #表示用年月作成
  $DispMonth = New-Object DateTime($Year, $Month, 1)
  $strDispMonth = ($DispMonth.ToString("MMMM",[System.Globalization.CultureInfo]'en-US') + " " + $Year)
  #横幅35文字の中間に表示されるようにする
  Write-Host ""
  Write-Host $strDispMonth.PadLeft([int](35 - (35 - $strDispMonth.Length) / 2))
  
  $firstSunday = Get-FirstSunday $Year $Month
  $lastDay = Get-LastDay $Year $Month
  Write-Host "Sun. Mon. Tue. Wed. Thu. Fri. Sat."
  
  # 第1日曜日が"1日"以外の第1週を表示
  if ( $firstSunday -ne 1 )
  {
    for ( $i = 1; $i -lt $firstSunday; $i++ )
    {
      $week += $i.ToString("  #  ");
    }
    $spc = "     "
    $spc *= [int](7 - ( $firstSunday - 1 ))
    Write-Host ($spc + $week)
  }
  
  #中間週を表示
  $loopWeek = [Math]::floor(($LastDay - $firstSunday) / 7)
  $Day = $firstSunday
  for ( $weekCnt = 0; $weekCnt -lt $loopWeek; $weekCnt++ )
  {
    $week = "";
    for ( $iDay = 0; $iDay -lt 7; $iDay++ )
    {
      if ( $Day -lt 10 ) { $week += $Day.ToString("  #  "); }
      else               { $week += $Day.ToString(" ##  "); }
      $Day += 1
    }
    Write-Host ($week)
  }
  
  #最終週を表示
  if ( $Day -le $LastDay )
  {
    $week = ""
    for ( $iDay = $Day; $iDay -le $LastDay; $iDay++ )
    {
      $week += $Day.ToString(" ##  ");
      $Day += 1
    }
    Write-Host ($week)
  }
}

 

ポイント

1.タイトル(年月)の表示

 「月」を英語で表示したかったので、ToString("MMMM")としましたが、”2月”と返ってくるので

  ToString("MMMM",[System.Globalization.CultureInfo]'en-US') として英語で取得しています。

 

 カレンダーを表示するのに必要な幅は35文字としています。

 これは1日を5文字使用して表示しているので、× 7日 = 35文字となっています。

 でタイトルは中心に表示したいので、計算して左側にスペースを入れています。(PadLeftメソッド)

 

2.カレンダーの表示

  表示は第1週、中間週、最終週の3つに分けて行っています。

  これは、第1週が必ずしも日曜日から始まるとは限らないこと、最終週が必ずしも土曜日で終わるとは限らないことを考慮したためです。

 

もうちょっとスマートに書けると良いんですが、これくらいの技量しかないので...

アドバイス等ありましたら、よろしくお願いします。

Monday, March 31, 2008 3:47:30 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/21にわんくまブログで書いたものです。

指定した年月の最終日を取得する関数を作成してみました。

Get-LastDay.ps1

#===============================================================================
# Get-LastDay: 指定した年月の最終日を取得する
#
# パラメータ:
#       $Year: 年(省略した場合は現在の年)
#      $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
#   PS > Get-LastDay 2008 2
#
# 使用例2(年月省略)
#   PS > Get-LastDay
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-LastDay
{
  Param ([int]$Year = $(Get-Date).Year, [int]$Month =  $(Get-Date).Month)
  return [System.DateTime]::DaysInMonth($Year, $Month)
}

 

関数本体よりコメントのほうが長い....

 

ポイント

DateTime構造体のDaysInMonthは、指定した年月が持つ日数を返します。

それをreturnしているだけです...

 

補足

パラメータを省略した場合は、当月の最終日を返します。

Monday, March 31, 2008 3:44:18 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/21にわんくまブログで書いたものです。

指定した年月の第1日曜日を取得する関数を作ってみました。

 

Get-FirstSunday.ps1

#===============================================================================
# Get-FirstSunday: 指定した年月の第1日曜日を取得する
#
# パラメータ:
#       $Year: 年(省略した場合は現在の年)
#      $Month: 月(省略した場合は現在の月)
#
# 使用例1(年月指定)
#   PS > Get-FirstSunday 2008 2
#
# 使用例2(年月省略)
#   PS > Get-FirstSunday
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-FirstSunday
{
  Param ([int]$Year = $(Get-Date).Year, [int]$Month =  $(Get-Date).Month)
  for ( $i = 0; $i -lt 7; $i++ )
  {
    $checkDay = New-Object DateTime($Year, $Month, [int]($i + 1))
    if ( $checkDay.DayOfWeek -eq 0 )
    {
      break
    }
  }
  return $i + 1
}

 

ポイント

なんのことはありません。

DateTime構造体のDayOfWeekメソッドを使用し、指定した年月の1~7までのどれが日曜日かを判定して返します。

 

補足

この関数は、パラメータ年、月を省略した場合は当月の第1日曜日を返すようにしてあります。

Monday, March 31, 2008 3:40:28 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/19にわんくまブログで書いたものです。

今日は、PowerShellでホスト名とIPアドレスを相互変換する関数を作ってみました。

まずはIPアドレスからホスト名を取得する関数です

Get-HostByName.ps1

#===============================================================================
# Get-HostByName: IPアドレスからホスト名を取得する
#
# 使用例
#   PS > Get-HostByName 10.84.5.10
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
[void][reflection.assembly]::LoadWithPartialName("System.Net")
function global:Get-HostByName
{
  Param ([string]$IPAddress)
  
  $hostEntry = New-Object System.Net.IPHostEntry
  $hostEntry = [System.Net.Dns]::GetHostEntry($IPAddress)
  
  return $hostEntry.HostName
}

 

ポイント

IPアドレスからホスト名を取得するのに、System.Net.DnsのGetHostEntryメソッドを使用しています。

HostEntry情報を取得したら、その中のHostNameプロパティを参照し、ホスト名を取得します。

 

次にホスト名からIPアドレスを取得する関数です。

Get-HostByAddress.ps1

#===============================================================================
# Get-HostByAddress: ホスト名からIPアドレスを取得する
#
# 使用例
#   PS > Get-HostByAddress "www.yahoo.co.jp"
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
[void][reflection.assembly]::LoadWithPartialName("System.Net")
function global:Get-HostByAddress
{
  Param ([string]$HostName)
  
  $hostEntry = New-Object System.Net.IPHostEntry
  $hostEntry = [System.Net.Dns]::GetHostEntry($HostName)
  
  return $hostEntry.AddressList[0].IPAddressToString
}

 

ポイント

こちらもSystem.Net.DnsのGetHostEntryメソッドを使用しています。

HostEntry情報を取得したら、その中のAddressList(配列で返されます)を取得し、IPAddressToString でIPアドレスのみを取得しています。

Monday, March 31, 2008 3:37:08 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/17にわんくまブログで書いたものです。

ちょっと前に、PowerShellで作ったタイピング練習用ソフトを紹介します。

 

このタイピングソフトは、CNNの記事をダウンロードしてきて、その記事から1単語ずつ画面に表示し、ユーザーにその通り入力してもらうというものです。

タイピング速度の速い人は、CNNの最新記事(英語)をちょろっと読めてしまう、一石二鳥のソフトとなっています。

制限時間は60秒1本勝負で(実際には正確に60秒にすることはできませんでした。後述します)、記事カテゴリを選択できるようにしてあります。

 

#===============================================================================
# Typing: CNNの記事(RSS)を利用してタイピング練習する
#
# パラメータ
#        なし
# 使用例
#   PS > Typing
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Typing
{
  #===============================================
  # 初期化処理
  #===============================================
  #背景色を保存
  $bgclr = $host.UI.RawUI.BackgroundColor
  
  #前景色を保存
  $fgclr = $host.UI.RawUI.ForegroundColor
  
  #問題の色を定義
  $questioncolor = [System.ConsoleColor]::Red

  $rss_list = @(
    @("Top Stories","http://rss.cnn.com/rss/cnn_topstories.rss"),
    @("World", "http://rss.cnn.com/rss/edition_world.rss"),
    @("Africa","http://rss.cnn.com/rss/edition_africa.rss"),
    @("Americas","http://rss.cnn.com/rss/edition_americas.rss"),
    @("Asia","http://rss.cnn.com/rss/edition_asia.rss"),
    @("Europe","http://rss.cnn.com/rss/edition_europe.rss"),
    @("Middle East","http://rss.cnn.com/rss/edition_meast.rss"),
    @("U.S.","http://rss.cnn.com/rss/edition_us.rss"),
    @("World Business","http://rss.cnn.com/rss/edition_business.rss"),
    @("Technology","http://rss.cnn.com/rss/edition_technology.rss"),
    @("Science & Space","http://rss.cnn.com/rss/edition_space.rss"),
    @("Entertainment","http://rss.cnn.com/rss/edition_entertainment.rss"),
    @("World Sport","http://rss.cnn.com/rss/edition_sport.rss"),
    @("Football","http://rss.cnn.com/rss/edition_football.rss"),
    @("Travel","http://rss.cnn.com/rss/edition_travel.rss"),
    @("Video","http://rss.cnn.com/rss/cnn_freevideo.rss"),
    @("Most Recent","http://rss.cnn.com/rss/cnn_latest.rss"),
    @("Art of Life Blog","http://rss.cnn.com/rss/edition_artoflife.rss"),
    @("Business Traveller Blog","http://rss.cnn.com/rss/edition_richardquest.rss"),
    @("In the Field Blog","http://rss.cnn.com/rss/edition_inthefield.rss"),
    @("World's Untold Stories Blog","http://rss.cnn.com/rss/edition_untoldstories.rss"),
    @("The Screening Room Blog","http://rss.cnn.com/rss/edition_screeningroom.rss"),
    @("Marketplace Middle East Blog","http://rss.cnn.com/rss/edition_mme.rss"),
    @("Inside the Middle East Blog","http://rss.cnn.com/rss/edition_ime.rss")
  )
  
  Write-Host "タイピング練習の問題カテゴリーを選択してください"
  for ( $icnt = 0; $icnt -lt $rss_list.Length; $icnt++)
  {
    Write-Host $($($icnt + 1).ToString("0#") + ": " + $rss_list[$icnt][0])
  }
  
  #ユーザーが選択したカテゴリ番号を保存
  $no = Read-Host
  
  if ( $([int]$no) -le 0 -and $([int]$no) -gt  $rss_list.Length )
  {
    Write-Host "Noを正しく入力してね"
    return
  }
  Write-Host "データダウンロード中..."
  $feed = [xml](new-object system.net.webclient).downloadstring($rss_list[$no - 1][1])
  $contents =$($feed.rss.channel.item | Select-Object -property DESCRIPTION)
  Write-Host "データダウンロード完了"

  foreach ( $content in $contents )
  {
    $a += $content.Description.split(" ")
  }

  Write-Host "[Enter]キーを押すと始まります"
  Read-Host
   
  $start = Get-Date
  $i = 0
  $score = 0
  $miss = 0
    
  #背景色を黒にする
  $host.UI.RawUI.BackgroundColor = [System.ConsoleColor]::Black
  cls
    
  while ( $(Get-Date).subtract($start).TotalSeconds -lt 60)
  {
    #問題を出す
    if ( $a[$i] -ne " ")
    {
      Write-Host $a[$i] -foregroundcolor $questioncolor
      
      #ユーザーからの回答入力を取得する
      $Host.UI.RawUI.ForegroundColor = $fgclr
      $input = Read-Host
      
      cls
      
      #正解したらスコアをカウントアップ
      if ( $input -ceq $a[$i] )
      {
        $score += 10
      }
      else
      {
        $miss++;
        Write-Host "`a"
        cls
      }
    }
    $i++
    
    #問題がなくなったら終了
    if ($a.Length -eq $i )
    {
      break;
    }
  }

  Write-Host $("start: " + $start)
  Write-Host $("end: " + $(Get-Date))
  Write-Host $("Score: " + $Score)
  Write-Host $("Miss:" + $miss)
}
ポイント

1.背景色と前景色

  PowerShellのコンソールウィンドウの背景色や前景色は $host.UI.RawUI のBackgroundColor と ForegroundColor を指定することで変更できます。

  色はSystem.ConsoleColor列挙体を指定します。

2.問題の色

  出題する問題(単語)の色は Write-Hostコマンドレットの-foregroundcolor パラメータで指定しています。

3.カテゴリを選択させる

 カテゴリはあらかじめ変数として持っておくこととしました。($rss_list) このとき変数は2次元配列変数にし、カテゴリ名とRSSのURLをペアで持たせています。

  $rss_list[0][1]とするとURL http://rss.cnn.com/rss/cnn_topstories.rss が取り出せるという寸法です。

  で、ユーザーにカテゴリを入力させるわけですが、Read-Hostコマンドレットを使用することで入力を取得することができます。

4.rssのダウンロード

  rssのダウンロードはsystem.net.webclientのdownloadstringメソッドを使用しています。

  [xml](new-object system.net.webclient).downloadstring($rss_list[$no - 1][1])  の部分です。

  先頭に[xml]と付けることでxmlにキャストしています。

5.descriptionタグ内容の取り出し

  $contents =$($feed.rss.channel.item | Select-Object -property DESCRIPTION)

 で行っています。 Select-Object でDescriptionを取り出します。

6.制限時間

  whileでループして60秒経過したら終わるようにしています。

  while ( $(Get-Date).subtract($start).TotalSeconds -lt 60)

  {

  }

  ただし、このタイピングソフトは正確には60秒を計測することはできません。

 なぜなら、Whileの中でRead-Hostコマンドレットを使用しているからです。

  Read-Hostコマンドレットはユーザーが[Enter]を押すまで処理を止めてしまいます。よって60秒経過してもユーザーが何も入力しなければ、このループは1時間経過しようが止まらないのです。 だれか良い方法知っていたら教えてください。 Read-Keyみたいなコマンドレット作れば良いのかしら?

7.入力ミスをしたらBeepを鳴らす

  Beep音はWrite-Host "`a" と書けば鳴らすことができます。

 

ほんとは、もう少しコードをきれいにしてから載せるつもりでしたが...

Monday, March 31, 2008 3:32:23 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/08にわんくまブログで書いたものです。

New-TimeSpanコマンドレットを使用すると、時間計算をすることができます。

まずは、単純に10:00:00~12:00:00までの差分を計算してみます。

PS> New-TimeSpan -start 10:00:00 -end 12:00:00

とすると、実行結果は

Days              : 0
Hours             : 2
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 72000000000
TotalDays         : 0.0833333333333333
TotalHours        : 2
TotalMinutes      : 120
TotalSeconds      : 7200
TotalMilliseconds : 7200000
のようになります。

-endパラメータで指定した12:00:00から-startパラメータで指定した10:00:00までの差分を表示していることがわかります。

つぎに日付まで含めた場合の、時間計算ですが下記のようにします。

(これが意外にも方法はあります。)

PS> New-TimeSpan -start (Get-Date "2007/02/03 10:00:00") -end (Get-Date "2007/02/07 12:00:00")

実行結果は下記のとおりです。

Days              : 4
Hours             : 2
Minutes           : 0
Seconds           : 0
Milliseconds      : 0
Ticks             : 3528000000000
TotalDays         : 4.08333333333333
TotalHours        : 98
TotalMinutes      : 5880
TotalSeconds      : 352800
TotalMilliseconds : 352800000

 

このように、New-TimeSpanを使用することで、簡単に時間計算を行うことができます。

Monday, March 31, 2008 3:28:58 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/02/04にわんくまブログで書いたものです。

ネタ元:http://forums.microsoft.com/TechNet-JA/ShowPost.aspx?PostID=2784931&SiteID=36

PowerShellのInvoke-Itemコマンドレットは外部アプリを起動できるコマンドレットですが、引数を渡す方法がありません。(というか見つけられれていない?)

Google先生に聞いたりしても、なかなか良い返事が聞けません。

 

PS>Invoke-Item "c:\Program Files\Mozilla Firefox\firefox.exe"  http://blog.hiros-dot.net/

と書いてもエラーになります。

 

Set-Aliasコマンドレットで

PS> Set-Alias fox "c:\Program Files\Mozilla Firefox\firefox.exe"
PS> fox http://blogs.wankuma.com/hiro/

だと、引数渡せるんですけどね....

 

Invoke-Itemでやる方法はあるのかな......?

Monday, March 31, 2008 3:20:18 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/29にわんくまブログで書いたものです。

昨年、デジタル一眼レフを購入したのですが、それをきっかけに息子のスポ少(ミニバス)の写真を撮る機会が増えました。

チームメンバーの方から写真がほしいと言われるので、専用サイトへアップするのですが元画像のままだとサイズが大きすぎるし、枚数は多いしで大変なのです。

ということでリサイズする関数を作ってみました。(jpeg専用です)

[void][reflection.assembly]::LoadWithPartialName("System.Drawing")
[void][reflection.assembly]::LoadWithPartialName("System.Drawing.Imaging")

#===============================================================================
# Resize-Image: 画像ファイルをリサイズする(jpegのみ)
#
# パラメータ
# -srcFile : リサイズ元画像ファイルパス
# -dstFile : リサイズ後画像ファイルパス
# -width   : リサイズ後の幅
# -height  : リサイズ後の高さ
# -quality : 品質
#             Default 既定の補間モード 
#             Low 低品質補間 
#             High 高品質補間 
#             NearestNeighbor 最近傍補間 
#             Bilinear 双一次補間 
#             Bicubic 双三次補間 
#             HighQualityBilinear 高品質双一次補間 
#             HighQualityBicubic 高品質双三次補間 
# 使用例
#   PS > Resize-Image "C:\Work\AAA.jpg" "C:\Work\BBB.jpg" 600 480 "HighQualityBicubic"
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Resize-Image
{
  Param([string]$srcFile, [string]$dstFile, [int]$width=0, [int]$height=0, [string]$quality="Default")

  #元画像ファイルの存在確認
  if ( (Test-Path $srcFile) -eq $False )
  {
    Write-Host "リサイズ元画像が存在しません。パスを確認してください!!"
    return
  }

  #元画像の読み込み
  $srcImg = New-Object System.Drawing.Bitmap($srcFile)
  
  $newWidth = 0
  $newHeight = 0
  #受け取った引数から、新しいサイズを決定する
  if ( $width -gt 0 -and $height -eq 0 )
  {
    $newWidth = $width
    $newHeight = $srcImg.Height / ($srcImg.Width / $newWidth)
  }
  elseif ( $height -gt 0 -and $width -eq 0 )
  {
    $newHeight = $height
    $newWidth = $srcImg.Width / ($srcImg.Height / $newHeight)
  }
  elseif ( $width -gt 0 -and $height -gt 0 )
  {
    $newWidth = $width
    $newHeight = $height
  }
  else
  {
    Write-Host "画像サイズを指定してください"
    return
  }
  
  $dstImg = New-Object System.Drawing.Bitmap($srcImg, $newWidth, $newHeight)
  $g = [System.Drawing.Graphics]::FromImage($dstImg)
  
  #画像品質の設定
  switch ($quality)
  {
    "Default" #既定の補間モード
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Default}
    "Low" #低品質補間 
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Low}
    "High" #高品質補間
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::High}
    "NearestNeighbor" #最近傍補間
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::NearestNeighbor}
    "Bilinear" #双一次補間 
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Bilinear}
    "Bicubic" #双三次補間
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Bicubic}
    "HighQualityBilinear" #高品質双一次補間 
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBilinear}
    "HighQualityBicubic" #高品質双三次補間
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::HighQualityBicubic}
    default
      {$g.InterpolationMode = [System.Drawing.Drawing2D.InterpolationMode]::Default}
  }
  
  #リサイズ画像を作成し保存する
  $g.DrawImage($srcImg, 0, 0, $newWidth, $newHeight)
  $dstImg.Save($dstFile, [System.Drawing.Imaging.ImageFormat]::Jpeg)
  
  #オブジェクトの破棄
  $srcImg.Dispose()
  $dstImg.Dispose()
}

使用方法

Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" 幅 高さ 品質

です。

品質には文字列を指定するのですが、指定できる値は下記のとおりです。

説明
"Default" 既定の補間モード
"Low" 低品質補間
"High" 高品質補間
"NearestNeighbor" 最近傍補間
"Bilinear" 双一次補間
"Bicubic" 双三次補間
"HighQualityBilinear" 高品質双一次補間
"HighQualityBicubic" 高品質双三次補間


ポイント

1.画像ファイルを扱うので、System.Drawingは必須です。 先頭でアセンブリをロードします。

2.縦横比率を維持する

 幅と高さを適切に指定すれば、見た目にもキチンとリサイズされますが、いちいち縦横比を計算してから指定するのは面倒です。 ということで幅または高さのどちらか一方を指定すると、縦横比率を計算したサイズを決定するようにしてあります。

関数内の"#受け取った引数から、新しいサイズを決定する "のコメント以下のif文がその計算を行っている箇所です。

 

ということでもう1つの使用方法ですが

Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" -width 幅 -quality 品質

または

Resize-Image "リサイズ元画像ファイルのパス" "リサイズ後の画像保存先パス" -height 高さ -quality 品質

のようにします。

これで縦横比が維持された画像が作成されます。

3.画像品質

 画像品質を指定するにはInterpolationModeを使用します。

 

Monday, March 31, 2008 3:15:04 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/23にわんくまブログで書いたものです。

データを取得してXMLファイルへ保存する(Oracle) (Windows PowerShell Tips)

データを取得してXMLファイルへ保存する その2(Oracle) (Windows PowerShell Tips)

で、Oracleから取得したデータをXML出力する例を紹介しました。

XMLを出力しただけでは見るのが不便なので、簡易XMLビューアを作ってみました。
実行例は下記のとおりです。

 

View-Xml.ps1

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

使用方法は
View-Xml "XMLファイルのパス"
です。

ポイントは
・データセットを作成して、XMLファイルを読み込む
  $dtSet = New-Object System.Data.DataSet
  $dtSet.ReadXml($XmlFile)


・データセットをDataGridViewに連結する
  $dgvXML.DataSource = $dtSet.Tables[0]

・anchorプロパティ
 anchorプロパティは -bor 演算子を使うとうまくいきます。(-or演算子は試してみたところダメでした)
  -bor はビットごとのOR演算を行います。


です。

あとは、前回までのポイントを御参考下さい。

Monday, March 31, 2008 3:02:28 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/22にわんくまブログで書いたものです。

ネタ元: データを取得してXMLファイルへ保存する(Oracle) (Windows PowerShell Tips)

でOracleデータベースからデータを取得し、XMLファイルへ保存する関数を紹介しました。
今回は、これを改善し、

  • 取得したデータをWinodwsフォームのDataGridViewへの表示
  • [XMLへ保存]ボタンが押されたら、ファイル保存ダイアログを表示し、任意の名前を付けて保存
    ができるようにしてみました。

Export-OracleDataXml2.ps1

#===============================================================================
# Export-OracleDataXml2: データを取得してXMLファイルへ保存する(Oracle)
#
# 使用例
#   PS > Export-OracleDataXml
#   PS > DataSource: データソース名
#   PS > User ID: ユーザーID
#   PS > Password: パスワード
#   PS > Query String: クエリ文字列
#
# copyright HIRO's.NET(http://hiros-dot.net.com/)
#===============================================================================
function global:Export-OracleDataXml2
{
  #===== 必要情報をユーザーから取得する =====
  $DataSource = Read-Host "Data Source"
  $UserID = Read-Host "User ID"
  $Password = Read-Host "Password" -assecurestring
  $QueryString = Read-Host "Query String"
  
  #===== newpopsさんのblog参照 http://d.hatena.ne.jp/newpops/20050923/p1 =====
  #SecureStringからパスワード文字列を取得する
  $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
  $pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
  
  #===== Oracleからのデータ取得 =====
  [reflection.assembly]::LoadWithPartialName("System.Data.OracleClient")
  $ConnectionString = "Data Source=" + $DataSource + ";User ID=" + $UserID + ";Password=" + $Pass + ";Integrated Security=no;"
  $OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
  $dtSet = New-Object System.Data.DataSet
  $OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($QueryString, $OraConn)
  $OraDa.Fill($dtSet)
  
  #===== Formの作成 =====
  [reflection.assembly]::LoadWithPartialName("System.Windows.Forms")
  $form = New-Object System.Windows.Forms.Form
  $form.Text = $DataSource + "@" + $UserID
  $form.Width = 500
  $form.Height = 400

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

  #===== [XMLへ保存]ボタンの作成 =====
  $btnExport = New-Object System.Windows.Forms.Button
  $btnExport.Location = New-Object System.Drawing.Point(324, 4)
  $btnExport.Text = "XMLへ保存"
  $btnExport.anchor = [System.Windows.Forms.AnchorStyles]::Top -bor [System.Windows.Forms.AnchorStyles]::Right
  $btnExport.Add_Click(
  {
    #===== ファイル保存ダイアログを作成 =====
    $dlgSave = New-Object System.Windows.Forms.SaveFileDialog
    $dlgSave.DefaultExt = "XML"
    $dlgSave.Filter = "XMLファイル(*.xml)|*.xml"
    if ( $dlgSave.ShowDialog() -eq [System.Windows.Forms.DialogResult]::OK )
    {
      #===== データを保存する =====
      $dtSet.WriteXml($dlgSave.Filename)
    }
  })
  $panel1.Controls.Add($btnExport)
  
  #===== [閉じる]ボタンの作成 =====
  $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()
}

 

実行結果は、下記のとおりです。

 

今回のポイント
・Windows フォームを作成する
VB.NETやC#で開発をされている方は、ソースを見ると何となくわかると思います。


**VB.NET**

Dim form As New Form()


**C#**

Form form = new Form();


**PowerShell**

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


でフォームのインスタンスを作成します。

・各コントロールの作成とフォームへの配置
コントロールを作成してフォームへ配置するには

$control = New-Object System.Windows.Forms.コントロール


のように記述してコントロールを作成して

$form.ControlAdd($control)


としてフォームへ配置します。
今回、ボタンはパネル上に配置したので

$panel1.Controls.Add($btnExport)


のようになっています。

・ボタンのクリックイベント


ボタンのクリックイベントは

$button.Add_Click({ここに処理したいスクリプトを記述})


のように記述します。

Monday, March 31, 2008 2:48:36 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/15にわんくまブログで書いたものです。

ネタ元:データを取得してXMLファイルへ保存する(Oracle) (PowerShell Tips)

で、SecurityStringの話をちらっとしたのですが、関数化しておくとSecurityStringからの文字列取得が少し楽になると思います。

ということで

Convert-ToStringBSTR.ps1

#===============================================================================
# Convert-ToStringBSTR: SecurityString文字列を解読した値を返す
#
# 使用例
#   PS > Convert-ToStringBSTR $SecurityString
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Convert-ToStringBSTR
{
  Param([System.Security.SecureString]$SecureString)
  
  $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($SecureString)
  $pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
  
  return $pass
}

使用方法ですが、まずSecurityStringを準備します

たとえば

PS C:\Work> $a = Read-Host "何か文字列を入力してね" -assecurestring

で、

PS C:\Work> Convert-ToStringBSTR $a

とすると解読した文字列が表示されます。

Monday, March 31, 2008 2:43:26 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/15にわんくまブログで書いたものです。

Windows PowerShellからOracleへアクセスし、取得したデータをXMLファイルへ落とし込む関数を作ってみました。

Export-OracleDataXml.ps1

#===============================================================================
# Export-OracleDataXml: データを取得してXMLファイルへ保存する(Oracle)
#
# 使用例
#   PS > Export-OracleDataXml
#   PS > DataSource: データソース名
#   PS > User ID: ユーザーID
#   PS > Password: パスワード
#   PS > Query String: クエリ文字列
#   PS > Save Path: 保存先を指定
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Export-OracleDataXml
{
  #===== 必要情報をユーザーから取得する =====
  $DataSource = Read-Host "Data Source"
  $UserID = Read-Host "User ID"
  $Password = Read-Host "Password" -assecurestring
  $QueryString = Read-Host "Query String"
  $SavePath = Read-Host "Save Path"
  
  #保存先パスに"\"が含まれていない場合(つまりファイル名のみが指定されていた場合)は
  #絶対パスにする(ファイル名のみが指定された場合、カレントディレクトリに保存するため)
  if ( $SavePath.IndexOf("\") -eq -1 )
  {
    $SavePath = $(Join-Path $(Get-Location).Path $SavePath)
  }
  
  #===== newpopsさんのblog参照 http://d.hatena.ne.jp/newpops/20050923/p1 =====
  #SecureStringからパスワード文字列を取得する
  $ptr = [System.Runtime.InteropServices.Marshal]::SecureStringToBSTR($Password)
  $pass = [System.Runtime.InteropServices.Marshal]::PtrToStringBSTR($ptr)
  
  #===== Oracleからのデータ取得とファイルへの保存 =====
  [reflection.assembly]::LoadWithPartialName("System.Data.OracleClient")
  $ConnectionString = "Data Source=" + $DataSource + ";User ID=" + $UserID + ";Password=" + $Pass + ";Integrated Security=no;"
  $OraConn = New-Object System.Data.OracleClient.OracleConnection($ConnectionString)
  $dtSet = New-Object System.Data.DataSet
  $OraDa = New-Object System.Data.OracleClient.OracleDataAdapter($QueryString, $OraConn)
  $OraDa.Fill($dtSet)
  $dtSet.WriteXml($SavePath)
}

最初に使用方法ですがコンソールウィンドウに

PS C:\Work> Export-OracleDataXml

と入力します。

つぎに、接続先、ユーザー名、パスワード、データを取得するためのselect文、取得データの保存先を聞かれるので順番に入力していきます。

下記はOracleのサンプルであるscott/tigerのemp表データをすべて取得し、結果をC:\Work\emp.xmlへ保存する例です

PS C:\Work> Data Source: YourServer
PS C:\Work> User ID: scott
PS C:\Work> Password: *****
PS C:\Work> Query String: select * from emp
PS C:\Work> SavePath: C:\Work\emp.xml

 

===== ポイント =====

今回の関数は対話式にしてみました。

1)Read-Hostコマンドレットを使用して、ユーザーからの入力を取得して、変数へ代入しています。

 Read-Hostコマンドレットは

 $a = Read-Host "メッセージ"

 のように使用します。

 この場合は、コンソールに "メッセージ:" と表示され

 ユーザーが[Enter]を押すまでの文字列を$aに代入します。

2)SecureStringでパスワードを*で表示する

 Read-Hostコマンドレットのパラメータに -assecurestring というのがあるんですが、このパラメータを使用すると、ユーザーが入力する文字列が * で表示されます。

 -assecurestringを使用すると、変数の型がSystem.Security.SecureStringになります。

  System.Security.SecureString型のデータはこのままでは使用できません。

 このままでif文などで比較しても正しい結果は得られないので、解読してString型に変換する必要があります。

 newpopsさんのblogにその方法が書かれてありましたので参考にさせていただきました。(http://d.hatena.ne.jp/newpops/20050923/p1

3)System.Data.OracleClientの読み込み

 PowerShell起動時はSystem.Data.OracleClientは読み込まれていません。

 [reflection.assembly]::LoadWithPartialName で System.Data.OracleClientをロードし、OracleClientクラスを使用可能にしています。

4) DataSetを作成する

 取得したデータをXmlへ出力するのに、DataSetのWriteXmlメソッドを使用することにしました。

 New-Obejctコマンドレットを使用してDatSetを作成しています。

5)DataAdapterを作成する

 これもNew-Objetctコマンドレットを使用しています。

6)XMLへ出力する

 4)で述べたとおり、DataSetのWriteXmlメソッドを使用してXMLファイルへの出力を行います。

Monday, March 31, 2008 2:39:43 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/09にわんくまブログで書いたものです。

指定したファイルの行数を取得する(Windows PowerShell Tips) を関数にしたものが下記です。

===============================================================================
# Get-LineCount: 指定したファイルの行数を取得する
# Param: 
#   $filepath : 行数カウントを行うファイルのパス
#
# 使用例
#   Get-LineCount Test.txt
#
#   ヘルプを見る場合は
#   Get-LineCount /?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Get-LineCount
{
  Param ([string]$filepath)
  
  #ヘルプの参照か?
  if ( $filepath -eq "/?" )
  {
    $helpmsg = @"
    書式`r`n
      Get-LineCount ファイル名
    `r`n
    使用例`r`n
      #Test.txtの行数を取得
      Get-LineCount `"Test.txt`"
      
      #ヘルプを参照する
      Get-LineCount /?
      
"@
    
    Write-Host $helpmsg
    return
  }
    
  $MeasureObject = Get-Content $filepath | Measure-Object
  return $MeasureObject.count
}

使用方法は

PS C:\Users\HIRO> Get-LineCount "Test.txt"
12

です

Monday, March 31, 2008 2:29:19 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/09にわんくまブログで書いたものです。

PowerShellにはファイル操作を行うコマンドレットがいくつか(Get-Content, Add-Contentなど)あるのですが、ファイルの行数を取得できるようなコマンドレットはありません。

たとえばGet-Contentコマンドレットはファイル内容を取得するコマンドレットですが、ファイル行数を取得すようなパラメータは存在しません。

既存のコマンドレットの組み合わせで何とかならないか模索していたところ Get-ContentとMeasure-Objectコマンドレットで行けそうなことがわかりました。

 

Get-Contentで読み取った内容を、パイプを使用してMeasure-Objectへ渡してやると Countプロパティで行数を取得することができます。

PS C:\Users\HIRO> Get-Content "Test.txt" | Measure-Object

Count    : 13
Average  :
Sum  :
Maximum  :
Minimum  :
Property :

といった感じです。

上記は、Test.txtは13行あることを示しています。

Monday, March 31, 2008 2:25:07 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

こ記事は2008/01/04にわんくまブログで書いたものです。

Windows PowerShell Visual Studio 2005 Templatesの導入 - コマンドレットの開発(2) -

で、コマンドレット属性の設定方法について説明しました。

簡単におさらいすると

public class ~ の1行上に

[Cmdlet(VerbsCommon.Get, "IPFromHost", SuppoertShouldProcess = true)]

と記述することでコマンドレット名称が決定します。

この場合は、Get-IPFromHost となります。

コマンドレット名称の動詞部分を決定するのに、VerbsCommon列挙体を指定しましたが、実はこのほかにも使用可能な列挙体があります。

使用可能な列挙体はVertbsCommonを含め、下記のとおりです。

列挙体 メンバ
VerbsCommon Add, Clear, Copy, Get, Join, Lock, Move, New, Remove, Rename, Select, Set, Split, Unlock    
VerbsCommunication Connect, Disconnect, Read, Receive, Send, Write
VerbsData Backup, Checkpoint, Compare, Convert, ConvertFrom, ConvertTo, Dismount, Export, Import, Initialize, Limit, Merge, Mount, Restore, Update, Out
VerbsDiagnostic Debug, Measure, Ping, Resolve, Test, Trace
LifecycleVerbs Disable, Enable, Install, Restart, Resume, Start, Stop, Suspend, Uninstall
Security Verbs Block, Grant, Revoke, Unblock

各列挙体のメンバ詳細のリンク先は下記の通りです。(英語のみです)

VerbsCommon
http://msdn2.microsoft.com/en-us/library/system.management.automation.verbscommon_members(VS.85).aspx

VerbsCommunication
http://msdn2.microsoft.com/en-us/library/system.management.automation.verbscommunications_members(VS.85).aspx

VerbsDiagnostics
http://msdn2.microsoft.com/en-us/library/system.management.automation.verbsdiagnostic_members(VS.85).aspx

VerbsLifecycle
http://msdn2.microsoft.com/en-us/library/system.management.automation.verbslifecycle_members(VS.85).asp

VerbsSecurity
http://msdn2.microsoft.com/en-us/library/system.management.automation.verbssecurity_members(VS.85).aspx

上記メンバに、自分が指定したい動詞がない場合どうするか

ですが

実はこのCmdlet属性の第1引数は、よく見るとstring型となっています。

なので、たとえば Insert-Data というコマンドレット名にしたい場合は

[Cmdlet("Insert", "Data", SuppoertShouldProcess = true)]

Replace-Contentというコマンドレット名にしたい場合は

[Cmdlet("Replace", "Content", SuppoertShouldProcess = true)]

のように記述すればOKということになります。

 

ただ、なるべくなら事前に準備されている動詞を使用することをお勧めします。

Monday, March 31, 2008 1:43:10 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/05にわんくまブログで書いたものです。

Windows PowerShell Visual Studio 2005 Templatesの導入 - インストール編 -
Windows PowerShell Visual Studio 2005 Templatesの導入 - コマンドレットの開発(1) -
Windows PowerShell Visual Studio 2005 Templatesの導入 - コマンドレットの開発(2) -

の続きです。

 

これまで、Windows PowerShell Visual Studio 2005 Templatesを使用して自作コマンドレットを開発してきました。

こうして開発したコマンドレットをスナップインと呼びます。

今回は、このスナップインをインストールし実際に使用するまでを説明します。

 

前回コマンドレット開発後にビルドをする説明が抜けていました。

各自ビルドを行いSampleCmdlet.dllというファイルを作成してから作業を始めてください。

 

まずWindows PowerShellを起動します。

Vistaを使用している方は「管理者として実行」でPowerShellを起動してください。

 

インストールディレクトリの作成

はじめにWindows PowerShellがインストールされているディレクトリに、スナップインのインストール先ディレクトリを作成したいと思います。

$PSHomeという自動変数に、Windows PowerShellのインストール先ディレクトリが格納されているので

PS C:\Work> cd $PSHome

と入力し、カレントディレクトリを移動し

PS C:\Windows\System32\WindowsPowerShell\v1.0> mkdir SnapIn

と入力してスナップインのインストール先ディレクトリを作成します。

 

スナップインのインストール

作成したスナップイン(SampleCmdlet.dll)を先ほど作成した SnapInディレクトリにコピーします。

次に  Visual Studio 2005 コマンドプロンプトを起動して(Vistaを使用している方は「管理者として実行」)

InstallUtil.exe "C:\Windows\System32\WindowsPowerShell\v1.0\SnapIn\SampleCmdlet.dll"

を実行します。

PowerShellからインストールする場合は

&"$env:windir/Microsoft.NET/Framework/v2.0.50727/InstallUtil.exe" ($PSHome + "\SnapIn\SampleCmdlet.dll")

とします。

 

最後にAdd-PSSnapinコマンドを実行します。

PS C:\Windows\System32\WindowsPowerShell\v1.0> Add-PSSnapin SampleCmdlet

スナップインが登録されたかどうかをGet-PSSnapinコマンドレットで確認してみます。

PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-Pssnapin SampleCmdlet

Name        : SampleCmdlet
PSVersion   : 1.0
Description : サンプルコマンドレットです

と表示されれば、登録されている状態です。

 

登録したスナップインを使用する

では、実際に使用してみましょう。

PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-IPFromHost "www.google.com"

として、確認してみてください。

IPアドレスを取得することができればOKです。

以上でWindows PowerShell Visual Studio 2005 Templatesの導入説明は終わりです。

 

注意事項

作成したスナップインを使用するには、PowerShellを起動するたびにAdd-PSSnapinコマンドレットを実行する必要があります。

毎回登録するのが面倒だと思う方は PowerShellにおけるプロファイルの作成 を参考にしてプロファイルを作成し

Add-PSSnapin SampleCmdlet

の1行を追加しておくことをおすすめします。

こうすることで、スナップインが自動で登録されるようになります。

Monday, March 31, 2008 1:18:10 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2008/01/04にわんくまブログで書いたものです。

Windows PowerShell Visual Studio 2005 Templatesの導入 - インストール編 -
Windows PowerShell Visual Studio 2005 Templatesの導入 - コマンドレットの開発(1) -

の続きです。

 

今回は、実際にVisual Studio 2005を使用したPowerShellのコマンドレットの開発方法について説明したいと思います。

まずは前回作成したSampleCmdletプロジェクトを開き、新しい項目の追加を行います。

テンプレート欄の「マイテンプレート」に Winodws PowerShell Cmdlet と Windows PowerShell PSCmdlet の2つの項目があることがわかります。

・Windows PowerShell CmdletはVB.NETやC#から直接呼び出せるコマンドレットの作成

・Windows PowerShell PSCmdlet はPowerShellに組み込まれたコマンドレットの作成

を行うことができます。

 

今回は、IPHostEntryクラスを使用して、ホスト名からIPアドレスを取得するコマンドレットGet-IPFromHostを作成してみようと思います。

1.マイテンプレートから「Windows PowerShell PSCmdlet」を選択

2.ファイル名を入力

 (ファイル名には作成するコマンドレットの名詞部分を使用することをおすすめします。

  今回はコマンドレット名がGet-IPFromHostなので"IPFromHost"をファイル名にします。

  あとで説明しますが、このファイル名が作成されるファイルのパラメータ部分に自動セットされます)

3.[追加]ボタンを押す

作成されたファイルIPromHost.csは下記のようになります。

コマンドレットの属性について

public class IPFromHost : PSCmdlet の1行上にあるの "[" から "]" までが、コマンドレットの属性となります。

VerbsCommon列挙体がコマンドレット名の動詞部分になります。作成する Get-IPFromHost コマンドレットは動詞部分が Get なので、ここではVerbsCommon.Getを選択します。

また名詞部分はIPFromHostなので、第2引数は"IPFromHost"を指定します。

これらの設定により、コマンドレット名がGet-IPHostEntryとなります。

属性の SupportShouldProcess ですが、True に設定するとシステムを変更する操作が実行される前にユーザーに確認を求めることができます。

これは-whatIf, -confirmパラメータをサポートすることを意味します。

SupportShouldProcess がFalse (既定値) に設定されている場合は、コマンドレットが ShouldProcess メソッドの呼び出しをサポートしないことを示します。

 

コマンドレットパラメータについて

コマンドレットのパラメータを作成する場合は、クラスにプロパティを追加する必要があります。

先ほど選択したテンプレート「Windows PowerShell PSCmdlet」はコマンドレットパラメータが自動で挿入されるようになっています。

#region Parametersから#endregion までがコマンドレットパラメータ記述用プロパティとなります。

ただしこの部分はコメントアウトされているので、コマンドレットにパラメータを持たせる場合には、この部分のコメントを外して作成します。

 

コマンドレット本体について

コマンドレット本体は protected override void ProcessRecordに記述します。

この中でWriteObjectメソッドを使用するとPowerShellのコマンドプロンプトにメッセージを出力することができます。

 

Get-IPFromHostの仕様

まず仕様について説明します。

Get-IPFromHost "ホスト名"

と入力すると、入力したホスト名からIPアドレスを取得して表示する というコマンドレットを作成したいと思います。

 

 

Get-IPFromHostのパラメータの作成

先ほど、パラメータはクラスのプロパティとして作成することを説明しました。

今回、パラメータ名はHostnameとしたいと思います。

#region Parameters ~#endregionまでのコメントを外して下記のように入力してください。


#region Parameters

private string _hostname = string.Empty;

[Parameter(Position = 0,
    Mandatory = true,
    ValueFromPipelineByPropertyName = true,
   HelpMessage = "ホスト名を指定します")]
[ValidateNotNullOrEmpty]
public string Hostname
{
    set { _hostname = value; }
}

#endregion

 

上述のコードですが、クラスのプロパティ名 = コマンドレットのパラメータ名になるので、プロパティ名をHostnameにします。

また、コマンドラインから受け取った値はvalue変数にセットされます。

今回はホスト名がvalue変数にセットされるので、プライベート変数 _hostnameにセットし、ProcessRecordメソッドで使用できるようにしておきます。

 

パラメータ属性について

属性のMandatoryですが、これはパラメータの省略可否を示します。省略できないパラメータにはtrueをセットします。

今回は、ホスト名からIPアドレスを取得するので、パラメータHostnameは省略できないパラメータとなりますので、Mandatory = true とします。

このようにすると、パラメータを省略してコマンドレットを実行した場合は、パラメータを指定するよう指示が表示されます。

またHelpMessage属性にはパラメータの説明を記述しておきます。

!? でパラメータのヘルプを表示することができるようになります。

 

 

Get-IPFromHost本体の作成

いよいよ本体のコーディングです。

ホスト名からIPアドレスを取得するにはSystem.Net.IPHostEntryクラスを使用します。

今回はコマンドレットの作成が主なので、この辺の説明は割愛させて頂きます。

 

コマンドレット本体のコードはProcessRecord()に記述します。

コードの説明ですが

パラメータとして受け取った値(_hostname)を使用してipentryを作成し、IPアドレスを取得します。

取得したIPアドレスはWriteObjectメソッドを使用して、コマンドラインに出力しています。


下記が本体のコードです。

 

protected override void ProcessRecord()
{
    try
    {
        System.Net.IPHostEntry ipentry = System.Net.Dns.GetHostEntry(_hostname);
        System.Net.IPAddress hostadd = ipentry.AddressList[0];

        WriteObject(hostadd.ToString());

        throw new NotImplementedException();
    }
    catch (Exception)
    {
    }
}

 

次回は作成したコマンドレットのインストールについて説明したいと思います。

Monday, March 31, 2008 12:48:15 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Saturday, March 29, 2008

この記事は、2008/01/03にわんくまブログで書いたものです。

前回はインストールについて説明を行ったので、今回は実際にコマンドレットの開発について説明をしたいと思います。

とはいっても全部説明すると長くなるので、今回はプロジェクトの作成方法とPSSnapinクラスについて説明します、

1.Visual Studio 2005を起動し、プロジェクトの作成を行います。

1-1)「新しいプロジェクト」のプロジェクトの種類で、Visual C#(VB.NETでもよい)の中の[Windows PowerShell]を選択

1-2)マイテンプレートで[Windows PowerShell]を選択

1-3)プロジェクト名を入力(ここではSampleCmdletとしました)

1-4)[OK]ボタンを押す


 

2.ソリューションエクスプローラを見ると、必要な参照設定が行われ、PSSnapin.csというファイルが追加されていることがわかります。

Windows PowerShell Visual Studio 2005 Templateを導入しないと自分で行う必要があります。


3.ソリューションエクスプローラでPSSnapin.csを右クリックし[コードの表示]を選択します。

(PSSnapin.csはダブルクリックでは開くことができません。ダブルクリックすると「デザイナの読み込み時に 1 つ以上のエラーが発生しました。」という画面が表示されますので注意してください)

 

4.PSSnapinクラスについて

   自動で作成された PSSnapin.cs はPSSnapInクラスの派生クラスです。

 このクラスによって、インストールとスナップインの登録が可能となります。

 Nameプロパティはスナップインの名称

 Vendorプロパティは制作者の名前

 Descriptionプロパティは、スナップインの説明

 を設定します。

 NameプロパティとDescriptionプロパティは、スナップイン登録後にGet-PSSnapinコマンドレットで確認することが可能です。


using System;
using System.Collections.Generic;
using System.Text;
using System.Management.Automation;
using System.ComponentModel;

namespace SampleCmdlet
{
[RunInstaller(true)]
public class SampleCmdletSnapIn : PSSnapIn
{
public override string Name
{
get { return "SampleCmdlet"; }
}
public override string Vendor
{
get { return "HIRO's.NET"; }
}
public override string VendorResource
{
get { return "SampleCmdlet,"; }
}
public override string Description
{
get { return "サンプルコマンドレットです"; }
}
public override string DescriptionResource
{
get { return "SampleCmdlet,Registers the CmdLets and Providers in this assembly"; }
}
}
}
次回は、実際のコマンドレット開発手法について説明したいと思います。
Saturday, March 29, 2008 10:31:18 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は、2008/01/03にわんくまブログで書いたものです。


Visual Studio 2005を使用するとWindows PowerShellのスナップインやコマンドレットの開発を行うことが可能です。

しかし、各種参照設定や属性の設定などの下準備が必要です。

この下準備を自動で行うWindows PowerShell Visual Studio 2005 Templatesと呼ばれるテンプレートをDavid Aikenさんという方が提供してくださっています。

1.  http://channel9.msdn.com/ShowPost.aspx?PostID=256835 にアクセスし[Save]と書かれたところクリックし256835_PSTemplates.zip をダウンロードします。

PowerShellTemplate01

2.ダウンロードしてきたファイルを解凍します。


3.自分が開発に使用する言語がC#の場合には Windows PowerShell (CS).vsi を

VB.NETを使用する場合はWindows PowerShell (VB).vsi をダブルクリックします。

4.「インストールするコンテンツの選択」が表示されるので全てにチェックを付けて[次へ]を押します。

(画像はC#を選択した場合の例です)


5.「署名が見つかりません」が表示されますが[はい]を押して、インストールを続行します。


6.「コンテンツにインストール」が表示されるので[完了]を押すと、インストールが始まります。


7.インストールが完了します


 

次回はこのテンプレートを使用した、PowerShellのコマンドレット開発について説明したいと思います。

Saturday, March 29, 2008 10:14:17 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/28にわんくまブログで書いたものです。

HTTPダウンロードするには を関数にしてみました。

使用方法は

HTTPダウンロードする。この場合はカレントディレクトリに保存されます。

Download-File "http://hiros-dot.net/index.html" 

保存先ディレクトリを指定してダウンロードする

PS > Download-File "http://hiros-dot.net/index.html" "c:\Work"

保存先ディレクトリに名前を付けてダウンロードする

PS > Download-File "http://hiros-dot.net/index.html" "C:\Work" "sample1.html"

ヘルプを表示するする

PS > Download-File /?

Download-File.ps1

#===============================================================================
# Download-File: 指定されたリモート ファイルをダウンロードする
# Param:
# $url : ダウンロードするファイルURL
# $SaveDir : 保存先ディレクトリ(省略した場合はカレントディレクトリ)
# $filename : 保存ファイル名(省略した場合はダウンロードしたファイル名となる)
#
# ヘルプを見る場合は
# Download-File /?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Download-File
{
Param ([string]$url, [string]$SaveDir, [string]$filename)

#ヘルプの参照か?
if ( $url -eq "/?" )
{
$helpmsg = @"
書式`r`n
Download-File [`$url] [[`$SaveDir]] [[`$filebame]]`r`n
パラメータ`r`n
`$url ダウンロードするファイルURL`r`n `$SaveDir ダウンロードしたファイルを保存するディレクトリ 省略した場合はカレントディレクトリに保存します`r`n `$filename 保存ファイル名 省略した場合はダウンロードしたフィル名となります`r`n `r`n 使用例`r`n # http://hiros-dot.net/index.html をダウンロードする # この場合はカレントディレクトリに index.html というファイル名で保存される Download-File "http://hiros-dot.net/index.html" #指定したディレクトリに保存する Download-File "http://hiros-dot.net/index.html" "C:\Work" #指定したディレクトリに名前を付けて保存する #この場合は C:\Work に sample1.html という名前で保存する Download-File "http://hiros-dot.net/index.html" "C:\Work" "sample1.html" #ヘルプを参照する Get-DateFileName /? "@ Write-Host $helpmsg return } $webClient = new-object System.Net.WebClient #保存先が指定されていない場合 if ( $SaveDir.Length -eq 0 ) { #カレントディレクトリを保存先にする $SaveDir = $(get-location).Path } #保存ファイル名が指定されていない場合 if ( $filename.Length -eq 0 ) { #指定されたURLからファイル名を取得 $uri = new-object Uri($url) $filename = $uri.Segments[$uri.Segments.Length-1] } if ( $filename -eq "/" ) { Write-Host "ダウンロードできません。`r`nURLはファイル名を含めて指定してください!!" -foregroundcolor red return } #保存先パス文字列の作成 $filePath = [System.IO.Path]::Combine($SaveDir, $filename) #ダウンロードする $webClient.DownloadFile($url,$filePath) }
Saturday, March 29, 2008 8:12:39 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/28にわんくまブログで書いたものです。

PowerShellでHTTPダウンロードするには、System.Net.WebClient クラスを使用します。

PS > $webClient = new-object System.Net.WebClient
PS > $webClient.DownloadFile("http://hiro.wankuma.com/index.html", "C:\Work\index.html")

上記は http://hiros-dot.net/index.html をダウンロードして C:\Work に index.html として保存します。

Saturday, March 29, 2008 8:08:58 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/28にわんくまBlogで書いたものです

ファイルの拡張子を変更する を関数にしてみました。

使用例

sample1.txt の拡張子を.bakに変更する

PS > Change-Extension "sample1.txt" "bak" 

sample1.txt と sample2.txt の拡張子を.bakに変更する

PS > Change-Extension "sample1.txt","sample2.txt" "bak" 

ヘルプを参照する

PS > Change-Extension /? 

Change-Extension.ps1

#===============================================================================
# Change-Extension: ファイルの拡張子を変更する
# Param:
# $path : 拡張子を変更するファイル
# $newExtension: 変更後の拡張子
# $echo : "on"を指定すると変更履歴を表示。規定値は"off"
#
# 使用例
# #sample1.txt の拡張子を.bakに変更する
# Change-Extension "sample1.txt" "bak"
#
# #sample1.txt と sample2.txt の拡張子を.bakに変更する
# Change-Extension "sample1.txt","sample2.txt" "bak"
#
# ヘルプを見る場合は
# Change-Extension /?
#
# copyright HIRO's.NET(http://hiros-dot.net/)
#===============================================================================
function global:Change-Extension
{
Param ([String[]]$path, [String]$newExtension, [String]$echo="off")

#ヘルプの参照か?
if ( $path -eq "/?" -or $newExtension -eq "/?" -or $echo -eq "/?" )
{
$helpmsg = @"
書式`r`n
Change-Extension [`$path], [`$newExtension], [`$echo ]`r`n
パラメータ`r`n
`$path 拡張子を変更する項目のパスを指定します。`r`n `$newExtension 変更後の拡張子を指定します`r`n `$echo 変更履歴を表示する場合は`"on`"を指定します。規定値は`"off`"です。`r`n `r`n 使用例`r`n #sample1.txt の拡張子を.bakに変更する Change-Extensio `"sample1.txt`" `"bak`" #sample1.txt と sample2.txt の拡張子を.bakに変更する Change-Extensio `"sample1.txt`",`"sample2.txt`" `"bak`" #変更履歴を表示する Change-Extension "sample1.txt" "bak" "on" #ヘルプを参照する Get-DateFileName /? "@ Write-Host $helpmsg return } foreach ( $file in $path ) { #拡張子返還後のファイル名を取得 $newfile = [System.IO.Path]::ChangeExtension($file, $newExtension) #ファイル名を変更する if ( Test-Path $file ) { Rename-Item $file $newfile # $echo が "on"なら変換結果を表示 if ( $echo -eq "on" ) { Write-Host ($file + " --> " + $newfile) } } elseif ( $echo -eq "on" ) { Write-Host ($file + " は存在しませんでした") } } }
Saturday, March 29, 2008 8:02:36 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/28 にわんくまブログで書いたものです。

ファイルの拡張子を変更するには、System.IO.PathクラスのChangeExtensionメソッドを使用します。

下記は sample1.txt の 拡張子 txt を 拡張子 log へ変更したファイル名を取得しています。
ChangeExtensionメソッドは、実際のファイルの拡張子を変更するのではなく、変更した場合のファイル名を文字列として返します。

PS C:\Work> [System.IO.Path]::ChangeExtension("sample1.txt",".log")
sample1.log

あとはRename-Itemコマンドレットを使用して、実際にファイルの拡張子を変更します。

手順としては

(1)拡張子を変更する前のファイル名を変数にセットします。
(2)拡張子変更後のファイル名を変数にセットします。
(3)Rename-Itemコマンドレットでファイル名を変更します。

PS C:\Work> $oldfile =sample1.txt"                                         ---(1)
PS C:\Work> $newfile = [System.IO.Path]::ChangeExtension($oldfile, ".log")   ---(2)
PS C:\Work> Rename-Item $oldfile $newfile                                    ---(3)

Saturday, March 29, 2008 7:37:33 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/26にわんくまブログで書いたものです。

現在日時でファイル名を作成する を関数にしてみました。

関数名がいけてないような気がしますが...

好みでカスタマイズしてお使いください。

 

使用方法

拡張子が.txtのファイル名を作成する場合は

PS > Get-DateFileName ".txt"

拡張子が.logのファイル名を作成する場合は

PS > Get-DateFileName ".log"

ヘルプの参照は

PS > Get-DateFileName /?

です。

突っ込みどころがありましたら、コメントしてくださいませ。

 

Get-DateFileName.ps1

#===============================================================================
# Get-DateFilename: 現在日時でファイル名を作成した文字列を返す
# Param:
# $extension : ファイル名につける拡張子(ドットは付けても付けなくても良い)
#
# 使用例
# #現在日時でテキストファイル名を作成する
# Get-DateFileName ".txt"
#
# ヘルプを見る場合は
# Get-DateFileName /?
#
# copyright HIRO's.NET(http://blog.hiros-dot.net/)
#===============================================================================
function global:Get-DateFileName {
Param ([string]$extension)

#ヘルプの参照か?
if ( $extension -eq "/?" )
{
$helpmsg = @"
書式`r`n
Get-DateFileName`" 付加する拡張子`"`r`n
`r`n
使用例`r`n
#現在日時でテキストファイル名を作成する
Get-DateFileName `".txt`"

#ヘルプを参照する
Get-DateFileName /?

"@

Write-Host $helpmsg
return
}

#パラメータが指定されていて且つ先頭にドットがない場合
if ( ($extension.length -gt 0) -and (-not $extension.StartsWith(".")) )
{
#ドット + 拡張子
$extension = "." + $extension
}

return $($(Get-Date).ToString("yyyyMMdd_hhmmss") + $extension)
}
Saturday, March 29, 2008 5:27:57 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は、2007/12/26にわんくまブログで書いたものに加筆修正したものです。

PowerShellで現在日時を取得するには Get-Dateコマンドレットを使用します。

これを利用してファイル名を作成します。

書式の設定方法は カスタム DateTime 書式指定文字列 を参照してください。
 

PS > $filename = $(Get-Date).ToString("yyyyMMdd_hhmmss") + ".txt"


せっかくなので、これを利用して最新のイベントログ(今回はアプリケーションログ)10件をファイルに書き込んでみます。

イベントログを取得するには、Get-EventLogコマンドレットを使用します。

また、最新の10件は -newest 10 、アプリケーションログは -logname application と指定して

PS > Get-EventLog -newest 10 -logname application > $filename

の用にします。

これを実行すると 最新のイベントログ10件が書かれたファイルが作成されます。

Saturday, March 29, 2008 4:14:28 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は2007/12/26にわんくまブログで書いたものに加筆修正したものです。

オブジェクトのメンバ情報を取得するには Get-Member コマンドレットを使用します。

使用方法は 

メンバ情報を取得したいオブジェクト | Get-Member

です。

たとえば、Get-Dateコマンドレットで取得できるオブジェクトメンバ一覧を確認するには

PS > Get-Date | Get-Member
TypeName: System.DateTime Name MemberType Definition ---- ---------- ---------- Add Method System.DateTime Add(TimeSpan value) AddDays Method System.DateTime AddDays(Double value) AddHours Method System.DateTime AddHours(Double value) AddMilliseconds Method System.DateTime AddMilliseconds(Double value) AddMinutes Method System.DateTime AddMinutes(Double value) AddMonths Method System.DateTime AddMonths(Int32 months) AddSeconds Method System.DateTime AddSeconds(Double value) AddTicks Method System.DateTime AddTicks(Int64 value) AddYears Method System.DateTime AddYears(Int32 value)
:
長いので省略
:

とします。

Get-Memberコマンドレットは、-MemberTypeというパラメータを持っており、メソッドだけまたはプロパティだけ確認する という使い方もできます。

プロパティだけを確認するには、-memberTypeパラメータに property を指定して

メンバ情報を取得したいオブジェクト | Get-Member -MemberType property

とします。

PS > Get-Date | Get-Member -MemberType property


TypeName: System.DateTime

Name MemberType Definition
---- ---------- ----------
Date Property System.DateTime Date {get;}
Day Property System.Int32 Day {get;}
DayOfWeek Property System.DayOfWeek DayOfWeek {get;}
DayOfYear Property System.Int32 DayOfYear {get;}
Hour Property System.Int32 Hour {get;}
Kind Property System.DateTimeKind Kind {get;}
Millisecond Property System.Int32 Millisecond {get;}
Minute Property System.Int32 Minute {get;}
Month Property System.Int32 Month {get;}
Second Property System.Int32 Second {get;}
Ticks Property System.Int64 Ticks {get;}
TimeOfDay Property System.TimeSpan TimeOfDay {get;}
Year Property System.Int32 Year {get;}

メソッドだけを確認するには、-memberType に method を指定して

メンバ情報を取得したいオブジェクト | Get-Member -MemberType method

とします。

PS > Get-Date | Get-Member -MemberType method


TypeName: System.DateTime

Name MemberType Definition
---- ---------- ----------
Add Method System.DateTime Add(TimeSpan value)
AddDays Method System.DateTime AddDays(Double value)
AddHours Method System.DateTime AddHours(Double value)
AddMilliseconds Method System.DateTime AddMilliseconds(Double value)
AddMinutes Method System.DateTime AddMinutes(Double value)
AddMonths Method System.DateTime AddMonths(Int32 months)
AddSeconds Method System.DateTime AddSeconds(Double value)
AddTicks Method System.DateTime AddTicks(Int64 value)
AddYears Method System.DateTime AddYears(Int32 value)

長いので省略

Saturday, March 29, 2008 3:52:45 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Friday, March 28, 2008

この記事は、2007/12/25 に わんくまブログで書いたものです。

アセンブリをロードするには、System.Reflection.AssemblyのLoadWithPartialNameメソッドを使用します。

System.Windows.Formsをロードするには

[System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")

とします。

アセンブリがロードされたかを確認するには 現在ロードされているアセンブリの一覧を確認するには(Windws PowerShell Tips) を参照してください。

Friday, March 28, 2008 9:31:11 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
この記事は2007/12/25にわんくまブログで書いたものに加筆修正したものです。


PowerShellでロード済みのアセンブリを確認するには

PS C:\Users\HIRO> ([AppDomain]::CurrentDomain).GetAssemblies()

と入力します。

一覧は下記のように表示されます。

Friday, March 28, 2008 7:42:48 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は、2007/12/18にわんくまブログで書いたものに加筆修正したものです。


.NET Reflector
は通常選択可能な言語は IL, C#, Visual Basic, Delphi, MC++, Chromeとなっています。


今回は、これにPowerShellを追加する方法を紹介します。

CodePlex にて .NET ReflectorのAddInが公開されているのですが、一覧 から PowerShellLanguage.zip というファイルをダウンロードします。

つぎに、ダウンロードしたzipファイルを解凍し、作成されたファイル(Reflector.PowerShellLanguage.dll)を任意の位置へコピーします。

ちなみに僕は、.NET Reflector本体がある場所へコピーしました。


次に、.NET Reflectorのメニューの[View]-[Add-Ins]から[Add]ボタンをクリックし、Reflector.PowerShellLanguage.dllを選択します。


これで、言語の一覧にPoweShellが追加されます。

VB.NETやC#で自作した関数などを、PowerSellに置き換えたいときに威力を発揮してくれるツールです。


Friday, March 28, 2008 7:14:53 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Thursday, March 27, 2008

私、HIROが書いた「VSTOでExcel2007のカスタムリボンを作成する」の記事がCodeZineにて公開となりました。

Visual Studio 2008のVSTO開発に関する記事は国内ではまだ少ないため、書いてみた次第です。

続編も予定しておりますのでお楽しみに!!

PowerShellの記事同様、読んでいただければ幸いです。

これまでに投稿したPowerShellの記事は下記の通りです。

記事タイトル 公開日
Windows PowerShell 入門(1)-基本操作編 08/01/23
Windows PowerShell 入門(2)-基本操作編 2 08/02/27
Windows PowerShell 入門(3)-スクリプト編 08/03/11

Thursday, March 27, 2008 2:42:37 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は、2008/12/13にわんくまブログで書いたものに加筆修正したものです。

PowerShellには、プロファイルと呼ばれるスクリプトファイルを利用することができます。

このプロファイルと呼ばれるスクリプトファイルは、PowerShell起動時に1度だけ実行されるもので、日常使う関数やエイリアスなどを登録しておくためのファイルです。登録しておくことで、PowerShellを使用するたびに、エイリアスを設定したりする必要がなくなります。関数においては、関数のスクリプトファイルのフルパスを指定することなく、関数名[Enter] と入力するだけで実行が可能になります。

プロファイルのスクリプトファイルは、PowerShellであらかじめ定義がされています。
このファイルは $Profile という自動変数に格納されています。

では、プロファイルの定義を確認してみましょう。
コンソールウィンドウで $Profileと入力して[Enter]キーを押すと下記のように返ってくると思います。
ここで表示された結果が、PowerShellがプロファイルとして認識しているスクリプトファイルのフルパスになります。

PS C:\Documents and Settings\HIRO> $Profile
C:\Documents and Settings\HIRO\My Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1

ですがこのファイルはPowerShellをインストールしても自動で作成されるファイルではありません。
せっかく PowerShell がこのファイルをプロファイルとして認識しているので、それを利用してプロファイルスクリプトのファイルを作成することにします。


New-Item -path $Profile -ItemType file -Force[Enter]


と入力します。

New-Itemコマンドレットは、新しい項目を作成するためのコマンドレットです。
-path パラメータの後に $Profile とすることで、PowerShellが認識しているプロファイルのフルパスを指定したことになり、ファイルが作成されるというわけです。


では、プロファイルが作成されたかを確認してみましょう。
確認方法は


PS C:\Documents and Settings\HIRO> Test-Path $Profile[Enter]


と入力し、Trueが返ってくればOKです。
(Test-Path コマンドレットは、パスが存在すればTrueを返します。)

これで、プロファイルができたので、あとは自分がよく使うコマンドにエイリアスを付けたり、自作関数を登録しておけば、次回 PowerShell 起動時から使えるようになります。

せっかくですので、


notepad $Profile[Enter]


として、すぐにカスタマイズしてしまいましょう。
メモ帳が開かれて、中身が空のプロファイルが表示されたと思います。

たとえば税込金額をもとめる自作関数を登録してみましょう。

function Get-Tax {
    return $args[0] * 1.05;
}

と入力して、上書き保存しPowerShellを再起動します。

コンソールウィンドウで

PS C:\Documents and Settings\HIRO> Get-Tax 100

としてみてください。 105と返ってくるようであれば、先ほど作成したプロファイル、そしてプロファイルに登録した関数がきちんと動作していることになります。

ぜひプロファイルを作成して、PowerShellを自分流にカスタマイズしましょう。

もしも実行がされないようであれば、スクリプトの実行ポリシーが設定されていない可能性があります。

次のコマンドで現在設定されている実行ポリシーを確認しましょう。

Get-ExecutionPolicy[Enter]


返された値が Restricted または AllSigned の場合はPowerShell起動時にプロファイルを実行することができません。
RemoteSigned または Unrestricted を設定する必要があります。
ここでは Unrestricted に設定してみます。


Set-ExecutionPolicy Unrestricted[Enter]


以上で次回 PowerShell 起動時からプロファイルを使用することが可能となります。

Thursday, March 27, 2008 12:51:26 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

この記事は 2007/11/20にわんくまブログで書いたものです。

PowerShell てキロバイト(KB)やメガバイト(MB)、ギガバイト(GB)の単位を認識してくれます。

PS C:\Users\HIRO> 1KB
1024
PS C:\Users\HIRO> 1MB
1048576
PS C:\Users\HIRO> 1GB
1073741824
C:\Users\HIRO> 1TB
数値定数 1TB が正しくありません。
発生場所 行:1 文字:3
+ 1TB <<<<
PS C:\Users\HIRO>

テラバイトは....認識してくれないんですね...

でも計算もきちんとしてくれます。

 

PS C:\Users\HIRO> 1GB / 256MB
4
PS C:\Users\HIRO> 1MB / 256KB
4
PS C:\Users\HIRO> 1MB / 128KB
8
Thursday, March 27, 2008 9:14:40 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback

Set-ExecutionPolicy コマンドレットは、PowerShellでスクリプトを実行する権限を設定するためのコマンドレットです。
(詳細は HIRO's.NETPowerShell Tips セキュリティーポリシーを設定するを参照ください)

Windows Vista では 通常起動したPowerShell で Set-ExecutionPolicy の実行しても失敗してしまします。

PowerShell を 「管理者として実行」することにより、Set-ExecutionPolicyコマンドレットを実行することができます。

 

Thursday, March 27, 2008 8:43:39 AM (Tokyo Standard Time, UTC+09:00)  #    Comments [0]  |  Trackback
Wednesday, March 26, 2008

このブログでは Microsoftの新しいシェルであるWindwos PowerShellを中心に書いていきたいと思っています。

技術解説は HIRO's.NET の PowerShell  コーナーで取り扱っておりますので、そちらの方もよろしくお願いいたします。

 

HIRO

 

Wednesday, March 26, 2008 11:27:40 PM (Tokyo Standard Time, UTC+09:00)  #    Comments [2]  |  Trackback

Theme design by Jelle Druyts

Pick a theme: