winget が使える状態で Windows Sandbox を起動する

Windows Sandbox は、Windows 10/11 Pro 以降に搭載されている仮想環境機能だ。
一時的でクリーンな Windows 環境を素早く作成し、アプリケーションのテストやファイルの検証を安全に行うことができる。

Windows Sandbox を使うにあたって、目的の作業に必要なツールをサクッとインストールしたいことがままある。
Windows 上でツールをインストールする場合、 Microsoft Store や winget を使う事が一般的だ。
しかし、 Windows Sandbox を立ち上げてすぐの環境ではこれらを使うことができない。
加えて、素直にこれらをインストールしようにも、依存関係が満たされていないためインストールに失敗してしまう。

そこで、 Windows Sandbox の設定ファイル (.wsb) を使用して、 Windows Sandbox 起動時に winget が使える状態を整えよう…というが、今回の話。

Windows Sandbox の設定ファイル (.wsb) とは

Windows Sandbox は、XML 形式の設定ファイル (.wsb) を使用して起動時の構成をカスタマイズできる。
この設定ファイルでは、主に以下のような設定が可能だ。

  • vGPU(仮想 GPU)の有効/無効
  • ネットワークの有効/無効
  • 共有フォルダの設定
  • メモリ使用量の制限
  • ログオン時のコマンド実行

詳細な設定オプションについては、以下のマイクロソフト公式ドキュメントを参照:

今回は、上記のうち「ログオン時のコマンド実行」の機能を利用する。

winget をインストールするログオンコマンド

続きを読む

Rust で Windows API のグローバルフック

本記事は、 Rust Advent Calendar 2024 シリーズ3 の 20日目 の記事だ。
ついでに、 Windows Advent Calendar 2024 20日目 の記事としても登録させてもらっている。
遅刻です。申し訳ない。

今回は、やや実践的な例として、 Rust で Windows API の グローバル フック を使って、各ウィンドウに届くマウスやキーボード・ウィンドウメッセージをダーッとリアルタイムで表示するコードを書いてみよう。

フックDLLでメモリリークやセグメント違反を引き起こすとシステム丸ごと死にかねないし、フックした情報を表示するためにプロセス間通信やマルチスレッドの処理が必要になるなど、割と Rust 向きな例ではなかろうか。

フックとは

Win32 アプリケーションでは、各ウィンドウやコントロールがそれぞれイベントハンドラ(プロシージャ)を持ち、これが届いたメッセージを処理することで様々な機能を振る舞わせる。
「フック」とは、本来のプロシージャに届くはずの処理を先に引っ掛けて(フックして)、処理を間に挟んでから本来のプロシージャに返したり、あるいは処理を奪ってしまう機能だ。

グローバル フック は、同じ PC 内の権限的に許されるあらゆるプロセスのスレッドに対して、フックをねじ込む機能だ。
キーロガーなどのウイルスや、クリップボード監視のソフトなどでよく使われている(と思う)。

グローバルフックした場合、フック対象それぞれのプロセス毎に、フックプロシージャを定義した DLL をロードさせ、そのプロシージャを呼び出させる。
つまり、フックされたプロセス毎に DllMain が呼ばれるし、メモリ空間も独立する。
標準出力も、フックされたプロセスのものが利用されるので、例えばフックプロシージャで println! しても、フックを登録したプロセスではなくて、フックされたプロセス側の標準出力に書き込まれるわけだ。

graph LR
    subgraph caller[呼び出し元 exe]
        D0[DLL]
    end
    subgraph sub1[フック対象プログラム1]
        D1[DLL]
    end
    subgraph sub2[フック対象プログラム2]
        D2[DLL]
    end
    D0 -->|"登録"| D1
    D0 -->|"登録"| D2
    D1 -->|"println!"| cfor1@{ shape: f-circ }
    D2 -->|"println!"| cfor2@{ shape: f-circ }
    cfor1 --> sub1
    cfor2 --> sub2

このため、フックしたメッセージを登録元プロセスにて表示するためには、スレッド間参照などは使えず、プロセス間通信などを使う必要がある。
今回は、名前付きパイプで登録元プロセスに情報を渡してみる。

