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 を開く仕組みを作成してみた。

導入手順

続きを読む

docker の snap パッケージをプロキシ環境で使う方法と、 compose で build エラーになる話

本記事は、 Docker/コンテナ仮想環境 Advent Calendar 2024 - Qiita 5日目の記事だ。

Linux で docker をインストールする場合、どのようにしているだろうか?
OS 標準のパッケージマネージャーからのインストールが一般的? それとも、 Docker 公式のリポジトリ (Install - Docker Docs) を使っているだろうか?

そんな docker インストールする方法のひとつに Snap (Snapcraft) がある。

Snap (Snapcraft) とは

Snap (Snapcraft) は、Canonical が開発・管理している、アプリケーションをパッケージ化して配布するためのシステムのひとつだ。 Canonical は Ubuntu を支援している企業だが、 Ubuntu 以外の多くの主要なディストリビューションでも Snap を利用できる。

依存関係を含む一式がコンテナ化されており、異なる Linux ディストリビューション間で共通のパッケージで動作するのが特徴だ。 サンドボックス化したファイルシステム内でインストールしたアプリケーションを動かすという、セキュリティ面の特徴もある。

snap 版 docker は、 /home/ 以下のファイルしか参照できない強い制限 1 や、インストール時に docker グループを作成してくれない制限があるが、それ以外はわりと問題なく動く。

Snap 版 docker に於けるプロキシ設定手順

プロキシの設定さえ適切に行えば、 snap 版 docker もプロキシ環境下で動作する。

基本的な設定箇所は、 Docker DaemonDocker CLI の設定と同じだが、前述のサンドボックス化の関係で、記述するファイルの場所が異なる。

具体的には

  • /etc/docker/daemon.json の替わりに /var/snap/docker/current/config/daemon.json
  • ~/.docker/config.json の替わりに ~/snap/docker/current/.docker/config.json

をそれぞれ書き換える。

特に後者 (~/snap/docker/current/* 以下) については、一度そのユーザーで何らかの docker コマンド (後述の例では docker info) を実行してから設定しなくてはならない。
そうしないと、フォルダが Snap サンドボックスへマッピングされないからだ。

では、インストールからの手順を追ってみよう

続きを読む

プロキシ環境下の 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 設定でセキュアブートを無効にしてしまえば良い。

続きを読む

MicroK8s で kustomization.yaml を apply すると error: accumulating resources になる問題

MicroK8s で kustomization.yaml を apply した際に、 error: accumulating resources が発生する問題についてのメモ。

端的に言うと、snap でインストールした MicroK8s で、内部的に git コマンドが実行される操作をすると、おかしくなる模様。

発生する問題

snap で MicroK8s をインストールし、 kubectl apply -k する。
このとき、Kustomize に指定する kustomization.yaml には、直接的または間接的に remote directory 方式のリソースを参照する。

$ sudo snap install microk8s --classic --channel=latest/stable
$ cat << EOF > ./kustomization.yaml
resources:
- https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/?timeout=120&ref=v3.3.1
EOF
$ microk8s kubectl apply -k .

すると、以下のようなエラーが発生する。

ホストOS に git がインストールされている場合:

error: accumulating resources: accumulation err='accumulating resources from 'https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/?timeout=120&ref=v3.3.1': URL is a git repository': failed to run '/snap/microk8s/6364/usr/bin/git fetch --depth=1 https://github.com/kubernetes-sigs/kustomize v3.3.1': /usr/lib/git-core/git-remote-https: symbol lookup error: /snap/core20/current/lib/x86_64-linux-gnu/libpthread.so.0: undefined symbol: __libc_pthread_init, version GLIBC_PRIVATE
: exit status 128

ホストOS に git がインストールされていない場合:

error: accumulating resources: accumulation err='accumulating resources from 'https://github.com/kubernetes-sigs/kustomize//examples/helloWorld/?timeout=120&ref=v3.3.1': URL is a git repository': failed to run '/snap/microk8s/6364/usr/bin/git fetch --depth=1 https://github.com/kubernetes-sigs/kustomize v3.3.1': fatal: unable to find remote helper for 'https'
: exit status 128

ワークアラウンド

続きを読む