azukipochette's weblog

memory dump (mini)

検証用の Windows ベース イメージを Compact OS にして約 30 % (1.6 GB) ディスク節約する話

Compact OS とは何なのか

マイクロソフトは、パートナーを通じて戦略的に Windows タブレット PC を複数出していますが、タブレットのような小型端末では、SSD などの大容量ディスクが搭載できないため Windows のようなディスクの占有率の大きい OS をインストールするとユーザー使用領域がほとんどないという問題が発生します。そこで、Windows 10 では特定条件を満たすと自動的に Compact OS と呼ばれる OS のシステム ファイルを圧縮するモードでインストールされるようになっています。また、条件を満たしていなくても OEM がマスターイメージ作成時にオプションを有効にすることもできます。compact.exe というコマンドを使うことであとから圧縮/非圧縮を変更できますが、今回はこの話はせずに、インストール時に Compact OS 化する話をします。なお、Compact OS というのは、ファイルアクセス時に展開することになるため、パフォーマンスが悪い HDD などのディスクでは推奨されません。

なぜ Compact OS なのか

私は Vagrant + VMWare を使って検証 VM を管理していますがベース イメージ自体を小さくするということは、ディスク使用量の減少だけでなく、BOX ダウンロード時間の短縮、BOX 管理用クラウド ドライブの使用料削減、など様々なメリットがあるからです。

Compact OS のインストール方法

Windows 10 のインストール画面で Shift+F10 を押し、コマンド プロンプトを起動します。

(オプション) 英語キーボードを使用している場合

英語キーボードを使用している場合、日本語版の OS では日本語配列のキーボードであることが想定されているため、うまく入力ができません。 英語のキーボードのリストを取得する場合、次のように入力します。

wpeutil ListKeyboardLayouts 0x411

表示されたリストの中から使用中のキーボードを選択します。たとえば英語 "(インターナショナル)" キーボードの場合は次のように実行します。

wpeuitl SetKeyboardLayout 0411:00020409

変更後、次のようにして新しくコマンド プロンプトを起動すれば、英語配列でキー入力ができるようになります。

start cmd

パーティションを設定する

パーティションは diskpart コマンドで行います。コマンドライン上で以下のコマンドを実行し、対話モードでパーティションを作成していきます。

diskpart

パーティションの作成方法は、マイクロソフトの以下のドキュメントを参考にします。

https://msdn.microsoft.com/ja-jp/library/windows/hardware/dn898510(v=vs.85).aspx

具体的には、以下のコマンドで UEFI/GPT ベースのハード ドライブ パーティションを設定していきます。なお、私の場合、回復パーティションのほうはディスク サイズ削減を目的に作成していません *1

select disk 0
clean
convert gpt
create partition efi size=100
format quick fs=fat32 label="System"
assign letter="S"
create partition msr size=16
create partition primary 
shrink minimum=500
format quick fs=ntfs label="Windows"
assign letter="W"

create partition primary
format quick fs=ntfs label="Recovery tools"
assign letter="R"
set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac"
gpt attributes=0x8000000000000001

list volume
exit

コンパクト OS イメージを適用する

必須ではありませんが、作業を高速化するために電源プランを "高パフォーマンス" に変更します。

powercfg /s 8c5e7fda-e8bf-4a96-9a85-a6e23a8c635c

以下のコマンドで、ISO に含まれるエディションを取得します。

dism /get-ImageInfo /ImageFile:D:\sources\install.wim

表示されたリストから、インストールするエディションをのインデックス番号を特定します。 たとえば、"Windows 10 1803 (Business Edition)" の場合、以下のリストが表示されます。

# 名前
1 Windows 10 Education
2 Windows 10 Enterprise
3 Windows 10 Pro
4 Windows 10 Pro Education
5 Windows 10 Pro for Workstations

次にコンパクト OS イメージを W:\ に適用します。以下の例では、"Windows 10 Enterprise" (2) をインストールの対象にしています。

dism /Apply-Image /ImageFile:D:\sources\install.wim /Index:2 /ApplyDir:W:\ /compact

BCDBoot を使ってシステム パーティションを構成します。

W:\Windows\System32\bcdboot W:\Windows /s S:

システムを再起動します。

wpeutil reboot

再起動後、Windows が "準備しています" と言いながら様々な設定をしますので、しばらく待ちます。 (結構長いです)

準備が完了するとコルタナが話しかけてきますので、あとは通常のセットアップ同様に作業を行います。

Compact OS になっているかどうかを確認する

