Delphi でアプリケーションマニフェストがサポートされたのは Delphi 7 からです。
バージョン | 外部マニフェスト | 内部マニフェスト | ||
XPMan 使用 | IDE が生成 | カスタム | ||
Delphi 2 ~ 6 | 実行ファイル名.manifest を実行ファイルと同じ場所に置く | - | - | リソースファイルを {$R} で埋め込むか、リソースエディタで直接書き換える |
Delphi 7 ~ 2006 | TXPmanifest をフォームに貼るか、XPMan を uses 節に加える | |||
Delphi 2007 ~XE | プロジェクトオプションでランタイムテーマを有効にする | |||
Delphi XE2 ~ | XPMan に効果はない | プロジェクトオプションでカスタムマニフェストを指定する |
アプリケーションマニフェストの優先順位は、XP の場合 "外部マニフェスト > 内部マニフェスト" で、 Vista またはそれ以降の場合、"内部マニフェスト > 外部マニフェスト" となります。つまり、XP でのみ "内部マニフェストを外部マニフェストでオーバライドする" という手法が使えます。
"Windows XP 対応アプリを作る (Delphi VCL Tips)" に詳細があります。
Delphi 7 ~ 2006 でアプリケーションマニフェストを埋め込むには XPMan を利用します。TXPManifest をフォームに貼るのは無駄なので、uses 節に XPMan を加えるのがいいと思います。
TXPmanifest の正体は中身のないコンポーネントです。TXPmanifest が定義されている XPMan.pas を uses 節に加えると WindowsXP.res をリソースとしてリンクします。逆に言えば、フォーム上の TXPmanifest を削除しても、uses 節に XPMan が残っていればアプリケーションマニフェストリソースはリンクされてしまいます。
Delphi 2007 以降では XPMan / TXPmanifest を使わず、プロジェクトオプションで "ランタイムテーマを有効にする" を選択すべきでしょう。
XE2 以降の場合、TXPmanifest を貼ったり XPMan を uses 節に加える事にもはや何の意味もありません。WindowsXP.res はリンクされないからです。
画像は XE3 で TXPmanifest を貼ったアプリケーションをコンパイルして実行した結果です。
"ランタイムテーマを有効にする" にチェックが入っている場合と、"ランタイムテーマを有効にする" にチェックが入っておらず、XPMan が uses 節に加えられている場合ではアプリケーションに埋め込まれたアプリケーションマニフェストの内容が異なります。
"ランタイムテーマを有効にする" チェック時のアプリケーションマニフェストの例 (Delphi 2007) |
|
XPMan 使用時のアプリケーションマニフェストの例 (Delphi 2007) |
|
"ランタイムテーマを有効にする" チェック時には、アプリケーション名に "RAD Studio" が、version には Delphi のビルドバージョンが埋め込まれます。
"ランタイムテーマを有効にする" にチェックを入れて、XPMan が uses された状態だと、マニフェストリソースが 2 つ登録されます。恐らく IDE が設定しているアプリケーションマニフェストが優先されると思いますが、誤動作の原因になりかねないので "ランタイムテーマを有効にする" と XPMan は排他で使用して下さい。
Delphi 7 ~ 2006 において XPMan が uses 節に加えられた時のアプリケーションマニフェストは次のようなものになっています。
XPMan 使用時のアプリケーションマニフェストの例 (Delphi 7) |
|
見ての通り、trustInfo 要素がありません。Vista 以降のアプリケーションマニフェストにするには、2007 ~ XE の $(BDS)\lib フォルダに存在する WindowsXP.res をコピーして持ってくるか、以下の手順で WindowsXP.res を修正します。
|
アプリケーションマニフェストに requestedExecutionLevel 要素の level 属性が存在する場合には UAC によるフォルダやレジストリの仮想化は行われません。
Windows Vista でのユーザー アカウント制御の理解と構成 (TechNet) より抜粋 |
|
仮想化による影響を回避したいのであれば、アプリケーションに (適切に記述された) アプリケーションマニフェストを埋め込むのが最も簡単だと思われます。
HKEY_LOCAL_MACHINE のレジストリをいじる (書き込む) アプリケーションや、ドライブルート、Program Files、システムフォルダへアクセスするようなアプリケーションは管理者権限が必要です。右クリックして "管理者として実行" しなければ正常動作しないアプリケーションがこれに該当します。
|
この level 属性の値を requireAdministrator へ変更すれば、アプリケーション起動時に自動で UAC プロンプトが表示されるようになります。
値 | 説明 | コメント |
asInvoker | アプリケーションは、アプリケーションを開始したプロセスと同じアクセス許可で実行されます。 | [管理者として実行] を選択すると、アプリケーションをより高いアクセス許可に昇格させることができます。Delphi 2007 以降のアプリケーションマニフェストのデフォルトです。 |
highestAvailable | アプリケーションは、可能な限り高いアクセス許可レベルで実行されます。 | アプリケーションを開始するユーザーが管理者グループのメンバーである場合、このオプションは requireAdministrator と同じです。 使用可能な最も高いアクセス許可レベルが、開始したプロセスのレベルより高い場合は、資格情報の入力が求められます。 |
requireAdministrator | アプリケーションは管理者のアクセス許可で実行されます。 | アプリケーションを開始するユーザーは、管理者グループのメンバーである必要があります。 開始したプロセスが管理者のアクセス許可で実行されない場合は、資格情報の入力が求められます。 |
"requireAdministrator を指定すれば管理者権限で動作する" という訳ではありません。管理者権限が必要なアプリケーションの起動時に、昇格用の UAC プロンプトを出すための設定です。
逆に "asInvoker" で ([管理者として実行] する事なしに) 動作させるためには、HKEY_LOCAL_MACHINE を読み取り専用で開く (TRegistry や TRegIniFile の create に KEY_READ を指定する) ように変更したり、環境ファイルを実行ファイルと同じ場所ではなく、アプリケーションデータパス (%APPDATA%) に保存する (または HKEY_CURRENT_USER なレジストリに保存する) ようにする等の工夫が必要となります。
Windows 7 で新しく追加された要素である compatibility 要素が存在しないアプリケーションは Windows 7 以降の OS において Windows Vista モードで動作します。
モードの確認にはリソースモニタ (resmon.exe) を使います。[オペレーティングシステムのコンテキスト] は標準では表示されていないので、ヘッダを右クリックして [列の選択(S)...] を選び、"オペレーティングシステムのコンテキスト" にチェックを入れます。
アプリケーションマニフェストに以下を追加するとネイティブモードにする事ができます。
|
ネイティブモード動作させるための ID (GUID) は OS 毎に異なり、新しい Windows がリリースされる都度 Microsoft から発行される事になっています。
よほど特殊な事をしていない限り、Delphi アプリケーションは ネイティブモードで動作させる事が可能だと思います。以下のサンプルを参考にしてカスタムマニフェストを組み込んでみるのもいいかもしれません。
ネイティブモード対応のカスタムマニフェストの例 |
|
ネイティブモードのテストは入念に行ってください。ネイティブモードで動作すれば PCA (プログラム互換性アシスタント) の影響を受けなくなったりするので、アプリケーションが高速化する可能性があります。
なお、PCA が問題を修正した履歴は レジストリの [HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Compatibility Assistant\Persisted] にあります。
$(BDS)\bin にある default_app.manifest を書き換えます。
Delphi 2007~XE ではアプリケーションマニフェストを、恐らく bds.exe (または delphicoreidennn.bpl) 内部にあるマニフェストから生成しています。つまり、アプリケーションマニフェストのデフォルト設定を変更するのは事実上不可能です。
アプリケーションが管理者権限で動作しているかそうでないかを判断するには IsUserAnAdmin() API を使います (Windows XP 以降)。IsUserAnAdmin() API は Delphi 2010 以降であれば (Winapi.)ShlObj 内で定義されています。Vista 以降でしか判断する必要がないのであれば、(System.)SysUtils.CheckWin32Version() を併用します。
※ アプリケーションマニフェストの重要情報は部分的に散在しており、日本語に翻訳されていないものも多く見受けられます。
BACK |