必要な場合にのみ特権を昇格させる方法は?


85

この質問はWindowsVistaに当てはまります!

通常は管理者権限がなくても動作するアプリケーションがあります。管理者権限を必要とするアクティビティが1つありますが、ほとんどの場合、ユーザーがその機能を使用しないことがわかっている場合は、アプリケーション自体をより高い権限で起動したくありません。

あるイベント(ボタンを押すなど)でアプリケーションの権限を上げることができる特定の方法を考えています。例:

ユーザーがこのボタンをクリックすると、UACダイアログまたは同意が表示されます。これどうやってするの?

回答:


58

現在実行中のプロセスを昇格させることは不可能だと思います。私が理解しているように、Windows Vistaには、起動時にプロセスに管理者権限が付与されることが組み込まれています。UACを利用するさまざまなプログラムを見ると、管理アクションを実行する必要があるたびに、実際には個別のプロセスが起動することがわかります(タスクマネージャーが1つ、Paint.NETがもう1つ、後者は実際には.NETアプリケーションです)。 )。

この問題の一般的な解決策は、昇格されたプロセスを起動するときにコマンドライン引数を指定することです(abatishchevの提案はこれを行う1つの方法です)。これにより、起動されたプロセスは特定のダイアログボックスを表示することだけを認識し、このアクションが実行された後に終了します。完了しました。したがって、新しいプロセスが起動されて終了したことにユーザーが気付くことはほとんどなく、同じアプリ内で新しいダイアログボックスが開かれたように見えます(特に、ハッカーがメインウィンドウを作成する場合)昇格されたプロセスは親プロセスの子です)。昇格されたアクセスにUIが必要ない場合は、さらに良いでしょう。

VistaでのUACの詳細については、このテーマに関する記事よく読んでください(コード例はC ++ですが、C#でほとんどのことを行うにはWinAPIとP / Invokeを使用する必要があると思いますとにかく)。UAC準拠のプログラムを設計することは簡単ではありませんが、少なくとも正しいアプローチが見られることを願っています...


4
Windows 7に変更はありますか、それとも「いいえ、新しいプロセスを使用してください」という答えが当てはまりますか?おかげで...
Radim Vansa

2
Windows7で変更はありません。申し訳ありません。(私が知る限り、私はWin7の通常のユーザー/開発者です。)
Noldorin 2011年

2
これはまさにタスクマネージャーが行う方法です。ボタンをクリックしてすべてのユーザーのタスクを表示すると、現在のタスクマネージャーが存在し、管理者権限を持つ別のタスクマネージャーが呼び出されます。
ナタリーアダムス

3
@NathanAdams技術的には、最初に新しいタスクマネージャーを開きます。そうでなければ、オープニングは何をしているのですか?:-)
wizzwizz4 2016

16

そこに言われたよう

Process.StartInfo.UseShellExecute = true;
Process.StartInfo.Verb = "runas";

管理者としてプロセスを実行し、レジストリで必要なことをすべて実行しますが、通常の権限でアプリに戻ります。


これには、新しいプロセスにまたがることが含まれます。正しい?現在のプロセス自体の特権を昇格させることを探していました。
ヘマント

Process.GetCurrentProcess()を使用してみてください
abatishchev 2009

27
現在実行中のプロセスを昇格させることはできません。
Jacob Proffitt

1
本当じゃない。あなたは....プロセスの所有者を変更し、それらを管理権限を与えるユーザーのためのDACLとACLの値を設定することができます
Nightforce2

4
@ nightforce2:確かに、これは、既に管理者権限を持っている(つまり、すでに昇格している)場合にのみ機能します。そうでなければ、AdjustTokenPrivilegesなどは単に失敗しますね。
ベンシュウェーン

13

次のMSDNKB記事981778では、アプリケーションを「自己昇格」する方法について説明しています。

http://support.microsoft.com/kb/981778

Visual C ++、Visual C#、VisualBasic.NETでダウンロード可能なサンプルが含まれています。

このアプローチは、別のプロセスを開始する必要性を回避しますが、実際には、昇格されたユーザーとして実行されて再起動されるのは元のアプリケーションです。それでも、別の実行可能ファイルでコードを複製することが現実的でない一部のコンテキストでは、これは依然として非常に役立つ場合があります。

標高を削除するには、アプリケーションを終了する必要があります。


1
ボタンには便利ですが、メニュー項目にも同じものが必要な場合は、非常に複雑な混乱が発生します。
Nyerguds 2016

3
@Toddここでコードを見つけることができます:https
//code.msdn.microsoft.com/windowsapps/CSUACSelfElevation-644673d3

Answerのリンクは無効であり、コメントのリンクは2608アイテムの長いリストを指しています。
DonBoitnott

あなたはここで
mirh


2

おそらく誰かがこの簡単な例を手伝ってくれるでしょう:

using System;
using System.Linq;
using System.Reflection;
using System.Diagnostics;
using System.Security.Principal;
using System.Windows.Forms;

namespace WindowsFormsApp1
{
    internal static class Program
    {
        private class Form1 : Form
        {
            internal Form1()
            {
                var button = new Button{ Dock = DockStyle.Fill };
                button.Click += (sender, args) => RunAsAdmin();
                Controls.Add(button);

                ElevatedAction();
            }
        }

        [STAThread]
        internal static void Main(string[] arguments)
        {
            if (arguments?.Contains("/run_elevated_action") == true)
            {
                ElevatedAction();
                return;
            }

            Application.Run(new Form1());
        }

        private static void RunAsAdmin()
        {
            var path = Assembly.GetExecutingAssembly().Location;
            using (var process = Process.Start(new ProcessStartInfo(path, "/run_elevated_action")
            {
                Verb = "runas"
            }))
            {
                process?.WaitForExit();
            }
        }

        private static void ElevatedAction()
        {
            MessageBox.Show($@"IsElevated: {IsElevated()}");
        }

        private static bool IsElevated()
        {
            using (var identity = WindowsIdentity.GetCurrent())
            {
                var principal = new WindowsPrincipal(identity);

                return principal.IsInRole(WindowsBuiltInRole.Administrator);
            }
        }

    }
}

1

私はこれが古い投稿であることを知っていますが、これはMarcPの提案に出くわした他の誰かへの応答です。彼が参照したmsdnの投稿は、実際、すべてのコード例でアプリケーションを再起動します。コードサンプルは、runas他の提案ですでに提案されている動詞を使用します。

念のためコードをダウンロードしましたが、これは元のmsdnの記事からのものです。

4. [はい]をクリックして、標高を承認します。次に、元のアプリケーションが再起動し、昇格した管理者として実行されます。
5.アプリケーションを閉じます。


1
問題のMSDNリンクを追加できますか?MarcPというユーザーが見つかりません。
アルフ2016年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.