Microsoft MVP성태의 닷넷 이야기
.NET Framework: 191. ClickOnce - 관리자 권한 상승하는 방법 [링크 복사], [링크+제목 복사]
조회: 69658
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 7개 있습니다.)
ClickOnce - 관리자 권한 상승하는 방법

개인적으로, ClickOnce에서 아쉬운 것이 있었다면 "관리자 권한 상승(Run as administrator)"이 불가능하다는 것입니다. 이전에도 제 웹 사이트 게시판에 아래와 같은 질문이 있었는데요.

[질문/답변] 클릭원스를 비스타에서 실행시 
; https://www.sysnet.pe.kr/3/0/822

ClickOnce에 배포되는 .exe.manifest의 requestedExecutionLevel 값을 강제로 requireAdministrator 값을 주어도 "The Execution level requested by this application is not supported"라는 오류 메시지만 클라이언트에 출력되고 동작되지 않습니다.

실제로 저 역시, 위에 제가 답변했던 그대로, 관리자 권한이 필요한 부분을 별도로 NT 서비스로 제작하고 클릭원스의 Bootstrapper에 넣어서 배포를 한 적이 있었습니다.

그런데, 갑자기... 오늘은 ^^; 늘 보아왔던 "작업관리자"의 "Show processes from all users" 버튼이 눈에 들어왔습니다.

clickonce_run_as_adminrights_0.png

'그렇지! ClickOnce로 배포된 응용 프로그램도 자신을 실행할 때 권한 상승시켜서 재실행하면 되지 않을까!'라는 간단한 해답이었습니다. 1년이나 지나서 이런 생각이 드는군요. ^^;




구현 방법은 모두 공개되어 있습니다. 자신의 프로세스를 권한 상승시켜서 재실행하는 방법은 다음의 글에서 자세하게 소개해주고 있습니다.

Add a UAC shield to a button when elevation is required for admin tasks
; http://www.codeproject.com/KB/vista-security/UAC_Shield_for_Elevation.aspx

위의 방법을 클릭원스 상황에 맞게 적용시키면 되는데요. Form이 실행되기 전에 "권한 상승된 프로세스"인지 스스로 점검하고, 그렇지 않은 경우라면 권한 상승시켜서 실행시키는 코드로 적절하게 바꾸는 것인데, 아래에 간단하게 실어보았습니다.

===== Program.cs =====
static class Program
{
    [STAThread]
    static void Main()
    {
        if (IsAdministrator() == false) // C/C++의 경우, 현재 사용자가 관리자 그룹에 속해 있는지 결정하는 코드 참고
        {
            try
            {
                ProcessStartInfo procInfo = new ProcessStartInfo();
                procInfo.UseShellExecute = true;
                procInfo.FileName = Application.ExecutablePath;
                procInfo.WorkingDirectory = Environment.CurrentDirectory;
                procInfo.Verb = "runas";
                Process.Start(procInfo);
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());
            }

            return;
        }

        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }

    public static bool IsAdministrator()
    {
        WindowsIdentity identity = WindowsIdentity.GetCurrent();

        if (null != identity)
        {
            WindowsPrincipal principal = new WindowsPrincipal(identity);
            return principal.IsInRole(WindowsBuiltInRole.Administrator);
        }

        return false;
    }
}

===== Form1.cs =====
public partial class Form1 : Form
{
    public Form1()
    {
        InitializeComponent();

        if (Program.IsAdministrator() == true)
        {
            this.Text += " (Administrator)";
        }
    }
}

예제 삼아서, 제 홈페이지에 위의 코드를 빌드시켜서 클릭원스로 배포한 경로는 다음과 같습니다.

WindowsFormsApplication1
; https://www.sysnet.pe.kr/temp/app/runasadmin/publish.htm

"Install" 버튼을 눌러서 실행시키면, 배포가 완료된 후 아래와 같이 권한 상승 창이 뜨고,

