# Windows 11 OOBE の sysprep スクリプトをフォークして自分のドメインに置いた

2026-08-09

Windows 11 Home / Pro のセットアップ画面（OOBE）は Microsoft アカウントの作成またはログインを要求する。
ローカルアカウントで済ませたい時、[zawa-lab のワンライナー](https://w1.zawa-lab.net/p/20260728_oobe_bypass/)が便利で、たまに使っている。

```powershell
powershell -c "irm w1.zawa-lab.net/w|iex"
```

[中身](https://w1.zawa-lab.net/w)は、OOBE の中で `unattend.xml` を組み立てて `sysprep /oobe /reboot` を叩く PowerShell スクリプトだ。

ただ、`w1.zawa-lab.net/w` は毎回思い出せない。
それに、upstream が消えたり書き換わったりしても、こちらから気付く手段がない。
あと、自分はコンピューター名も入力段階で決めておきたい（元のスクリプトは Windows のデフォルトに任せる）。

そこで、CC BY-NC-SA は再配布と改変を認めているので、帰属表示を付けてフォークし、自分の管理下に置いた。

```powershell
powershell -c "irm bypassnro.sougen.dev|iex"
```

## fork の要件

- upstream の設計をそのまま踏襲する（動作は同じ、追加分はオプション扱い）
- 自分の変更は upstream の意図と競合しない範囲に留める
- ブラウザで開いたら「これは何か、出典はどこか、どう使うか」がすぐ読める
- 常設の運用コストがゼロ

これらは Cloudflare Pages で全部満たせる。

## 配信の仕組み

自分のリポジトリの `src/header.html` と `src/oobe-localaccount.ps1` を連結して `dist/index.html` に書き出す。

```sh
#!/usr/bin/env sh
set -eu

# 空ファイル押し込みなどを catch する簡易 sanity check
grep -q 'oobe-localaccount.ps1' src/oobe-localaccount.ps1

mkdir -p dist
cat src/header.html src/oobe-localaccount.ps1 > dist/index.html
```

Pages プロジェクトの build コマンドとして `./build.sh` を指定してあるので、`git push` すると CF Pages が自動でビルド → デプロイまで走る。

なお、DNS は `bypassnro.sougen.dev` を `bypassnro.pages.dev` に CNAME して Proxy を有効にする。
証明書も配信も CF Pages 側が持つ。

## 独自機能: コンピューター名プロンプト

upstream との差分はスクリプト側の 1 点だけ。
User name と Password の入力に続いてコンピューター名を対話的に取得し、`unattend.xml` の `specialize` パスに `<ComputerName>` を差し込む。

```powershell
# --- computer name (optional) ---
while ($true) {
    $cn = (Read-Host 'Computer name (blank = Windows default)').Trim()
    if ($cn -eq '') { break }
    if ($cn.Length -gt 15) { ... continue }
    if ($cn -notmatch '^[A-Za-z0-9-]+$') { ... continue }
    if ($cn -match '^[0-9]+$') { ... continue }
    if ($cn -match '^-|-$') { ... continue }
    if ($cn -ieq $name) { ... continue }
    break
}
```

バリデーションは Windows のホスト名規約に沿った 5 点：15 文字以内、英数とハイフンのみ、全数字禁止、ハイフンで開始/終了禁止、ユーザー名と一致禁止。

空入力なら、`unattend.xml` の `specialize` パス自体を出力しない（Windows のデフォルト命名に任せる）。
入力があった時のみ、以下のブロックを組み込む。

```xml
<settings pass="specialize">
  <component name="Microsoft-Windows-Shell-Setup" ...>
    <ComputerName>$cn</ComputerName>
  </component>
</settings>
```

初回セットアップの中で決めておくと、ドメイン参加もその後の作業も進めやすい。

## HTML と PowerShell を両立させるハイブリッドコメント

案内用の `src/header.html` は、同じ URL を `irm | iex` で叩いてもブラウザで開いても機能するように書いてある。
先頭部分が、PowerShell のコメントとしても HTML のマークアップとしても成立する構造にしてある。
とある PowerShell スクリプトが採用している方式をそのまま真似した。

```html
# This script is hosted at <b>https://bypassnro.sougen.dev</b><br>
# Fork of <a href="https://w1.zawa-lab.net/w">https://w1.zawa-lab.net/w</a> - adds an optional Computer name prompt.<br>
# Upstream article: <a href="https://w1.zawa-lab.net/p/20260728_oobe_bypass/">https://w1.zawa-lab.net/p/20260728_oobe_bypass/</a><br>
# License: CC BY-NC-SA 4.0 by zawa-lab (<a href="https://w1.zawa-lab.net/">https://w1.zawa-lab.net/</a>)<br>
# Usage:   powershell -c "irm bypassnro.sougen.dev|iex"<hr><pre>
```

要点は三つある。

**各行が `#` で始まる**。
PowerShell では `#` から行末までがコメント扱いなので、HTML タグは実行時に完全に無視され、続くスクリプト本体だけが評価される。

**各行末に `<br>` を置く**。
HTML では素の改行はスペース扱いなので、`<br>` を明示しないと 5 行のヘッダーが 1 行に潰れて表示される。
PowerShell 側では `<br>` はコメント内の文字列として無視される。

**末尾の `<hr><pre>` を閉じない**。
閉じないまま HTML を終わらせると、その後に連結されるスクリプト本体がブラウザから見て `<pre>` 内のプレーンテキストとして表示される。
同じ 1 ファイルで「実行可能な PowerShell」と「読める Web ページ」を兼ねられる。

## ライセンス

CC BY-NC-SA 4.0 は「同一条件で継承」なので、リポジトリの `LICENSE` には zawa-lab への帰属表示と、この配布物も同ライセンスであることを明記した。

なお、CC ライセンスが規制するのは複製・配布・翻案といった著作権上の行為なので、`irm` で取得して自分の PC で実行するだけの利用者にはそもそも影響しない。

## まとめ

`irm bypassnro.sougen.dev|iex` で自分の fork（元は zawa-lab のスクリプト、コンピューター名プロンプトを追加）が走る。
配信は Cloudflare Pages のビルド枠だけで完結している。

良い Windows 11 ライフを。
