簡易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メソッドを使ったけど・・・。

tarよりzipコマンドをつけんかい!

どーでもいい記録です。

長年Windows標準のファイル圧縮・解凍ツールはCAB形式のファイルでした。今もそうですが・・・。そのため、cab形式のファイルを作成したり(makecab.exe)や解凍したり(expand.exe)するコマンドが標準であります。また、GUIシェルであるWindowsエクスプローラは標準でcab形式のファイルをフォルダとして扱えるようになってます。

・・・で、最近 ssh,curl,tarなど、従来では別途どこからか(cygwinやmsysなど)調達してこないといけないようなコマンドがWindows標準で使えるようになりました。特に tar コマンドは・・・それ、いる???? って感じ。

tarコマンドを標準で揃えるぐらいなら、zipコマンドをつけんかい! って思うのです。

Windowsって事実上の世界標準?であるzip形式のコマンドラインツールが付属していません。そうです、コマンドプロンプトでZIP書庫を解凍したり作ったりできないのです。しかし、GUIシェルであるエクスプローラはcabファイルと同じくzip書庫ファイルをフォルダとして扱えるようになってますが、そこまでするなら、なぜzipコマンドを付けないのか・・・ライセンスの問題なのか、何らかの制限があるのかわかりませんが、とっととzipコマンドをつけてほしい。

まぁ、文句を言っててもしょうがないので、代替方法。

■ PowerShellなら可能
コマンドプロンプトでは無理ゲーですが、PowerShellだとZIP形式のファイルを扱えます。

# 書庫展開
>> Expand-Archive -Path <書庫ファイルパス> -DestinationPath <解凍先パス>

# 圧縮
>> Compress-Archive -Path <圧縮するファイルパス(カンマで区切って複数指定可能、ワイルドカード認識)> -DestinationPath <書庫ファイルパス> 

これを 利用してコマンドプロンプトから powershell -Command を実行します。

# sampleディレクトリをそのままzipファイルにします。
>> powershell -Command "Compress-Archive .\sample\ sample.zip"

めんどくさいですが、まぁライトユースには十分です。客先のWindowsデスクトップにリモートデスクトップで接続してデータファイルを圧縮してコピーとかやるとき、zipで固めてからコピーする時とか。好き勝手にツール類をインストールとか、フツーはできないよね?勝手にやったら怒られるわ、セキュリティーの警告が出るわで大変だからね・・・。Windows上でゴニョゴニョする時、できるだけ素のWindowsでできる方法を身に付けとかないと詰みますよね。

まぁ、単に圧縮するだけなら、標準のmakecabの方が便利だけど。分割圧縮書庫にもできるし。メールで1MB制限とかチョーめんどくさい環境でも分割してメールで送れるしね。でも cabファイルって結局Windowsアプリの配布にしか使われなかったよねぇ。まぁマイクロソフト・アレルギーで毛嫌いしてる人多いからねぇ。

どうしてもWindows10の起動サウンドを鳴らしたい

期限が迫っているのに、どーでもいいことが気になって時間食ってしまう💦
どーでもいいプログラムを書く時間です。

歴代のWindowsで一番気に入ってるスタートアップサウンドは、Windows2000とMe の時のピアノ音。あれが一番心地よい。まぁ人それぞれなんですが・・・

最近のWindowsって起動サウンドが鳴らないんですね・・・ググると Windows8ぐらいからデフォルトで無効にされているみたいですね。まぁ仕事場のパソコンは別にいいとして、家で使うPCぐらい鳴らしてもいいんじゃないすかねぇ。

で、そもそも コンパネのサウンドの設定で、起動時のサウンドを鳴らす設定が消されています。なんで?
これもググるとレジストリをいじることで有効になるみたいですが、結局はシステムにブロックされて起動サウンドは鳴らないみたいでつね。。。

しかたないので、タスクスケジューラに登録することにした。起動サウンドのWAVファイルは Windows2000のインストールCDから抜いた。ライセンス的に不味いかもしれん。が、別にばら撒くわけでもなし。

基本タスクを作成し、トリガーとして「ログイン時」を選択。次に登録するプログラムなんですが・・・Windows標準で、サウンドファイルを再生するコマンドはないみたいです・・・
これもググると Powershell のワンライナーがヒットします。。。というか、これしかヒットしません。
要点は・・・コマンドプロンプトで下記コマンドを打つだけ。

>> powershell -WindowStyle hidden -c (New-Object Media.SoundPlayer "wavファイルのパス").PlaySync();

このコマンドをそのままタスクスケジューラに登録してもいいんですが・・・コンソールウィンドウが立ち上がってしまいます。

