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