Compact OS としてインストールできているかどうかを確認するには次のコマンドを実行します。

compact /compactos

Compact OS になっていれば、以下のように表示されます。

システムは圧縮状態です。管理者が変更しない限り、この状態のままになります。

それでは、よい Compact OS 生活を。Enjoy!

*1:検証用の VM を大切に使う方は回復パーティションを用意したほうがいいと思います。私は壊れたら作り直す精神です。

空白の変更を無視して本当に変更されたファイルだけを git add する方法

社内的には Git リポジトリとしてコード管理しているが、お客様には git リポジトリをそのまま渡したくないので export したものをご提供。後日、お客様から改修依頼があって、現状のコードを送って git status したら大量の変更が!...しかし、git diff すると空白が違うだけのファイルばかり...というときに本当に変更されたファイルだけを git add したい、そういう話です。

この問題は、以下のコマンドで解決できます。

git diff -U0 -w --no-color | git apply --cached --ignore-whitespace --unidiff-zero -

alias として登録して登録する場合は以下のコマンドを実行します。

ユーザー単位で設定するなら --global、システム単位で設定するなら --system オプションをつけてください。

git config alias.addnw=!sh -c 'git diff -U0 -w --no-color "$@" | git apply --cached --ignore-whitespace --unidiff-zero -

参考

参考というか、ここの回答をそのまま書いたようなものなんですが...備忘録を兼ねて書きました。

では、よい git add 生活を。Enjoy!

.NET Compiler Platform (aka "Roslyn") を使う場合に必要なコンポーネント群

以下のコンポーネントをインストールします。

コンポーネント ID 名前 説明
Microsoft.VisualStudio.Workload.CoreEditor Visual Studio のコア エディター 構文認識コード編集機能、ソース コード管理、作業項目管理などの Visual Studio の基本的なシェル エクスペリエンス。
Microsoft.VisualStudio.Workload.VisualStudioExtension Visual Studio 拡張機能の開発 Visual Studio 用のアドオンや拡張機能 (新しいコマンド、コード アナライザー、ツール ウィンドウを含む) を作成します。
Microsoft.Component.CodeAnalysis.SDK .NET Compiler Platform SDK .NET Compiler Platform SDK

なお、検証用のプロジェクトを作成する目的で、以下のプロジェクトも入れておくといいと思います (この辺りはお好みで)。

コンポーネント ID 名前 説明
Microsoft.VisualStudio.Workload.ManagedDesktop .NET デスクトップ開発 説明: C#、Visual Basic、F# を使用して、WPF、Windows フォーム、コンソール アプリケーションをビルドします。

私は以下も一緒にいれています (T4 いいですよね)。

コンポーネント ID 名前 説明
Microsoft.VisualStudio.Component.TextTemplating テキスト テンプレート変換 テキスト テンプレート変換 (T4)

それでは、よい Roslyn 生活を。Enjoy!

Vagrant Provision を Chocolatey で快適にした話

以前に Vagrant up するときに Visual Studio を自動インストールする方法を書きましたが、ほかのツールもいろいろとインストールしたいですよね。

Windows のアプリケーションは基本的にサイレント インストールする設計になっていないアプリも多いので、いろいろと面倒なのですが、apt-get install と同じぐらいの手軽さで Windows アプリもインストールさせてよ!と思う人は多いようで、ちゃんとプロジェクトがあります。名前は、"Chocolatey" です。

たぶん .NET 開発者なら知らない人はいないであろう NuGet と呼ばれる技術をバックエンドにつかったもので、choco install でアプリケーションを手軽にインストールできます。

実際のところ、ホスト マシンですら Chocolatey で構築してしまおうという人も多いのですが、サイレント インストールなので細かい設定ができなかったりして、私はあまりホストのセットアップに使うのは好きではありません。 一方、1 日 1 回以上作成する可能性すらある検証マシンの場合、とにかく入ってくれればいいというシチュエーションは少なくなく、Chocolatey との相性は抜群と言えます。

Chocolatey をインストールする

Chocolatey を使うためには、まずは Chocolatey をインストールしなければなりません。 ワンライナーで手軽にインストールできるようにしてくれているので、ありがたくその方法を使います。

インストール方法は以下に記載があります。

https://chocolatey.org/install

Vagrant において Provisioner の 1 つである shell は Windows においては PowerShell を呼び出すよ、と書かれているので Install with Powershell.exe のほうを使いましょう。

具体的には以下のように Vagrantfile を記載します (必要に応じて設定などを追加してください)。