なんか、すっげぇカッコ悪りぃ!

標準でできないならプログラムを組むしかない。 上記のコマンドラインは .NET Frameworkのクラスライブラリ System.Media.SoundPlayer のインスタンスを生成してサウンドファイルを渡すだけなので、C#でも数行で済みそうです。というわけで組んでみる・・・組むというレベルでもない。

主要部分は一行ですね(笑)
これを、-target:winexe 付きでビルドするとコンソールウィンドウなしのプログラムができるので、このプログラムを適当のフォルダに配置してサウンドファイルとともにタスクスケジューラに登録します。
c:\your\binary\path\playsound.exe logon.wav

やっとこさ、ログイン時に あの Windows2000 の心地よい起動サウンドが聞けるようになったとさ。おわり。

一応実行バイナリを置いておきますが、自己責任で。いかなる損害も補償は一切いたしません。あしからず。

テーブルヘッダの固定

2020/12/25 間違い修正

これまで、tableタグ内で thead要素を固定してtbody要素をスクロール可能にするために、
table要素の外側の要素の高さを固定してposition:relative、overflow:autoと指定して、下記のような自作の簡易jQueryプラグインを使用していました。

実際のデモ

HTMLとCSS

jQueryのプラグインは適当に作成。汎用性はなし。

で、最近 display: sticky というのがあって便利だよ、というのを今更ながら知りまして、chrome,firefox用の画面にはこれを使うようしました。
MDNサイトで見ると「粘着位置指定要素 (stickily positioned element)」と言うそうで、要はイケてるサイトでよく見る、
下方スクロールしたら勝手にメニューなんかがページ上部に張り付く(固定される)挙動を簡単に実現できる CSSプロパティみたいです。

stickily positioned elementとは、 position の計算値が sticky である要素です。これは包含ブロックがフロールート (又はその中でスクロールするコンテナー) 内の指定されたしきい値 (例えば top に設定された auto 以外の値など) を達するまでは相対的な配置として扱われ、包含ブロックの反対の端が来るまでその位置に「粘着」するものとして扱われます。

これ読んでも、正直よく分かりません💦 すみません。

で、これをテーブルヘッダに利用しよう、というわけです。
ググると結構記事になっていて、要するに thead要素内の th要素に display:sticky position:sticky を指定して固定するようです。

実際のデモ

theadをstickyにするのが真っ当な感じですが、現在のブラウザのバージョンでは thead を固定することはできないみたい(無視される)。
それと、th要素をstickyで固定しても、th要素に適用されている border は固定されないみたいな挙動になる感じです(若干ずれてしまう?)

/* 実際のCSS */
.table-container {
  position: relative;
  overflow: auto;
  height: 100px;
  width: 80%;
  border: 1px solid #ccc;
}
.table-container table {
  width: 100%;
  border-collapse: collapse;
}
.table-container table > thead {
  background-color: #eee;
}
.table-container table > thead th {
  border-bottom: 2px solid #ccc !important;
  position: -webkit-sticky !important;
  position: sticky !important;
  z-index: 2 !important;
  top:0 !important;
}
.table-container table > tbody {
  background-color: white;
}
.table-container table tr > * {
  text-align: left;
  border-bottom: 1px solid #ccc;
}
.table-container table > tbody > tr:last-child > * {
  border-bottom: none !important;
}

HTMLはほとんど同じ 。最後のscript要素が要らないだけ。

<div class="table-container">
  <table>
    <thead>
      <tr>
        <th>カラム1</th>
        <th>カラム2</th>
        <th>カラム3</th>
        <th>カラム4</th>
        <th>カラム5</th>
      </tr>
    </thead>
    <tbody>
      <tr>
        <td>カラムデータ1</td>
        <td>カラムデータ2</td>
        <td>カラムデータ3</td>
        <td>カラムデータ4</td>
        <td>カラムデータ5</td>
      </tr>
       ...
       ...
    </tbody>
  </table>
</div>

ただし、Internet Explorerには全バージョンを通して非対応なので(display:stickyは単に無視される)、
かっこ悪いけどブラウザで判別し(navigator.userAgent)、IEの時のみjQueryプラグインを使用するように分岐するようにした。

たとえば、ウェブシステムで行をjavascriptで動的に増やしたり減らしたりするときは、行を追加したり削除したりする関数を一個作っておき、もしブラウザがIEなら 複製テーブル、複製元テーブル両方に行を追加したり、削除したり。なんにしてもメンドクサイが。
IEユーザーがいなくなれば、これも必要なくなるかなと。