clickonce_run_as_adminrights_1.png

이후, 원했던 대로 "관리자 권한"으로 실행된 클릭원스 응용 프로그램을 확인할 수 있습니다. ^^ (다른 코드 없으니, 두려워하지 마시고 ^^ 그냥 실행해 보셔도 됩니다.)

clickonce_run_as_adminrights_2.png

물론, 여전히 권한 상승창은 사용자에게 귀찮은 작업이므로 "Bootstrapper + NT 서비스 배포"는 유용할 수 있습니다. 어쨌든, 이로써 클릭원스 배포의 한 가지 장벽이 허물어지는군요. ^^



[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 3/22/2023]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2010-11-26 09시20분
[lancers] 그런데, 프로그램을 실행할 때마다 매번 사용자에게 권한상승 확인을 누르라고 하는 것도 만만치 않은 일이 된다는 거죠. -_-;
참고로 그 서비스를 만들었던 곳에서는.. 이제 더 이상 그 서비스를 사용하지 않는다는..
알다시피 그 서비스를 사용했던 목적이 있었는데, 그걸 꽤 엽기적인 방법(?)으로 다른 방식으로 처리했다는...
[guest]
2010-11-26 10시38분
엽기적인 방법이라? ^^;;;
정성태
2010-11-26 11시42분
[정중희] CAS 등록 및 신뢰된 사이트 등록을 위해 만들었던 설치 모듈에 위와 같이 권한 상승 기능을 넣고 배포 테스트를 했는데
아래와 같이 권한상승이 필요하다는 에러가 나네요? 혹시 어떤 이유에서 일까요?
혹시나 해서 배포바이너리 Setup.exe를 독립적으로 실행시키면 상승된 권한으로 실행이 되는데도 동일한 에러가 납니다.

ERROR DETAILS
    Following errors were detected during this operation.
    * [2010-11-26 오전 11:30:22] System.Runtime.InteropServices.COMException
        - 요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4)
        - Source: System.Deployment
        - Stack trace:
            at System.Deployment.Application.NativeMethods.CorLaunchApplication(UInt32 hostType, String applicationFullName, Int32 manifestPathsCount, String[] manifestPaths, Int32 activationDataCount, String[] activationData, PROCESS_INFORMATION processInformation)
            at System.Deployment.Application.ComponentStore.ActivateApplication(DefinitionAppId appId, String activationParameter, Boolean useActivationParameter)
            at System.Deployment.Application.SubscriptionStore.ActivateApplication(DefinitionAppId appId, String activationParameter, Boolean useActivationParameter)
            at System.Deployment.Application.ApplicationActivator.Activate(DefinitionAppId appId, AssemblyManifest appManifest, String activationParameter, Boolean useActivationParameter)
            at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl)
            at System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)
[guest]
2010-11-26 11시46분
[정중희] 아 한가지 이상한점을 발견하였습니다.

웹을 통하여 설치를 할때는 권한상승 요구 문제가 발생하는데
브라우저를 모두 닫고 Setup.exe 만가지고 설치를 하게 되면
잘 설치가 되네요. 이건 무슨조화인지?
[guest]
2010-11-26 12시50분
정중희 님... 그러니까 문제를 정리해 보면.
CAS 등록을 위한 코드 실행을 iexplorer.exe가 없이 setup.exe만으로 실행하면 정상적으로 실행되는데, 클릭원스를 이용해서 실행하면 "권한상승" 창이 떠서 확인을 했는데도 불구하고 0x800702E4 오류가 발생한다는 것인가요?

가볍게 재현 가능한 소스 코드를 올려주시면 한번 시도해 보도록 하겠습니다.
정성태
2010-11-26 04시58분
[정중희] 코드를 약간 첨부하였습니다.
WinForm형식이구요.
실행시 신뢰된 사이트에 등록하고, CAS 권한 설정을 등록하는 기능을 합니다.
먼저 권한 상승을 하고 이후에 작업을 진행하도록 하였는데, 권한상승 시 에러가 나는듯 합니다.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Security;
using System.Security.Policy;
using System.Runtime.InteropServices;

