現在のアプリケーションを管理者権限で再実行させる

.NET アプリケーションの実行時に、管理者権限で実行されていない場合は動的に昇格させて再実行させる方法について記述します。

ポイントは次の通りです。

  • WindowsPrincipal オブジェクトを利用して、現在の実行ユーザーが管理者グループに含まれているかどうかを判定する。
  • 現在のアプリケーションを新しいプロセスで実行する。
    動詞に runas を指定することで、UAC の権限昇格ダイアログが現れる。
  • UAC の権限昇格ダイアログで [いいえ] が選択された場合、呼び出し元に Win32Exception がスローされる。

以下がコードのサンプルです。コンソール アプリケーションとして作成しています。


using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Security.Principal;
using System.Text;

namespace ConsoleApplication1
{
    static class Program
    {
        static void Main(string[] args)
        {
            if (IsAdmin)
            {
                // 本来の処理を実行します。
                MainAsAdmin(args);
            }
            else
            {
                // 自身を runas で実行します。
                RunSelfAsAdmin(args);
            }
        }

        static void MainAsAdmin(string[] args)
        {
            // 例として、Program Files 内にファイルを作成します。
            var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Temp", "RunAsTest.txt");
            Directory.CreateDirectory(Path.GetDirectoryName(filePath));
            File.WriteAllText(filePath, "Test Text", Encoding.UTF8);
        }

        static bool IsAdmin
        {
            get
            {
                var principal = new WindowsPrincipal(WindowsIdentity.GetCurrent());
                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

        static void RunSelfAsAdmin(string[] args)
        {
            var assembly = Assembly.GetEntryAssembly();
            var startInfo = new ProcessStartInfo(assembly.Location, ToCommandArgs(args))
            {
                UseShellExecute = true,
                Verb = "runas",
            };

            try
            {
                Process.Start(startInfo);
            }
            catch (Win32Exception ex)
            {
                // ユーザーが [いいえ] を選択すると例外が発生します。
                Console.WriteLine(ex.Message);
            }
        }

        static readonly Func<string, string> EscapeCommandArg = x => x.Contains(‘ ‘) ? string.Format("\"{0}\"", x) : x;
        static readonly Func<string[], string> ToCommandArgs = x => string.Join(" ", x.Select(EscapeCommandArg));
    }
}


このアプリケーションを通常の方法で (ダブルクリックなどで) 実行すると、UAC の権限昇格ダイアログが表示されます。
この時点では、「Process.Start(startInfo);」の部分で実行がブロックされています。

ユーザー アカウント制御

[はい] を選択すればアプリケーションが新しいプロセスで再実行され、IsAdmin プロパティの値が true になります。

なお、上記の場合は IsAdmin プロパティを一度だけしか呼び出していませんが、
これをアプリケーション内で頻繁に呼び出す場合は、
次のように最初に一度だけ WindowsPrincipal オブジェクトを作成して、スレッドに設定しておく方法が考えられます。


static bool isPrincipalInitialized;
static bool IsAdmin
{
    get
    {
        if (!isPrincipalInitialized)
        {
            AppDomain.CurrentDomain.SetPrincipalPolicy(PrincipalPolicy.WindowsPrincipal);
            isPrincipalInitialized = true;
        }
        var principal = (WindowsPrincipal)Thread.CurrentPrincipal;
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
    }
}


バージョン情報
.NET Framework 4

参照
UACが有効の時、アプリケーションを管理者に昇格させて起動する (DOBON.NET)
管理者としてほかのアプリケーションを実行するには? (@IT)

カテゴリー: .NET Framework, OS. タグ: . Leave a Comment »

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト / 変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト / 変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト / 変更 )

Google+ フォト

Google+ アカウントを使ってコメントしています。 ログアウト / 変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。