Windows VistaからUAC(ユーザーアカウント制御、User Account Control)が導入されました。これによって、特別な場所へファイルやレジストリを書き込む等の操作を行なうアプリケーションを実行する時、管理者権限に昇格させないと正常に機能しない恐れがあります。ここでは、管理者権限に昇格させてアプリケーションを起動する方法と、作成したアプリケーションが起動される時に自動で管理者権限に昇格されるようにする方法を紹介します。
まずは基本を確認する意味で、.NET Frameworkとは関係ありませんが、アプリケーションを管理者権限に昇格させて起動する方法を2つ説明します。分かっている方は読み飛ばしてください。
アプリケーションの実行ファイルやショートカットを右クリックすると、コンテキストメニューが表示されます。このメニューに「管理者として実行」という項目があります。この「管理者として実行」を選択することで、昇格させて実行することができます。
このようにアプリケーションを実行すると、「ユーザーアカウント制御」ダイアログが表示されます。このダイアログでユーザーが「OK」(Vistaでは「続行」)を選択した場合のみアプリケーションが起動します。
アプリケーションの実行ファイルやショートカットのプロパティダイアログには「互換性」というタブがあり、この「特権レベル」に「管理者としてこのプログラムを実行する」という設定があります。これを有効にすると、アプリケーションが起動した時に自動で昇格(「ユーザーアカウント制御」ダイアログが表示)されます。
このような設定をしたファイルのアイコンには、盾のマークが付きます。後に紹介するマニフェストを使用した場合も、同じ盾のマークが付きます。盾のマークが付いたアイコンは、そのアプリケーションが管理者権限で実行されることを示します。
補足:メモ帳やコマンドプロンプトなどのアプリケーションでは、上記の「管理者としてこのプログラムを実行する」という設定を変更できないようになっています。この場合は、そのアプリケーションのショートカットのプロパティダイアログを表示し、「ショートカット」タブにある「詳細設定」ボタンをクリックして、「管理者として実行」を有効にします。
ここからが本番です。上記の方法では、ユーザー自らが適切な操作をしなければ昇格されません。しかしマニフェストファイルを使用すると、ユーザーが特別なことをしなくても、普通に起動するだけで、管理者権限に昇格(「ユーザーアカウント制御」ダイアログが表示)されるようにできます。
この方法を、Visual Studio 2008以上で使える機能を用いる場合と、そうでない場合とに分けて説明します。
注意:アプリケーションが起動する時、常に昇格されるようにするケースは、そのアプリケーションが管理者専用の場合です。もしアプリケーションが一般ユーザー向けで、一部の機能のみ管理者権限が必要であれば、その部分を分離することを検討してください。その方法は、「UACが有効の時、必要な処理だけ管理者に昇格させて実行する」で説明しています。
Visual Studio 2008以上では、次のようにすると比較的簡単にできます。
まず、マニフェストファイルを作成します(すでにある場合は、読み飛ばしてください)。対象となるプロジェクトをソリューションエクスプローラーで右クリックしてメニューを表示し、「追加」-「新しい項目」を選択します。「新しい項目の追加」ダイアログが開きますので、「アプリケーションマニフェストファイル」(「全般」カテゴリにあります)を選択して、「追加」ボタンをクリックします。すると、ファイル名を変更していなければ、「app.manifest」というファイル名のマニフェストファイルが作成され、プロジェクトに追加されます。
Visual Studio 2010以下のVB.NETの場合は、この方法では作成できません。その場合は、まずメニューの「プロジェクト」-「(プロジェクト名)のプロパティ」を選択して、プロジェクトのプロパティを表示させます。「アプリケーション」タブを表示し、「Windows設定の表示」ボタン(Visual Studio 2008では、「UAC設定の表示」ボタン)をクリックします。すると、「app.manifest」というファイル名のマニフェストファイルが作成されます。
マニフェストファイルが新規作成されると、自動的にVisual Studioで開かれ、その内容が表示されます。もし開かれなかったら、ソリューションエクスプローラーでダブルクリックして開いてください(VB.NETでは、「Windows設定の表示」ボタンをクリックしてください)。
作成されたマニフェストファイルの中身は、次のようになっています。なお以下の内容はVisual Studio 2010で作成されたものです。
<?xml version="1.0" encoding="utf-8"?> <asmv1:assembly manifestVersion="1.0" xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv1="urn:schemas-microsoft-com:asm.v1" xmlns:asmv2="urn:schemas-microsoft-com:asm.v2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <assemblyIdentity version="1.0.0.0" name="MyApplication.app"/> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <!-- UAC マニフェスト オプション Windows のユーザー アカウント制御のレベルを変更するには、 requestedExecutionLevel ノードを以下のいずれかで置換します。 <requestedExecutionLevel level="asInvoker" uiAccess="false" /> <requestedExecutionLevel level="requireAdministrator" uiAccess="false" /> <requestedExecutionLevel level="highestAvailable" uiAccess="false" /> requestedExecutionLevel ノードを指定すると、ファイルおよびレジストリの仮想化は無効になります。 旧バージョンとの互換性のためにファイルおよびレジストリの仮想化を 使用する場合は、requestedExecutionLevel ノードを削除します。 --> <requestedExecutionLevel level="asInvoker" uiAccess="false" /> </requestedPrivileges> </security> </trustInfo> <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1"> <application> <!-- このアプリケーションが動作するように設計されている、Windows のすべてのバージョンの一覧。Windows は最も互換性の高い環境を自動的に選択します。--> <!-- アプリケーションが Windows 7 で動作するように設計されている場合は、次の supportedOS ノードのコメントを解除します。--> <!--<supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>--> </application> </compatibility> <!-- Windows のコモン コントロールとダイアログのテーマを有効にします (Windows XP 以降) --> <!-- <dependency> <dependentAssembly> <assemblyIdentity type="win32" name="Microsoft.Windows.Common-Controls" version="6.0.0.0" processorArchitecture="*" publicKeyToken="6595b64144ccf1df" language="*" /> </dependentAssembly> </dependency>--> </asmv1:assembly>
このマニフェストファイルのコメントにあるように、requestedExecutionLevelノードがUAC関係の部分です。requestedExecutionLevelのlevelを「asInvoker」から「requireAdministrator」に変更すると、管理者として実行されるようになります。
なお、assemblyIdentityノードのversionとnameもアプリケーションのバージョンとユニークな名前に変更しておいた方が良いでしょう。マニフェストの書き方について詳しくは、「Application Manifests」をご覧ください。
C#では、最後に、このマニフェストファイルが実行ファイルに埋め込まれることを確認しておきましょう。プロジェクトのプロパティを表示させ(メニューの「プロジェクト」-「(プロジェクト名)のプロパティ」を選択)、「アプリケーション」タブにある「マニュフェスト」で「app.manifest」が選択されていることを確認してください。もしそうなっていなかったら、「app.manifest」を選択してください。「app.manifest」がリストに表示されないのであれば、「app.manifest」をプロジェクトに追加してください。
次に、Visual Studioの機能を使用しない方法を紹介します。Visual Studio 2008以上の環境でこの方法を使っても大丈夫です。
まずは、マニフェストファイルを作ります。以下の内容のテキストファイルをUTF-8で作成し、ファイル名を「(実行ファイルのファイル名).manifest」として保存します。例えば実行ファイル名が「MyApp.exe」なら、「MyApp.exe.manifest」というファイル名になります。
もしすでにマニフェストファイルが存在しているのであれば、そのマニフェストに以下のようなtrustInfoノードを追加します。
<?xml version="1.0" encoding="UTF-8" standalone="yes"?> <assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v2"> <security> <requestedPrivileges xmlns="urn:schemas-microsoft-com:asm.v3"> <requestedExecutionLevel level="requireAdministrator" uiAccess="false"/> </requestedPrivileges> </security> </trustInfo> </assembly>
このマニフェストファイルを実行ファイルと同じフォルダに置けば、OKです。または、マニフェストファイルを実行ファイルに埋め込むこともできますが、その方法は「コントロールの外観をビジュアルスタイル(XPスタイル)にする」で説明しています。
Visual Studio 2008以上の場合は、マニフェストファイルを実行ファイルと同じフォルダに置いてもうまく行かないかもしれません。なぜなら、すでに別のマニフェストが実行ファイルに埋め込めれている可能性が高いからです。実行ファイルにマニュフェストを埋め込まないようにするには、C#では、上で紹介したプロジェクトのプロパティの「マニュフェスト」で「マニュフェストなしでアプリケーションを作成します」を選択します。VB.NETでは、それができるか不明です。
注意:Windows XP SP2では、requestedExecutionLevelなどのVista拡張機能を持つマニフェストが追加されているEXEやDLLを使用すると、青画面になってフリーズしたり、リブートする場合があります。Visual Studio 2005のMt.exeを使ってマニフェストを追加した時にこのような問題が起こり得ますが、Visual Studio 2005 SP1のMt.exeでは修正されています。詳しくは、「Windows XP Service Pack 2 (SP2) または WEPOS で Windows Vista の拡張機能を持つマニフェストを .exe ファイルまたは .dll ファイルに追加するとコンピューターが再起動することがある」や「Manifest files for Vista」などをご覧ください。
この記事の一番初めにコンテキストメニューで「管理者として実行」を選択してアプリケーションを起動する方法を紹介しましたが、これと同じ事をプログラムで行なう方法を紹介します。
「runas」という動詞をつけてアプリケーションを起動させると、管理者として起動することができます。動詞をつけてアプリケーションを起動させる方法は、「動詞を指定してファイルを開く」で説明していますが、ProcessStartInfoオブジェクトを作成してからProcess.Startメソッドで起動します。
Windows XPで「runas」動詞を付けて実行すると、「別のユーザーとして実行」ダイアログが表示されます。
この方法は、管理者権限が必要な処理を別のアプリケーションとして分離し、それが必要な時に「runas」動詞をつけて起動するといった使い方が考えられます。これについて詳しくは、「UACが有効の時、必要な処理だけ管理者に昇格させて実行する」説明します。
以下に、自分自身を「runas」動詞をつけて起動する例を示します。
'管理者として自分自身を起動する Dim psi As New System.Diagnostics.ProcessStartInfo() 'ShellExecuteを使う。デフォルトtrueなので、必要はない。 psi.UseShellExecute = True '自分自身のパスを設定する psi.FileName = Application.ExecutablePath '動詞に「runas」をつける psi.Verb = "runas" Try '起動する System.Diagnostics.Process.Start(psi) Catch ex As System.ComponentModel.Win32Exception '「ユーザーアカウント制御」ダイアログでキャンセルされたなどによって '起動できなかった時 Console.WriteLine("起動しませんでした: " & ex.Message) End Try
//管理者として自分自身を起動する System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo(); //ShellExecuteを使う。デフォルトtrueなので、必要はない。 psi.UseShellExecute = true; //自分自身のパスを設定する psi.FileName = Application.ExecutablePath; //動詞に「runas」をつける psi.Verb = "runas"; try { //起動する System.Diagnostics.Process.Start(psi); } catch (System.ComponentModel.Win32Exception ex) { //「ユーザーアカウント制御」ダイアログでキャンセルされたなどによって //起動できなかった時 Console.WriteLine("起動しませんでした: " + ex.Message); }
この方法で起動できるのは、.exeや.batファイルです。.vbsや.jsファイルは、基本的には、同じようにはできません(「Add "Run as Administrator" to Any File Type in Windows 7 or Vista」で紹介されているような方法で設定を変更すればできます)。ただし、例えばProcessStartInfo.FileNameにwscript.exeを、ProcessStartInfo.Argumentsにvbsファイルを指定して起動することはできます。
注意:この記事では、基本的な事柄の説明が省略されているかもしれません。初心者の方は、特に以下の点にご注意ください。