Windows 셸 통합의 현재 ── 컨텍스트 메뉴, 파일 연결, Windows 11의 변화

· 업데이트: · · Windows, 셸 확장, 컨텍스트 메뉴, 파일 연결, COM, Windows 11, 파일 탐색기, MSIX, Windows 개발

수정 이력(1건, 최종 수정 2026년 09월 03일)

이 글에 적용한 변경 사항의 기록입니다. 보관해 둔 수정 전 버전은 DOI가 부여된 고정 URL에서 읽을 수 있습니다.

한국어 전면 재작성에 맞춰 본문 표현을 바로잡았습니다. 기술적인 주장은 일본어판과 같습니다.
최초 공개
이 글을 인용하기(DOI(등록된 아카이브): 10.5281/zenodo.22176270)

아래 DOI는 이전에 등록된 아카이브를 가리키며 현재 본문과 다를 수 있습니다. 현재 본문을 참조할 때는 이 페이지의 URL을 사용하세요.

Go Komura (2026). 「Windows 셸 통합의 현재 ── 컨텍스트 메뉴, 파일 연결, Windows 11의 변화」. 합동회사 코무라소프트. https://comcomponent.com/ko/blog/windows-shell-integration-context-menu-file-association/

DOI(등록된 아카이브)
10.5281/zenodo.22176270
DOI(마지막 등록 버전)
10.5281/zenodo.22176271

「Windows 11 PC로 바꿨더니, 예전에 만들어 주신 앱의 컨텍스트 메뉴가 나오지 않습니다」라는 상담을 받았습니다. 자세히 들어 보니 사라진 것은 아니었습니다. 파일을 마우스 오른쪽 단추로 클릭한 뒤 메뉴 맨 아래의 「더 많은 옵션 표시」를 선택하면, 익숙한 메뉴가 예전처럼 나타납니다. 즉 자사 앱의 메뉴 항목이 한 단계 더 안쪽으로 숨은 것입니다. 현장에서는 「클릭이 한 번 늘었다」, 「항목을 찾지 못한다는 문의가 늘었다」는 이야기가 나옵니다.

이것은 고장도 설정 실수도 아니며, Windows 11의 설계 변경입니다. 파일 탐색기의 컨텍스트 메뉴가 새 메뉴와 기존 메뉴의 이중 구조가 되었고, 새 메뉴에 항목을 올리기 위한 조건은 예전과 전혀 달라졌습니다.

한편 그 아래를 받치는 파일 연결과 셸 확장 구조는 지금도 COM과 레지스트리의 기존 세계입니다. 확장자 키가 ProgID를 가리키고, ProgID의 verb가 명령줄을 가지며, 복잡한 확장은 파일 탐색기에 로드되는 in-process COM 서버(DLL)로 동작합니다. 이 구조는 20년 넘게 바뀌지 않았습니다. 바뀌지 않은 기반과, Windows 11에서 이중화된 메뉴를 둘 다 알지 못하면 「메뉴가 나오지 않는다」「숨었다」「두 번 나온다」의 원인을 가를 수 없습니다.

이 글은 중소기업 IT 담당자와 업무 앱을 맡은 Windows 개발자를 대상으로, 파일 연결의 3단계 구조부터 기존형 셸 확장의 주의점, Windows 11 새 컨텍스트 메뉴 대응, 설치 프로그램의 등록·정리·문제 해결까지를 한 흐름으로 이어서 설명합니다.

1. 먼저 결론

  • 컨텍스트 메뉴와 파일 연결의 기반은 레지스트리의 「확장자 키 → ProgID → verb」라는 3단계 구조입니다. 확장자 키는 ProgID를 가리키는 포인터이고, ProgID가 실체이며, 그 아래의 shell\<verb>\command가 명령줄을 가집니다.1
  • HKEY_CLASSES_ROOT(HKCR)는 독립 하이브가 아니라 HKLM\Software\Classes와 HKCU\Software\Classes의 병합 뷰입니다. 모든 사용자 대상 등록은 HKLM에, 사용자 단위 등록은 HKCU에 쓰고, HKCR은 읽기용으로 생각합니다.2
  • 기본 앱(더블클릭으로 여는 앱)은 사용자가 고르는 설계이며, 프로그램이 가로챌 수 없습니다. 사용자 선택은 OS가 보호하므로, 설치 프로그램이 할 수 있는 일은 후보로 등록하는 것까지입니다.3
  • 기존형 셸 확장은 파일 탐색기에 로드되는 in-process COM DLL입니다. 확장의 크래시나 지연은 파일 탐색기 전체(그리고 셸을 쓰는 다른 앱)로 퍼지고, 64비트 환경에서는 64비트 DLL이 필수이며, 관리 코드 구현은 지원되지 않습니다.45
  • Windows 11에서 컨텍스트 메뉴는 이중화되었습니다. 새 메뉴에 올라가는 것은 IExplorerCommand와 패키지 ID로 등록된 명령뿐이며, 기존형 IContextMenu 확장은 「더 많은 옵션 표시」(Shift+F10)의 기존 메뉴 쪽으로 옮겨집니다.67
  • 새 메뉴에 자체 명령을 내는 공식 경로는 IExplorerCommand를 구현한 네이티브 DLL을 MSIX 매니페스트(desktop4:FileExplorerContextMenus)로 등록하는 것입니다. MSIX로 바꿀 수 없는 앱은 sparse package(외부 위치 MSIX)로 ID만 부여할 수 있습니다.78
  • 단순히 「이 앱으로 연다」만 구현하면 된다면, 지금도 파일 연결과 정적 verb로 충분합니다. 셸 확장 DLL은 필요 없고, Microsoft 스스로 「요구 사항을 충족하는 가장 단순한 방법(정적 verb)을 고르라」고 분명히 말합니다.9
  • 등록·변경 뒤에는 SHChangeNotify(SHCNE_ASSOCCHANGED)로 알리고, 제거할 때는 ProgID를 지워도 확장자 키의 기본값은 지우지 않는 것이 공식 안내입니다. 정리 설계까지가 셸 통합입니다.110

한 문장으로 말하면, 연결과 verb의 세계는 그대로이고, 메뉴를 보여주는 방식만 Windows 11에서 이중화되었다는 것입니다. 아래에서는 기반부터 순서대로 설명합니다.

그림의 실선은 항상 성립하는 관계, 점선은 조건이 붙는 관계입니다(성립 조건은 상세 페이지의 관계별 설명에 적혀 있습니다). 관계 전체 목록(총 16건, 근거와 확신도 포함)과 주요 개념의 정의는 지식 맵 상세 페이지에 정리되어 있습니다(일본어). 데이터: JSON-LD / Turtle

2. 파일 연결의 구조 ── 확장자 키 → ProgID → verb의 3단계

2.1. 한 가지 예로 3단계 구조를 읽기

어떤 확장자의 파일을 더블클릭했을 때 일어나는 일은 레지스트리의 3단계 키로 결정됩니다.1