graph LR
    subgraph caller[呼び出し元 exe]
        D0[DLL]
    end
    subgraph sub1[フック対象プログラム1]
        D1[DLL]
    end
    subgraph sub2[フック対象プログラム2]
        D2[DLL]
    end
    D0 -->|"登録"| D1
    D0 -->|"登録"| D2
    D1 -->|"名前付きパイプ等"| caller
    D2 -->|"名前付きパイプ等"| caller

名前付きパイプによるプロセス間通信

続きを読む

Rust と Win32 API RawInput で HID の TouchPad を深堀り

本記事は、 Rust Advent Calendar 2024 シリーズ1 の 17日目 の記事だ。
ついでに、 Windows Advent Calendar 2024 17日目 の記事としても登録させてもらっている。

Win32 API の RawInput を、先日紹介した Rust + windows-rs を使って呼び出し、 USB/Bluetooth HID の生入力情報を読み取っていきたい。

PC にはキーボードやマウス以外にも、スタイラスやタッチパッド等々の多くの入力デバイスが繋がるが、通常 Windows アプリにはひとつの「マウス」または「キーボード」と抽象化された状態で情報(ウィンドウメッセージ)が届く。

生入力… もとい RawInput を使うと、複数のマウス・キーボードや、任意のヒューマンインターフェイスデバイス (HID) などの、より低レベルなメッセージを受け取れるようになる。

受け取れる情報は以下の3種類。

  • マウスからの RawInput
  • キーボードからの RawInput
  • マウスやキーボード以外の、任意の HID からの RawInput

マウスやキーボードの RawInput は Windows 側で使いやすく整形された情報を取得できる。
ゲームなどでよく使われる事もあり、サンプルも数多く見つかるだろう。

本記事では、このうち最後の「任意の HID からの RawInput 情報の取得」について、高精度タッチパッドを例に簡単に説明していく。

Rust 書き始めてまだ数週間なので、あまり Rust らしい書き方になってないかもだが、その点はご容赦を。

HID プロトコルとは

続きを読む

毎日最初のロック解除時に特定の URL を開くためタスクトレイに常駐する PowerShell スクリプト

シェルスクリプト&PowerShell Advent Calendar 2024 の 15日目 の記事だ。
ついでに、 Windows Advent Calendar 2024 15日目 の記事としても登録させてもらっている。

電子タイムカードの打刻など、毎日出勤時に PC で特定の Web サイトを操作する事を強要されることは無いだろうか?
その作業習慣が血肉となるまで魂に刻み込まれるまで飼い慣らされていないと、頻繁に操作を忘れてしまう。

普段 PC をシャットダウンしているのであれば、スタートアップにその Web サイトの URL を登録しておくことで、 PC ログイン時に自動的にそのページが立ち上げられるので、やり忘れを防止できる。

しかし、普段 PC をスリープしっぱなしな運用にしている場合、朝初めてPCを立ち上げ(スリープ解除)した際に、特定のページを開かせるのは意外と難しい。

そこで、 PC のタスクトレイに PC のロック解除イベントを監視する PowerShell スクリプトをタスクトレイに常駐させ、「その日最初のロック解除」の時に特定の URL を開く仕組みを作成してみた。

導入手順

続きを読む

Rust で Win32 API ことはじめ

本記事は、 Rust Advent Calendar 2024 シリーズ3 の 14日目 の記事だ。
ついでに、 Windows Advent Calendar 2024 14日目 の記事としても登録させてもらっている。

Rust で Win32 API を叩くにあたって、最初に知っておきたい情報をまとめておく。

Win32 API を呼ぶ手段

C# の P/Invoke のように一つ一つの API をソースコード上で定義してリンクすれば、呼び出せなくはない。 1

しかしそれは流石に面倒なので、 Microsoft による windows-rs のクレートを使うのが基本となる。

windows-rs とは

windows-rs は、 Microsoft 自身が Windows API のメタデータから生成されたコードを用いて、 Rust から Windows API を呼び出しやすくするクレートを提供するプロジェクトだ。
その仕組みの通り、 Win32 API のほぼ全てに加え、 COM API や WinRT もその多くがカバーしている。

大まかな情報は、以下のページにまとまっていて基本的にはこれを読み進めればよい。

しかしそれではわざわざ記事を書く必要性が薄いので、この記事では Win32 API コードを書くにあたって、最初に知っておきたい情報をまとめておこう。

なお、後述するが windows-rs は COM や WinRT の API もカバーしており、それぞれ呼び出し方にコツがある。
すべてを解説すると分量が多いので、本記事では Win32 API の範囲に限って説明する。


