簡易ISOファイル作成コマンド

これの続きです。

自分用のツールの置き場、備忘録として記録しています😅

CDやDVDのメディアからISOファイルを作成するのは結構カンタンにできました。
これで殆どやりたいことはできたのですが、やっぱりディレクトリからISOファイルを作るにはどうするんだろう??? という素朴な考えがでてきまして・・・
ググるとこれもWindowsで標準機能でできるようで・・・具体的にはイメージマスタリングAPIとしてCD/DVD等のファイルシステム作成からメディアへの書き込みまでの機能がCOMサーバーとして提供されているようです。COMサーバーで実装ってことは、WSHやC#から簡単に使える・・・ってことです。

サンプルのコードはもうマイクロソフトのコミュニティーサイトに載ってましたので、これを適当にいじって、任意のディレクトリをISOファイルにビルドできるコードを書いてみました。一つ前に書いたDVDメディアからISOファイルを作るコードも統合してみました。

イメージマスタリングAPIは.NET Frameworkのクラスライブラリで提供されておらず、C#から使用するには、TLBIMPコマンドを使用してタイプライブラリからCLRアセンブリに変換し、コンパイルするときにこのアセンブリを参照しないといけません。Visual Studio のIDE環境を使用する場合はプロジェクトにIMAPI2FS.dllの参照を追加するだけでいいかもしれません。
僕みたいにコンソール画面でカチャカチャする場合は・・・

>> tlbimp c:\WINDOWS\System32\imapi2fs.dll

のようにすると、同名のアセンブリ(dllファイル)ができるので、ソースコードをコンパイルするときに、このDLLファイルを /r オプションで追加します。

殆どサンプルコードをコピペしただけなので、特に特筆するところはありません・・・githubにリポジトリ作ろうと思ったけど、ファイル1個だけなんでgistにした。

一応、タイプライブラリのインポートもあるので nmake用の makefileも書く。

DVDメディアのダンプ

Windows7の環境が必要になり開発用のプロダクトキー?を発行してもらい、後はHyperV環境で仮想マシンを作ってインストールするだけ。
って思ってたら、罠が・・・HyperVで稼働しているマシンにDVDを読めるドライブがねぇよ。。。
DVDメディアからISOファイルを作れば・・・と思い、Windows10のアクセサリの中にISOファイルを作るアプリを一応探してみたけど当然なく・・・、WindowsってISOファイルからメディアに焼く機能はエクスプローラから呼び出せるのに、その反対ができない・・・。

むむむ、linuxとかだと、ddコマンドで一発なのに・・・WSLからddでDVDドライブのデバイスを指定して・・・ってできないのかなぁ・・・。

仕方ないので窓の杜でフリーソフトを漁るか・・・とも思いましたが・・・、単にドライブをオープンしてダンプすればエエだけやろ? ってことで、C#で書いた。C#からWindows APIをコールするところはマイクロソフトのサイトからコピペして、適当に。

要点は、Windows APIの CreateFile から返る SafeFileHandleをFileStreamに渡してバッファを介してコピーするだけ。
FileStream.CopyToAsyncメソッドを使えば一行で済むんだけど、やっぱり途中経過(進捗状況)は必要かなー、と思って無理やり FileStream.ReadAsync/WriteAsyncメソッドを使ったけど・・・。

SQLServer on Linux !?

これは、マイクロソフトがWindowsを捨て去る布石なのか??

来年中盤以降に マイクロソフトのサーバーソフトウェア群における中核とも言える SQLServer の Linux 用・・・(たぶん Redhat Enterprise Linux用だと思うんだけど)をリリースするという・・・。
http://blogs.microsoft.com/blog/2016/03/07/announcing-sql-server-on-linux/

SQLServerがLinux上で稼働する、ということは、次に来るのは当然 “.NET Framework on Linux”とか???(Monoプロジェクトがありますけど・・・) もしそうなったら、もうWindows Serverである意味がないやん!

サーバーOSに関して考えればOSを選んでからサーバーウェアを選ぶという時代じゃないですよね。実現したいサービスがあって、それを実現するためのサーバーウェアを選択して、それから最終的にOSを選ぶ・・・っていう。

