Windows Vista の新しい UAC の機能 (セキュリティ) でコードが例外を出す場合の対処について 【Part 2】
環境: Windows Vista
こんにちは
以前、UAC について記載しましたが(こちら)、この方法ではマニフェストを作成する方法のため、動的に解決できないか(実行中に UAC の昇格が必要になったら昇格し普段はしたくない、など) とご質問を受けることがたまにあります。
そこで今回は、UAC で昇格をおこなうもう1つの方法について記載します。
結論から記載しますが、この方法は起動中の状態を維持したまま昇格するというものではありませんが、UAC の昇格を実行時に動的に解決して昇格することは可能です。(Vista の新しい Recovery の仕組みと組み合わせられるといろいろできるかもしれません、、、)
サンプルとして、C# の Windows アプリケーションを想定します。
まず、後述のサンプルを動かすため、以下のネームスペースを取り込んでおきましょう。
using System.Diagnostics;
using System.Security;
using System.Security.Principal;
管理者権限が必要な処理として、例えば、ボタンを押したら以下のように処理するように実装してみましょう。
private void button1_Click(object sender, EventArgs e)
{
MessageBox.Show(EventLog.SourceExists("testsrc").ToString());
}
このまま実行すると、以前も記載した通り例外が発生します。(Windows Vista のセキュリティ設定で UAC の設定を切っていない場合は、、、)
そこで、この処理は、「管理者権限がない場合には昇格画面を表示して現在ログインしている管理者としてアプリを再起動する」ように処理を変更していきます。まず、管理者のロールがあるかどうかを判断するメソッドを作成します。
private bool IsAdmin()
{
WindowsIdentity usrId = WindowsIdentity.GetCurrent();
WindowsPrincipal p = new WindowsPrincipal(usrId);
return p.IsInRole(@"BUILTIN\Administrators");
}
つぎに、「昇格画面を表示して管理者としてアプリを再起動する」というメソッドを記述します。今開いているアプリは、無論、閉じることになります。まず、そのメソッドを記載します。
private void RestartApplication()
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true;
startInfo.WorkingDirectory = Environment.CurrentDirectory;
startInfo.FileName = Application.ExecutablePath;
startInfo.Verb = "runas";
try
{
Process p = Process.Start(startInfo);
}
catch
{
return;
}
Application.Exit();
}
このメソッドのポイントは、"runas" にあります。この Verb の設定により、管理者として実行をおこなうため、新しいプロセスにおいて昇格用の確認ダイアログが表示されます。
また、try - catch - は、UAC ダイアログでユーザがキャンセルボタンを押した場合に catch されますので、このように、catch の箇所で return をしておきます。
さいごに、ボタンを押した際の処理として、以下の通り、管理者権限がなければ管理者として再起動するように処理を追加します。
private void button1_Click(object sender, EventArgs e)
{
if (IsAdmin())
MessageBox.Show(EventLog.SourceExists("testsrc").ToString());
else if(System.Environment.OSVersion.Version.Major >= 6)
RestartApplication();
}
実行すると、ボタンを押した際に UAC ダイアログが表示され、アプリが管理者権限で再起動されて、次回以降は、ボタンを押すと正しく処理されます。
このソースですと、ボタンを押すと、ボタンを押したときの処理はされないので、ちょっと期待はずれな動きかもしれません。また、管理者ロールでないユーザでログインした場合の動きへの配慮が不充分ではありますね。この辺りは、業務にあわせてソースを変更してください(上記はあくまでもサンプルです)。