# -*- mode: ruby -*-
# vi: set ft=ruby :

# Install Chocolatey inline script
$script = <<SCRIPT
Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://chocolatey.org/install.ps1'))
SCRIPT

Vagrant.configure("2") do |config|
  config.vm.box = "<your box>"
    config.vm.provision "shell", inline: $script
end

なお、config.vm.provison は複数書けます。複数書いた場合は上から順番に実行されるようです。

Chocolatey でアプリを自動インストールする

Chocolatey でアプリをインストールするには、上記の SCRIPT に追記してもいいですし、次のように PowerShell を呼び出して手動でインストールしてもいいです。 同じ環境を何度も作る必要があるなら SCRIPT に追記したほうがいいですし、一時的にアプリをインストールしたいなら Powershell 経由でもいいですね。

たとえば、Git をインストールする場合は、以下のように実行すれば勝手にインストールしてくれます。

choco install git -y

ポイントは、最後の -y でこれをつけないと "インストールしますか?(Y/N)" な対話型な状態になってしまうので、自動的に Y (Yes) になるよう -y をつけます。 特に Vagrantfile に記載した場合は、インストールに失敗してしまうのでご注意を。

それでは、よい Chocolatey 生活を。Enjoy!

Git リポジトリ上の Markdown ファイルを編集したら自動的に PowerPoint ファイルを生成するようにした話

前回の続編です。

前回までで Pandoc が動く Docker イメージを作ったので docker pull と docker run をすれば手軽に Markdown から PowerPoint が生成できるようになったのですが、自分はいいもののほかの人に使ってもらうためには Docker の環境を構築して docker run のためのコマンドを説明して...とかなり大変なので、Git リポジトリ上の Markdown を書き換えたら自動的に PowerPoint を生成されるよ!というふうにする気になりました。今回はその自動化の話です。

Markdown (*.md) ファイルを再帰的に探索して Pandoc で PowerPoint ファイル (.pptx) に変換する

手動を前提にしていた時は気にしなくてよかったのですが、自動化するので複数ファイルの変換をどうやってやるか考えます。

今回の場合は、サブ フォルダーも含めてどこかにある *.md から同じ名前の *.pptx を生成するようにします。「ほかのフォルダーに同名のファイルがあった場合はどうするの?」という問題はありますが、私の利用用途では問題にならないので、考慮していません。

また、生成した "*.pptx" は out フォルダーを作ってそこに放り込むことにします。ここでも「フォルダ構造は無視でいいの?」という話がありますが、これも考慮しません。*1

というわけで、以下のようなシェルス クリプトを書きました。

#!/bin/sh
mkdir out

find `pwd` -name "*.md" | while read line
do
  echo $line
  filename=`basename $line .md`
  pandoc $filename.md -o ./out/$filename.pptx 
done

カレント フォルダー配下の Markdown ファイルを取得し、そのパスから Pandoc で次々に PowerPoint ファイル化するようにしています。

echo しているのは、ちゃんとファイルを見つけられているかどうかを確認するためのものですので、不要なら消しちゃってください。

docker run 時にシェルスクリプトを実行するようにする

作ったシェルスクリプトをホスト側で実行するかコンテナ側で実行するかは人によって好みがことなるかも知れませんが、結局コンテナ側で実行することにしました。 というわけで、前回の Dockerfile を以下のように書き換えます *2。 なお、先ほどのシェル スクリプト ファイルは run.sh という名前にしています。

FROM ubuntu:18.04

# Update ubuntu
RUN apt-get update -qq
RUN apt-get upgrade -qq

RUN apt-get install -y wget
RUN wget -q https://github.com/jgm/pandoc/releases/download/2.2.1/pandoc-2.2.1-1-amd64.deb
RUN dpkg -i pandoc-2.2.1-1-amd64.deb

# Install texlive
RUN apt-get install -y texlive-latex-recommended

# install wkhtmltopdf
RUN apt-get install -y -qq xvfb libfontconfig wkhtmltopdf

RUN apt-get clean

VOLUME /workspace
WORKDIR /workspace

COPY run.sh /usr/local/bin/run.sh
RUN chmod +x /usr/local/bin/run.sh
CMD ["run.sh"]

最後の 3 行を追加しました。

パスの通っている適切な場所にスクリプト ファイルをコピーして、chmod で実行権限をつけて CMD で呼び出しています。

docker build は大変遅いので、作った docker イメージを Docker Hub ようなパブリックなリポジトリか、Container Repository のようなプライベートなリポジトリに docker push するとよいと思います。

