PowerShell で中身がランダムな大きめのファイルを高速に作る

色々テストをしていると、ユニークなランダムの中身で、任意サイズの、ダミーファイルが欲しくなることがままある。

デバイスを全てファイルとして扱う Unix や Linux なら、 /dev/urandom 擬似デバイスを使って dd if=/dev/urandom of=out.bin bs=1M count=64 みたいに任意サイズでファイルをコピーして作れば良い。

しかし API ベースの Windows だとそういうわけにいかないので、何らかのスクリプトから API を呼んでやる必要がある。

呼ばせるスクリプトは、 Windows に標準で搭載されていて追加でインストール不要な、毎度おなじみ PowerShell が良いだろう。
作りたいランダムなファイルのサイズが小さければ、 PowerShell 上で以下のような雑なコードを実行すればよい。

$Size = 16KB;
[byte[]]$bin = &{foreach($i in 1..$Size) { Get-Random -Maximum 255 }};
[System.IO.File]::WriteAllBytes((Join-Path (Get-Location) .\out.bin), $bin);

しかし、 MiB オーダーを越えてくると、上記のコードでは速度が実用的ではなくなる。

と言うことで、出力速度も気にしながら、大きめなランダムなファイルを作成するコードを考えてみる。

コード

続きを読む

PowerShell でインストール済プログラム一覧を取得する

PowerShell を Windows の管理ツールとしてみたときに、割と昔から意味がわからないと思っていることが 1点 ある。
Windows のインストール済みプログラム一覧を取得するコマンドがないことだ。

もう少し具体的に言うと、appwiz.cpl で開ける、コントロールパネルのプログラムと機能の一覧や、 設定の「アプリと機能」の一覧を取得するコマンドレットがない。
コマンドレットがないだけじゃなく、コードを書いて取得する確立して手段すら存在しないのだ。

とりあえず、それに近い情報がとれる代替方法として、レジストリのアンインストーラー一覧を取得する方法が知られている。
ただ、ググってもあまり PowerShell らしい綺麗 (?) なコードで書かれているサンプルが少なかったので、ワンライナーで書いてみる。

Get-ChildItem -LiteralPath (('HKLM:', 'HKCU:' | %{ "${_}\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall" }) + 'HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall') | Get-ItemProperty -Name DisplayName, DisplayVersion, Publisher, InstallDate -ErrorAction Ignore;

これで取得した内容を | Sort-Object DisplayName, DisplayVersion| Select-Object DisplayName, DisplayVersion などにパイプしてから使うと良いだろう。


ちなみに WMI の Win32_Product クラスを使って取得する方法 (Get-CimInstance -ClassName Win32_Product) は、

  • MSI でインストールしたアプリしか取得できない
  • コンピューターはMSIがインストールされているすべてのアプリケーションを再検証するので、負荷がかかるし遅い

と言うことから使うべきではないとされている。

.NET Interactive で C# と PowerShell を股に掛ける

この記事は、「C# Advent Calendar 2020」 9日目の記事、かつ 「PowerShell Advent Calendar 2020」 9日目の記事だ。

スミマセン。横着した。

この時期になれば .NET Interactive の Preview 4 が出てるだろうしその記事でも書こうかな~ などと目論んでいたものの、 残念ながら登場しなかった。

このため、 .NET Interactive .NET 5 対応版の導入と、 Variable sharing の内容でお茶を濁そうと思う。

.NET Interactive のなんたるかについては、以前の以下の記事で取り扱っているので、そちらを参照願いたい。

.NET Interactive を .NET 5 で動かしてみる

いきなり本題とは関係ない話になるが、 せっかく .NET 5 がリリースされたところなので、 .NET Interactive を .NET 5 で動かしてみよう。

続きを読む

.NET Interactive の C# REPL を Jupyter で

今回は、 .NET Interactive を利用し、ローカルマシンで C# や PowerShell Core の REPL を利用するまでをまとめる。

なお、 とりあえず動かしてみたいだけであれば、 Binder バッジのリンクをクリックして、 オンライン上の Binder にブラウザにアクセスするだけで、利用することができる。
Use Jupyter with .NET Interactive on Binder

.NET Interactive とは

.NET Interactive は、 以前 Try.NET と言う名前で提供されていた、 .NET のインタラクティブな機能を提供する API スイートだ。
JupyterLab に .NET カーネルを追加する形で、 REPL の実行やノートブックの作成する仕組みを提供することが、 主なユースケースとなっている。

REPL ではコード補完も効くので、非常に便利なものになっている。

Jupyter について

まず、 Jupyter についても軽く説明しておく。
既にご存じなら読み飛ばして欲しい。