ところで、↑のドキュメントのドメインである kennykerr.ca って誰のやねんって話だが、 Microsoft のエンジニア らしい。
Microsoft 公式マニュアルが個人名のドメインに置かれているってどうなのと言う気もせんでもないが、元々個人の趣味プロジェクトだったのかな…?

また、 2024年12月現在最新版が 0.58.0 と、セマンティックバージョン的にもまだ破壊的変更が入りうるものだ。
最近こそ更新は落ち着いてきているものの、以下の情報が今後変わりうることはご留意いただきたい。

windows クレート と windows-sys クレートの使い分け

続きを読む

プロキシ環境下の Rust の導入方法と Rust Analyzer のコード補完トラブル解決ガイド

本記事は、 Rust Advent Calendar 2024 4日目 の記事だ。
ついでに、 Windows Advent Calendar 2024 4日目 の記事としても登録させてもらっている。

どちらもまだ空きが在るので是非登録してね!

Rust Advent Calendar 2024 シリーズ 2 の 3日目 の記事は、 @yo-naka 氏の Observable Framework のデータローダーを Rust で書く方法 #ObservableFramework
データ可視化用の静的サイトジェネレーター Observable Framework のデータローダーを、省メモリで高速に処理できる Rust で書くという内容だった。


さて4日目の本記事では、プロキシ環境下にて Windows + vscode + Rust Analyzer の組み合わせで使用しようとしたところ、標準ライブラリ等のコード補完が期待通り動いてくれなかった問題の対処メモを共有したい。

ついでに、プロキシ環境下のセットアップや、 vscode でデバッグする手順も示す。

再現手順

続きを読む

バッチや JScript に PowerShell を埋め込んでダブルクリックで起動する Polyglot 色々

本記事は、 シェルスクリプト&PowerShell Advent Calendar 2024 2日目の記事だ。
まだまだ始まったばかり。 執筆者求む、執筆者!


さて、 PowerShell スクリプトファイル (.ps1) は、 WSH や Office VBA のウイルス蔓延を許した反省からか、 Windows の標準ではスクリプトファイルをダブルクリックしても実行できない。
ただ、これだと人にファイルを渡して実行してもらうのに手間がかかるので、特別な関連付け設定をせずダブルクリックで実行できる PowerShell スクリプトを作りたい。

ひとつのスクリプトファイルを、異なる複数のプログラミング言語で正しく解釈できるように書く、 Polyglot というテクニックがある。
そういったテクを活用して、「ダブルクリックで起動できるバッチやスクリプトを使って、自分自身を PowerShell スクリプトと解釈させて実行」する単一ファイルを作成する方法をいくつか考えてみよう。

仕組み上、 PowerShell スクリプトファイル (.ps1) を介さないので、以下のような制限がある。

  • 標準入力を受け付けられない (パイプ先になれない)
  • PowerShell 的にはスクリプトファイルを実行しているわけではないので、 $PSScriptRoot, $PSCommandPath, $MyInvocation.MyCommand.Path あたりが空になる

このため以降で紹介するどのパターンでも、自身のファイルのフルパスを環境変数 SCRIPT_PATH に入れてから PowerShell を呼び出している。
PowerShell スクリプト内では $env:SCRIPT_PATH を呼び出すことで、少なくとも後者の問題については回避できる。

コンソールウィンドウありバッチファイル

続きを読む

Hyper-V で「リンクしたクローン」の VM を作成し、容量を節約する

本記事は、 Windows Advent Calendar 2024 初日の記事だ。
今年もついに始まった技術記事の Advent Calendar シーズン。 みんなこぞって参加しよう!!!


突然だが、 VirtualBox や VMware には、 "リンクしたクローン" という機能がある。

例えば、同じ OS のサーバーを 10台 用意する必要がある際に、まず1台キッティングした後にこの機能を使って複製すると、仮想HDDのサイズを大幅に節約することができる。

Hyper-V には同じ機能は用意されていないのだが、「差分ディスク」という機能を使えば、似たようなことを実現できる。 1

流れ:

  1. 仮想マシン作る
  2. 自動チェックポイントを外す
  3. キッティング
    • Windows ならページングファイル(仮想メモリ)サイズを小さめに (256-512MB)
    • 仮想 DVD ドライブからメディアを取り外し
  4. チェックポイントを作成
  5. 差分ディスクだけ作成
  6. 仮想マシンを差分ディスクを指定して作成