自動ビルドを使って Markdown ファイルが変更されたら PowerPoint ファイルを生成するようにする

無料で使える自動ビルド サービスといえば、Circle CI が有名だと思うのですが、今回の場合は Markdown ファイルのバージョン管理も一緒にさせたいので、まるっと 5 名までなら無料枠で使える Visual Studio Team Services を使います。*3

Visual Studio Team Services の場合、自動ビルドに使用するホストされたエージェントは Windows、MacOS、Linux から選べますが...今回は Linux を選びました *4

せっかくなので、自動化に使用した YAML ファイルを共有します。docker pull するときのイメージ名などはご自身の環境に合わせて変更してください (<yourname> の部分)。

resources:
- repo: self
queue:
  name: Hosted Linux Preview
  condition: succeeded()
steps:
- bash: |
   docker pull <yourname>/pandoc:latest
   docker run --rm -v $(Build.SourcesDirectory):/workspace <yourname>/pandoc 
  displayName: Bash Script

- task: PublishBuildArtifacts@1
  displayName: Publish Artifact: drop
  inputs:
    PathtoPublish: '$(Build.SourcesDirectory)/out'

あとは、継続的インテグレーション設定にしておけば、ファイルが変更されるたびに自動的に PowerPoint ファイルが生成されるようになります! (そんなに頻繁に生成したい?...という話はありますが...)

おまけ

これまで Visual Studio Team Services の自動ビルド設定を説明するときには、設定手順を書かなくてはならずとてもツラかったのですが、YAML ファイルの登場で方法の共有が手軽になったのはいいですね。ただ、まだ Preview 機能なので、[Preview features] から [Build YAML definitions] を有効にしないと使えませんのでご注意を (アカウント単位で有効化が必要)。

それでは、よい自動化生活を。Enjoy!

*1:どちらも大規模/無管理でないかぎり運用で回避できると予想

*2:はてなブログって Dockerfile の Syntax Highlight って対応していないのでしょうか...??

*3:ツールの組み合わせについては、Jenkins がいい!、GitLab がいい!などいろいろと好みがあると思いますので、お好きな組み合わせでどうぞ

*4:Windows 以外は preview なのですが、Windows を選ぶ必要が理由がないので...

Vagrant Provision で Visual Studio 2017 を自動的にインストールする話

これまで開発環境を入れたマシンは別途 BOX として持っていたのですが、Visual Studio 2017 の更新の頻度といったら...。とってくるたびに最新版がありますよと確実に言われるような状態です。

実際に開発されている方は特定のバージョンで固定していると思いますが、私の場合は常に最新版にする必要があるので、Visual Studio 2017 が入っている環境を各 OS ごとに準備するのは面倒だし、いっそのことプロビジョニングするか...という気持ちになりました。というわけで、今日は Visual Studio 2017 を vagrant up しただけで勝手にインストールしてくれるようにしようという話です。

Vagrant が Provisioners はいろいろあります。Chef、Ansible...など。Ansible を使ってみようと思ったのですが、Windows ホストでは使えないようなので、今回は素直に shell を使います。vagrant の場合、Windows に対しては WinRM 経由で PowerShell を実行できるので、PowerShell スクリプトを書けばいいわけです。

Provisioning するには、Vagrantfileconfig.vm.provision を追加します。今回の場合は、こんな感じにしました。

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.box = "win10_1803"
  
  config.vm.provision "shell", path: "install_vs2017.ps1"
end

こうしておくと、BOX が用意できた段階で WinRM 経由で install_vs2017.ps1 を実行してくれます。

さて、肝心のスクリプトですが、以下のような感じで書きました。

Write-Host "Create workspace directory"
$dir = New-Item -Path "C:\" -Name "workspace" -ItemType "directory" -Force
Set-Location -Path $dir

Write-Host "Downloading Visual Studio 2017..."
Invoke-WebRequest "https://aka.ms/vs/15/release/vs_enterprise.exe" -OutFile "vs_enterprise.exe"

Write-Host "Installing Visual Studio 2017..."
# See the following documents
# https://docs.microsoft.com/en-us/visualstudio/install/use-command-line-parameters-to-install-visual-studio
# https://docs.microsoft.com/en-us/visualstudio/install/workload-and-component-ids
# https://docs.microsoft.com/en-us/visualstudio/install/workload-component-id-vs-enterprise
Start-Process -FilePath ".\vs_enterprise.exe" -Wait -ArgumentList '--add', 'Microsoft.VisualStudio.Workload.CoreEditor', '--add', 'Microsoft.VisualStudio.Workload.ManagedDesktop', '--add', 'Microsoft.VisualStudio.Workload.NetCoreTools', '--add', 'Microsoft.VisualStudio.Workload.NetWeb', '--quiet'