JupyterLab とは?

続きを読む

大量の nanaco ギフトを自動登録して、オトクに税金を支払う

本記事は、 CUI のコンソール画面から使用する中級者向けのツールのに関する内容だ。
別途、 簡単に使用できる GUI 版も作成したので、そちらについては、以下の記事も参照。


突然だが、自動車税や固定資産税などの税金や、公共料金などの払込票などを、どのように支払っているだろうか?
支払う額も大きくなりがちなので、なるべくお得に支払いたいのではないだろうか。

そこでオススメなのが nanaco ギフト だ。

クレジットカードで直接納税したり nanaco 残高にチャージする場合、手数料がかかったり、ポイントがたまらなかったりと、あまりお得にならない。
しかし nanaco ギフトであれば、額面よりも安く入手する手段が知られている。

  • ベネフィット・ステーション
    • 福利厚生型の会員制割引サービス。
    • 2020年4月現在、 毎月 10万 円分まで 額面の 2% OFF で nanaco ギフトを購入できる。
    • 所属組織による団体加入か、 「ベネフィット・ステーション プライベート」 や 「デイリーPlus」などといった個人向けの有料サービス、 「(JACCS カードの) J’s コンシェル」などの付帯サービスで利用できる。
  • Kiigo (廃止)
    • 以前はクレジットポイントを貯めながら nanaco ギフトを購入できたのだが、 2019年 に nanaco ギフトの取り扱いがなくなってしまった。
  • ちょコムショップ
    • NTT系列の決済会社が運営する、電子マネー購入サイト。
    • 0.5% OFF 程度で、一部ブランドのクレジットカードを使って購入できる。 クレジットカードのポイントと併せればそこそこお得に購入できる。

また nanaco 残高と違ってセンターお預かりへのチャージなので、 チャージ残高の上限が非常に高く (50万円以上も可能らしい)、 nanaco 残高のチャージ上限である 5万円を超えるような金額の支払いでも使える大きなメリットがある。

nanaco ギフトでのお得な納税の話は、他のサイトでもっと詳しくわかりやすく書かれているだろうから、これくらいにしておく。

nanaco ギフトの登録がめんどくさい

さて、 ここからが本題だ。

そんな nanaco ギフトにもひとつ 大きな欠点がある。
それは、 1,000 円単位で提供されることが多い ということだ。

例えば 10万円分 チャージしようとすると、 100 回も nanaco ギフトID のコードを入力しなくてはならないのだ。

更に、 nanaco ギフトの登録を行う UI が、大量のギフト登録に とても優しくない
1回 コードを入力する毎に nanaco にログインしたり、 コードを 4文字 ずつテキストボックスに入力しなくてはならなかったりと、 数をこなすのにとにかく手間がかかるのだ。

10万円 の納税で 2,000円 得するために、 2,000円分 相当以上の手間をかけるのでは愚の骨頂だ。
こうなったら、自動入力させるしかない。

続きを読む

タスクトレイで指令を待ち続ける健気な PowerShell スクリプト

この記事は PowerShell Advent Calendar 2019 の 23日目 の記事だ。
日程が埋まりきっていなかったので、適当な内容で埋めていこう。

あなたは、 PowerShell の短いコードを、 デスクトップのアイコンをクリックするのも億劫なほど、手軽に実行したいと思ったことはないだろうか?

ないって?
私はある。

例えば、ブラウザなどでコピーして WYSIWYG エディターにペタリと貼り付けるときに、クリップボード内の装飾情報を削除したいとか。

(Get-Clipboard -TextFormatType UnicodeText -Raw) -replace '^[ \r\n\t]*|[ \r\n\t]*$','' | Set-Clipboard

PowerShell なら上記のような一行コード実行すれば済む話だ。 しかし、 ウィンドウをシェルに切り替えたり、 ショートカットクリックするのも面倒。 タスクトレイのアイコン一つクリックして実行できたらいいのに。

はい、それを叶えます。

続きを読む

同一ファイルに対して、 複数種類のファイルハッシュを高速に計算する

ネットワークドライブ上の GB オーダーのファイルに対して、複数のハッシュアルゴリズムでファイルハッシュを計算する必要に駆られていた。
「そんなシチュエーションが本当にあるのか?」と思うかも知れないが、あったのだから仕方ない。

最初は、 PowerShell を使って 愚直に Get-FileHash を 2回 計算していた。
しかし当たり前だが、 2回ファイルをダウンロードすることになるこの方法は遅くて仕方ない。

