コマンドラインで権限昇格を起こす(UAC)

2011年10月 本文修正と別解
ちょっと放置していましたが・・・マイクロソフトから配布されている、Elevation PowerToys をインストールすると、elevateコマンド(本体はVBSCRIPT?)で出来るみたいですね。
VBScript自体、文法とかぜんぜん知らないので何をやってるのか理解不能。まぁ、やってることは同じだと思うけど。

というわけで、マイクロソフト製の由緒正しいelevateコマンド使ってね(^^; ・・・・ということで、このページの内容はフリーズです 🙂

2013年6月 追記
何の有益性もないこんな私的記録のページがgoogle検索で比較的上位に来てしまうので、このページにアクセスされる方が異常に多いのですが・・・おそらく違う意味の権限昇格を検索されている方が誤ってこのページに来ているんだと思います。なんか、申し訳ない。

あくまでセキュアーデスクトップ上の権限昇格ダイアログをコマンドラインから出すことができないか? という趣旨のエントリです。従って、権限昇格ダイアログを出さずにコマンドラインから特定のコマンド(あくまで外部プログラム)を権限昇格する、という趣旨のエントリではありません。

UAC機能を温存しつつ、権限昇格ダイアログを出さずに、権限昇格が必要な外部プログラムを実行する一番手っ取り早い方法は、Windowsのタスクスケジューラにそのコマンドを登録し、コマンドラインからタスクの実行を行うschtasksコマンドを実行することです。タスクスケジューラに登録する際に、「最上位の特権で実行する」というようなチェックボックスがあると思います。タスクスケジューラを起動する際、もしくは、登録する際におそらく一度権限昇格ダイアログが出るはずです。

詳しくは、「Windows 権限昇格 タスクスケジューラー」というようなワードでググってもらうと、より詳しい解説サイトが見つかるはずです。


 
何かと評判のよろしくない、UAC(ユーザーアカウント制御)の権限昇格ダイアログ。便利さを取るか、セキュリティーを取るか・・・僕的には、UACは必要と思うのだが・・・、確かに、たまにムカッと来るときがある(^^ゞ

よく遭遇するケースなんですが、コマンドライン(CMD.EXE)で作業しているときに、権限昇格が必要なCMDの内部コマンド(たとえば、mklinkとか)を実行すると、アクセス権が足りないとか、そういうエラーで実行できないときがある。そのたびにいちいちcmd.exe自体を「管理者として実行」を選択して起動しなおしてました。

Linux とかでよく使う sudo みたいな、権限を昇格するコマンドが、Vistaなんだからあるはずだ、と思って探して見るも分からない。別ユーザーで実行する、runas.exeというWindows2000時代からある、コンソールコマンドもあるんだけど、当然ながらVista以降のUACとは無関係で権限を昇格(elevate)してくれるわけがない。またvista以降、administratorアカウントはデフォルトで無効なので、普通は有効にはしないし・・・。
もっと言うと、ビルトインアカウントadministratorは、権限昇格が必要かどうかがデフォルトでチェック済の非常に特別なアカウントなので、このアカウントを有効にすることは、UAC機能を無効にすることと同じことといえます。
詳しくはこちらのMSDNサイトから>>ユーザー アカウント制御

Vista自体システム的なことについてはあまり詳しくないので、何らかのコマンドor何か別の方法があるのかもしれない。お知りの方は教えてくらはい~。。。

で、とりあえず、なんとかならないもんか・・・と思って考えてみれば、要はコマンドラインをそのまま CreateProcess API に渡すラッパーコマンドを作って、自動的に昇格ダイアログが出るようにマニフェストを埋め込めばいいんじゃないか??? と気づき、早速作ってみました。

単にコマンドライン文字列をCreateProcess APIに渡しているだけ。カンタン・カンタン。

// 疑似 sudo 
//sudo.exe 

#include <windows.h>
#include <strsafe.h>

int main(int argc,char **argv)
{
  if(argc >= 2)
    {
      PROCESS_INFORMATION pi;
      STARTUPINFO si;
      ZeroMemory(reinterpret_cast<LPVOID>(&si),sizeof(STARTUPINFO));

      si.cb = sizeof(STARTUPINFO);

      size_t size = 0;
      for(int i=1;i<argc;i++)
        {
            size_t len = 0;
            StringCchLength(argv[i],STRSAFE_MAX_CCH,&len);
            size += (len+1);
         }

      size++;
      CHAR* cmdline = new CHAR[size];
      ZeroMemory(reinterpret_cast<LPVOID>(cmdline),size);

      for(int i=1;i<argc;i++)
        {
           StringCchCat(cmdline,size,argv[i]);
           StringCchCat(cmdline,size," ");
         }

      if(FALSE == CreateProcess(NULL,
                                cmdline,
                                NULL,
                                NULL,
                                FALSE,
                                NORMAL_PRIORITY_CLASS,
                                NULL,
                                NULL,
                                &si,
                                &pi)) goto cleanup;

      WaitForSingleObject(pi.hProcess,INFINITE);

      CloseHandle(pi.hProcess);
      CloseHandle(pi.hThread);

cleanup:
      delete [] cmdline;
    }

  return 1;
}
//ソースここまで

リンカオプション、/MANIFESTUAC:level=requireAdministrator をつけてビルドする。
リンカオプション、/MANIFESTUAC:uiAccess=requireAdministrator をつけてビルドする。
すげー間違い。すみません。(m_m)

エラーチェックとか、まったくしてませんので実用には耐えられませんが、とりあえず、これでmklinkするときも、

sudo cmd /c mklink /D linkdir targetdir

のように実行すると、自動的に昇格ダイアログが出るようになりました。デジタル署名がないので黄色のバー(危ねーコードかもしれないから気をつけろよのサイン)ですが・・・(^^;;

コマンドラインで権限昇格を起こす(UAC)」への1件のフィードバック

  1. あああああ のコメント:

    こういうのがデフォルトでOSについていればいいんですけど
    GUI万歳なwindowsはやってくれないんでしょうね

コメントを残す