PowerShellの起動を速くする

by 入海 30. 7月 2008 00:38

PowerShellのコンソールを起動すると普通のコマンドラインに比べて起動が遅いなと感じる。これは.NETの性質に由来するもので、MSIL(中間言語)を実行時にJIT(Just in Time)コンパイルするためである。実行時に機械言語へのコンパイルを行っているのだ。このJITコンパイル方式はあらゆるCPUやOSに対応させるためにインタプリタの利点を生かしたまま実行時には機械言語の処理速度を保てるという利点がある。

でも考えても見るとPowerShellが必要な環境では多種のOSで動く必要が今のところはない。速く起動してくれるに越したことはないのだ。それを実現するためにはMSILをすでに機械言語にコンパイルさせていればその実行時にその過程が不必要になるために速くなる。.NET Frameworkにはngenというのがあってこれを使うと事前コンパイルを可能にしてくれる。

ネイティブ イメージ ジェネレータ (Ngen.exe) は、マネージ アプリケーションのパフォーマンスを向上するツールです。Ngen.exe は、コンパイルされたプロセッサ固有のマシン コードを含むファイルであるネイティブ イメージを作成してローカル コンピュータのネイティブイメージ キャッシュにインストールします。ランタイムは、JIT (Just-In-Time) コンパイラを使用してオリジナルのアセンブリをコンパイルする代わりに、キャッシュにあるネイティブ イメージを使用できます。(MSDNより

 

そのngenを使って実際に起動を速くするスクリプトがPowerShell Team Blogに載っていたので下に抜粋しておく。

Set-Alias ngen @(
dir (join-path ${env:\windir} "Microsoft.NET\Framework") ngen.exe -recurse |
sort -descending lastwritetime
)[0].fullName
[appdomain]::currentdomain.getassemblies() | %{ngen $_.location}

上のスクリプトを.ps1ファイルに保存してPowerShellから実行してPowerShellのコンソールを起動してみると、起動が数倍速くなっている。ぜひ試してみてほしい。

最新のブログ

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

PowerShell

PowerShell で try - catch - finally を実現

by よこけん 28. 7月 2008 02:33

# この記事は以前 C#と諸々 に書いた記事 (を一部修正したもの) です。

PowerShell V1.0 では、C# の try - catch - finally のような構造化例外処理がサポートされていません。しかし、trap ブロック、throw ステートメント、break ステートメント、continue ステートメント、そしてスコープについて理解すれば、try - catch - finally を擬似的に再現することができます。

というわけで、次のコードのように C# の try - catch - finally に近い例外処理を実現する関数を書きました。

try {
    # 処理
} catch ([例外の型]) {
    param($ex)
    # 例外処理
} finally {
    # 後処理
}

使用する際は次の点に気を付けてください。

  • 各ブロックの開始の "{" の前と各ブロックの終了の "}" の後ろは、上記のように、改行せずに記述する必要があります。
  • 例外の型は、上記のように、必ず "()" で囲む必要があります。
  • catch または finally は、省略可能です。例外の型も省略可能です。
  • catch ブロック内では、break ステートメントを使用して例外を再スローすることができます。当然、任意の例外を throw ステートメントでスローすることもできます。

で、これらを実現するための関数がこちらです。

function global:try
{
    $currentArgIndex = 0;
    $tryBlock = $args[$currentArgIndex];
    $currentArgIndex++;
    if ($tryBlock -isnot [System.Management.Automation.ScriptBlock])
    {
        throw New-Object "ArgumentException" @("try ブロックの指定が不正です。");
    }
    if ("catch" -eq $args[$currentArgIndex])
    {
        $currentArgIndex++;
        if ($args[$currentArgIndex] -is [Type])
        {
            $targetExceptionType = $args[$currentArgIndex];
            $currentArgIndex++;
        }
        $catchBlock = $args[$currentArgIndex];
        $currentArgIndex++;
        if ($catchBlock -isnot [System.Management.Automation.ScriptBlock])
        {
            throw New-Object "ArgumentException" @("catch ブロックの指定が不正です。");
        }
    }
    if ("finally" -eq $args[$currentArgIndex])
    {
        $currentArgIndex++;
        $finallyBlock = $args[$currentArgIndex];
        $currentArgIndex++;
        if ($finallyBlock -isnot [System.Management.Automation.ScriptBlock])
        {
            throw New-Object "ArgumentException" @("finally ブロックの指定が不正です。");;
        }
    }
    if (($() -eq $catchBlock) -and ($() -eq $finallyBlock))
    {
        throw New-Object "ArgumentException" @("catch ブロックまたは finally ブロックを指定してください。");
    }
    &{
        $requireFinally = ($() -ne $finallyBlock);
        &{
            &$tryBlock;
            trap
            {
                if ($() -eq $catchBlock)
                {
                    break;
                }
                $ex = $_.Exception;
                if (($() -ne $targetExceptionType) -and (!$targetExceptionType.IsAssignableFrom($ex.GetType())))
                {
                    break;
                }
                &$catchBlock $ex;
                continue;
            }
        };
        if ($requireFinally)
        {
            $requireFinally = $False;
            &$finallyBlock;
        }
        trap
        {
            if ($requireFinally)
            {
                $requireFinally = $False;
                &$finallyBlock;
            }
            break;
        }
    };
}

以下のスクリプトを実行すると、動作が確認できます。

try {
    "try ブロック実行";
    throw New-Object "ArgumentException";
    "この文は出力されない";
} catch ([ArgumentException]) {
    param ($ex)
    "{0} がスローされたから catch ブロック実行" -f $ex.GetType().Name;
} finally {
    "finally ブロック実行";
}

出力は以下のようになります。

try ブロック実行
ArgumentException がスローされたから catch ブロック実行
finally ブロック実行

なお、PowerShell V2.0 では、try - catch - finally が標準でサポートされるようです。なので、V2.0 ではこの関数は不要になるのですが、もし V1.0 で try - catch - finally を使用したいという方はぜひこの関数を試してみてください。

最新のブログ

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

PowerShell

変数 その1(PowerShell 入門)

by HIRO 24. 7月 2008 23:37

この記事は以前 http://blog.hiros-dot.net/ に書いたものです。

PowerShellはコマンドレットを実行するだけの環境ではありません。

スクリプト実行環境も備えたシェルです。

PowerShellで実行可能なスクリプトを作成していく上で(いやどんな言語においても)変数は欠かせません。

今回はPowerShellにおける変数について説明したいと思います。

PowerShellでの変数は先頭に$記号をつけます。

$var や $hensu のように表します。

変数の宣言方法ですが、New-Variableコマンドレットを使用して

New-Variable var -value "Test"

のようにするか

$var = "Test"

のように変数に値を割り当てます。

PowerShellは代入された値によって型を自動で認識しますので、先ほどのように

$var = "Test"

とした場合には、変数はString型になります。また

$var = 10

とした場合はint型になります。

変数にどんな値が這いいてるかを確認するには、コマンドラインで単純に 変数名[Enter] と入力します。

PS > $var
Test

次に変数の型の確認方法ですが、コマンドラインで 変数名.GetType()[Enter] と入力します。

PS> $var.GetType()
IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object

Name列に表示されているのが、変数の型になります。

最後に、PowerShellではスペースを組み合わせた変数を作成することができます。

この場合は{}を使用して表す必要があります。

${var x}
次回は型を指定して変数を作成する方法について説明したいと思います

最新のブログ

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

PowerShell | PowerShell入門

ロゴを作成してみました

by Administrator 23. 7月 2008 09:55

PowerShell from Japan!!のロゴを作ってみました。

宣伝していただけると助かります。

大きいサイズのタグは下記の通りです

<a href="http://powershell.hiros-dot.net" target="_blank" title="PowerShell from Japan!!">
<img src="http://powershell.hiros-dot.net/images/LogoBig.jpg" width="323" height="87" />
</a>

小さいサイズのタグは下記の通りです

<a href="http://powershell.hiros-dot.net" target="_blank" title="PowerShell from Japan!!">
<img src="http://powershell.hiros-dot.net/images/LogoSmall.jpg" width="223" height="44" />
</a>

最新のブログ

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

PowerShellスクリプトをHTMLに変換

by 21. 7月 2008 13:26

はじめまして、嗣永モモコーラと申します。

編集方法がよくわからず、何回も失敗して変なエントリをあげてしまいました。すいません……。

PowerShellは、2.0 CTPのみだったと思うのですが、パーサが利用できます。これを使って、PowerShellのスクリプトファイルをHTMLへ変換するスクリプトを作成しました。以下は、そのスクリプトを自分自身でHTMLへ変換したものです。

前にも一度作った事があったので、今回は余分な機能として、Alias(コマンドの別名)が設定されている場合に、元の名前に戻した上でHTMLを出力するようにしてみました。たとえば、"gc"はデフォルトで用意されたGet-ContentコマンドレットのAliasなので、スクリプト中に gc "hogehoge.txt" という部分があった場合、Get-Content "hogehoge.txt"に変換して出力します。

Aliasは普段利用しない人にとっては可読性が落ちるかもしれないのと、profile.ps1などで独自に設定したAliasがスクリプトに残っていると、他の環境では動かなかったりしてつらい思いをすることがあるからです。

利用する際は以下のスクリプトをファイルに保存し、第一引数に変換したいスクリプトファイル名を渡してください。変換後のHTMLはそのまま戻り値になるので、リダイレクトしてファイルに保存するなどしてください。

スクリプトファイルの文字コードがutf-8決め打ち、CSSファイルを編集できない環境を想定してスタイル埋め込みになっている、色が好みでない、などの点は適宜改造していただけるとありがたいです。ではでは。

追記:ここ(PowerShell from Japan!!)が空行や空スペースに手を入れる?仕組みのようなので、改行やスペースを全て実体参照に変更しました

追々記:<br /><br />も変換されてしまうようなので、<br />&nbsp;<br />に変換してます。

# Token単位でHTMLへ変換
function TokenToHtml($t){
  # NewLineは単に改行
  if($t.Type -eq "NewLine"){ return "<br />" }
 
  # 該当部分のソースを取得
  $w = (Get-Src $t.StartLine $t.StartColumn $t.EndLine $t.EndColumn)
 
  # Tokenのタイプ別にhtmlへ
  switch($t.Type) {
    "Comment"  { return '<span style="color: rgb(0, 255, 0);">' + $w + '</span>' }
    "Keyword"  { return '<span style="color: rgb(160, 160, 255);">' + $w + '</span>' }
    "Operator" { return '<span style="color: rgb(255, 165, 0);">' + $w + '</span>' }
    "String"   { return '<span style="font-weight: bold;">' + $w + '</span>' }
    "Type"     { return '<span style="font-weight: bold; color: rgb(46, 139, 87);">' + $w + '</span>' }
    "Command"  { return '<span style="color:rgb(160, 160, 255); ">' + (ToDefinition $w) + '</span>' }
    default { return $w }
  }
}
 
# エイリアスだったら元の名前を返す。なければそのまま
function ToDefinition($name){
  $def = (Get-Alias -Name $name -ErrorAction SilentlyContinue)
  if($def -ne $null){
    return $def.Definition
  }
  return $name
}
 
# 変換元ソースの該当箇所を取得 / 0スタートなので、Tokenの返す値から-1する
function Get-Src($s_line, $s_col, $e_line, $e_col){
  $s_line -= 1; $s_col -= 1; $e_line -= 1; $e_col -= 1;
 
  # 複数行にわたる場合があるため、ループ
  for($line = $s_line; $line -le $e_line; $line++){
    if($line -eq $s_line) { $s = $s_col }
                    else  { $s = 0 } 
    if($line -eq $e_line) { $e = $e_col }
                    else  { $e = $src[$line].Length } 
    $ret += $src[$line].Substring($s, $e - $s) + "`n"
  }
  $ret = $ret.Substring(0, $ret.Length - 1);
  return $ret.Replace('&', '&amp;').Replace('<', '&lt;').Replace('>', '&gt;').Replace(' ', '&nbsp;').Replace("`n", "<br />")
}
 
# ヘッダ
$header = 
@"
<html>
  <head>
    <title>out</title>
  </head>
 
  <body>
    <pre class="pssource" style="background-color: rgb(0, 0, 0); color: rgb(0, 255, 255); padding: 3px; font-family: consolas;">
"@
 
# フッタ
$footer =
@"
    </pre>
  </body>
</html>
"@
 
##############################################
# ここからMain
##############################################
# 変換するPSのソース
$src = Get-Content $args[0] -enc utf8
 
# parserへ渡せる形式へ変換
$sb = New-Object System.Text.StringBuilder
$src | ForEach-Object { [void]$sb.Append($_ + "`n") }
 
# エラー出力 / 使わないけど宣言してないと怒られるので
Set-Variable err
 
# パース
$token = [System.Management.Automation.PsParser]::Tokenize($sb.ToString(), [ref]$err)
 
# HTMLへ出力する文字列
$html = New-Object System.Text.StringBuilder
 
[void]$html.Append($header)
 
$pre = $null
 
# Tokenごとに出力
$token | ForEach-Object {
  # Tokenに含まれないもの(空白など)を出力
  if($pre -ne $null -and ($pre.EndLine -ne $_.StartLine -or $pre.EndColumn -ne $_.StartColumn)){
    [void]$html.Append((Get-Src $pre.EndLine $pre.EndColumn $_.StartLine $_.StartColumn))
  }
 
  # Tokenを出力
  [void]$html.Append((TokenToHtml $_))
 
  $pre = $_
}
 
[void]$html.Append($footer)
 
$html.ToString().Replace("<br /><br />", "<br />&nbsp;<br />")

最新のブログ

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Tags:

PowerShell

Calendar

<<  3月 2010  >>
月曜火曜水曜木曜金曜土曜日曜
22232425262728
1234567
891011121314
15161718192021
22232425262728
2930311234

View posts in large calendar
Disclaimer
The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2010 PowerShell from Japan!!