Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일

Protocol Handler - 웹 브라우저에서 데스크톱 응용 프로그램을 실행하는 방법

예를 들어, github 같은 경우 "Open in Visual Studio"라는 이름으로 다음과 같은 형식의 링크를 제공합니다.

git-client://clone/?repo=https%3A%2F%2Fgithub.com%2Fstjeong%2FXmlCodeGenerator

Edge 웹 브라우저로 저 링크를 누르면 실행 여부를 묻는 질문 창이 뜹니다.

Did you mean to switch apps? 
"Microsoft Edge" is trying to open "Microsoft Visual Studio Web Protocol Handler Selector".

사용자가 허락하면, 이제부터는 Visual Studio가 실행되고 해당 프로젝트를 로드하게 됩니다.




웹 브라우저에서 이 기능을 제공하는 방법은 다음의 문서에서 잘 설명하고 있습니다.

Registering an Application to a URI Scheme
; https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/platform-apis/aa767914(v=vs.85)

그러니까, 결국 레지스트리에 원하는 URL Scheme 이름을 등록하고 그것에 따른 응용 프로그램만 지정해 주면 되는 것입니다.

간단하니까, 한번 만들어 볼까요? ^^ 가령 웹 페이지에 다음과 같은 URL을 포함한 경우,

<!DOCTYPE html>

<html lang="en" xmlns="http://www.w3.org/1999/xhtml">
<head>
    <meta charset="utf-8" />
    <title></title>
</head>
<body>
    <a href="getallimages://www.naver.com">download images</a>
</body>
</html>

getallimages 이후에 지정된 주소의 페이지에 포함된 모든 그림 파일을 다운로드하는 프로그램을 다음과 같은 식으로 등록할 수 있습니다. (즉, 사용자가 이전에 한 번은 해당 프로그램을 등록해 주는 절차가 필요합니다.)

static void Main(string[] args)
{
    if (args.Length > 0 && args[0] == "-r")
    {
        RegisterProtocolHandler(true);
    }
}

static void RegisterProtocolHandler(bool doRegistration)
{
    string exePath = typeof(Program).Assembly.Location;
    string exeName = Path.GetFileName(exePath);

    if (doRegistration == true)
    {
        using (RegistryKey appKey = Registry.ClassesRoot.CreateSubKey(Key_AppUniqueName, true))
        {
            appKey.SetValue(null, "URL:Get All Images Protocol");
            appKey.SetValue(Key_URLProtocol, "");

            using (RegistryKey defaultIconKey = appKey.CreateSubKey(Key_DefaultIcon, true))
            {
                defaultIconKey.SetValue(null, string.Format("{0},1", exeName));
            }

            using (RegistryKey shellKey = appKey.CreateSubKey(Key_Shell, true))
            using (RegistryKey openKey = shellKey.CreateSubKey(Key_Open, true))
            using (RegistryKey commandKey = openKey.CreateSubKey(Key_Command, true))
            {
                string value = string.Format("\"{0}\" \"%1\"", exePath);
                commandKey.SetValue(null, value);
            }
        }
    }
}

레지스트리 등록 이후, 웹 브라우저에서 사용자가 getallimages://www.naver.com 링크를 누르면 프로그램을 실행할지 여부를 묻고,

protocol_handler_1.png

허락한 경우 우리가 만든 프로그램을 실행하게 됩니다.

이때, 프로그램 측에서는 Main 메서드에 전달된 args의 첫 번째 인자로 "getallimages://www.naver.com" 문자열을 받게 됩니다. 이후에 해야 할 일은 사용자가 원하는 대로 제어하면 됩니다. 이번 예제의 경우에는 단지 www.naver.com 페이지를 WebClient로 내려받은 후,

WebClient wc = new WebClient();
string htmlText = wc.DownloadString("http://www.naver.com");

HtmlAgilityPack을 이용해,

Html Agility Pack 소개 - 웹 문서에서 텍스트만 분리하는 방법
; https://www.sysnet.pe.kr/2/0/1494

웹 페이지에 포함된 모든 IMG 태그를 열람 후 이미지 파일들을 다운로드하는 작업을 하면 됩니다.

HtmlAgilityPack.HtmlDocument doc = new HtmlAgilityPack.HtmlDocument();
doc.LoadHtml(htmlText);

foreach (var imgNode in doc.DocumentNode.SelectNodes("//img"))
{
    string src = imgNode.GetAttributeValue("src", "");

    // ... 이하, src에 해당하는 이미지를 다운로드
}

간단하죠! ^^

(첨부 파일은 이 글의 예제 코드를 포함합니다.)




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







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

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

비밀번호

댓글 작성자
 



2021-10-21 10시16분
[Wnsl] 좋은 글 너무 잘 봤습니다. 질문이 있습니다. 혹시 Registry.ClassesRoot.CreateSubKey 루트가 아닌 로컬머신에 등록해서도 사용할 수 있을까요? 그럼 getallimages://param 이아니라 다르게 호출해야 할까요?
[guest]
2021-10-21 10시30분
일단 문서상으로 보면 HKCR만 나오고 HKLM은 없으니 아마 안 될 듯합니다. (사실, 보안 강화로 인해 저 단계는 반드시 사용자의 허락을 얻는 것을 요구하므로 전체 등록은... 글쎄요, 그래도 일단 해보면 되지 않을까요?)

