PowerShellからC#, SQL Serverのコードをとっても便利に呼び出す

この記事はPowerShell Advent Calendar 2014の7日目の記事です。
初めてAdvent Calenderに参加してみます。淡々とした記事ですが、よろしくお願いします。

PowerShellからC#を呼び出す

私は基本的にはC#erなのですが、

  • C#スクリプト言語として使いたい
  • C#を使いたいが、Visual Studioをインストールするのが面倒くさい(ユーザー部門では、システム部門に申請しないとインストールできなかったり…)

というケースがあり、PowershellからC#を呼びだせると結構便利です。

そこで、Add-Typeコマンドレットを使えば、C#のソースを呼び出してクラスを作成することができます。

# コンパイル・実行を行う関数の定義
function ComplieAndRun(){

# CSharpコードのソース $source=@" public class SampleClass{ public static string SayHello(string Name) { return "Hello " + Name; } } "@

# CSharpコードのコンパイル Add-Type -Language CSharpVersion3 -TypeDefinition $Source

# CSharpコードの実行 [SampleClass]::SayHello("World") }

ComplieAndRun [Console]::ReadKey() | Out-Null # 実行後入力を待つ

ただ、一つ落とし穴があって、Add-Typeは一度コンパイルした後にソースを修正して再度実行しても受け付けてくれません。 スクリプト言語風に使う場合、ちょっと修正しながら何度が走らせることがあるのですが、そんな場合には一度セッションを切る必要があり、かなり面倒です。
というわけで、子プロセスを呼び出してその中でコンパイル→実行するPowershellスクリプトを作ることにします。

 # 引数の取得
 # Python風に、トップレベルであれば$moduleに"main"が入るようにしている。
 # 他のPowershellプロセスを立ち上げるときには、$moduleに"called"を入れるようにする。
param([string]$module)
if($module -eq ""){ $module = "main"}

# コンパイル・実行を行う関数の定義 function ComplieAndRun(){

# CSharpコードのソース $source=@" public class SampleClass{ public static string SayHello(string Name) { return "Hello " + Name; } } "@

# CSharpコードのコンパイル Add-Type -Language CSharpVersion3 -TypeDefinition $Source

# CSharpコードの実行 [SampleClass]::SayHello("World") }

# トップレベルでない場合のみ、コンパイル・実行を行う。 if($module -ne "main"){ ComplieAndRun [Console]::ReadKey() | Out-Null # 実行後入力を待つ }

# トップレベルの場合は、別のPowershellプロセスを立ち上げ、自身のスクリプトを呼び出す。 if($module -eq "main"){ $path = '"' + $Script:MyInvocation.MyCommand.Path + '"' start-process powershell.exe -ArgumentList @("-File", $path, "called") }

こうして、C#スクリプト言語として簡単に使えるようになりました。PowerShellの文字列展開を使うとC#ソースコードの一部を可変にできたりと、C#よりも柔軟な記述をすることもできます。

(参考)
CodeZine PowerShell 2.0の新機能(6)――他言語の利用
http://codezine.jp/article/detail/5007
PowerShell C#のクラスをPowershellから使う(Add-Type)
http://mtgpowershell.blogspot.jp/2010/06/cpowershelladd-type.html

PowerShellからSQL Serverを呼び出す

SQL Serverを時々使うのですが、テーブル名や抽出条件を変えて何度もデータを加工・抽出したい場合があります。 SQL Serverの文字列処理は書きづらいし、テーブル名を可変にするとパラメータクエリも使えないし、みなさんどうしているんでしょう?

そんなときに、Powershellの文字列展開を使うととっても柔軟に書くことができます。
どうやってPowershellからSQL Serverにつなぐかが問題ですが、sqlcmdを使えば良いです。

sqlcmd ユーティリティ
http://msdn.microsoft.com/ja-jp/library/ms162773.aspx

-Q オプションで、文字列としてクエリを選択することができます。 複数行のクエリも問題なく実行できるようですし、「クエリでは GO ターミネータを使用しないでください。」とありますが、GOも使用できるようです。
また、-o オプションで、Selectの結果を出力することもできます。

 # サーバ名、データベース名の指定
$server = "TestServer"
$database = "TestDatabase"

# SQL文を生成する関数 function CreateSQL($idx){

$tablename = "table" + $idx $value = $idx @" update [dbo].[$tablename] set col1 = $value where col2 = $value "@ }

# sqlcmdを使って連続でクエリを実行する for ($i = 0; $i -lt 10; $i++){ & sqlcmd -E -S $server -d $database -Q (CreateSQL $i) }

これで、こちらも柔軟にSQL Serverを操ることができるようになりました。
ちなみに、SQL Serverコマンドレットなるものがあるようですが、コマンドレットの使い方を覚えるのが面倒なので無視です。
http://technet.microsoft.com/ja-jp/library/cc281847(v=sql.105).aspx

(参考)
SE の雑記 PowerShell から SQLCMD.exe で SQL を実行
https://engineermemo.wordpress.com/2014/05/27/powershell-%E3%81%8B%E3%82%89-sqlcmd-exe-%E3%81%A7-sql-%E3%82%92%E5%AE%9F%E8%A1%8C/
TechNet Forum SQLCMDの-QオプションのGO ターミネータについて
https://social.technet.microsoft.com/Forums/en-US/0da03654-000c-45e6-9dfe-ebeddc815364/sqlcmdqgo-?forum=sqlserverja