あれとアレは混ぜるな危険

日々精進をしているふり

Azureのインスタンスにフォントを入れたいんですが?

こんばんは、はるたまです。順調に多忙ですが、餃子の王将の餃子倶楽部スタンプは順調に収集できてます。

はてさて、スタートアップタスクができてから何でもありのWindows Azure。今回はフォントでもインストールしてみようかという主旨であります。

フォントの用意

とりあえずインストールするフォントがないと始まらないので、フォントを用意しましょう。今回は「font」というフォルダを掘ってみかちゃんフォントを入れてみましょうか。
ソリューションエクスプローラーから見た時の最終型としてはこんな感じです。本来であればフォントのファイル名に日本語で名前が付けれられていますが、ちょっと嫌な感じがするのでアルファベットで「mika-p.ttf」とリネームしてあります。
f:id:haru-tama:20111019005415j:image
「font.vbs」と「font.bat」というファイルは今回自分で作ってますので、ココらへんは後で説明します。その他はWorkerロールを1個作ったばかりの素の状態になってます。
ポイントは、フォントをソリューションと言うかプロジェクトに追加したときに、フォントファイルのプロパティの「出力ディレクトリーにコピー」の部分を「常にコピーする」or「新し場合はコピーする」にしておかないとAzureにアップロードするパッケージに含まれないので注意です。ファイルは違いますがプロパティはこんな感じで。
f:id:haru-tama:20111019005455j:image

そもそもコマンドでどうやってフォントをインストールするの?

ちょっと話は脱線して、そもそもWindowsにフォントをインストールするときは、フォントフォルダにフォントをドラッグ・アンド・ドロップすればおしまいです。
「ああ、じゃあフォントコピーすればおしまいね!」となるとそうはいかないんです。
フォントフォルダにフォントをドラッグ・アンド・ドロップすると、実際には裏側でレジストリにフォントの情報をガリガリ書いているので、単純にファイルをコピーしただけだと足りないんです。じゃあどうするかというと、これがどうもVBScript経由でコピーしないと、Windows側がよしなにやってくれないみたいなんです。詳しい話は以下のリンクを参照ということで。
スクリプトを使用してフォントをインストールする方法はありますか

VBScriptの用意(font.vbs)

さて、先ほどの情報を元にVBScriptを作ってみるとこんな感じ。

'日本語のコメントは後付けしてるので入れないほうがいいかもしれないです

'Windowsのフォントフォルダをとってくる
Const FONTS = &H14&
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.Namespace(FONTS)

'アップロードしたパッケージのルートを取得
Set objWshShell = WScript.CreateObject("WScript.Shell")
root = objWshShell.ExpandEnvironmentStrings("%RoleRoot%")

'パッケージ内にあるフォントをWindowsのフォントフォルダにコピー
objFolder.CopyHere root & "\approot\font\mika-p.ttf"

こんな感じの内容のファイルを「font.vbs」という名前で作ってます。フォントファイルと同じように、vbsファイルのプロパティの「出力ディレクトリーにコピー」の部分を「常にコピーする」or「新し場合はコピーする」に設定しておくのを忘れると、アップロードするパッケージに入らないので注意ですね。

バッチファイルの用意(font.bat)

さてさてVBScriptは作ったので、今度はこれを実行するバッチファイルも作りましょう。これはいつもの感じで作れば問題ないです。

cscript //nologo font.vbs

こんな内容で「font.bat」を作りましょう。もちろん、ファイルのプロパティの「出力ディレクトリーにコピー」の部分を「常にコピーする」or「新し場合はコピーする」に設定しておくことをお忘れなく。またVisualStudioからバッチファイルの中身を編集すると、UTF-8のBOMが勝手に追加されて動かなくなるのは、よく訓練されたアジュラーでは常識なので、必ず何らかのテキストエディターから編集しないと動かないので超絶要注意です。

スタートアップタスクの設定

さて、スタートアップタスクに対してさっき作った「font.bat」を実行するよう登録しましょう。「ServiceDefinition.csdef」に対してこんな風に書いておけばOK。

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="FontInstall" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WorkerRole name="WorkerRole1" vmsize="Small">
    <Startup>
      <Task commandLine="font.bat" executionContext="elevated" taskType="background" />
    </Startup>
    <Imports>
      <Import moduleName="RemoteAccess" />
      <Import moduleName="RemoteForwarder" />
    </Imports>
  </WorkerRole>
</ServiceDefinition>

リモートデスクトップ接続の設定はしてありますがそれはそれとして、「Startup」要素の中に「font.bat」を登録しておきましょう。フォントのインストールには管理者権限がいるので「executionContext="elevated"」と指定します。今回はWorkerロールで作ってますが、Webロールでも同じです。
ところで「commandLine="font.vbs" っていきなりVBScriptを指定しておけばよくね?」と思われるかもしれませんが、いきなりスタートアップタスクにVBScriptを指定してしまうとAzureのインスタンスが起動するときにエラーが発生して起動できなくなります。どうやら、スタートアップタスクに指定できるものはバッチファイルだけみたいなので「スタートアップタスク→バッチファイル→VBScript」の流れじゃないとダメっぽいというのもハマりどころです。

デプローイ!!

以上ここまでが手順です。本当にフォントがインストールされているかはリモートデスクトップでAzureのインスタンスにつないでみて、フォントフォルダの中身を見れば確認できます。