HKEY_CLASSES_ROOT
   .kmrpt                                  ← (1) 확장자 키
      (Default) = KomuraSoft.Report.1      ←     ProgID를 가리키기만 하는 포인터
      OpenWithProgids
         KomuraSoft.Report.1               ←     「연결 프로그램」 후보
   KomuraSoft.Report.1                     ← (2) ProgID(연결의 실체)
      (Default) = 코무라 리포트 문서
      DefaultIcon
         (Default) = "C:\Program Files\KomuraSoft\Report.exe",0
      shell                                ← (3) verb(동사) 목록
         open
            command
               (Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
  • (1) 확장자 키(.kmrpt)는 기본값으로 ProgID 이름만 가리킵니다. 여기에 명령을 직접 쓰는 것은 잘못입니다.
  • (2) ProgID(KomuraSoft.Report.1)가 연결의 실체이며, 표시 이름·아이콘·verb 목록을 가집니다.
  • (3) verb는 「열기」「인쇄」와 같은 동사이며, shell\open\command의 기본값이 실제로 실행되는 명령줄입니다.

이 분리 덕분에 여러 확장자(.kmrpt와 .kmrpt-file 등)를 같은 ProgID로 향하게 하거나, 앱 버전 업에서 ProgID를 갈아 끼울 수 있습니다.

파일 연결의 3단계 구조확장자 키는 기본값으로 ProgID를 가리키는 포인터일 뿐이고, ProgID가 표시 이름·아이콘과 verb 목록을 가진 실체이며, verb 아래 command의 기본값이 실제로 실행되는 명령줄이 된다기본값으로 ProgID를 가리킴확장자 키 .kmrptProgID KomuraSoft.Report.1verb(shell 아래의 open 등)command의 기본값Report.exe가 실행된다표시 이름·DefaultIcon도 가진다

그림 1: 확장자 키는 포인터, ProgID가 실체, verb의 command가 실제로 실행되는 명령줄.

2.2. HKCR는 「병합 뷰」 ── 어디에 쓰느냐에 따라 의미가 달라진다

위 예는 HKEY_CLASSES_ROOT(HKCR)로 보였지만, HKCR는 물리적인 저장 위치가 아니라 HKLM\Software\Classes와 HKCU\Software\Classes를 겹친 병합 뷰입니다. 같은 키가 양쪽에 있으면 HKCU 쪽이 이깁니다.2

HKCR는 병합 뷰HKLM과 HKCU 각각의 Classes를 겹친 것이 HKCR이고, 같은 키가 양쪽에 있으면 HKCU 쪽이 우선되며, 등록의 쓰기는 HKLM 또는 HKCU를 명시하고 HKCR는 읽기용으로 여긴다HKLM\Software\Classes(모든 사용자)HKCR(병합 뷰)HKCU\Software\Classes(사용자 단위)같은 키가 있으면 HKCU 쪽이 이긴다읽기(확인)용으로 여긴다

그림 2: HKCR는 HKLM과 HKCU의 Classes를 겹친 모습이며, 쓰기 대상은 반드시 어느 한쪽을 명시한다.

쓰기 대상 의미 필요한 권한
HKLM\Software\Classes 모든 사용자 공통 등록 관리자 권한
HKCU\Software\Classes 그 사용자만의 등록 불필요
HKCR에 직접 쓰기 기존 키의 위치에 따라 나뉜다 경우에 따라 다름

실무에서는 등록은 반드시 HKLM 또는 HKCU 중 하나를 명시해 쓰고, HKCR는 읽기(확인)용으로 여기는 편이 안전합니다. 아울러 WOW64의 레지스트리 리다이렉트와의 관계도 정리해 둡니다. 확장자 키나 ProgID처럼 HKLM\Software\Classes 바로 아래의 연결 데이터는 Windows 7 이후 32비트/64비트 레지스트리 뷰 사이에서 공유되며, 32비트 설치 프로그램이 써도 Wow6432Node 쪽으로 달아나지 않습니다. 반면 Classes\CLSID 등 COM 등록 계열의 일부 하위 키는 리다이렉트 대상이며, 뒤에서 다루는 셸 확장(in-process COM) 등록에서는 32비트/64비트 쓰기 구분이 중요해집니다. 자세한 내용은 「레지스트리의 32bit/64bit 리다이렉트와 가상화의 함정」에서 다룹니다.

2.3. 앱 쪽 등록 ── App Paths·Applications·RegisteredApplications

파일 쪽(확장자와 ProgID)과 짝을 이루는 앱 쪽 등록도 세 종류가 있습니다.11

  • App Paths(HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths): 실행 파일 이름만으로 ShellExecuteEx에서 실행할 수 있게 하는 등록입니다. PATH 환경 변수를 더럽히지 않아도 되므로 Microsoft는 이쪽을 권장합니다.
  • Applications(HKCR\Applications\<앱.exe>): 「연결 프로그램」으로 임의의 파일을 받았을 때의 기본 여는 방식과, 앱의 표시 이름(FriendlyAppName)을 정의합니다.
  • RegisteredApplications + Capabilities: 앱이 다룰 수 있는 확장자·MIME 유형을 선언하고, Windows의 기본 앱 설정 화면에 후보로 나열되기 위한 등록입니다.

「우리 앱이 기본 앱 목록에 나오지 않는다」는 상담의 대부분은 ProgID는 등록했는데 이 Capabilities 등록을 빼먹은 경우입니다.

앱 쪽의 세 종류 등록앱 쪽 등록에는 App Paths와 Applications와 RegisteredApplications의 세 종류가 있으며, 각각 실행 파일 이름만으로의 실행, 연결 프로그램에서의 기본 여는 방식, 기본 앱 설정 화면 게재라는 역할을 맡는다앱 쪽 등록App PathsApplicationsRegisteredApplications파일 이름만으로 실행연결 프로그램의 기본기본 앱 화면에 오른다Capabilities로 선언이 조건

그림 3: 앱 쪽 등록은 세 종류이며, 기본 앱 화면의 후보에 오르려면 Capabilities 등록이 필요하다.

2.4. 기본 앱은 사용자의 것 ── UserChoice의 보호

확장자 키의 기본값에 ProgID를 쓴다고 해서 그것만으로 기본 앱이 되는 것은 아닙니다. 사용자가 「연결 프로그램」 등에서 명시적으로 고른 결과는 HKCU\...\Explorer\FileExts\<확장자>\UserChoice에 보관되며, 연결을 해석할 때는 이쪽이 우선됩니다.

그리고 중요한 점은, Windows는 프로그램이 기본 앱을 바꾸는 것을 지원하지 않는다는 것입니다. 기본 앱 설정은 시스템 설정 UI를 통해 사용자가 하는 설계이며, UserChoice 데이터는 난독화되고, 필터 드라이버(UCPD.sys)가 앱의 쓰기를 차단합니다. 관리 환경에서는 그룹 정책/MDM 정책이 공식 수단입니다.3

예전에 SetUserFTA처럼 「해시를 흉내 내어 다시 쓰는」 도구가 쓰여 온 것은, 이 보호의 이면입니다. 자사 앱의 설치 프로그램에 넣어야 할 것은 기본값 탈취가 아니라, (a)ProgID와 verb의 올바른 등록, (b)OpenWithProgIds에 추가, (c)필요하면 설정 화면으로 안내의 세 가지입니다.

기본 앱의 해석과 UserChoice의 보호사용자가 명시적으로 고른 결과는 UserChoice에 보관되어 연결 해석에서 우선되며, 앱의 다시 쓰기는 UCPD.sys가 차단하므로, 설치 프로그램이 할 수 있는 일은 후보로서의 등록과 설정 화면으로의 안내까지가 된다우선UCPD.sys가 차단UserChoice(사용자의 선택)연결의 해석확장자 키의 기본값앱에서의 다시 쓰기설치 프로그램의 일ProgID와 verb의 등록OpenWithProgIds에 추가설정 화면으로 안내

그림 4: 연결 해석에서는 사용자의 선택(UserChoice)이 우선되며, 앱의 다시 쓰기는 OS가 보호한다.

3. 「열기」 이외의 verb ── print·edit·runas·사용자 지정 verb

verb는 open만이 아닙니다. OS가 의미를 아는 표준 verb에는 open 외에 edit, print, play, preview 등이 있으며, 표준 verb에는 OS 로캘에 따른 표시 이름이 자동으로 붙습니다. 더블클릭 때 쓰이는 기본 verb는 shell 키의 기본값 → 레지스트리상의 첫 verb → open → openwith 순으로 결정됩니다.12

기본 verb의 결정 순서더블클릭 때 쓰이는 기본 verb는 shell 키의 기본값, 레지스트리상의 첫 verb, open, openwith 순으로 처음 찾은 것으로 결정된다없으면없으면없으면shell 키의 기본값레지스트리상의 첫 verbopenopenwith

그림 5: 더블클릭 때의 기본 verb는 이 순서로 처음 찾은 것이 쓰인다.

고유한 동사를 더하고 싶을 때는 사용자 지정 verb를 등록합니다.

KomuraSoft.Report.1
   shell
      open
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
      print
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" /print "%1"
      verify                          ← 사용자 지정 verb
         (Default) = 보고서 검증(&V)   ← 메뉴의 표시 이름
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" /verify "%1"

알아 두면 도움이 되는 작은 이야기를 세 가지 듭니다.

  • runas라는 verb를 등록하면 「관리자 권한으로 실행」에 해당하는 권한 상승 실행을 정의할 수 있으며, ShellExecute 계열 API에서 runas를 지정한 실행에도 쓰입니다.
  • verb 키에 Extended라는 빈 값을 두면, Shift 키를 누른 채로 마우스 오른쪽 단추를 클릭했을 때만 표시되는 확장 verb가 됩니다. 거의 쓰지 않는 위험한 조작을 숨기는 데 편리합니다.12
  • 오래된 앱의 연결에는 DDE(ddeexec 키)로 기존 프로세스에 문서를 보내는 구성이 남아 있는 경우가 있지만, DDE에 의한 verb 실행은 이미 비권장(Deprecated) 유산입니다. 새로 쓸 이유는 없습니다.12

하나 더, 사고가 많은 것이 명령줄의 따옴표입니다. 명령 문자열의 요소에 공백이 들어갈 수 있으면 반드시 따옴표로 감싸야 합니다. C:\Program Files\... 같은 EXE 경로는 물론이고, %1(선택한 파일의 경로)은 항상 "%1"로 써야 합니다. 사용자 파일 경로에 공백이 없음을 보장할 수 없기 때문입니다. 따옴표가 없는 My Program.exe는 「My를 Program.exe라는 인수로 실행한다」고 해석됩니다.13

명령줄 따옴표 사고따옴표가 없는 명령은 공백 위치에서 나뉘어 My를 Program.exe라는 인수로 실행한다고 잘못 해석되므로, 공백을 포함할 수 있는 EXE 경로와 선택한 파일 경로를 나타내는 %1은 항상 따옴표로 감싼다공백으로 분할따옴표 없는 command다른 EXE 실행으로 오해석따옴표 있는 command의도대로 실행EXE 경로를 따옴표로 감싼다%1도 항상 따옴표로 감싼다

그림 6: 따옴표가 없는 명령은 공백에서 잘못 나뉘므로, EXE 경로와 %1은 항상 따옴표로 감싼다.

여기까지의 레지스트리만으로 되는 구조(정적 verb)는 DLL을 하나도 쓰지 않고 구현할 수 있으며, 파일 탐색기를 불안정하게 할 위험도 없습니다. Microsoft 스스로 「셸 확장을 쓰기 전에, 요구 사항을 충족하는 가장 단순한 정적 verb로 끝나지 않는지 검토하라」고 반복해서 말합니다.9

4. 기존형 셸 확장 ── 파일 탐색기 안에서 동작하는 DLL

4.1. 셸 확장의 종류

정적 verb로는 부족한 「선택 내용에 따라 메뉴를 동적으로 바꾼다」「아이콘이나 속성 화면을 교체한다」 같은 요구에는 셸 확장 핸들러를 씁니다. 대표적인 종류는 다음과 같습니다.4

핸들러 주요 인터페이스 할 수 있는 일
컨텍스트 메뉴 핸들러 IContextMenu + IShellExtInit 메뉴 항목을 동적으로 추가·제어
아이콘 핸들러 / 아이콘 오버레이 IExtractIcon / IShellIconOverlayIdentifier 파일별 아이콘·겹쳐 표시
속성 시트 핸들러 IShellPropSheetExt 속성 화면에 탭 추가
미리 보기 / 정보 팁 IThumbnailProvider / IQueryInfo 축소 표시·가리킬 때 설명
끌어서 놓기 / 복사 훅 핸들러 IDropTarget / ICopyHook 놓을 때·복사 이동 때 개입

이들은 모두 COM 클래스로 구현하고, CLSID를 레지스트리에 등록합니다. COM 자체의 사고방식은 「COM / ActiveX / OCX란 무엇인가」를 참고하십시오.

4.2. in-process COM 서버라는 것의 의미

기존형 셸 확장의 본질은, 파일 탐색기(나 공용 파일 대화 상자를 연 임의 앱)의 프로세스 안에 로드되는 in-process COM 서버(DLL)라는 점입니다. 모든 주의점은 여기서 나옵니다.4

  • 확장이 크래시하면 파일 탐색기가 함께 크래시합니다. 멈추면 마우스 오른쪽 클릭이 수 초 동안 굳습니다. 게다가 피해는 파일 탐색기에 그치지 않고, 파일 열기 대화 상자를 표시한 모든 앱에 미칩니다.
  • 메뉴 구축은 UI 스레드에서 이루어지므로, 네트워크 접근이나 파일 I/O처럼 느린 처리를 메뉴 표시 때 해서는 안 됩니다.
  • 스레딩 모델은 Apartment로 등록하는 것이 원칙입니다.
in-process 확장의 연쇄 피해 구조셸 확장 DLL은 파일 탐색기뿐 아니라 파일 대화 상자를 연 임의 앱의 프로세스에도 로드되므로, 확장의 크래시나 정지는 호스트 프로세스 전체로 퍼진다프로세스 안에 로드프로세스 안에 로드셸 확장 DLL파일 탐색기대화 상자를 여는 임의 앱크래시나 정지가 퍼진다느린 처리를 표시 때 하지 않는다

그림 7: 확장 DLL은 호스트 프로세스 안에서 동작하므로, 크래시나 정지는 호스트 전체로 퍼진다.

「특정 폴더를 열면 파일 탐색기가 굳는다」「마우스 오른쪽 클릭에 5초가 걸린다」는 상담을 조사하면, 원인이 자사 앱이 아니라 서드파티 셸 확장이었던 일은 드물지 않습니다. 원인 분리 방법은 8장에서 다룹니다.

4.3. 비트 수 일치 ── 64비트 환경에서는 64비트 DLL이 필수

in-process DLL은 로드하는 프로세스와 비트 수가 일치해야 합니다. 64비트 Windows의 파일 탐색기는 64비트 프로세스이므로, 32비트로만 빌드한 셸 확장 DLL은 애초에 로드되지 않고 메뉴에 전혀 나타나지 않습니다. 오류도 나오지 않으므로 「등록했는데 안 나온다」 원인의 단골입니다. 32비트 앱 본체와 64비트 셸 확장 DLL의 조합은 정당한 구성이지만, COM 등록이 bitness마다 갈라진다(Wow6432Node)는 점에 주의가 필요합니다. 참고로 verb의 command에서 실행하는 것은 별도 프로세스의 EXE이므로 이 제약을 받지 않습니다(32비트 EXE 그대로여도 문제 없습니다).

셸 확장 DLL의 비트 수 일치64비트 파일 탐색기에 로드할 수 있는 것은 64비트 셸 확장 DLL뿐이며, 32비트만의 DLL은 오류도 없이 메뉴에 나타나지 않고, verb의 command에서 실행하는 EXE는 별도 프로세스이므로 제약을 받지 않는다로드할 수 있다로드할 수 없다별도 프로세스64비트 파일 탐색기64비트 셸 확장 DLL32비트만의 DLL오류 없이 메뉴에 나오지 않는다verb로 실행하는 EXE32비트 그대로여도 문제 없음

그림 8: 64비트 파일 탐색기에 로드되는 것은 64비트 DLL뿐이며, verb로 실행하는 EXE는 이 제약을 받지 않는다.

4.4. 관리 코드로 쓰면 안 되는 이유

「C#으로 셸 확장을 쓸 수 없느냐」는 질문을 자주 받지만, Microsoft는 in-process 셸 확장을 관리 코드(.NET)로 쓰는 것을 비권장으로 두고, 지원 대상 외라고 분명히 말합니다.5

이유는 확장이 임의 프로세스에 로드되는 성질에 있습니다. CLR의 버전 충돌(특히 .NET Framework 4 미만), 잠금을 기다리다가 CLR이 메시지 루프에 재진입하는 문제, 가비지 컬렉션에 의한 객체 수명의 비결정성이 COM의 참조 카운트 계약과 충돌하는 문제 등, 호스트 앱을 불안정하게 하는 요인이 구조적으로 존재하기 때문입니다. .NET Framework 4 이후나 최신 .NET에서 완화된 항목도 있지만, 공식 입장은 바뀌지 않았습니다.

실무 지침은 단순합니다. in-process 확장은 네이티브 C++로 씁니다. 관리 코드를 쓰고 싶다면 verb의 command로 실행하는 일반 EXE로 하거나, 별도 프로세스에서 동작하는 out-of-process 확장(미리 보기 핸들러 등)으로 합니다.5

관리 코드 가부의 판단파일 탐색기 프로세스 안에서 동작하는 in-process 확장은 네이티브 C++로 쓰는 것이 원칙이며, 관리 코드를 쓰고 싶은 경우에는 verb의 command로 실행하는 일반 EXE나 별도 프로세스에서 동작하는 out-of-process 확장으로 한다예아니요프로세스 안에서 동작하는 확장?네이티브 C++로 쓴다관리 코드여도 가능CLR 충돌이나 재진입으로 호스트가 불안정verb로 실행하는 일반 EXE미리 보기 등 별도 프로세스 확장

그림 9: in-process 확장은 네이티브 C++이 원칙이며, 관리 코드는 별도 프로세스에서 동작하는 구성으로 한정한다.

5. Windows 11의 새 컨텍스트 메뉴 ── 메뉴의 이중화

5.1. 무엇이 일어났는가

Windows 11은 파일 탐색기의 컨텍스트 메뉴를 새로 그렸습니다. 잘라내기·복사 등이 위쪽 아이콘 열이 되고, 「열기」「연결 프로그램」이 위쪽에 모아 배치되며, 앱이 추가하는 명령은 셸 표준 명령 아래에 그룹화됩니다. 한 앱이 여러 명령을 추가하는 경우에는 앱 이름이 붙은 플라이아웃(하위 메뉴)으로 모입니다.6

그리고 핵심은 이것입니다. 기존형 IContextMenu 기반 셸 확장은 삭제된 것이 아니라, 「더 많은 옵션 표시」(Shift+F10)로 여는, Windows 10 메뉴를 그대로 로드한 기존 메뉴 쪽으로 옮겨졌습니다.6 글머리 상담의 「메뉴가 숨었다」의 정체가 이 이중화입니다.

Windows 11에서 이중화된 컨텍스트 메뉴마우스 오른쪽 클릭으로 먼저 열리는 것은 새 메뉴이며, 거기에 올라가는 것은 IExplorerCommand와 패키지 ID로 등록한 명령뿐이고, 기존형 IContextMenu 확장은 더 많은 옵션 표시로 여는 기존 메뉴 쪽으로 옮겨진다더 많은 옵션 표시 Shift+F10파일을 마우스 오른쪽 단추로 클릭새 메뉴(Windows 11)IExplorerCommand+ID의 명령기존 메뉴(Windows 10의 메뉴)기존형 IContextMenu 확장여러 명령은 플라이아웃으로 모인다

그림 10: 새 메뉴에 올라가는 것은 IExplorerCommand+ID의 명령뿐이며, 기존형 확장은 기존 메뉴 쪽으로 옮겨진다.

5.2. 새 메뉴에 올리는 공식 경로 ── IExplorerCommand+매니페스트 등록

새 메뉴에 자체 명령을 내는 방법은 하나입니다. IExplorerCommand 인터페이스를 구현한 네이티브 DLL을 준비하고, MSIX 패키지의 매니페스트에서 COM 서버와 컨텍스트 메뉴 확장을 선언하는 것입니다.7

<!-- 패키지 매니페스트(발췌) -->
<com:Extension Category="windows.comServer">
  <com:ComServer>
    <com:SurrogateServer DisplayName="Komura commands">
      <com:Class Id="01234567-89AB-CDEF-0123-456789ABCDEF"
                 Path="KomuraCommand.dll" ThreadingModel="STA" />
    </com:SurrogateServer>
  </com:ComServer>
</com:Extension>
<desktop4:Extension Category="windows.fileExplorerContextMenus">
  <desktop4:FileExplorerContextMenus>
    <desktop5:ItemType Type=".kmrpt">
      <desktop5:Verb Id="VerifyReport"
                     Clsid="01234567-89AB-CDEF-0123-456789ABCDEF" />
    </desktop5:ItemType>
  </desktop4:FileExplorerContextMenus>
</desktop4:Extension>

ItemType의 Type에는 특정 확장자 외에 *(모든 파일), Directory(폴더), Directory\Background(폴더의 배경)를 지정할 수 있습니다. DLL은 파일 탐색기의 아키텍처(64비트/ARM64)에 맞춥니다.7

IExplorerCommand 자체는 Windows 7 시대부터 있는 인터페이스이며, 제목(GetTitle), 아이콘(GetIcon), 사용/사용 안 함/숨김 상태(GetState), 실행(Invoke)을 구현합니다. 메서드는 UI 스레드에서 호출되므로 네트워크 자원에 대한 접근은 금지이며, 메뉴 구축 계열 메서드는 빠르게 반환해야 합니다. 무거운 처리는 Invoke 뒤에 합니다.147

새 메뉴 등록의 매니페스트 구조MSIX 매니페스트의 COM 서버 선언이 CLSID와 DLL을 대응시키고, 컨텍스트 메뉴 확장 선언이 ItemType과 Verb로 대상과 구현을 묶음으로써, 자체 명령이 새 메뉴에 표시된다CLSID와 DLL을 대응시킴ItemType과 Verb로 지정MSIX 매니페스트COM 서버 선언메뉴 확장의 선언IExplorerCommand 구현 DLL새 메뉴에 명령 표시대상은 확장자나 모든 파일 등

그림 11: 매니페스트의 두 선언이 구현 DLL과 대상을 묶어, 새 메뉴에 명령이 오른다.

5.3. 비패키지 앱의 선택지 ── sparse package로 ID만 얻는다

「우리 앱은 MSI가 아니면 배포할 수 없다. MSIX화는 무리」라는 경우의 우회로가 sparse package(외부 위치 MSIX)입니다. 앱 본체를 넣지 않은, 매니페스트만의 작은 MSIX를 서명해 만들고, 기존 설치 프로그램의 마지막에 등록합니다. 이로써 앱은 패키지 ID를 얻고, 위의 매니페스트 등록(=새 메뉴 표시)이 가능해집니다. Windows 10 버전 2004 이후에서 이용할 수 있으며, 패키지는 대상 컴퓨터에서 신뢰되는 인증서로 서명해야 합니다.8

sparse package로 ID를 얻는 흐름기존 설치 프로그램으로 앱 본체를 배치한 뒤, 매니페스트만의 sparse package를 외부 위치로 등록하면 앱은 패키지 ID를 얻고, 새 메뉴에 대한 매니페스트 등록이 가능해진다기존 설치 프로그램앱 본체를 배치sparse package매니페스트만이고 본체 없음외부 위치로 등록패키지 ID를 획득새 메뉴 등록이 가능해진다신뢰되는 서명이 필요

그림 12: 본체를 넣지 않은 sparse package를 외부 위치로 등록하면, 앱은 패키지 ID를 얻는다.

설치 프로그램을 갈아 끼우지 않아도 되는 것이 최대 이점이며, 기존 MSI/EXE 설치 프로그램 자산을 가진 앱의 현실적인 해법입니다. MSIX로의 전면 이전과의 비교는 「Windows 앱 배포 방식의 고르기」도 참고하십시오.

5.4. 연결의 verb는 새 메뉴에서 어떻게 보이는가

오해하기 쉬운 점이지만, 2~3장의 연결(ProgID와 verb)은 새 메뉴에서도 살아 있습니다. 더블클릭의 기본 verb, 「열기」, 「연결 프로그램」 후보는 연결에서 해석되어 새 메뉴 위쪽에 표시됩니다. 즉 「이 앱으로 열 수 있게 하고 싶다」만이면 Windows 11에서도 추가 대응은 필요 없습니다. 한편 연결은 범용 메뉴 확장이 아니므로, 임의의 사용자 지정 명령을 새 메뉴의 첫 계층에 내려면 IExplorerCommand+ID가 필요하다는 역할 분담입니다.7

연결과 새 메뉴의 역할 분담ProgID와 verb의 연결은 새 메뉴에서도 더블클릭의 기본 verb나 열기와 연결 프로그램의 해석에 쓰여 위쪽에 표시되며, 임의의 사용자 지정 명령을 새 메뉴의 첫 계층에 내려면 IExplorerCommand와 ID가 필요해진다연결(ProgID와 verb)기본 verb와 열기의 해석새 메뉴 위쪽에 표시Windows 11에서도 추가 대응 불필요임의의 사용자 지정 명령IExplorerCommand+ID새 메뉴 첫 계층에 표시

그림 13: 연결은 새 메뉴에서도 「열기」 계열의 해석을 맡으며, 사용자 지정 명령만 IExplorerCommand+ID를 필요로 한다.

6. 실무 판단표 ── 세 선택지 중 무엇을 고를 것인가

여기까지를 실무의 3지선다로 정리합니다.

실현하고 싶은 것 권장하는 수단 Windows 11에서의 보이는 방식 필요한 작업·비용
(a) 더블클릭이나 「열기」로 자사 앱을 실행하고 싶다 연결+정적 verb(레지스트리 등록만) 새 메뉴의 「열기」「연결 프로그램」에 통합 표시 설치 프로그램의 레지스트리 등록만. DLL 불필요·서명의 추가 요구 없음
(b) 선택한 파일/폴더에 대한 자체 명령을 새 메뉴에 내고 싶다 IExplorerCommand 구현+MSIX 매니페스트 등록. 비패키지 앱은 sparse package로 ID를 부여 새 메뉴의 첫 계층(여러 명령은 앱 이름 플라이아웃으로 모음) 네이티브 C++ DLL+패키지 ID+코드 서명
(c) 이미 있는 기존형 IContextMenu 확장을 계속 쓴다 당분간 그대로 유지(신규 개발에는 고르지 않음) 「더 많은 옵션 표시」(Shift+F10)의 기존 메뉴 쪽만 64비트 빌드와 COM 등록의 유지. 장래에는 (b)로의 이전을 계획

판단 포인트는 두 가지입니다. 첫째, (a)로 끝나는 요구에 (b)나 (c)를 끌어오지 않는 것. 셸 확장은 쓰는 순간부터 파일 탐색기 안정성에 대한 책임을 집니다. 둘째, (c)는 「고장 난 것은 아니다」일 뿐이며, 사용자 경험으로는 한 단계 낮은 위치에 계속 놓인다는 것입니다. 일상 조작에서 쓰는 빈도가 높은 명령일수록 (b)로 이전하는 투자 대비 효과가 커집니다.

세 선택지의 고르기더블클릭이나 열기로 실행하고 싶을 뿐이라면 연결과 정적 verb로 족하고, 새 메뉴에 자체 명령을 내려면 IExplorerCommand와 MSIX 매니페스트 등록이며, MSIX화할 수 없는 경우에는 sparse package로 ID를 부여하고, 이미 있는 기존형 IContextMenu 확장은 기존 메뉴 쪽에서 당분간 유지한다예아니요예예아니요아니요열기만으로 되는가?연결+정적 verb새 메뉴에 자체 명령?MSIX화할 수 있는가?IExplorerCommand+MSIXsparse package로 ID기존형을 당분간 유지기존 메뉴 쪽에만 표시DLL 불필요이며 위험 작음

그림 14: 요구에 따라 정적 verb, IExplorerCommand+ID, 기존형 유지의 3지선다에서 고른다.

7. 배포·등록의 실무 ── 설치 프로그램·sparse package·정리

7.1. HKLM인가 HKCU인가

설치 프로그램의 형태에 맞춥니다. 모든 사용자 대상(Program Files에 배치, 관리자 권한)이면 HKLM\Software\Classes, 사용자 단위 설치(권한 상승 없음)이면 HKCU\Software\Classes입니다. 섞으면 「A에서는 열리는데 B에서는 열리지 않는다」 형의 문의가 생깁니다. CLSID 등록을 수반하는 셸 확장에서는, 레지스트리 등록 자체를 불필요하게 하는 Reg-Free COM이라는 선택지도 앱 내 COM 이용에서는 유효하지만, 파일 탐색기가 로드하는 셸 확장에는 적용할 수 없으므로 정식 등록이 필요합니다(「Reg-Free COM이란」).

7.2. 바꿨으면 알린다 ── SHChangeNotify

연결을 등록·변경·삭제했으면 SHChangeNotify로 SHCNE_ASSOCCHANGED 이벤트를 알립니다. 이것을 빼먹으면 변경이 다시 시작할 때까지 파일 탐색기에 인식되지 않는 경우가 있습니다.110

// 설치 프로그램의 사용자 지정 동작 등에서, 연결을 바꾼 뒤에 한 번 호출한다
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);

