UAC対策の罠

Vista以降プログラマを悩ますUACだが、対策としてはプログラムレジストリの置き場所に配慮すれば大概済んでしまう。Oldスタイルで使われるプログラムの初期化ファイル、所謂INIファイルがその一つだ。
通常はプログラムのインストール先にINIファイルを置き、さまざまな情報を読書きしている。
ところがプログラムのインストール先は「Program Files」が一般的で、しかもVista以降はこのフォルダのリソースにプログラムが安易に変更を加えることが制限されている。
要は昔のようにINIファイルにプログラム情報を書き込めないのだ。
そこで考えられるのがこのINIファイルをApplication Dataフォルダに置くことだ。
この場合Application Dataフォルダのパスをプログラムが知らなければならないが、これにはAPIのGetFolderPathを使う。
GetFolderPathはシステムの特殊フォルダを調べる関数で、Application DataフォルダはSpecialFolder.LocalApplicationDataで取得できる。
※ローミング等を考慮する場合は別途
Application Dataフォルダでは会社名、アプリケーション名でフォルダを構成するのが一般的で、その取得ロジックは以下のようになるだろう。

string dir = System.Environment.GetFolderPath(
  System.Environment.SpecialFolder.LocalApplicationData);
string path = System.IO.Path.Combine(
  dir,
  System.IO.Path.Combine(
    Application.CompanyName, Application.ProductName));
if(!System.IO.Directory.Exists(path)) {
  System.IO.Directory.CreateDirectory(path);
}
// path配下のINIファイルを読書き

ところが上記はインストーラ(拙宅はInstallShield2013)と組み合わせると失敗する。
Microsoftアカウントが関連付けられている場合だ。
この場合Microsoftアカウントとして元のユーザー名が加工された「username_000」なる変な名前が割り当てられてしまう。
この影響でインストーラではMicrosoftアカウントに対するApplication Dataフォルダにファイルが転送されてしまうのだ。
(おそらくインストーラでは特殊フォルダを調べる方法が違うのだろう。この辺りは不明…。)
インストーラとアプリケーションでApplication Dataフォルダの探索方法が違う(らしい)というのは致命的だ。
これはどちらかに統一しなければいけない。
おそらくインストーラに合わせるのが現実的だろう。
InstallShield2013では「ターゲットシステムの構成」-「INIファイルの変更」でINIファイル(ターゲット[INSTALLDIR])を作り、Application Dataフォルダのパスを書き込むキーワードを一つ用意する。
この値に[LocalAppDataFolder]を設定しておく。
インストール完了後には以下のようなINIファイルがインストールフォルダーにできているはずだ。
(エントリー=path、キーワード=datafolder)

[path]
datafolder=c:Usersuser nameAppDataLocal

アプリケーション側ではこのdatafolderキーの値をGetFolderPathの代わりに使えば正確なApplication Dataフォルダの場所を知ることができる。


[LocalAppDataFolder]はあまり良い方法とは言えません。
下記も読んで下さい。

UAC対策の罠の罠

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です