ただし、 VirtualBox などと異なり、任意のチェックポイントからの差分は作成できない。
必ず初回のチェックポイントからの差分となる。

では、細かい手順を見ていこう。

仮想マシンを作る ~ キッティング

続きを読む

Ventoy ブート時の Verifiying shim SBAT data エラーのワークアラウンド

久々に、 Ventoy: A New Bootable USB Solution をブートしようとしたら、以下のようなエラーが発生してしまった。

Verifiying shim SBAT data failed: Security Policy Violation
Something has gone seriously wrong: SBAT self-check failed: Security Policy Violation

スペルのブレで場合によっては以下の表記となっているかもしれない。

Verifying shim SBAT data failed: Security Policy Violation
Something has gone seriously wrong: SBAT self-check failed: Security Policy Violation

どうやら、セキュアブートをサポートする UEFI 環境で起動しようとすると、上記エラーが発生するようだ。

本記事執筆時の Ventoy 最新版 1.99 では修正されていない。
もしかしたらより新しいバージョンでは修正されているかもしれないので、古いバージョンを使用しているなら、まずはバージョンアップを試してみよう。

ただ、大分前 (2023年12月) から問題になっているのに、 Ventoy 側にはこの修正が反映されていない。
このため、この問題のワークアラウンドについて紹介しよう。

ワークアラウンド方法1) セキュアブートを無効にする

単純な話、セキュアブートでエラーになっているのだから、 UEFI 設定でセキュアブートを無効にしてしまえば良い。

続きを読む

HP Pavilion 15-eh3000 : タッチ対応で32GBメモリに増設可能な格安PCのメモリ交換記

以前使っていた DELL Inspiron の 2-in-1 の PC のバッテリーが、2時間程度しか持たず実用的ではなくなってきたので、買い換えたい。

予算もあまりないので安く済ませたいのだが、どうしてもタッチ対応は外せないし、PCを更新するなら RAM は 32GB にしたい。

しかし選択肢は意外となく、最終的に HP Pavilion 15-eh3000 を購入し、メモリを 32GB に増設(換装)する方法に行き着いたので、そのメモ。

購入 PC の条件

条件を決めないことには PC を選べないので、とりあえず以下の条件で探すことにした。

  • ノート PC
  • タッチ対応
  • メモリ (RAM) は 32GB
  • 予算は 8~9万 程度
  • CPU は Core i5 / Ryzen 5 程度ならなんでも
  • 内蔵グラフィックで OK
  • DELL 以外

本当は筆圧対応ペン入力対応な 2-in-1 の方がよかったのだが、価格やメモリサイズ的に条件を合わせるのが難しいのがわかっていたので、泣く泣く妥協している。

タッチパネルやペン入力載せるようなモデルは、実装スペースの関係かオンボードメモリのものばかりで、BTO のカスタマイズで 32GB の選択肢すら存在しないものが大半である。

価格.com では、メモリの空きスロットや、メモリ交換の可否で絞り込むことができない。
価格.com のキーワードに「メモリスロット」と入れ、 PCビューで詳細表示すれば、絞り込めはせずともSO-DIMMスロットがあるモデルが多少探しやすくはなるが、そんなに選択肢がない(価格.comに載っていないだけかもだが)ことがわかる。

この方法で、SODIMM スロットが2つ存在するモデルを検索し、自分で 32GB メモリに換装する方針で絞り込んでいった。

Lenovo あたりだと、1枚オンボードで 1枚 SODIMM スロットという変態構成の端末がある。
しかし1枚だけメモリを増量させても、デュアルチャンネルにならないことや、相性問題が起きやすいリスクがあるので避けている。

DELL を除外しているのは、以前私用で使っていた Inspiron も、会社で使っていた Latitude も、どちらもスリープ処理が下手くそで非常に困ったからだ。
ちゃんとスリープされず、電源につないでいれば24時間ファンをぶん回してうるさいし、バッテリー状態にしておくと勝手に5%まで残量減らしてるし、どれもどうも調子が悪かった。
毎日そんな不要な充放電が繰り返された結果、あっという間にバッテリーが劣化してしまったのが、若干トラウマになっている。

結局、 HP Pavilion 15-eh3000 の Ryzen 5 7530U + 16GB RAM モデルに...

続きを読む