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

CMDとBashと変数展開と・・・

備忘録。

CUIではほとんど WSL1/ubuntu を使っています。WSL2の方が実行パフォーマンスはいいんでしょうけど・・・。

WSL1メインとはいいつつ、コマンドプロンプト(cmd.exe)を全く使わない・・・ということはない。たとえばタスクスケジューラに仕事をしてもらいたい処理は バッチファイル(CMDファイル)に書いて渡す方が何かとトラブルは少なくなりますし。
bitlockerで暗号化しているVHDファイルのマウント処理とかをWindowsのスタートアップスクリプトに登録したりとか、ログオン/ログアウトスクリプトに、後始末するスクリプトとか・・・Windowsのサービスを制御したりとか、コンピュータ名とIPアドレスの対応を調べたりとか、IPのルーティングを変えたりとか、やっぱりcmdファイル(バッチファイル)じゃないと不便なこともあります。

Powershellもありますが・・・ps1ファイルの実行がデフォルトでブロックされているので他所のPCで手軽に動かせない・・・とか、なんかイマイチです。

bashでのシェルスクリプトもウェブ開発では必須なので、いろんな処理の自動化スクリプトをちょくちょく書きます。
・・・で、bashとcmdのスクリプトをいったりきたり、色々書く時いつも躓くのは、変数展開の文法・・・要は書き方をよく忘れてしますこと。頭は悪い上、加齢でどんどん記憶力が落ちていく・・・。
あれ、bashのシェルスクリプトのこういう書き方って、バッチファイルではどうやるんだっけ???ということが度々あるので、カンタンな対応・比較表があれば便利だなと思い、メモついでに書いておく。

最低限こんだけ覚えてればなんとかなる・・・かもしれない。

  bash cmd
