Windowsの設定の多くは、レジストリ1の値で決まります。 グループポリシー2の「管理用テンプレート」3に並ぶ設定項目は、ADMXというXMLファイルから作られています。 ADMXには、設定ごとに、どのレジストリキーのどの値に何を書き込むかが書かれています。
今回は、ADMXの仕様と読み方を中心に、設定した値がどこに保存され、どのレジストリに書き込まれるのかを紹介します。
ADMXとは
ADMXは、レジストリで制御できる設定の設計図です。 1つの設定項目について、次の2つを定義します。
- ポリシーを「有効」にしたときと「無効」にしたときのそれぞれで、どのレジストリキーのどの値に何を書き込むか(入力欄に入れた値の書き込み先も含む)
- エディタに、どの分類でどのような入力欄を表示するか
ここでのエディタは、ドメインのGPOを編集するグループポリシー管理エディタと、ローカルグループポリシーエディタ(gpedit.msc)を指します。
ADMX自体は、設定値を持ちません。
ADMXが持つのは、「有効ならDisableAutoUpdateを1にする」のような規則だけです。
管理者がエディタで選んだ状態や入力した値は、この規則に従ってRegistry.polというファイルに保存されます。
Windowsデバイスはこのファイルを読んでレジストリに値を書き込み、OSやアプリケーションはそのレジストリの値を読んで動作を変えます。
つまり、ADMXとADMLはエディタのための定義、Registry.polは管理者が選んだ値、レジストリはWindowsデバイスで適用された結果です。
ADMX、ADML、ADMの違い
管理用テンプレートに関係するファイルには、ADMX、ADML、ADMの3種類があります。 ADMXはポリシーの定義、ADMLは表示用の文字列と入力欄などの画面部品の配置を持つXMLファイルです。 ADMは旧形式の管理用テンプレートで、定義と表示用の文字列を1つのテキストファイルに持ちます。
ADMXとADMLは、次のどちらかのフォルダに置きます。
どちらのフォルダも構成は同じで、ADMXはフォルダの直下に、ADMLは言語別のフォルダ(ja-JP、en-USなど)に置きます。
通常はローカルストアが使われます。 ドメインでは、管理者全員が同じADMXとADMLを使えるようにセントラルストアを作れます。 セントラルストアがあれば、そちらが優先されます。 詳しくは、後述の「ADMXファイルの配置と読み込み」で説明します。
ADMXは言語に依存しない定義で、エディタに表示する文字列は$(string.ID)のような参照で書かれています。
この参照先の文字列は、言語ごとのADMLで定義します。
同じADMXに日本語と英語のADMLを用意すれば、管理者は自分の言語で同じポリシーを設定できます。
ADMLが必要なのは、エディタやgpresultのレポート(後述)のように、人がポリシーの名前を読む場面だけです。
レジストリに書き込む値を決めるのに必要な情報は、すべてADMXにあります。
| 場面 | ADMX | ADML |
|---|---|---|
| エディタでポリシーを表示、編集する | 必要 | 必要 |
| グループポリシーを適用するWindowsデバイス | 不要 | 不要 |
| MDMでADMXをWindowsデバイスに取り込む | 必要 | 不要 |
ADMは、Windows Vistaより前の形式です。
ADMは、ローカルストアやセントラルストアではなく、GPO4ごとのフォルダ(\\<ドメイン名>\SYSVOL\<ドメイン名>\Policies\{GPOのGUID}\Adm)に置かれていました。
GPOを作成して最初に編集した時点で、ADMがそのGPOのフォルダへコピーされるためです。
そのため、同じファイルがGPOの数だけ保存されていました。
ADMXはGPOのフォルダにコピーされず、GPOには設定値のRegistry.polだけが保存されます。
レジストリの基本
ADMXの仕様を読む前に、書き込み先であるレジストリの構造を確認しておきます。 レジストリは、フォルダのような「キー」の階層と、キーの中に入る「値」からなります。 値は、名前、型、データの3つを持ちます。 キーの階層の一番上にあるキーをルートキーと呼び、ADMXでは次の2つを使います。
HKEY_LOCAL_MACHINE(HKLM)はWindowsデバイス全体の設定で、どのユーザーでも同じ値が使われます。
HKEY_CURRENT_USER(HKCU)はサインインしているユーザーの設定で、ユーザーごとに別の値を持ちます。
図の左側は、後述する例の「自動更新を無効にする」ポリシーを有効にしたときの値です。
HKLM\Software\Policies\ExampleAppキーに、名前がDisableAutoUpdate、型がREG_DWORD(32ビットの数値)、データが1の値が書き込まれます。
型には、ほかに文字列を表すREG_SZなどがあります。
グループポリシーの「コンピューターの構成」はHKLMに、「ユーザーの構成」はHKCUに書き込まれます。
ADMXファイルの仕様
要素の一覧は、Microsoft LearnのPolicyDefinitions schemaにまとまっています。
ADMXの構造
<?xml version="1.0" encoding="utf-8"?><policyDefinitions revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <!-- このファイルの名前空間と、参照する他のファイルの名前空間 --> <policyNamespaces> <target prefix="smartscreen" namespace="Microsoft.Policies.SmartScreen" /> <using prefix="windows" namespace="Microsoft.Policies.Windows" /> </policyNamespaces> <!-- 対応するADMLの最小のリビジョン --> <resources minRequiredRevision="1.0" /> <!-- 対応する製品やバージョンの定義(必要な場合だけ) --> <supportedOn>...</supportedOn> <!-- エディタでの分類 --> <categories>...</categories> <!-- ポリシーの定義 --> <policies> <policy>...</policy> </policies></policyDefinitions>ルート要素のpolicyDefinitionsには、このファイルのリビジョン(revision)とスキーマのバージョン(schemaVersion)を書きます。
その下に、主に次の5つの要素を置きます(旧形式のADMを置き換えるときに使うsupersededAdmは省略します)。
本体はpoliciesです。
policiesの各ポリシーは、所属する分類をcategoriesから、対応するバージョンをsupportedOnから参照します。
policyNamespacesとresourcesは、ファイル全体に関する情報です。
必須の属性は、要素ごとに異なります。
classはpolicy要素だけの属性です。
keyはpolicy要素のほか、後述するitem要素やelementsの各項目にも指定できます。
| 要素 | 必須の属性 | 任意の属性 |
|---|---|---|
policyDefinitions |
revision、schemaVersion |
なし |
target、using |
prefix、namespace |
なし |
resources |
minRequiredRevision |
fallbackCulture |
definition(supportedOnの中) |
name、displayName |
なし |
category |
name、displayName |
explainText |
policy |
name、class、displayName、key |
explainText、presentation、valueName |
名前空間とカテゴリ
「Windows コンポーネント」のようなカテゴリや、「Windows 8以降」のような対応バージョンは、多くのADMXで共通して使います。
こうした共通の定義は、Windows標準のWindows.admxにまとめられています。
Windows.admxにはポリシーが1つもなく、共通のカテゴリと対応バージョンの定義だけがあります。
ほかのADMXは、これらを自分で定義せずにWindows.admxの定義を参照します。
たとえば、SmartScreenのポリシーは、エディタで「Windows コンポーネント」の下に表示されます。
SmartScreen.admxが、親のカテゴリとしてWindows.admxの「Windows コンポーネント」を指定しているためです。
ほかのADMXの定義を参照するには、名前空間を使います。
- 各ADMXは、
target要素で自分の名前空間(Microsoft.Policies.Windowsなど)を宣言する - 参照する側は、
using要素で相手の名前空間に接頭辞(prefix)を付ける - 定義を参照するときは、
windows:WindowsComponentsのように接頭辞を付けて書く
名前空間は、ほかのADMXと重ならないように付けます。 同じ名前空間のADMXが2つあると、エディタはエラーを表示します(後述の「読み込み時のエラー」を参照)。
カテゴリはcategory要素で定義し、parentCategory要素で親のカテゴリを指定して階層を作ります。
親を指定しないカテゴリは、「管理用テンプレート」の直下に表示されます(後述の例のExampleAppカテゴリがこれにあたります)。
policy要素
policy要素は、エディタに表示されるポリシー1つ分の定義です。
主な属性は次のとおりです。
| 属性 | 必須 | 内容 |
|---|---|---|
name |
○ | ポリシーの名前。ファイル内で一意にする |
class |
○ | 適用対象。Machine、User、Bothのいずれか |
displayName |
○ | エディタに表示する名前。ADMLの文字列を$(string.ID)で参照する |
explainText |
ポリシーの説明。ADMLの文字列を参照する | |
presentation |
入力欄などの画面部品。ADMLのpresentationを$(presentation.ID)で参照する |
|
key |
○ | 書き込むレジストリキー。HKEY_LOCAL_MACHINEなどのルートは含めない |
valueName |
有効、無効を切り替えたときに書き込むレジストリの値の名前 |
子要素では、parentCategoryで所属するカテゴリを、supportedOnで対応するバージョンを指定します。
対応するバージョンは、supportedOn要素のdefinitionで定義し、policy要素からnameで参照します。
<supportedOn> <definitions> <definition name="SUPPORTED_ExampleApp_1_0" displayName="$(string.SUPPORTED_ExampleApp_1_0)" /> </definitions></supportedOn><policies> <policy name="ExamplePolicy" class="Machine" displayName="$(string.ExamplePolicy)" key="Software\Policies\ExampleApp" valueName="ExampleValue"> <parentCategory ref="ExampleCategory" /> <supportedOn ref="SUPPORTED_ExampleApp_1_0" /> </policy></policies>ADMLでこの文字列を「ExampleApp 1.0以降」と定義すると、エディタの「サポートされるバージョン」欄にそのまま表示されます。 この定義は表示に使われるだけで、対象外のバージョンのWindowsデバイスにも値は書き込まれます。
有効、無効のときに書き込む値
ポリシーの有効時と無効時にvalueNameへ書き込む値は、enabledValueとdisabledValueで指定します。
値には、数値を表すdecimal、64ビットの数値を表すlongDecimal、文字列を表すstring、値を削除するdeleteのいずれかを使います。
<policy name="ExamplePolicy" class="Machine" displayName="$(string.ExamplePolicy)" key="Software\Policies\ExampleApp" valueName="ExampleValue"> <parentCategory ref="ExampleCategory" /> <supportedOn ref="windows:SUPPORTED_Windows_10_0" /> <enabledValue> <decimal value="1" /> </enabledValue> <disabledValue> <decimal value="0" /> </disabledValue></policy>1つのポリシーで複数の値を書き込みたい場合は、enabledListとdisabledListを使います。
item要素ごとにkeyとvalueNameを指定できるので、policy要素のkeyとは別のキーにも書き込めます。
<policy name="ExampleListPolicy" class="Machine" displayName="$(string.ExampleListPolicy)" key="Software\Policies\ExampleApp"> <parentCategory ref="ExampleCategory" /> <supportedOn ref="windows:SUPPORTED_Windows_10_0" /> <enabledList> <item key="Software\Policies\ExampleApp" valueName="FeatureEnabled"> <value> <decimal value="1" /> </value> </item> <item key="Software\Policies\ExampleApp\Feature" valueName="Mode"> <value> <string>Strict</string> </value> </item> </enabledList> <disabledList> <item key="Software\Policies\ExampleApp" valueName="FeatureEnabled"> <value> <decimal value="0" /> </value> </item> <item key="Software\Policies\ExampleApp\Feature" valueName="Mode"> <value> <delete /> </value> </item> </disabledList></policy>enabledValueとdisabledValueはどちらも任意です。
ただし、Microsoftのリファレンスによると、enabledValueを省略するとエディタが有効、無効、未構成の状態を正しく表示できない場合があります。
自作のADMXでは、両方を書いておくのが無難だと思います。
elements要素
有効にしたポリシーで文字列や数値などの入力を受け付けたい場合は、入力項目をelements要素で定義します。
それぞれの項目は、valueNameで指定したレジストリの値に書き込まれます。
keyを省略すると、policy要素のkeyが使われます。
| 要素 | 内容 | 書き込まれる値 |
|---|---|---|
boolean |
オンとオフの2択 | trueValueとfalseValueで指定した値 |
decimal |
数値 | REG_DWORD(storeAsText="true"の場合は文字列) |
longDecimal |
64ビットの数値 | REG_QWORD |
text |
1行の文字列 | REG_SZ(expandable="true"の場合はREG_EXPAND_SZ) |
multiText |
複数行の文字列 | REG_MULTI_SZ |
enum |
選択肢から1つを選ぶ | 選んだitemのvalueで指定した値 |
list |
複数の項目の一覧 | 指定したキーの下に、項目ごとの値 |
elementsの各項目に付けるidは、ADMLの画面部品との対応付けに使います。
listは、1つのキーの下に複数の値を書き込む項目です。
デフォルトでは、ポリシーの適用時にそのキーの既存の値を削除してから、一覧の値を書き込みます。
additive="true"にすると、既存の値を残したまま追加します。
エディタで表示するためのADML
ADMLは、エディタでADMXのポリシーを表示するためのファイルです。 MDMでADMXを取り込む場合など、エディタを使わない場面ではADMLは必要ありません。
<?xml version="1.0" encoding="utf-8"?><policyDefinitionResources revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <displayName>表示名</displayName> <description>説明</description> <resources> <!-- displayNameやexplainTextから参照される文字列 --> <stringTable> <string id="ExamplePolicy">ポリシーの表示名</string> </stringTable> <!-- presentation属性から参照される画面部品の配置 --> <presentationTable> <presentation id="ExamplePolicy"> <textBox refId="ExampleText"> <label>入力欄の説明:</label> </textBox> </presentation> </presentationTable> </resources></policyDefinitionResources>stringTableには、ADMXの$(string.ID)から参照される文字列を定義します。
presentationTableには、ADMXの$(presentation.ID)から参照される画面部品の並びを定義します。
画面部品はrefId属性で、ADMXのelementsのidと対応付けます。
代表的な画面部品と、対応するADMXの要素は次のとおりです。
| ADMLの画面部品 | 対応するADMXの要素 | エディタでの表示 |
|---|---|---|
checkBox |
boolean |
チェックボックス |
decimalTextBox |
decimal |
数値の入力欄 |
longDecimalTextBox |
longDecimal |
数値の入力欄 |
textBox |
text |
1行の入力欄 |
comboBox |
text |
候補を選べる入力欄 |
multiTextBox |
multiText |
複数行の入力欄 |
dropdownList |
enum |
ドロップダウンリスト |
listBox |
list |
一覧を編集する画面を開くボタン |
text |
なし | 説明の文字列だけを表示 |
書き込み先のレジストリ
レジストリのパス
書き込み先は、policy要素のclass、key、valueNameの3つの属性で決まります。
key属性にはルートを含めず、ルートはclass属性から決まります。
この例の書き込み先は、HKLM\Software\Policies\ExampleAppキーのExampleValueです。
class属性の値によって、エディタでの表示場所とルートは次のように変わります。
class |
エディタでの表示場所 | 書き込み先のルート |
|---|---|---|
Machine |
コンピューターの構成 | HKEY_LOCAL_MACHINE(HKLM) |
User |
ユーザーの構成 | HKEY_CURRENT_USER(HKCU) |
Both |
両方 | 設定した側に応じて、どちらか |
ADMXが書き込めるのは、HKLMとHKCUの配下だけです。
HKEY_CLASSES_ROOTなど、ほかのルートの配下は指定できません。
Software\Policies配下とそれ以外のキー
Microsoftは、次の4つのキーをポリシー用の場所と定めています。 Windows標準のADMXのほとんどは、これらのキーの配下に書き込みます。
HKLM\Software\Policies(推奨)HKLM\Software\Microsoft\Windows\CurrentVersion\PoliciesHKCU\Software\Policies(推奨)HKCU\Software\Microsoft\Windows\CurrentVersion\Policies
これらのキーに書き込まれる設定は「管理されたポリシー(Managed)」として扱われ、標準ユーザーには書き換えられないように保護されています。 GPOの適用対象から外れると、値は削除されます。 ポリシーの値は、アプリケーション自身が保存する通常の設定(Preference)とは別のキーにあるので、ポリシーを外せばもとの設定に戻ります。
一方で、アプリケーションが自分の設定を保存しているHKCU\Software\ExampleAppのようなキーに、ADMXから直接書き込むこともできます。
ただし、こうしたキーの値は「管理されていないポリシー(Unmanaged)」として扱われ、GPOの適用対象から外れても残り続けます。
この状態は「入れ墨(tattooing)」と呼ばれます。
HKCU\Software\ExampleAppのThemeにDarkを書き込むポリシーを配布した後でGPOを外しても、ThemeはDarkのまま残ります。
エディタはデフォルトで管理されていないポリシーも表示しますが、フィルタオプションの「管理」で管理されたポリシーだけに絞れます。
入れ墨への対策
入れ墨を避けるには、次の3つの方法があります。
1つ目は、書き込み先をSoftware\Policiesの配下にすることです。
自作のアプリケーションなら、この配下の値を通常の設定より優先して読むようにしておけば、入れ墨は起こりません。
最も確実な方法のため、自作のADMXではまずこの形を検討するのがよいと思います。
2つ目は、disabledValueにdelete要素を指定し、「無効」を適用したときに値を削除させることです。
<policy name="ExampleTheme" class="User" displayName="$(string.ExampleTheme)" key="Software\ExampleApp" valueName="Theme"> <parentCategory ref="ExampleCategory" /> <supportedOn ref="windows:SUPPORTED_Windows_10_0" /> <enabledValue> <string>Dark</string> </enabledValue> <disabledValue> <delete /> </disabledValue></policy>ただし、この方法でも「無効」を経由せずにGPOを外したり未構成に戻したりすると、値は残ります。 GPOを外す前に「無効」を適用し、値が削除されたことを確認してから外します。
3つ目は、ADMXではなく、グループポリシーの基本設定(Group Policy Preferences)のレジストリ項目で書き込むことです。 レジストリ項目の共通オプションには、次のオプションがあります。
- Remove this item when it is no longer applied(適用されなくなったときにこの項目を削除する)
このオプションを有効にすると、GPOの適用対象から外れたときに値が削除されます。 なお、有効にすると、項目の操作は「置換」になります。
GPOとRegistry.pol
エディタで設定した値は、まずRegistry.polに記録されます。
レジストリに書き込まれるのは、Windowsデバイスがポリシーを適用したときです。
Registry.polはGPOの一部で、GPOごとに、コンピューターの構成用のMachineフォルダと、ユーザーの構成用のUserフォルダに1つずつあります。
GPOの種類とRegistry.polの場所
GPOには、各Windowsデバイスにあるローカルグループポリシー(ローカルGPO)と、ドメインで管理するGPOがあります。
どちらのGPOかによって、編集するツールとRegistry.polの保存場所が変わります。
ローカルGPOは、ドメインに参加していないWindowsデバイスにもあります。
gpedit.mscで設定した値は、そのデバイスの次の場所に保存されます。
C:\Windows\System32\GroupPolicy\Machine\Registry.polC:\Windows\System32\GroupPolicy\User\Registry.pol
ドメインのGPOは、グループポリシーの管理コンソール(GPMC)から開くグループポリシー管理エディタで編集します。 GPOはドメインコントローラのSYSVOL5に、GPOごとのフォルダとして保存されます。
\\<ドメイン名>\SYSVOL\<ドメイン名>\Policies\{GPOのGUID}\Machine\Registry.pol\\<ドメイン名>\SYSVOL\<ドメイン名>\Policies\{GPOのGUID}\User\Registry.pol
適用対象の各Windowsデバイスは、SYSVOLにあるRegistry.polをネットワーク越しに読み取ります。
Registry.polの中身
Registry.polはバイナリ形式のファイルです。
PRegというシグネチャとバージョンのヘッダに続いて、レジストリに書き込む値が1つずつエントリとして並びます。
[キー;値の名前;型;サイズ;データ]1つのエントリは、セミコロンで区切った5つの項目からなります。
たとえば、「既存のADMXの読み方」で題材にするSmartScreenのポリシーを有効にして「警告」を選ぶと、コンピューターの構成のRegistry.polに次の2つのエントリが記録されます。
ここでは読みやすいように、型と数値をテキストで表しています。
[Software\Policies\Microsoft\Windows\System;EnableSmartScreen;REG_DWORD;4;1][Software\Policies\Microsoft\Windows\System;ShellSmartScreenLevel;REG_SZ;10;Warn]どちらのエントリも、キーはSoftware\Policies\Microsoft\Windows\Systemです。
キーにはHKLMなどのルートを含めず、ファイルの置き場所(MachineまたはUser)でルートが決まります。
残りの項目は、次のとおりです。
| 項目 | 1つ目のエントリ | 2つ目のエントリ |
|---|---|---|
| 値の名前 | EnableSmartScreen |
ShellSmartScreenLevel |
| 型 | REG_DWORD |
REG_SZ |
| サイズ(バイト) | 4 |
10 |
| データ | 1 |
Warn |
サイズはデータのバイト数です。
REG_SZはUTF-16の文字列のため、Warnの4文字と終端の文字で10バイトになります。
エントリは先頭から順に処理されるので、同じ値に対する指定が複数あれば後のものが優先されます。
値を削除する指定も、同じ形式のエントリとして記録されます。
通常のエントリでは、値の名前にEnableSmartScreenのような書き込む値の名前が入ります。
削除のエントリでは、値の名前がアスタリスク2つ(**)で始まる決まった名前になり、その名前で削除の方法を指定します。
同じポリシーを無効にすると、コンピューターの構成のRegistry.polのエントリは次のように置き換わります。
[Software\Policies\Microsoft\Windows\System;EnableSmartScreen;REG_DWORD;4;0][Software\Policies\Microsoft\Windows\System;**del.ShellSmartScreenLevel;REG_SZ;4; ]1行目は、EnableSmartScreenに0を書き込むエントリです。
2行目は、有効時に書き込まれたShellSmartScreenLevelを削除するエントリです。
削除のエントリではデータを使いませんが、仕様では空白と終端の文字を入れることになっています(UTF-16で4バイト)。
削除の指定には、次の4種類があります。
| 値の名前 | 削除するもの |
|---|---|
**del.〇〇 |
〇〇という名前の値(例:**del.ShellSmartScreenLevelはShellSmartScreenLevelを削除) |
**DeleteValues |
データにセミコロン区切りで書いた値(例:データがValueA;ValueBならValueAとValueBを削除) |
**DelVals. |
エントリのキーにある、すべての値 |
**DeleteKeys |
データにセミコロン区切りで書いた、キー直下のサブキー |
ADMXのdelete要素や、listが既存の値を削除してから書き込む動作も、これらのエントリで表されます。
詳しくは、Microsoft LearnのRegistry Policy File Formatを参照してください。
IntuneではRegistry.polを使わない
Microsoft IntuneなどのMDMでADMXのポリシーを配布する場合は、Registry.polとGPOのどちらも使われません。
MDMから届いた設定はWindowsのPolicy CSPというしくみが受け取り、ADMXの定義に従ってレジストリに値を書き込みます。
MDMで設定した値の状態は、HKLM\SOFTWARE\Microsoft\PolicyManagerの配下でも調べられます。
デバイス向けの設定では、PolicyManager\current\deviceの配下に有効な値が、PolicyManager\providersの配下に管理元ごとの値が記録されます。
ただし、記録される場所は設定によって異なります。
簡単な例:ADMXを書いてみる
ここまでの仕様を使って、架空のアプリケーション「ExampleApp」のADMXを書いてみます。 次の3つのポリシーを定義します。
- 自動更新を無効にする(コンピューターの構成、有効と無効の切り替えだけ)
- 更新サーバーを指定する(コンピューターの構成、文字列と数値の入力)
- 起動時のヒント(ユーザーの構成、チェックボックス)
<?xml version="1.0" encoding="utf-8"?><policyDefinitions revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <policyNamespaces> <target prefix="exampleapp" namespace="Example.Policies.ExampleApp" /> </policyNamespaces> <resources minRequiredRevision="1.0" /> <supportedOn> <definitions> <definition name="SUPPORTED_ExampleApp_1_0" displayName="$(string.SUPPORTED_ExampleApp_1_0)" /> </definitions> </supportedOn> <categories> <category name="ExampleApp" displayName="$(string.ExampleApp)" /> <category name="Update" displayName="$(string.Update)"> <parentCategory ref="ExampleApp" /> </category> </categories> <policies> <policy name="DisableAutoUpdate" class="Machine" displayName="$(string.DisableAutoUpdate)" explainText="$(string.DisableAutoUpdate_Help)" key="Software\Policies\ExampleApp" valueName="DisableAutoUpdate"> <parentCategory ref="Update" /> <supportedOn ref="SUPPORTED_ExampleApp_1_0" /> <enabledValue> <decimal value="1" /> </enabledValue> <disabledValue> <decimal value="0" /> </disabledValue> </policy> <policy name="UpdateServer" class="Machine" displayName="$(string.UpdateServer)" explainText="$(string.UpdateServer_Help)" presentation="$(presentation.UpdateServer)" key="Software\Policies\ExampleApp"> <parentCategory ref="Update" /> <supportedOn ref="SUPPORTED_ExampleApp_1_0" /> <elements> <text id="UpdateServerUrl" valueName="UpdateServerUrl" required="true" /> <decimal id="CheckIntervalHours" valueName="CheckIntervalHours" minValue="1" maxValue="168" /> </elements> </policy> <policy name="StartupTips" class="User" displayName="$(string.StartupTips)" explainText="$(string.StartupTips_Help)" presentation="$(presentation.StartupTips)" key="Software\Policies\ExampleApp"> <parentCategory ref="ExampleApp" /> <supportedOn ref="SUPPORTED_ExampleApp_1_0" /> <elements> <boolean id="ShowTips" valueName="ShowTips"> <trueValue> <decimal value="1" /> </trueValue> <falseValue> <decimal value="0" /> </falseValue> </boolean> </elements> </policy> </policies></policyDefinitions>ポリシーの定義は、このADMXだけで完成しています。 グループポリシーのエディタで表示する場合は、ADMXが参照する文字列と画面部品をADMLで用意します。
<?xml version="1.0" encoding="utf-8"?><policyDefinitionResources revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <displayName>ExampleAppのポリシー</displayName> <description>ExampleAppを管理するためのポリシーです。</description> <resources> <stringTable> <string id="SUPPORTED_ExampleApp_1_0">ExampleApp 1.0以降</string> <string id="ExampleApp">ExampleApp</string> <string id="Update">更新</string> <string id="DisableAutoUpdate">自動更新を無効にする</string> <string id="DisableAutoUpdate_Help">有効にすると、ExampleAppは更新を自動で確認しません。</string> <string id="UpdateServer">更新サーバーを指定する</string> <string id="UpdateServer_Help">ExampleAppが更新を確認するサーバーと間隔を指定します。</string> <string id="StartupTips">起動時のヒント</string> <string id="StartupTips_Help">ExampleAppの起動時にヒントを表示するかどうかを指定します。</string> </stringTable> <presentationTable> <presentation id="UpdateServer"> <textBox refId="UpdateServerUrl"> <label>更新サーバーのURL:</label> </textBox> <decimalTextBox refId="CheckIntervalHours" defaultValue="24">確認する間隔(時間):</decimalTextBox> </presentation> <presentation id="StartupTips"> <checkBox refId="ShowTips" defaultChecked="true">起動時にヒントを表示する</checkBox> </presentation> </presentationTable> </resources></policyDefinitionResources>ExampleApp.admxをPolicyDefinitionsフォルダに、ExampleApp.admlをその下のja-JPフォルダに置くと、エディタに次のように表示されます。
- コンピューターの構成 > 管理用テンプレート > ExampleApp > 更新
- 自動更新を無効にする
- 更新サーバーを指定する
- ユーザーの構成 > 管理用テンプレート > ExampleApp
- 起動時のヒント
書き込み先のキーは、コンピューターの構成のポリシーがHKLM\Software\Policies\ExampleApp、ユーザーの構成のポリシーがHKCU\Software\Policies\ExampleAppです。
それぞれのポリシーを設定すると、次の値が書き込まれます。
| ポリシー | 設定 | 値の名前 | 値(型) |
|---|---|---|---|
| 自動更新を無効にする | 有効 | DisableAutoUpdate |
1(REG_DWORD) |
| 自動更新を無効にする | 無効 | DisableAutoUpdate |
0(REG_DWORD) |
| 更新サーバーを指定する | 有効 | UpdateServerUrl |
入力したURL(REG_SZ) |
| 更新サーバーを指定する | 有効 | CheckIntervalHours |
入力した数値(REG_DWORD) |
| 起動時のヒント | 有効 | ShowTips |
チェックありは1、なしは0(REG_DWORD) |
| 起動時のヒント | 無効 | ShowTips |
値を削除 |
「起動時のヒント」のpolicy要素にはvalueNameがないので、書き込まれるのはelementsのbooleanで定義したShowTipsだけです。
そのため、「起動時のヒント」を無効にしても無効を表す値は書き込まれず、ShowTipsが削除されるだけです。
たとえば、gpedit.mscで「自動更新を無効にする」を有効にすると、C:\Windows\System32\GroupPolicy\Machine\Registry.polに次のエントリが記録されます。
[Software\Policies\ExampleApp;DisableAutoUpdate;REG_DWORD;4;1]グループポリシーが適用されると、このエントリからHKLM\Software\Policies\ExampleAppキーのDisableAutoUpdateに1が書き込まれます。
既存のADMXの読み方
題材には、Windows標準のSmartScreen.admxにある「Windows Defender SmartScreen を構成します」というポリシーを使います。
SmartScreenは、ファイルやアプリケーションの安全性を確認するMicrosoft Defenderの機能です。
Windows標準のADMXは、WindowsデバイスのC:\Windows\PolicyDefinitionsにあります。
最新版は、Microsoftのダウンロードセンターで配布されている管理用テンプレートにも含まれています。
このポリシーは、エディタの次の場所にあります。
- コンピューターの構成 > 管理用テンプレート > Windows コンポーネント > Windows Defender SmartScreen > エクスプローラー
ADMXでpolicy要素を読む
書き込み先は、ADMX(SmartScreen.admx)のpolicy要素だけで読み取れます。
このポリシーは、name属性がShellConfigureSmartScreenのpolicy要素です。
<policyDefinitions revision="1.0" schemaVersion="1.0" xmlns="http://schemas.microsoft.com/GroupPolicy/2006/07/PolicyDefinitions"> <policyNamespaces> <target prefix="smartscreen" namespace="Microsoft.Policies.SmartScreen" /> <using prefix="windows" namespace="Microsoft.Policies.Windows" /> <!-- 省略 --> </policyNamespaces> <resources minRequiredRevision="1.0" /> <categories> <category name="SmartScreen" displayName="$(string.SmartScreen)"> <parentCategory ref="windows:WindowsComponents" /> </category> <category name="Shell" displayName="$(string.Shell)"> <parentCategory ref="SmartScreen" /> </category> <!-- 省略 --> </categories> <policies> <policy name="ShellConfigureSmartScreen" class="Machine" displayName="$(string.ShellConfigureSmartScreen)" explainText="$(string.ShellConfigureSmartScreen_Help)" key="Software\Policies\Microsoft\Windows\System" valueName="EnableSmartScreen" presentation="$(presentation.ShellConfigureSmartScreen)"> <parentCategory ref="Shell" /> <supportedOn ref="windows:SUPPORTED_Windows8" /> <enabledValue> <decimal value="1" /> </enabledValue> <disabledValue> <decimal value="0" /> </disabledValue> <elements> <enum id="ShellConfigureSmartScreen_Dropdown" key="Software\Policies\Microsoft\Windows\System" valueName="ShellSmartScreenLevel" required="true"> <item displayName="$(string.SmartScreen_PreventBypass)"> <value> <string>Block</string> </value> </item> <item displayName="$(string.SmartScreen_Warn)"> <value> <string>Warn</string> </value> </item> </enum> </elements> </policy> <!-- 省略 --> </policies></policyDefinitions>この抜粋から、次のことが読み取れます。
- 名前空間は
Microsoft.Policies.SmartScreenで、Windows.admx(windows)を参照している - カテゴリは「Windows コンポーネント > Windows Defender SmartScreen > エクスプローラー」の階層になっている
class="Machine"のため、「コンピューターの構成」に表示され、HKLMに書き込まれる- 有効、無効で書き込む値は
valueNameのEnableSmartScreen、ドロップダウンリストで選んだ項目はShellSmartScreenLevelに書き込まれる
書き込まれるレジストリの値
このポリシーを設定すると、HKLM\Software\Policies\Microsoft\Windows\Systemキーに次の値が書き込まれます。
- 有効にして「警告してバイパスを回避」を選んだ場合は、
EnableSmartScreenに1、ShellSmartScreenLevelにBlock - 有効にして「警告」を選んだ場合は、
EnableSmartScreenに1、ShellSmartScreenLevelにWarn - 無効にした場合は、
EnableSmartScreenに0
エディタの表示名から探すとき
エディタに表示されている名前しかわからない場合は、ADMLで表示名から文字列のIDを調べます。
ADMLは表示に使うファイルです。
ADMXだけで目的のpolicy要素を見つけられる場合は、ADMLを開く必要はありません。
日本語のADML(ja-JP\SmartScreen.adml)から、エディタに表示されている名前を探します。
<stringTable> <string id="SmartScreen">Windows Defender SmartScreen</string> <string id="Shell">エクスプローラー</string> <string id="ShellConfigureSmartScreen">Windows Defender SmartScreen を構成します</string> <string id="SmartScreen_PreventBypass">警告してバイパスを回避</string> <string id="SmartScreen_Warn">警告</string> <!-- 省略 --></stringTable><presentationTable> <presentation id="ShellConfigureSmartScreen"> <dropdownList refId="ShellConfigureSmartScreen_Dropdown" noSort="true" defaultItem="0">次のいずれかの設定を選択してください。</dropdownList> </presentation></presentationTable>表示名の文字列のIDはShellConfigureSmartScreenです。
ADMXでdisplayName="$(string.ShellConfigureSmartScreen)"を検索すると、先ほどのpolicy要素が見つかります。
同じIDのpresentationには、ドロップダウンリスト(dropdownList)が1つ置かれています。
ADMXのpolicy要素から書き込み先を読み、表示名から探すときだけADMLを使う手順は、サードパーティー製アプリケーションのADMXでも同じです。
ADMXファイルの配置と読み込み
エディタは、決まったフォルダからADMXとADMLを読み込んでポリシーを表示します。
各Windowsデバイスには、Windows標準のADMXとADMLがC:\Windows\PolicyDefinitionsに入っています。
このフォルダをローカルストアと呼びます。
ドメインに参加していないWindowsデバイスでは、gpedit.mscはここのADMXを読み込みます。
ドメインのGPOを編集するときも、何もしなければ、グループポリシー管理エディタを開いたWindowsデバイスのローカルストアが使われます。 そのため、管理者が使うWindowsデバイスによって、エディタに表示されるポリシーが変わります。 たとえば、古いバージョンのWindowsでエディタを開くと、新しいWindowsで追加されたポリシーは表示されません。
これを避けるために、GPOの保存先と同じSYSVOLの\\<ドメイン名>\SYSVOL\<ドメイン名>\Policies\PolicyDefinitionsにADMXとADMLを置きます。
このフォルダをセントラルストアと呼び、管理者全員で共有します。
gpedit.mscを含むエディタは、ドメインにセントラルストアがあればローカルストアの代わりにそちらを使います。
表示言語のADMLがない場合は、ADMXのresources要素のfallbackCulture属性で指定した言語(デフォルトはen-US)のADMLを探します。
日本語のADMLがなく英語のADMLだけを置いたサードパーティー製アプリケーションのポリシーが、英語で表示されるのはそのためです。
読み込み時のエラー
ADMXとADMLの組み合わせに問題があると、エディタを開いたときにエラーが表示されます。 よく見かけるのは、次の2つです。
- 同じ名前空間のADMXが複数ある:
Namespace '...' is already defined as the target namespace for another file in the store.- ファイル名を変えた新しいADMXを追加し、古いADMXを消し忘れたときによく起こります
- ADMXから参照される文字列がADMLにない:
Resource '$(string.ID)' referenced in attribute displayName could not be found.- ADMXとADMLのバージョンが食い違っているときに起こります
ADMXを更新するときの注意点
Windowsの新しい管理用テンプレートをセントラルストアに反映するときは、既存のフォルダへ上書きコピーしないほうが安全です。
MicrosoftはCreate and Manage Central Storeで、次の手順を紹介しています。
新しいバージョン用のフォルダ(PolicyDefinitions-newなど)を作ってファイルをそろえ、最後にフォルダ名を入れ替えます。
この手順なら、問題が起きたときに古いフォルダへ戻せます。
また、ダウンロードセンターで配布されている管理用テンプレートは、セントラルストアで使うためのものです。
C:\Windows\PolicyDefinitionsのファイルを置き換える使い方はサポートされていないので注意してください。
Windowsデバイスでどのように評価されるのか
Windowsデバイスでは、まずGroup Policyサービス(gpsvc)が適用対象のGPOを決めます。
次に、クライアント側の拡張機能(CSE: Client-Side Extension)を呼び出します。
CSEは、GPOの設定の種類ごとに適用を担当するコンポーネントです。
管理用テンプレートを担当するのはRegistry CSEで、Registry CSEが各GPOのRegistry.polを読み取り、レジストリに値を書き込みます。
適用のタイミング
グループポリシーは、次のタイミングで適用されます。
- コンピューターの構成は、Windowsの起動時
- ユーザーの構成は、ユーザーのサインイン時
- 起動後やサインイン後も、バックグラウンドで定期的に更新
バックグラウンドでの更新は、デフォルトでは90分ごとです。
多くのWindowsデバイスが同時に問い合わせないように、0〜30分のランダムな時間が加えられます。
なお、ドメインコントローラ自身のコンピューターの構成は、5分ごとに更新されます。
これらのデフォルト値は、GroupPolicy.admxのポリシーの説明に書かれています。
「コンピューターのグループ ポリシーの更新間隔を設定する」の説明などで確認できます。
すぐに適用したい場合は、Windowsデバイスで次のコマンドを実行します。
gpupdate /force適用の順序
1台のWindowsデバイスには、複数のGPOを適用できます。 GPOは、通常は次の順に適用され、後から適用されたGPOの設定が優先されます。
- ローカル
- サイト(拠点などのネットワークの単位)
- ドメイン
- OU(部署などでまとめる組織単位)
頭文字を取ってLSDOUとも呼ばれます。 ただし、同じ場所にリンクされた複数のGPOの順序や、「強制」「継承のブロック」の設定によって、結果は変わります。 ドメインに参加していないWindowsデバイスでは、ローカルGPOだけが適用されます。
未構成、有効、無効の違い
エディタのポリシーには、「未構成」「有効」「無効」の3つの状態があります。
| 状態 | Registry.polに記録される内容 |
|---|---|
| 未構成 | 何も記録しない。このGPOではそのポリシーを管理しない |
| 有効 | ADMXのenabledValue、enabledList、elementsで定義した値 |
| 無効 | ADMXのdisabledValueやdisabledListで定義した値 |
「無効」は無効を表す値(SmartScreenの例ではEnableSmartScreenに0)を書き込むのに対し、「未構成」は何も書き込みません。
未構成のポリシーには、ほかのGPOの設定や、OSやアプリケーションのデフォルトの動作がそのまま使われます。
有効や無効にしていたポリシーを未構成に戻すと、Software\Policies配下などの管理されたポリシーの値は、次の適用時に削除されます。
適用結果の確認方法
ポリシーが期待どおりに適用されているかは、Windowsデバイスで次の方法で確認できます。
gpresult /h report.htmlで、適用されたGPOと設定をHTMLのレポートに出力するgpresult /rで、適用されたGPOの一覧をコマンドプロンプトに表示するregeditで、ADMXから読み取ったキーと値を直接確認する
既存のADMXの読み方を知っていれば、レポートの設定名から書き込み先のキーと値を特定し、regeditで実際の値と照らし合わせられます。
SmartScreenの場合は、まずgpresult /h report.htmlのレポートで「Windows Defender SmartScreen を構成します」がどのGPOで有効になっているかを確認します。
次に、regeditでHKLM\Software\Policies\Microsoft\Windows\Systemキーを開き、EnableSmartScreenとShellSmartScreenLevelの値を確かめます。
MDMでの評価との違い
グループポリシーとMDMでは、ADMXを使ってレジストリの値に変換する場所が異なります。
グループポリシーでは、管理側のエディタがADMXを使って値を決め、Registry.polとしてWindowsデバイスに届けます。
MDMでは、Windowsデバイス自身がADMXを使い、MDMから受け取った設定をレジストリの値に変換します。
変換に使うADMXは、Windows標準の設定のうちMDMに対応したものなら、OSに組み込まれています。 サードパーティー製アプリケーションのADMXは、MDM経由でWindowsデバイスに取り込みます。
MDMからポリシーを指定するときは、エディタの表示名ではなく、決められた名前を使います。
取り込んだサードパーティー製アプリケーションのADMXでは、policy要素のname、カテゴリのname、elementsの子要素のidで指定します。
Windows標準の設定は、Policy CSPのドキュメントで名前を確認します。
SmartScreenのように、ADMXのname(ShellConfigureSmartScreen)とPolicy CSPの名前(EnableSmartScreenInShell)が異なる設定もあるためです。
どちらの場合も、ADMXを読めば、その設定がどのレジストリの値を変えるのかを確かめられます。
MDMでのしくみの詳細は、Microsoft LearnのUnderstanding ADMX policiesを参照してください。
終わりに
今回は、ADMXのしくみと読み方を紹介しました。
ADMXが決めているのは、エディタに何を表示し、どのレジストリの値に何を書き込むかです。
設定値そのものはRegistry.polとレジストリにあります。
この構造がわかっていれば、ADMXのpolicy要素を読んで、どのポリシーがどのレジストリの値を変えるのかを自分で確かめられます。
次回は、Microsoft IntuneでADMXを使ってWindowsデバイスを管理する方法について紹介する予定です。
参考資料
- PolicyDefinitions schema
- enabledValue Element
- list Element
- policyDefinitions Element
- Implementing Registry-Based Group Policy for Applications
- Working with the Administrative Template policy settings using the Local Group Policy Editor
- Registry Policy File Format
- [MS-GPREG]: New or Changed GPO List Processing
- Create and Manage Central Store
- Understanding ADMX policies
- [MS-GPREG]: Registry Extension Encoding Overview
- Group Policy processing for Windows
- Recommendations for managing Group Policy administrative template (.adm) files
- Group Policy preferences in Windows
- SmartScreen Policy CSP