2017/12/23

Bash on Ubuntu on WindowsならぬC# on PowerShell on bat

この記事はPowerShell Advent Calendar 2017の23日目です。
そして明日が私の誕生日です。(?)

前置き

たまたまググッて出てきた幾つかの技術を組み合わせたら大変便利過ぎて危険だった
みんな知ってたのこれ?ていうお話。

PowerShellはWindowsに標準で搭載されるようになり、いわゆる「OS入ってればすぐ動く」の好例となったわけなんですが、
ps1ファイルがアレゲ。凄くアレ。
少なくともPC初心者の方にはダブルクリックで確実に実行出来ないとダメだと思うんです。
案の定7日目の大鷲さんがゾーン/セキュリティ(或いは場合によりExecutionPolicyなど……)に振り回されておられるわけです。
堅いのは良い事だ。良い事だけど、思ったより使い勝手悪いかなと。WSHくらいお手軽でありたい。

本題

そして、以下の超危険な一行に出会ってしまったのです。
@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
これはbatファイルの1行目に書くおまじないです。そしてこのおまじないがあれば、
2行目以降にPowerShell記述が出来てしまいます。ヤベェ。
二行目以降をPowerShellスクリプトとして実行させているbat……てイメージ。
batからps1を呼び出す手法は結構あちこちで見かけるのですが、
たった1行のおまじないでbat拡張子のPowerShellスクリプトが爆誕。
ExecutionPolicyも自由に書けます。
@powershell -WindowStyle Hidden -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
こうするとDOS窓(conhostってやつ、黒い窓)も消える。

.NETによる凶悪な発展

PowerShellでもちょこっと「Add-Type -ReferencedAssemblies」なんてやってあげると、C#のソース埋め込んで実行とか出来るんですよ。

……ん?

@powershell -NoProfile -ExecutionPolicy Unrestricted "$s=[scriptblock]::create((gc \"%~f0\"|?{$_.readcount -gt 1})-join\"`n\");&$s" %*&goto:eof
$assemblies = ("System")
$src = @"
using System;
public static class cstest {
        public static void main(string[] args) {
            Console.WriteLine(args[0] + "!" + args[0] + "!" + args[0] + "!");
        }     }
"@
Add-Type -ReferencedAssemblies $assemblies -TypeDefinition $src -Language CSharp
[cstest]::main('hello!')
うおおおおおこのbat動くぞぉぉぉぉぉこれ動くぞぉぉぉぉ
とにかく表題通り「batの中で動いているPowerShellの中でC#がコンパイルされながら実行されている」のです!何を言っているか分からない!!
副次的なメリットも多方に及びます。

  • bat起動時のパラメータ渡しもきちんと機能し、C#にまで渡せます
  • WPF利用、XAMLを同時に埋め込む事も難なく可能です
  • やってないけどどうせVB.NETとかも埋め込めるんじゃねーかな
  • C#にまで到達していれば.NETなdllはおろかDLLImportでWin32APIやらDLL関数も利用可能
宇宙ヤバイ。

こんなにステキ

.NET Frameworkのバージョンは恐らく実行しているOS上でのPowerShellのバージョンに依存するはず。……んーがそもそも
「実行時に自動的に判定される」という点だけで超便利。
「3.5と4.xでコンパイル分けなくてええねん」て言えば「(@益@.:;)ノシ なんだと」てならないかな。

気になる点

  • これ将来的に塞がれたりしないの
  • セキュリティリスクにならんの
    • セキュリティリスクになってhtaみたいに迫害ry
C#やりたい時はアセンブリ書くのちょこっと面倒かな、とは思ってますが、
PowerShell的にはやりたい放題です。
最後の良心で「自身を管理者実行し直すbat」を混ぜ込んでいないのですが……やっぱりすげーセキュリティリスクになりそう。ならないかな。
あと細かい事だけど各種エディタでデフォルトでbatとして認識されるので実に自動補完されないとかハイライトされないとかはある。


今後の発展

DLLImportをより手軽に扱える関数を作ってみたりしています。
妄想だけどReferencedAssembliesも何とかC#ソースから動的に生成出来ないかな。
画像ファイルのEXIFとファイルのタイムスタンプを相互に変換するようなのも作ったりしてますが概ね良好です。
結局「PowerShell結構スゴイんです」が故のメリットばかりなんですけどね。
何か面白いアイデアとかあったら是非教えて下さい。

最後になりましたが

あ、ほんとはミュージシャンらしいです。私。サンレコにも載ったから多分。
新譜出たばかりなのでヨロシクドーゾ。
bandcamp iTunes Amazon Spotify

0 件のコメント:

コメントを投稿