1行目 #!/bin/bash @echo off
変数代入 hoge=”This is a sample” SET hoge=This is a sample
変数参照 echo $hoge or echo ${hoge} echo %hoge%
入力 echo -n “please input: ”
read hoge
echo $hoge
SET /P hoge=please input:
echo %hoge%
文字列置換 hoge=”this is my appple pen”
echo ${hoge//this/that}
SET hoge=this is my appple pen
echo %hoge:this=that%
部分文字列 hoge=”this is my appple pen”
echo ${hoge:8:2}
echo ${hoge:8}
SET hoge=this is my appple pen
echo %hoge:~8,2%
echo %hoge:~8%
パス分解
パス
ベース名
拡張子
ファイル名
echo $0
echo ${0%/*}
filename=${0##*/}; echo ${filename%.*}
echo ${0##*.}
echo ${0##*/}
echo %0
echo %~dp0
echo %~n0
echo %~x0
echo %~nx0
日付時刻
乱数(簡易)
echo $(date)
echo $RANDOM
echo %DATE% %TIME%
echo %RANDOM%
IF-ELSE文 if [ expression ] ; then
 …
else
 …
fi
if expression (
 command1
 command2
  ….
) else (
 command3
 command4
 …
)
ループ(while) while [ expression ]
do
 …
done
loop:

if expresssion goto loop
※gotoで代替

間違いは随時修正中。思いついたら随時追加中。

ロック画面のスポットライト画像をコピーしてデスクトップにも流用させたい

ロック画面は何にしてますか?僕は設定でWindowsスポットライトにしてます。
これ、たぶんBingから定期的にダウンロードしてロック画面にスライドショー的に表示していると思うんだけど、なぜかログイン後のデスクトップの背景の設定でWindowsスポットライトの選択肢がないんですよねぇ。

Microsoft Storeで壁紙系のアプリを探せばたぶんあると思いますが、たぶんに要らん機能がくっついてきたり個人情報が抜かれたりと面倒なのでやっぱり自分でなんとかするのが基本です。そうです、信じられるのは唯一自分なのです(笑)

Windowsスポットライトで使用される画像ファイルは、
%LOCALAPPDATA%\Packages\Microsoft.Windows.ContentDeliveryManager_cw5n1h2txyewy\LocalState\Assets
に保存されているようです。拡張子がないので判別はできませんが、概ね400KB以上のファイルサイズのファイルが該当する画像で、任意のフォルダにコピーして拡張子.JPGでリネームすれば使いまわせます。ライセンスとか分からんが、どこぞに配布するわけではないので大丈夫でしょう。

定期的にピクチャフォルダにコピーすればいいんですが・・・いちいちフォルダ開いてファイルを選別してコピーしてリネームして・・・うわぁぁぁあーーーーーーん、超絶メンドクセーーーーーーー。
さらに、バックグラウンドでダウンロードされる画像ファイルには縦長と横長がごちゃまぜになっている。縦長の画像は不要なので、これも選別項目です。さらにメンドクサイ。

UNIX系のOSなら find コマンドやらimagemagickを駆使してシェルスクリプト化すればいいんですが・・・。
PowerShellを使えばできそうですけど、んーーーー、C#で組んだ方が早ぇよ。。。ということで、組んでみる。

ファイルサイズを判別するのは簡単で、JPEGファイルの高さと幅を取得するのがメンドクサそうですが・・・単純にSOFマーカーから取得することで手抜きします。完璧にしようとすると僕の知識では無理です。

github

JavaScript Map オレオレ拡張

今、かつてないほどJavaScriptと関わっている。
※JavaScriptという名称は正式にはOracleの登録商標で一般的には ECMA Script って事になるんだろうけど、めんどくさいので JavaScript と明記する。あらかじめご了承のほど。

僕のJavaScriptの文法、その他の知識は正直2010年(ES5)ぐらいで止まってる。というのも今持っている知識だけで要求されるほとんどのケースが実現可能だからだ。
もちろんパフォーマンス的な、効率的な・・・というのは棚に上げまくっているんだけど。その当時も ES6 も意識していましたが、まだブラウザでの実装状況が混沌としててInternetExplorerがまだまだ全盛時代だったので、どうしてもすべてのケースで動くように ES5 を強制していた。

今の JavaScript って5~6年前によく見たコーディングスタイルとは全然違いますよね。
ブラウザでホスティングされているJavaScriptで普通にラムダ式が使えるし、変数宣言で var ではなく let を使うことでブロックスコープを意識したコーディングができる。
まぁ、今頃こんなこと書いても、今更感が半端ないんですけどね。

去年から現在進行形で携わっている仕事では、徐々に(少しずつ) ES6 を意識したコーディングを心がけるようになってきました。ほんとに少しずつですけどね💦

余談:(余談ばっかりだが・・・)——————
理由はマイクロソフトが正式に Internet Explorer 及び edge-HTMLをベースにしたEdgeブラウザのサポートを止める、もしくは新規開発しない、事を宣言したから。
残念なことだけど、ITリテラシーの低い人たちからすれば、未だにInternet Explorer がインターネット業界(笑)の標準だと思っている人が結構多い。
マイクロソフトがレガシーブラウザと決別宣言してくれたおかげで、ChromeやFireFox,Chromium版Edgeを強制することが可能になったことが非常に大きい。
———————-

一番意識しているのは(オブジェクト初期化子{}でインスタンスを作る)オブジェクトを連想配列的に使用するのを止めてMap や Set を使うことにしたこと。
MapやSetもかなり以前から実装されているけど、やっぱり InternetExplorer11 では限定的な実装なので使うのも躊躇してた。

Map,Set は非常に便利ですよね。オブジェクトを使用した連想配列では、キー(プロパティー)に文字列ぐらいしか使えない。Mapだとキーに何でも入る。
MDNでの説明だと、頻繁に削除・挿入を繰り返すケースでパフォーマンスが上がるんだそうで。

たいがいの場合、キーには文字列を使うのが大半の用途だと思います。DOM要素やオブジェクトもキーにできると思うけど、正直僕には使いどころが分からない。まぁ、思いつくのは コールバック(関数)なんかをためておく用途にするぐらい。それでも、そういう時は Map よりSetを使うし。。。

でも特にブラウザ上でDOMとか扱っていると、やっぱりプレーンなオブジェクトの方がコーディングが楽な時もある。ので、Map.prototype空間にオレオレMap拡張メソッドを追加して使うことになってくる。

※2020/04/02 ちょっと追記した。

Map.prototype.toPlainObject

たぶん誰もが書いてる・・・と思う、文字通り、文字列をキーにしたMapをオブジェクトに変換する。
最新のブラウザとかだと、Object.fromEntries とかいう Object.entriesの逆動作を行う関数が実装されているので↓は不要なのかも。

Map.prototype.toPlainObject = function()
{
  var rv = {};
  this.forEach(function(v,k) { 
    if(typeof k === 'string')
      rv[k] = v;
  });
  return rv;
};
// もしくはもっと簡単に・・・
Map.prototype.toPlainObject = function()
{
  return Object.fromEntries(this);
};

Map.from

オブジェクトからMapへの変換は・・・↓でいいのかな? Object.entries は比較的新しめのブラウザしか対応してなくない?

Map.from = function(o)
{
  return new Map(Object.entries(o));
};

Map.prototype.stringify

JSON.stringify のもろパクリですね。toString をオーバーライドすればいいんでしょうけど、そこまでするのは止めましょう。
主に localStorage/SessionStorage へ格納するときに使う。

Map.prototype.stringify = function()
{
  return JSON.stringify(this.toPlainObject());
};

Map.parse

これも JSON.parse のパクリ。JSONのパクリというか、文字列を直接parseするのではなく、一旦オブジェクトにJSON.parseで変換して Map に変換します💦

Map.parse = function(str)
{
  return new Map(Object.entries(JSON.parse(str)));
};

Map.prototype.numIncr/Map.prototype.numDecr

オブジェクトだと、普通にobj.counter++ とか、obj.counter += 10 とかできますよね。。。。
Mapだと一旦 getで取得してsetで更新しないといけません。JavaScriptは演算子を定義もしくはオーバーロードできませんよねぇ。。。。
演算子のオーバーロードは混乱の元になるので極力やっちゃいけない、ってC++の時言われてたな・・・。今もそうなのかなぁ。。。

Map.prototype.numIncr = function(key,delta)
{
  if(typeof delta !== 'number' || delta == 0)
    delta = 1;

  var value = this.get(key);
  if(typeof value === 'number')
  {
    value += delta;
    this.set(key,value);
  } 
  return this;
};
Map.prototype.numDecr = function(key,delta)
{
  if(typeof delta !== 'number' || delta == 0)
    delta = 1;

  return this.numIncr(key,-1 * delta);
};

なんか、Mapの良さ(キーはなんでもOK)を殺してしまうようなものばかりだな。。。キーをstringに限定するようなものあればな~・・・とは思いますが、型が強制されない言語だと難しい。

ざっとよく使うものを列挙しました。自分がコピペできるように💦
ここまで書いてて、気づいたのは・・・var使いすぎ問題! ついつい癖で var って書いてしまうんす。
ラムダ式もイマイチ好きになれない記法だったりします。 C#だと当たり前のよう書くんですけどね。。。好き嫌いというより単に癖なのかも。