ということで、 C# でコンパイルしたコード上で、 一度メモリに読み込ませてから複数のハッシュアルゴリズムで計算できるようなコードを作成した。

バッファーサイズを 80KiB 程度とすると、 .NET の仕様で 85KB を境にメモリの扱いが変わる (LOH と呼ばれる特別なヒープに移動する) ことから、 このサイズを超えると一般的に動作速度が下がると言われている。
しかし、今回のコードの場合バッファーが小さいと、 Task 周りの処理がボトルネックになってしまうので、 8MiB くらいのサイズとしている。

80KiB としているのは、 .NET mscorlib の System.IO.Stream.CopyTo メソッドなどでもおなじみなのだが、これが必ずしも正解とは限らないわけだな。


パフォーマンス

800Mbps 位でシーケンシャルリードできるリモート上の 4GB のファイルを、 4回 ずつ計測した平均を計測した。
Get-FileHash の 2種類目 以外はクライアントキャッシュが効かないように注意し、 計測の各回でハッシュを計算するファイルはそれぞれ別のファイルで、中身はランダムバイナリとした。
Get-FileHash については、 計測の各回では同じファイルに対して -Algorithm パラメータを変えて複数回連続で呼び出した。

計算したハッシュの種類 Get-FileHash 上記の改良スクリプト
1種類 (SHA1) 48.8s 43.3s
2種類 (MD5, SHA1) 60.4s 44.2s
3種類 (MD5, SHA1, SHA256) 83.3s 48.2s

ん? 計算したハッシュが 1種類 の場合でも、改良スクリプトの方が早いぞ?


うわっ… HashAlgorithm.ComputeHash の実行速度、低すぎ…?

PowerShell v5 相当

PowerShell v6 相当

上記のように、 Get-FileHash は、内部的に HashAlgorithm.ComputeHash でハッシュ計算を実行している。

で、その HashAlgorithm.ComputeHash がどうなっているかというと、 4KiB 毎に ファイルの読み込みと、 ハッシュストリームへの書き込みを 同期的に 行っている。

ファイルの読み込みも、 (使うアルゴリズムにもよるけど) ハッシュの計算も、 どちらもコストがかかるので、同期的にやってたらそりゃ遅いわ。

ZoneId を PowerShell を使って一括削除 [v3 以上]

Windows では、リモートからダウンロードしたファイルに、 "ZoneId" という物が付加される。
このID が付加されたファイルは、 exe として 実行する際にセキュリティ警告が表示されたり、 .NET アセンブリ dll として PowerShell に読み込む際に、

Add-Type : ファイルまたはアセンブリ 'file:///*.dll'、またはその依存関係の 1 つが読み込めませんでした。操作はサポートされません。 (HRESULT からの例外: 0x80131515)
発生場所 行:1 文字:1
+ Add-Type -Path 'C:\*.dll'
+ ~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : NotSpecified: (:) [Add-Type], FileLoadException
    + FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.PowerShell.Commands.AddTypeCommand

などとエラーになってしまう。
160925_1

ファイルが一つだけなのであれば、ファイルのプロパティから『ブロックの解除』をチェックすれば、簡単に ZoneId を削除することができる。
160925_2
しかし、複数個のファイルの ZoneId を一回の操作で同じように削除することができないため、 ZoneId を削除したいファイルが大量にある場合はなかなかウザい。

PowerShell v3 以上を使えば、この ZoneId 削除をいとも簡単に行うことができるので、紹介しよう。

続きを読む

PowerShell バージョンごとのスクリプティング機能の新機能概略

PowerShell v3 以降のそれぞれのバージョン毎のスクリプティングを中心とした新機能のうち、私の独断で選んだ主な機能を列挙してみた。
(PowerShell の本来の役割のはずの) コンピュータ管理機能などはばっさり省いている。

意外と、そういう情報まとまっているのを見たことなかったので。。。

続きを読む

PowerShell の組織の中で使えそうで使えないニッチな Tips

この記事は、 PowerShell Advent Calendar 2015 の 18日目 の記事だ。
私はこれまでずっとネットヒッキーだったので、ネット上でほかの人とのかかわりを持ったことがほとんどなかったが、今回意を決して参加させてもらうことになった。

バリバリの 情シス や プログラマ ではなくても、日常のちょっとした業務で PowerShell を使っている人もいるだろう。
そういったひとびと(主に私)が、組織の中で使えそうだと思ったニッチな話題を書こうと思う。

  • PowerShell Tools for Visual Studio を商用利用する環境は、無料でできる
  • コンソールウィンドウを極力表示せずにスクリプトを実行
  • ネットワーク共有上の DLL を読み込む

続きを読む