さらにクラウドコンピューティングとか仮想化とか・・・、正直、OSなんか、もう、どれでもいいんですよね。なんかもうWindowsとかLinuxとかMacOSとかBSDとか、どれでも、いいんすよ。

ま、こんなこと、今更感が満載なんですけどね。
追記:
そういえば、マイクロソフトは Xamarinも買収しましたよね。SQLServer on Linuxも含め、いずれはmonoプロジェクトも取り込んで、ネット上のクライアントとなるアプリ開発、サービス開発に必要なバックエンドソフトウェアと、必要なものがほとんどすべてマイクロソフトからリリースされることになったわけで。

Vista以降では安易にスレッドを作るな!?

LinuxやBSDなどのUNIX互換のOSと違って、Windowsではスレッドを起こすのは普通に行われてることだと思います。で、スレッドを起こすには、CreateThread API もしくは、Cランタイムライブラリの_beginthreadex関数を使うことになります。

が、一方でスレッドを生成するのではなく、スレッドプールを利用する、というケースもあり、パフォーマンス的な事を考えれば、むしろこちらの方が多いかもしれません。

Windows 2000/XPなどのNT5.x系では、QueueUserWorkItem APIというスレッドプールに関するAPIが使えます。。。けど、はっきりいって、このAPI、よほど簡単なロジックでないと使えません。いったんこのAPIでキューに入れてしまうと、もう手が出ません。外からキャンセルできないし、強制終了させようとしてもTerminateThread APIは使っちゃだめ!ですし・・・。
結局、ちょっと凝ったことさせようと思ったら、自前でI/O完了ポートを駆使してスレッドプールを実装する他なかったと思います。

