Microsoft MVP성태의 닷넷 이야기
.NET Framework: 191. ClickOnce - 관리자 권한 상승하는 방법 [링크 복사], [링크+제목 복사]
조회: 69650
글쓴 사람
정성태 (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)
13447정성태11/16/20232480닷넷: 2162. ASP.NET Core 웹 사이트의 SSL 설정을 코드로 하는 방법
13446정성태11/16/20232416닷넷: 2161. .NET Conf 2023 - Day 1 Blazor 개요 정리
13445정성태11/15/20232691Linux: 62. 리눅스/WSL에서 CA 인증서를 저장하는 방법
13444정성태11/15/20232452닷넷: 2160. C# 12 - Experimental 특성 지원
13443정성태11/14/20232489개발 환경 구성: 687. OpenSSL로 생성한 사용자 인증서를 ASP.NET Core 웹 사이트에 적용하는 방법
13442정성태11/13/20232305개발 환경 구성: 686. 비주얼 스튜디오로 실행한 ASP.NET Core 사이트를 WSL 2 인스턴스에서 https로 접속하는 방법
13441정성태11/12/20232644닷넷: 2159. C# - ASP.NET Core 프로젝트에서 서버 Socket을 직접 생성하는 방법파일 다운로드1
13440정성태11/11/20232350Windows: 253. 소켓 Listen 시 방화벽의 Public/Private 제어 기능이 비활성화된 경우
13439정성태11/10/20232838닷넷: 2158. C# - 소켓 포트를 미리 시스템에 등록/예약해 사용하는 방법(Port Exclusion Ranges)파일 다운로드1
13438정성태11/9/20232457닷넷: 2157. C# - WinRT 기능을 이용해 윈도우에서 실행 중인 Media App 제어
13437정성태11/8/20232653닷넷: 2156. .NET 7 이상의 콘솔 프로그램을 (dockerfile 없이) 로컬 docker에 배포하는 방법
13436정성태11/7/20232889닷넷: 2155. C# - .NET 8 런타임부터 (Reflection 없이) 특성을 이용해 public이 아닌 멤버 호출 가능
13435정성태11/6/20232825닷넷: 2154. C# - 네이티브 자원을 포함한 관리 개체(예: 스레드)의 GC 정리
13434정성태11/1/20232617스크립트: 62. 파이썬 - class의 정적 함수를 동적으로 교체
13433정성태11/1/20232341스크립트: 61. 파이썬 - 함수 오버로딩 미지원
13432정성태10/31/20232373오류 유형: 878. 탐색기의 WSL 디렉터리 접근 시 "Attempt to access invalid address." 오류 발생
13431정성태10/31/20232699스크립트: 60. 파이썬 - 비동기 FastAPI 앱을 gunicorn으로 호스팅
13430정성태10/30/20232596닷넷: 2153. C# - 사용자가 빌드한 ICU dll 파일을 사용하는 방법
13429정성태10/27/20232849닷넷: 2152. Win32 Interop - C/C++ DLL로부터 이중 포인터 버퍼를 C#으로 받는 예제파일 다운로드1
13428정성태10/25/20232897닷넷: 2151. C# 12 - ref readonly 매개변수
13427정성태10/18/20233079닷넷: 2150. C# 12 - 정적 문맥에서 인스턴스 멤버에 대한 nameof 접근 허용(Allow nameof to always access instance members from static context)
13426정성태10/13/20233260스크립트: 59. 파이썬 - 비동기 호출 함수(run_until_complete, run_in_executor, create_task, run_in_threadpool)
13425정성태10/11/20233084닷넷: 2149. C# - PLinq의 Partitioner<T>를 이용한 사용자 정의 분할파일 다운로드1
13423정성태10/6/20233059스크립트: 58. 파이썬 - async/await 기본 사용법
13422정성태10/5/20233199닷넷: 2148. C# - async 유무에 따른 awaitable 메서드의 병렬 및 예외 처리
13421정성태10/4/20233237닷넷: 2147. C# - 비동기 메서드의 async 예약어 유무에 따른 차이
1  2  3  4  5  6  [7]  8  9  10  11  12  13  14  15  ...