namespace SetupSecurity
{
    public partial class SetupSecurity : Form
    {
        public static Guid CLSID_InternetSecurityManager = new Guid("7b8a2d94-0ac9-11d1-896c-00c04fb6bfc4");
        public static Guid IID_IInternetSecurityManager = new Guid("79eac9ee-baf9-11ce-8c82-00aa004ba90b");

        private const uint SZM_CREATE = 0;
        private const uint SZM_DELETE = 1;

        public const uint ZoneLocalMachine = 0;
        public const uint ZoneIntranet = 1;
        public const uint ZoneTrusted = 2;
        public const uint ZoneInternet = 3;
        public const uint ZoneUntrusted = 4;

        public SetupSecurity()
        {
            InitializeComponent();

            if (Program.IsAdministrator() == true)
            {
                this.Text += " (Administrator)";
            }
        }

        private void SetupSecurity_Load(object sender, EventArgs e)
        {
            btnOk.Visible = false;
                        
            AddSiteToZone(ZoneTrusted, "HTTP://XXX.XXX.XX.XX");
            AddUrlCodeGroup("XXXXXXXX", "http://XXX.XXX.XX.XX/*", "XXX Assembly의 권한집합입니다.");

            btnOk.Visible = true;
        }
[guest]
2010-11-26 10시27분
정중희 님... 혹시나 싶어서 확인 질문드리는 건데요? 위에 올려주신 코드는, static void Main() 처리의 권한 상승을 위한 재실행 부분을 일부러 빼신 건가요? 아니면, 실제 테스트 코드에서 그 부분을 빼고 돌려보신 건가요?
정성태
2010-11-27 04시54분
[정중희] 물론 static void main 부분은 권한상승을 위한 재실행 부분을 설명해 주신 그대로 넣은 상태입니다.
그럼에도 불구하고 권한상승을 요구하는 이유가 뭘까 궁금합니다.
[guest]
2010-11-27 08시34분
에... 또 그러니까... 이상해서 다시 질문드리게 되는데요. "그럼에도 불구하고 권한상승을 요구하는 이유"라고 표현하셨는데, "재실행 시 권한상승" 창이 한 번 뜨게 되고, 확인을 했는데 다시 실행되는 과정에서 SetupSecurity_Load 메서드에서 AddSiteToZone 메서드를 실행하면서 "요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4) - Source: System.Deployment"라는 오류가 발생한다는 것이죠?
정성태
2010-11-27 08시50분
http://www.sysnet.pe.kr/temp/app/runasadmin/publish.htm
위의 예제 응용 프로그램에 "신뢰할 수 있는 사이트 등록" 기능을 추가했습니다.

신뢰할 수 있는 사이트 자동등록 하기
; http://wonx.egloos.com/1661425

위에서 소개한 AddSiteToZone 메서드만 추가 기능 구현해보았습니다.
정성태
2010-11-29 05시06분
[정중희] 죄송하지만 제가 쓰고 있는 IDE가 VS2005여서 샘플파일을 그대로 수행해보지는 않았습니다.
다만 내부 코드들을 보았을때 제가 사용하는 부분과 동일하게 작성되어 있음을 확인하였습니다.
위의 신뢰된 사이트 등록 코드도 마찬가지이구요. 다만 배포사이트에 들어가서 배포를 위해
'실행' 버튼을 누르고 'Setup.exe를 실행 또는 저장하겠습니까?' 라는 질문에서 '실행' 버튼을 누르면
권한상승창이 뜨게 되고, 이때 '예'를 눌러 진행하면 설치 중 'Application cannot be started, Contact the application vendor.' 이라는 에러가 뜨게 됩니다. 이때 Details 버튼을 눌러 에러 메시지를 확인하면 아래와같은 에러가 나옵니다.

PLATFORM VERSION INFO
Windows : 6.1.7600.0 (Win32NT)
Common Language Runtime : 4.0.30319.1
System.Deployment.dll : 4.0.30319.1 (RTMRel.030319-0100)
clr.dll : 4.0.30319.1 (RTMRel.030319-0100)
dfdll.dll : 4.0.30319.1 (RTMRel.030319-0100)
dfshim.dll : 4.0.31106.0 (Main.031106-0000)

SOURCES
Deployment url : http://.../SetupSecurity/SetupSecurity.application
Server : Microsoft-IIS/5.1
X-Powered-By : ASP.NET

IDENTITIES
Deployment Identity : SetupSecurity.application, Version=1.0.0.13, Culture=ko, PublicKeyToken=c793062a7786dbe6, processorArchitecture=x86

APPLICATION SUMMARY
* Online only application.

ERROR SUMMARY
Below is a summary of the errors, details of these errors are listed later in the log.
* Activation of http://.../SetupSecurity/SetupSecurity.application resulted in exception. Following failure messages were detected:
+ 요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4)

COMPONENT STORE TRANSACTION FAILURE SUMMARY
No transaction error was detected.

WARNINGS
There were no warnings during this operation.

OPERATION PROGRESS STATUS
* [2010-11-29 오후 4:17:55] : Activation of http://.../SetupSecurity/SetupSecurity.application has started.
* [2010-11-29 오후 4:17:55] : Processing of deployment manifest has successfully completed.

ERROR DETAILS
Following errors were detected during this operation.
* [2010-11-29 오후 4:17:55] System.Runtime.InteropServices.COMException
- 요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4)
- Source: System.Deployment
- Stack trace:
at System.Deployment.Application.NativeMethods.CorLaunchApplication(UInt32 hostType, String applicationFullName, Int32 manifestPathsCount, String[] manifestPaths, Int32 activationDataCount, String[] activationData, PROCESS_INFORMATION processInformation)
at System.Deployment.Application.ComponentStore.ActivateApplication(DefinitionAppId appId, String activationParameter, Boolean useActivationParameter)
at System.Deployment.Application.SubscriptionStore.ActivateApplication(DefinitionAppId appId, String activationParameter, Boolean useActivationParameter)
at System.Deployment.Application.ApplicationActivator.Activate(DefinitionAppId appId, AssemblyManifest appManifest, String activationParameter, Boolean useActivationParameter)
at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension, BrowserSettings browserSettings, String& errorPageUrl)
at System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)