しかし、Windows Vista以降のNT6.x系のWindowsでは、より進化したスレッドプールAPIが追加されています。もはや、Vista以降のWindowsで、CreateThreadや_beginthreadex関数を使ってスレッドを起こすコーディングはダサイといわざる得ません(^^;;;

というか、CPUがデュアルコアは当たり前、マルチコアがデフォルトってな状況の中で、これからはメニーコアだ! っていう時代なので、アプリケーション開発者側が、コア数のことまで考えて組む・・・とかもう無理!そんなのは限られたスーパープログラマーしかできんわ(笑) ってことです。

だから、CreateThread APIや_beginthreadex関数でスレッドを起こす前提のロジックでコーディングしちゃだめ。ってことに。

ただ・・・スレッドを作ってそこにウィンドウを作成する、というようなケースには向きません。とどのつまり、プロセス開始から終了まで生存するようなスレッドの場合、スレッドプールに処理を投げる意味はありません。あくまで、一つのスレッドの生成・削除が頻繁に行われるケースや、スレッドの生存期間が短いケース等でスレッドプールの恩恵を受けることができると思います。

ま、今更ですが(^^;;; この新たに追加されたスレッドプールなAPI群は、スレッドの生成と管理をすべてWindowsが肩代わりしてマシンに積まれているCPUの数(コア数?)と負荷状態に応じて最適な性能を発揮できるようになっているようです(・・・なっているはずです)。

例えば、ちょっとしたユーティリティアプリなんかで、単純な処理を非同期(並行)処理させる場合、TrySubmitThreadpoolCallbackもしくは、CreateThreadpoolWork/SubmitThreadpoolWorkでほとんど事足りると思います。

CreateThreadや_beginthreadexのあの引数の多さにうんざりすることが無くなり、スレッドハンドルを管理するコード、同期のためにイベントオブジェクトを作成して待機するようなコード諸々を実装する手間が大幅に軽減されます。ヒャッホーーー!

当然ですが、上記はXPでは実行できません。

他にも、タイマーオブジェクトを利用した関数の繰り返し処理、jscriptでいうところのsetTimeout / setIntervalメソッドみたいな、一定時間毎にコールバック関数を実行してくれるCreateThreadpoolTimer APIや、カーネルオブジェクトがシグナル状態になったらコールバック関数を実行してくれる CreateThreadpoolWait API、ReadFile/WriteFileなどのI/O非同期処理に利用できるCreateThreadpoolIo API。

一連のスレッドプールに関するAPIは非常に強力で、使い勝手もいい。デフォルトのスレッドプールの動作が気に入らなければ、カスタマイズしたスレッドプールを利用することもできる。

自分的に便利だと思ったのが、ReadFIle/WriteFileでI/O非同期処理に利用できる、CreateThreadpoolIo/StartThreadpoolIo。
今まではI/O完了ポートで通知を受け取って・・・というようなコードを書いてましたが、Vista以降のOSに限定すれば、これらのスレッドプールAPIを使うことでコード量が減ります。

ReadDirectoryChangesW APIを使ったディレクトリへの変更を監視するコードをスレッドプールを使ったコードに強引にリプレースしてみました。

まずは、昔作った、WindowsXPで動作する、IO完了ポートとワーカースレッドを単純に作って利用したバージョン。

要点は、スレッドを作成して監視が終了するまで待機。ReadDirectoryChangeW APIの非同期処理が完了するとIO完了ポートのキューにI/O完了パケットが追加され、ワーカースレッドのGetQueuedCompletionStatus APIが制御を戻すことでReadDirectoryChangeW APIの処理結果のデータを得て、再びReadDirectoryChangeW APIをコールし非同期処理を継続します。

続いて、上記をVista以降のスレッドプールのAPIを利用したバージョン。

あまり違いがないように思いますが、スレッドを何個作るべき?だとか細々とした調整などが不要になり、何より_beginthread関数などのプリミティブなAPIを使わなくても良くなりました。以前なら、スレッド処理をラップする、なんらかのクラスライブラリが必須だったと思いますが、ちょっとしたツールを書くときはこれらの新しいスレッドプールなAPIを使えば良くなりました。

ま、ちょっとしたツールを作るにはC#を使えば済む話で、わざわざC++を使う必要性があるとは思えませんが・・・。ま、要するに自己満です(^^;;;

cygwin with mintty

いまさらながら、(個人的に)必要に迫られてcygwinを夏に買ったVAIO Zにインストールした。

もともと vpsのssh接続用にTera Term Proをインストールしていたので、Tera Term Proに入っているCygtermを介して Tera Term Pro 上で使うようにしました。コピペもWindowsのコマンドプロンプトなシェル より遥かに使い勝手がいいし。

で、ちょっと調べてみたら、cygwin の端末エミュレータとして標準で mintty というのがインストールされてて、どうやらこのminttyがcygwin 推奨の?端末ソフトらしい。Tera Term Proでもほとんど不満はないのですが、やはりcygwin 関係はcygwin 内ですべてを完結させたいところ。
使ってみると、日本語もちゃんと表示されるし、最低限の機能を備えているので問題なし。Windows7でウィンドウの透過を”Glass”にしたら、結構かっこよく見える(^^;;;

ただ、一点、不満がありまして・・・、それが・・・環境変数 HOME の扱い。Windowsのアプリですでに環境変数HOMEを設定していて、これは変えたくない。

で、どうやら、mintty を起動すると、cygwinのインストーラが作成した、/etc/passwd(実際にはc:cygwinetcpasswd) を見ているらしく、デフォルトでホームディレクトリが、Windowsの%USERPROFILE%になるみたい。

Tera Term Pro では、「設定 → その他の設定」で、環境変数を設定できる項目があるのでHOMEを /home/username と設定することで解決してたんですが・・・。

環境変数HOMEをバッチファイルに埋め込めばいいんだけど、それだといちいちコンソールウィンドウが立ち上がってブサイク。

・・・というわけで、バッチファイル(コマンドファイル)ではなく、wsh + jscript の力を借りて下記のような起動スクリプトを作ってスタートメニューに登録。

var wshl = WScript.CreateObject("WScript.Shell");
var env = wshl.Environment("PROCESS");

env.item('HOME') = '/home/' + env.item('USERNAME');
env.item('MAKE_MODE') = "unix";

wshl.Run("c:\\cygwin\\bin\\mintty.exe -i /Cygwin-Terminal.ico -");

vpsへのログインも、cygwin + ssh で。 非WIndows環境はすべてcygwinにしてしまいました。

ええ感じ~、と思っていたら、Tera Term Proで操作ログを常に保存していたのを思い出し・・・mintty のオプション ” -l ” を指定しないと・・・んーーーなんか挫折しそう。

(2012/1/2 : 若干記述修正済み)