(만약 윈도우가 그것을 허용한다면) HKLM에 등록해도 호출 방식은 같을 것입니다.
정성태
2021-10-21 12시12분
[Wnsl] 답변 감사합니다. 여러가지 시도해 보았는데 HKCR가 HKLM/software/classes 의 정보를 담고 있기 때문에 HKLM/software/classes 에 등록했다면 위 글에서 사용하신 것과 동일하게 동작하는 것을 확인했습니다.
[guest]
2021-10-21 04시19분
아... 제가 혼동했군요. ^^; HKCR은 말씀하신데로 HKLM 쪽의 링크가 맞습니다. (위에서 제가 쓴 답변은 HKEY_CURRENT_USER로 착각을 한 것이므로 무시해도 됩니다. ^^;)
정성태
2023-03-09 08시20분
From a Windows app, how can I check whether there is an app installed that implements a particular URI scheme?
; https://devblogs.microsoft.com/oldnewthing/20230308-04/?p=107915

From a Windows app, how can I check whether there is an app installed that implements a particular URI scheme?, part 2
; https://devblogs.microsoft.com/oldnewthing/20230309-00/?p=107922
정성태

... [106]  107  108  109  110  111  112  113  114  115  116  117  118  119  120  ...
NoWriterDateCnt.TitleFile(s)
11274정성태8/22/201719320.NET Framework: 674. Thread 타입의 Suspend/Resume/Join 사용 관련 예외 처리
11273정성태8/22/201721624오류 유형: 415. 윈도우 업데이트 에러 Error 0x80070643
11272정성태8/21/201724746VS.NET IDE: 120. 비주얼 스튜디오 2017 버전 15.3.1 - C# 7.1 공개 [2]
11271정성태8/19/201719166VS.NET IDE: 119. Visual Studio 2017에서 .NET Core 2.0 프로젝트 환경 구성하는 방법
11270정성태8/17/201730618.NET Framework: 673. C#에서 enum을 boxing 없이 int로 변환하기 [2]
11269정성태8/17/201721423디버깅 기술: 93. windbg - 풀 덤프에서 .NET 스레드의 상태를 알아내는 방법
11268정성태8/14/201720999디버깅 기술: 92. windbg - C# Monitor Lock을 획득하고 있는 스레드 찾는 방법
11267정성태8/10/201725077.NET Framework: 672. 모노 개발 환경
11266정성태8/10/201724874.NET Framework: 671. C# 6.0 이상의 소스 코드를 Visual Studio 설치 없이 명령행에서 컴파일하는 방법
11265정성태8/10/201753125기타: 66. 도서: 시작하세요! C# 7.1 프로그래밍: 기본 문법부터 실전 예제까지 [11]
11264정성태8/9/201724008오류 유형: 414. UWP app을 signtool.exe로 서명 시 0x8007000b 오류 발생
11263정성태8/9/201719476오류 유형: 413. The C# project "..." is targeting ".NETFramework, Version=v4.0", which is not installed on this machine. [3]
11262정성태8/5/201718203오류 유형: 412. windbg - SOS does not support the current target architecture. [3]
11261정성태8/4/201720780디버깅 기술: 91. windbg - 풀 덤프 파일로부터 강력한 이름의 어셈블리 추출 후 사용하는 방법
11260정성태8/3/201718870.NET Framework: 670. C# - 실행 파일로부터 공개키를 추출하는 방법
11259정성태8/2/201718128.NET Framework: 669. 지연 서명된 어셈블리를 sn.exe -Vr 등록 없이 사용하는 방법
11258정성태8/1/201718894.NET Framework: 668. 지연 서명된 DLL과 서명된 DLL의 차이점파일 다운로드1
11257정성태7/31/201719129.NET Framework: 667. bypassTrustedAppStrongNames 옵션 설명파일 다운로드1
11256정성태7/25/201720582디버깅 기술: 90. windbg의 lm 명령으로 보이지 않는 .NET 4.0 ClassLibrary를 명시적으로 로드하는 방법 [1]
11255정성태7/18/201723163디버깅 기술: 89. Win32 Debug CRT Heap Internals의 0xBAADF00D 표시 재현 [1]파일 다운로드3
11254정성태7/17/201719477개발 환경 구성: 322. "Visual Studio Emulator for Android" 에뮬레이터를 "Android Studio"와 함께 쓰는 방법
11253정성태7/17/201719759Math: 21. "Coding the Matrix" 문제 2.5.1 풀이 [1]파일 다운로드1
11252정성태7/13/201718415오류 유형: 411. RTVS 또는 PTVS 실행 시 Could not load type 'Microsoft.VisualStudio.InteractiveWindow.Shell.IVsInteractiveWindowFactory2'
11251정성태7/13/201717071디버깅 기술: 88. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 (2)
11250정성태7/13/201720662디버깅 기술: 87. windbg 분석 - webengine4.dll의 MgdExplicitFlush에서 발생한 System.AccessViolationException의 crash 문제 [1]
11249정성태7/12/201718455오류 유형: 410. LoadLibrary("[...].dll") failed - The specified procedure could not be found.
... [106]  107  108  109  110  111  112  113  114  115  116  117  118  119  120  ...