COMPONENT STORE TRANSACTION DETAILS
* Transaction at [2010-11-29 오후 4:17:55]
+ System.Deployment.Internal.Isolation.StoreOperationSetDeploymentMetadata
- Status: Set
- HRESULT: 0x0
+ System.Deployment.Internal.Isolation.StoreTransactionOperationType (27)
- HRESULT: 0x0

꼼꼼한 답변에 감사드립니다.
[guest]
2010-11-29 11시16분
아래의 별도 답글로 설명을 했으니, 참고하세요. ^^

[답변] 클릭원스 - 요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4)
; http://www.sysnet.pe.kr/2/0/954
정성태
2010-12-03 02시36분
[저는 누구일까요?] 헙~! 실행했더니 디스크가 포멧됐어요...

^^' 농담입니다.

잘 봤습니다.
[guest]
2010-12-03 02시48분
"포멧" 아니죠. "포맷" 맞습니다~~~. ^^
정성태
2013-11-18 11시56분
How can I launch an unelevated process from my elevated process and vice versa?
; https://devblogs.microsoft.com/oldnewthing/20131118-00/?p=2643
정성태
2016-03-06 12시38분
[guest] 좋은 글 감사 합니다.
UCOMIEnumString 더 이상 쓰이지 않고 아래로 변경 되었네요.

System.Runtime.InteropServices.ComTypes.IEnumString
[guest]