スクリプトを読めばわかりますが、C ドライブ直下に workspace というフォルダーを用意して、最新版の Visual Studio 2017 Enterprise のインストーラーをダウンロードします。そして、コマンドラインでインストールします。

今回の場合、次のコンポーネントをインストールしますが、この辺はお好みで調整してください。

  • コア エディタ (Microsoft.VisualStudio.Workload.CoreEditor)
  • .NET デスクトップ開発 (Microsoft.VisualStudio.Workload.ManagedDesktop
  • .NET Core クロス プラットフォーム 開発 (Microsoft.VisualStudio.Workload.NetCoreTools)
  • .NET Web 開発 (Microsoft.VisualStudio.Workload.NetWeb

C++ のプロジェクトを追加したいのだけど?というような場合は、下記の URL から Component ID を調べて、引数に追記してください。

これで、vagrant up すれば Visual Studio 2017 がインストールされた環境が手に入ります。素敵ですね。

では、よい Vagrant Provision 生活を。Enjoy!

Markdown から PowerPoint (pptx) を作成したくて Docker イメージを作ったという話

Markdown から PowerPoint を生成できたら便利そうなのにと思ったら、いつの間にか Pandoc が公式に PowerPoint (pptx) への出力に対応していました。

昔は、PDF までは変換できて、あとは Adobe Acrobat の機能で PowerPoint 化する必要があったのですが、PDF を経由しなくても変換できるのはいいですね *1

https://pandoc.org

インストールするイメージはここにあります。結構よい頻度で更新されているのも好印象です。

ただ...この Pandoc というのは、Haskell ベースなツールなのです。 Windows な人は普通に msi をインストールしそうなものですが、私はこういう一時的にしか使わないツールなのに、結構大きな実行環境がセットなものをインストールしたくない!という人なので、msi は使いたくありません。

実行環境をまるっと手に入れて使い終わったら捨てたい...そう、いまこそ Docker の出番です。

ただ、Ubuntu のパッケージマネージャーで落ちてくるのが古くて PowerPoint 変換に未対応だったりする罠がありまして、なかなか簡単ではありませんでした。 とうわけで、結局、自分で Dockerfile から Docker イメージを作ることにしました。

せっかくなので、下記に張り付けておきます。

FROM ubuntu:18.04

# Update ubuntu
RUN apt-get update -qq
RUN apt-get upgrade -qq

RUN apt-get install -y wget
RUN wget -q https://github.com/jgm/pandoc/releases/download/2.2.1/pandoc-2.2.1-1-amd64.deb
RUN dpkg -i pandoc-2.2.1-1-amd64.deb

# Install texlive
RUN apt-get install -y texlive-latex-recommended

# install wkhtmltopdf
RUN apt-get install -y -qq xvfb libfontconfig wkhtmltopdf

RUN apt-get clean

VOLUME /workspace
WORKDIR /workspace

Pandoc で PowerPoint へ変換する

まず、上記の Dockerfile から Docker Image を作ります。 お使いのエディターで Dockerfile を作ってそのフォルダー上で下記のコマンドを実行します。 Dockerfile の作成には時間がかかりますので、ご注意を。

docker build -t <yourname>/pandoc .

作成が完了したら、作成したイメージを下記のコマンドで実行します。 -v はホスト環境のボリュームを Docker のコンテナにマッピングするものです。この値は私の環境用の値にしているので、お好きな値に変えてください。

docker run -v /Users/<yourname>/share:/workspace -it <yourname>/pandoc /bin/bash

bash が起動したら、以下のコマンドで Markdown から pptx に変換します。拡張子から判定してくれるので、簡単でいいですね。

pandoc test.md -o test.pptx

おまけ

Dockerfile から docker build を試していると気が付けば大量の停止コンテナと<none>:<none> なイメージができますよね。

これの削除方法も紹介しておきます。Web で検索すると古い削除方法をよく見かけますが、今のコマンドは以下です。

停止中のコンテナを一括削除するコマンド

docker container prune

リポジトリ名とタグがない (<none>:<none> な) イメージを一括削除するコマンド

docker images prune

では、良い Pandoc 生活を。Enjoy!

*1:なにより Adobe Acrobat を買わなくていいのがいい(笑)