7.3. sparse package의 등록과 해제

sparse package의 등록·해제는 설치 프로그램의 일입니다. 등록은 파일 배치 뒤에, 해제는 파일 삭제 전에 합니다.8

# 설치 시: 파일 배치 뒤에, 설치 위치를 외부 위치로 등록
Add-AppxPackage -Path "C:\Program Files\KomuraSoft\KomuraReport.identity.msix" `
                -ExternalLocation "C:\Program Files\KomuraSoft"

# 제거 시: 파일을 지우기 전에 패키지 등록을 해제
Remove-AppxPackage <패키지의 전체 이름>

주의점으로서, Add-AppxPackage는 실행한 사용자에 대해 등록됩니다. 컴퓨터별 MSI에서 사용자 지정 동작으로 호출하는 경우, LocalSystem으로 실행하면 설치한 사용자에게 ID가 부여되지 않으므로, 사용자 가장(impersonate)으로 실행하는 구성으로 합니다. 다만 가장으로 등록되는 것도 그 설치를 실행한 사용자뿐입니다. 한 대의 PC를 여러 사용자가 쓰는 환경에서는 다른 사용자나 나중에 만든 사용자에게 패키지 ID가 없고, 새 메뉴에 명령이 나오지 않습니다. 모든 사용자에게 쓰게 하려면 앱의 첫 실행 때 자신의 패키지 등록을 확인해 미등록이면 등록하는(사용자마다의 등록) 같은 장치를 준비하고, 제거 때도 등록된 각 사용자로부터의 해제를 계획에 넣습니다. 또한 매니페스트 등록의 반영에는 파일 탐색기의 다시 시작(또는 로그아웃)이 필요한 경우가 있습니다.7

sparse package의 등록과 해제 순서설치 때는 파일 배치 뒤에 sparse package를 등록하고, 제거 때는 파일 삭제 전에 등록을 해제하지만, 등록은 실행한 사용자에게만 유효하다는 점에 주의한다설치파일을 배치sparse package를 등록제거패키지 등록을 해제파일을 삭제등록은 실행 사용자에게만 유효

그림 15: 등록은 파일 배치 뒤, 해제는 파일 삭제 전에 하며, 등록이 실행 사용자 단위라는 점에 주의한다.

7.4. 제거 때의 정리 ── 지울 것과 남길 것

제거 때의 정리에는 공식 안내에 명확한 지침이 있습니다.1

  • 지울 것: 자사 ProgID 키 전체, Capabilities/RegisteredApplications 등록, 셸 확장의 CLSID 등록, sparse package(Remove-AppxPackage).
  • 남길 것: 확장자 키(.kmrpt)의 기본값. 자사 ProgID를 가리킨 채로여도 지우지 않는 것이 공식 권장입니다. 설치 뒤에 다른 앱이 기본값을 가져가지 않았는지의 판정은 어렵고, Windows는 기본값의 ProgID가 미등록이면 그냥 무시하므로, 남겨도 실질 해가 없기 때문입니다.
  • 정리의 마지막에도 SHChangeNotify(SHCNE_ASSOCCHANGED)를 호출합니다.

「제거했는데 메뉴에 잔해가 나온다」 문제의 상당수는 이 정리 설계의 누락입니다.

제거 때 정리의 설계제거에서는 자사 ProgID 키나 CLSID 등록과 sparse package는 지우고, 확장자 키의 기본값은 미등록이면 무시되므로 남기며, 정리의 마지막에 SHChangeNotify로 변경을 알린다제거지울 것남길 것ProgID나 CLSID 등록sparse package확장자 키의 기본값미등록 ProgID는 무시된다마지막에 SHChangeNotify로 알림

그림 16: 자사 등록은 지우고, 확장자 키의 기본값은 남기며, 정리의 마지막에 변경을 알린다.

8. 문제 해결 ── 나오지 않음·이중·무거움

8.1. 메뉴에 나오지 않는다

순서대로 원인을 가릅니다.

  1. 어느 메뉴를 보고 있는가: 기존 방식 등록은 Shift+F10의 기존 메뉴 쪽에만 나옵니다. 먼저 양쪽을 확인합니다.
  2. 비트 수: 32비트만의 셸 확장 DLL은 64비트 파일 탐색기에 로드되지 않습니다(4.3절).
  3. 등록 위치: HKLM/HKCU, Wow6432Node의 혼동. reg query로 실제 키를 확인합니다.
  4. 패키지 등록: 새 메뉴용이면 Get-AppxPackage로 등록 유무, 서명 인증서의 신뢰, -ExternalLocation의 경로를 확인하고, 파일 탐색기를 다시 시작합니다.7
  5. 알림 누락: SHChangeNotify를 빼먹었으면, 파일 탐색기를 다시 시작해 반영되는지로 판별할 수 있습니다.
메뉴에 나오지 않을 때의 원인 분리 순서어느 메뉴를 보고 있는지의 확인부터 시작해, DLL의 비트 수, 레지스트리의 등록 위치, 패키지 등록과 서명, SHChangeNotify의 알림 누락 순으로 원인을 가른다새 메뉴인지 기존 메뉴인지 확인DLL의 비트 수를 확인HKLM과 HKCU의 등록 위치를 확인패키지 등록과 서명을 확인알림 누락을 다시 시작으로 판별

그림 17: 「나오지 않는다」일 때는 보고 있는 메뉴·비트 수·등록 위치·패키지 등록·알림 누락 순으로 원인을 가른다.

8.2. 두 번 나온다·사라지지 않는다

전형적인 원인은 기존 방식의 레지스트리 등록과 매니페스트 등록의 공존, 제거 정리의 누락(7.4절), 이전 버전 ProgID의 잔해입니다. 기존 메뉴에만 두 번 나오면 잔해 계열, 새 메뉴와 기존 메뉴 양쪽에 나오면 공존 계열로 가늠할 수 있습니다.

이중 표시의 원인 분리기존 메뉴에만 두 번 나오면 정리 누락이나 이전 ProgID의 잔해 계열, 새 메뉴와 기존 메뉴 양쪽에 나오면 기존 방식의 레지스트리 등록과 매니페스트 등록의 공존 계열로 가늠한다기존 메뉴만양쪽 모두어디에 두 번 나오는가잔해 계열공존 계열정리 누락이나 이전 ProgID의 잔여기존 레지스트리 등록과 새 등록의 공존

그림 18: 기존 메뉴에만 이중이면 잔해 계열, 양쪽 모두에 나오면 공존 계열로 가늠한다.

8.3. 파일 탐색기가 무겁다·크래시한다

마우스 오른쪽 클릭이 느리거나 특정 폴더에서 크래시하는 경우에는, 먼저 설치된 셸 확장의 목록 정리가 출발점입니다. NirSoft의 ShellExView 같은 도구로 Microsoft 이외의 확장을 나열하고, 의심스러운 것을 잠시 비활성화한 뒤 이진 탐색하면 원인 DLL을 특정할 수 있습니다. 크래시라면 이벤트 뷰어의 「장애가 발생한 모듈」도 단서가 됩니다. 자사 확장이 원인이었던 경우에는 메뉴 구축 경로에서의 동기 I/O·네트워크 접근을 의심하십시오(4.2절·5.2절).

무겁거나 크래시할 때의 원인 DLL 특정ShellExView로 Microsoft 이외의 셸 확장을 나열하고, 의심스러운 것을 잠시 비활성화하면서 이진 탐색해 원인 DLL을 특정하며, 크래시의 경우에는 이벤트 뷰어의 장애 모듈도 단서로 한다셸 확장의 목록 정리Microsoft 이외를 나열잠시 비활성화해 이진 탐색원인 DLL을 특정크래시의 경우장애 모듈을 확인

그림 19: Microsoft 이외의 확장을 잠시 비활성화하면서 이진 탐색하고, 크래시 때는 이벤트 뷰어도 함께 쓴다.

8.4. 검증에는 Windows Sandbox가 편리하다

셸 통합의 검증은 「깨끗한 환경에서 설치 → 동작 → 제거 → 잔해 제로」의 확인이 기본입니다. 여기서 편리한 것이 Windows Sandbox(Pro/Enterprise/Education)이며, 실행할 때마다 깨끗한 일회용 Windows가 수 초 만에 뜨므로, 설치 프로그램의 등록·정리 테스트를 몇 번이든 돌릴 수 있습니다. 닫으면 전부 사라지므로 레지스트리 잔해 조사에도 맞습니다.15

9. 정리

  • 파일 연결은 「확장자 키 → ProgID → verb」의 3단계 구조이며, HKCR는 HKLM/HKCU의 Classes 병합 뷰입니다. 쓰기 대상은 명시하고, %1은 반드시 따옴표로 감쌉니다.
  • 기본 앱은 사용자가 고르는 설계이며, 프로그램에서는 바꿀 수 없습니다. 설치 프로그램의 일은 후보로서 올바르게 등록하는 것까지입니다.
  • 기존형 셸 확장은 파일 탐색기에 로드되는 in-process COM DLL입니다. 크래시·지연은 전체로 퍼지고, 64비트가 필수이며, 관리 코드는 지원되지 않고, 구현은 네이티브 C++이 원칙입니다.
  • Windows 11에서 컨텍스트 메뉴는 이중화되었습니다. 새 메뉴에 자체 명령을 내려면 IExplorerCommand+MSIX 매니페스트가 필요하며, 기존형 IContextMenu는 「더 많은 옵션 표시」 쪽으로 옮겨집니다.
  • MSIX화할 수 없는 앱은 sparse package(외부 위치 MSIX)로 ID를 얻는 것이 현실적인 해법입니다.
  • 「이 앱으로 연다」만이면 연결과 정적 verb로 지금도 충분합니다. 가장 단순한 수단부터 검토하는 것이 공식 지침이기도 합니다.
  • 등록·변경·삭제 뒤에는 SHChangeNotify로 알리고, 제거 때는 ProgID를 지워도 확장자 키의 기본값은 남깁니다. 검증에는 Windows Sandbox가 편리합니다.

Windows 11 PC 교체로 「메뉴가 숨었다」고 알아차렸다면, 먼저 6장의 판단표에서 (a)(b)(c) 중 어디에 해당하는지 확인하십시오. 대응의 규모를 그 자리에서 가늠할 수 있을 것입니다.

관련 기사

관련 상담 영역

합동회사 코무라소프트에서는 업무 앱의 파일 연결·컨텍스트 메뉴·셸 확장의 설계와 구현, Windows 11의 새 컨텍스트 메뉴 대응(IExplorerCommand화, sparse package 도입), 기존 설치 프로그램의 등록·정리 재검토, 파일 탐색기가 무겁거나 크래시하는 문제의 원인 조사를 다룹니다. 「더 많은 옵션 표시에 숨어 버린 메뉴를 어떻게 할 것인가」의 방침 결정부터여도 괜찮습니다.

참고 링크

  1. Microsoft Learn, File Types. 확장자 키가 ProgID를 가리키는 구조, OpenWithProgIds, HKLM/HKCU\Software\Classes로의 등록 구분, 연결 변경 뒤에 SHChangeNotify(SHCNE_ASSOCCHANGED)를 호출해야 한다는 점, 제거 때 ProgID는 삭제하되 확장자 키의 기본값은 남겨야 한다는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5

  2. Microsoft Learn, HKEY_CLASSES_ROOT Key. HKEY_CLASSES_ROOT가 HKLM\Software\Classes와 HKCU\Software\Classes를 병합한 뷰라는 점, 사용자 쪽 정의가 컴퓨터 쪽보다 우선된다는 점, 쓸 때의 분배 규칙에 대해. ↩ ↩2

  3. Microsoft Learn, Windows app defaults platform. 기본 앱 변경이 시스템 설정 UI를 통해서만 이루어지는 설계라는 점, 사용자 설정 데이터가 난독화되고 필터 드라이버(UCPD.sys)로 쓰기 보호된다는 점, 레지스트리 기반 변경이 지원되지 않는다는 점, 관리 환경에서는 그룹 정책/MDM 정책을 쓴다는 점에 대해. ↩ ↩2

  4. Microsoft Learn, Working with Shell Extensions. 셸 확장 핸들러의 종류, 확장이 파일 탐색기(및 셸을 호스트하는 프로세스)에 로드되는 in-process COM DLL이며 크래시나 정지가 Explorer 전체로 퍼진다는 점, ThreadingModel=Apartment로의 등록, 셸 확장보다 단순한 대체 수단을 먼저 검토해야 한다는 점에 대해. ↩ ↩2 ↩3

  5. Microsoft Learn, Guidance for Implementing In-Process Extensions. 관리 코드에 의한 in-process 셸 확장 구현을 Microsoft가 권장하지 않으며 지원 대상 외로 둔다는 점, CLR의 버전 충돌·재진입·객체 수명의 비결정성 등의 이유, out-of-process 확장(미리 보기 핸들러나 shell\verb\command에서의 실행)에서는 관리 코드가 허용된다는 점에 대해. ↩ ↩2 ↩3

  6. Windows Developer Blog, Extending the Context Menu and Share Dialog in Windows 11. Windows 11 새 컨텍스트 메뉴의 설계, IExplorerCommand+앱 ID에 의한 확장, 「열기」「연결 프로그램」의 위쪽 배치, 여러 명령의 앱 이름 플라이아웃으로의 집약, 기존 IContextMenu 확장이 「더 많은 옵션 표시」(Shift+F10)의 Windows 10 메뉴로 로드된다는 점에 대해. ↩ ↩2 ↩3

  7. Microsoft Learn, Add a File Explorer context menu command to a packaged desktop app. Windows 11의 새 컨텍스트 메뉴 등록이 IExplorerCommand 구현+windows.comServer+desktop4:FileExplorerContextMenus의 매니페스트 선언으로 이루어진다는 점, ItemType에 *·Directory·Directory\Background를 지정할 수 있다는 점, DLL의 아키텍처 일치, 메뉴 구축 메서드를 빠르게 유지할 것, sparse package에 의한 비패키지 앱 대응, 등록 반영에 파일 탐색기 다시 시작이 필요한 경우가 있다는 점, 파일 연결은 범용 메뉴 확장이 아니라는 점에 대해. ↩ ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 ↩8

  8. Microsoft Learn, Grant package identity by packaging with external location. 기존 설치 프로그램을 바꾸지 않고 외부 위치 패키지(sparse package)를 등록해 패키지 ID를 얻을 수 있다는 점, Windows 10 버전 2004 이후에서 이용 가능하다는 점, ID가 필수인 Windows 기능(컨텍스트 메뉴 등록·알림 등)을 쓸 수 있게 된다는 점에 대해. ↩ ↩2 ↩3

  9. Microsoft Learn, Choosing a Static or Dynamic Shortcut Menu Method. 요구 사항을 충족하는 가장 단순한 정적 verb 방식을 골라야 한다는 점, IContextMenu가 가장 강력하지만 가장 복잡하고 비권장 쪽으로 분류된다는 점, IExplorerCommand/IExplorerCommandState가 권장되는 방식이라는 점에 대해. ↩ ↩2

  10. Microsoft Learn, SHChangeNotify function. 파일 연결 변경을 시스템에 알리는 SHCNE_ASSOCCHANGED 이벤트의 발행 방법과, 셸이 변경을 인식하게 하기 위한 쓰임에 대해. ↩ ↩2

  11. Microsoft Learn, Application Registration. App Paths 하위 키에 의한 실행 파일 등록이 권장된다는 점, Applications 하위 키의 역할, SystemFileAssociations에 의한 verb 등록, 기본 앱 변경 때 ProgID와 관련 정보의 우선순위에 대해. ↩

  12. Microsoft Learn, Creating Shortcut Menu Handlers. 정적 verb의 등록 방법, 기본 verb의 결정 순서(기본값→첫 verb→Open→Open With), 표준 verb의 표시 이름이 OS에 의해 공급된다는 점, Extended에 의한 확장 verb, DDE 명령과의 연결이 비권장(Deprecated)이라는 점, 64비트 환경에서의 WOW64 리다이렉트 주의에 대해. ↩ ↩2 ↩3

  13. Microsoft Learn, Verbs and File Associations. verb가 ShellExecuteEx에서도 쓰이는 동사라는 점, 명령 문자열에서 공백을 포함할 수 있는 요소는 따옴표로 감싸야 하며 “%1”을 항상 따옴표와 함께 써야 한다는 점, HKCR\Applications 아래로의 기본 절차 등록에 대해. ↩

  14. Microsoft Learn, IExplorerCommand interface. GetTitle·GetIcon·GetState·Invoke·EnumSubCommands 등의 메서드 구성, 메서드가 UI 스레드에서 호출되므로 네트워크 자원과 통신해서는 안 된다는 점, Windows Vista 이후에서 이용 가능하다는 점에 대해. ↩

  15. Microsoft Learn, Windows Sandbox. 일회용의 격리된 Windows 환경을 수 초 만에 실행할 수 있고, 닫으면 모든 변경이 버려진다는 점, 소프트웨어 테스트나 설치 프로그램 검증에 맞다는 점, Pro/Enterprise/Education에서 이용할 수 있다는 점에 대해. ↩

같은 태그를 공유하는 최신 기사입니다. 더 가까운 주제로 지식을 넓힐 수 있습니다.

이 기사와 가까운 토픽 페이지입니다. 기사를 출발점 삼아 관련 서비스와 다른 기사로 이어집니다.

ActiveX 이관

COM / ActiveX / OCX 자산을 유지할지, 감쌀지, 교체할지의 단계적 판단을 정리한 토픽 페이지입니다.

이 기사는 다음 서비스 페이지로 이어집니다. 가까운 입구부터 확인해 주세요.

자주 묻는 질문

이 기사 주제에 대해 상담 시 자주 나오는 질문을 모았습니다.

Windows 11에서 자사 앱의 컨텍스트 메뉴가 「더 많은 옵션 표시」 안에만 나오는 이유는 무엇인가요?
Windows 11에서 파일 탐색기의 컨텍스트 메뉴가 새 메뉴와 기존 메뉴의 두 계층으로 나뉘었기 때문입니다. 새 메뉴에 항목을 올릴 수 있는 것은 IExplorerCommand 인터페이스를 구현하고 MSIX 패키지 매니페스트로 등록한(=패키지 ID를 가진) 명령뿐이며, 기존형 IContextMenu 기반 셸 확장은 「더 많은 옵션 표시」(Shift+F10)로 여는 기존 메뉴 쪽으로 옮겨졌습니다. 확장 자체가 고장난 것은 아니므로 당분간은 그대로 동작하지만, 새 메뉴에 올리려면 IExplorerCommand로 이전하고 MSIX화 또는 sparse package로 ID를 부여해야 합니다.
설치 프로그램에서 자사 앱을 파일의 기본 앱(더블클릭으로 여는 앱)으로 설정할 수 있나요?
할 수 없습니다. 기본 앱 선택은 사용자가 하도록 설계되어 있으며, Windows는 시스템 설정 UI 이외의 경로에서 기본 앱을 바꾸는 것을 지원하지 않습니다. 사용자별 선택을 보관하는 UserChoice 정보는 난독화되어 있고, 필터 드라이버(UCPD.sys)가 앱의 쓰기도 막습니다. 설치 프로그램이 할 수 있는 일은 ProgID와 verb를 등록하고, OpenWithProgIds에 자신을 추가해 「연결 프로그램」 후보에 올리며, 사용자를 기본 앱 설정 화면으로 안내하는 것까지입니다. 올바른 구현은 기본값을 가로채는 것이 아니라, 선택받을 준비를 갖추는 것입니다.
셸 확장을 C# 같은 관리 코드로 작성해도 되나요?
in-process로 로드되는 셸 확장(컨텍스트 메뉴 핸들러나 아이콘 핸들러 등)을 관리 코드로 작성하는 것은, Microsoft가 비권장이며 지원 대상 외라고 분명히 말합니다. 확장은 파일 탐색기나 공용 파일 대화 상자를 여는 임의 앱의 프로세스에 로드되므로, CLR 버전 충돌이나 재진입, 객체 수명의 비결정성이 호스트 앱을 불안정하게 만들기 때문입니다. 구현은 네이티브 C++이 원칙입니다. 한편 verb의 command로 실행되는 일반 EXE나, 별도 프로세스에서 동작하는 미리 보기 핸들러 같은 out-of-process 확장이라면 관리 코드여도 문제 없습니다.
sparse package(외부 위치 MSIX)란 무엇인가요?
앱 본체의 파일은 넣지 않고 매니페스트(ID 정보)만 가진 작은 MSIX 패키지입니다. 기존 설치 프로그램(MSI, Inno Setup 등)으로 보통처럼 설치한 앱에 Add-AppxPackage의 -ExternalLocation으로 설치 폴더를 가리켜 등록하면, 그 앱은 패키지 ID를 얻고 Windows 11의 새 컨텍스트 메뉴 등록이나 토스트 알림처럼 ID가 필수인 기능을 쓸 수 있게 됩니다. Windows 10 버전 2004 이후에서 이용할 수 있으며, 패키지에는 대상 컴퓨터에서 신뢰되는 코드 서명이 필요합니다. 배포 방식을 MSIX로 전면 이전하지 않고 새 메뉴에 대응하고 싶을 때의 현실적인 선택입니다.
컨텍스트 메뉴 항목이 두 번 나오거나, 사라지지 않으면 어떻게 하면 되나요?
먼저 원인 분리로, 새 메뉴와 기존 메뉴(더 많은 옵션 표시) 중 어디에 나오는지 확인합니다. 이중 표시는 기존 방식의 레지스트리 등록과 MSIX 매니페스트 등록이 함께 있거나, 제거 시 ProgID나 확장 기능의 CLSID 등록이 정리되지 않고 남은 경우가 전형적입니다. 파일 연결을 바꾼 뒤에는 SHChangeNotify(SHCNE_ASSOCCHANGED) 알림 누락, 패키지 등록 직후에는 파일 탐색기 다시 시작 누락도 의심하십시오. 그래도 해결되지 않으면 ShellExView에서 Microsoft 이외의 확장을 잠시 끄고 이진 탐색하면 원인 DLL을 특정할 수 있습니다.

저자 프로필

기사 저자의 프로필 페이지입니다.

Go Komura

합동회사 코무라소프트 대표

Windows 소프트웨어 개발, 기술 상담, 장애 조사를 중심으로 재현이 어려운 장애 조사와 기존 자산이 남아 있는 프로젝트에 강점이 있습니다.

블로그 목록으로 돌아가기