1  2  3  4  5  6  7  8  9  10  11  [12]  13  14  15  ...
NoWriterDateCnt.TitleFile(s)
13322정성태4/15/20234936VS.NET IDE: 182. Visual Studio - 32비트로만 빌드된 ActiveX와 작업해야 한다면?
13321정성태4/14/20233735개발 환경 구성: 676. WSL/Linux Octave - Python 스크립트 연동
13320정성태4/13/20233740개발 환경 구성: 675. Windows Octave 8.1.0 - Python 스크립트 연동
13319정성태4/12/20234181개발 환경 구성: 674. WSL 2 환경에서 GNU Octave 설치
13318정성태4/11/20233989개발 환경 구성: 673. JetBrains IDE에서 "Squash Commits..." 메뉴가 비활성화된 경우
13317정성태4/11/20234146오류 유형: 855. WSL 2 Ubuntu 20.04 - error: cannot communicate with server: Post http://localhost/v2/snaps/...
13316정성태4/10/20233473오류 유형: 854. docker-compose 시 "json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)" 오류 발생
13315정성태4/10/20233667Windows: 245. Win32 - 시간 만료를 갖는 컨텍스트 메뉴와 윈도우 메시지의 영역별 정의파일 다운로드1
13314정성태4/9/20233743개발 환경 구성: 672. DosBox를 이용한 Turbo C, Windows 3.1 설치
13313정성태4/9/20233836개발 환경 구성: 671. Hyper-V VM에 Turbo C 2.0 설치 [2]
13312정성태4/8/20233822Windows: 244. Win32 - 시간 만료를 갖는 MessageBox 대화창 구현 (개선된 버전)파일 다운로드1
13311정성태4/7/20234317C/C++: 163. Visual Studio 2022 - DirectShow 예제 컴파일(WAV Dest)
13310정성태4/6/20233879C/C++: 162. Visual Studio - /NODEFAULTLIB 옵션 설정 후 수동으로 추가해야 할 library
13309정성태4/5/20234034.NET Framework: 2107. .NET 6+ FileStream의 구조 변화
13308정성태4/4/20233924스크립트: 47. 파이썬의 time.time() 실숫값을 GoLang / C#에서 사용하는 방법
13307정성태4/4/20233720.NET Framework: 2106. C# - .NET Core/5+ 환경의 Windows Forms 응용 프로그램에서 HINSTANCE 구하는 방법
13306정성태4/3/20233568Windows: 243. Win32 - 윈도우(cbWndExtra) 및 윈도우 클래스(cbClsExtra) 저장소 사용 방법
13305정성태4/1/20233907Windows: 242. Win32 - 시간 만료를 갖는 MessageBox 대화창 구현 (쉬운 버전)파일 다운로드1
13304정성태3/31/20234263VS.NET IDE: 181. Visual Studio - C/C++ 프로젝트에 application manifest 적용하는 방법
13303정성태3/30/20233565Windows: 241. 환경 변수 %PATH%에 DLL을 찾는 규칙
13302정성태3/30/20234182Windows: 240. RDP 환경에서 바뀌는 %TEMP% 디렉터리 경로
13301정성태3/29/20234319Windows: 239. C/C++ - Windows 10 Version 1607부터 지원하는 /DEPENDENTLOADFLAG 옵션파일 다운로드1
13300정성태3/28/20233950Windows: 238. Win32 - Modal UI 창에 올바른 Owner(HWND)를 설정해야 하는 이유
13299정성태3/27/20233736Windows: 237. Win32 - 모든 메시지 루프를 탈출하는 WM_QUIT 메시지
13298정성태3/27/20233675Windows: 236. Win32 - MessageBeep 소리가 안 들린다면?
13297정성태3/26/20234350Windows: 235. Win32 - Code Modal과 UI Modal
1  2  3  4  5  6  7  8  9  10  11  [12]  13  14  15  ...