אינטגרציית מעטפת Windows היום ── תפריטי הקשר, שיוכי קבצים ומה שהשתנה ב-Windows 11

· · Windows, הרחבות מעטפת, תפריט הקשר, שיוך קבצים, COM, Windows 11, סייר הקבצים, MSIX, פיתוח Windows

התייעצו איתי ש«החלפנו את המחשבים ל-Windows 11, ותפריט ההקשר של האפליקציה שבניתם לנו לפני שנים נעלם». בהקשבה מדויקת יותר, הוא לא נעלם. לוחצים לחיצה ימנית על קובץ, בוחרים “הצג אפשרויות נוספות” בתחתית התפריט, והתפריט המוכר מופיע בדיוק כמו תמיד. כלומר פריטי התפריט של האפליקציה הפנימית הוסתרו לחיצה אחת פנימה. מהשטח שומעים «לחיצה אחת נוספת» ו«פניות על כך שלא מוצאים את הפריט התרבו».

זו לא תקלה ולא טעות הגדרה; זה שינוי עיצוב של Windows 11. תפריט ההקשר של סייר הקבצים הפך למבנה דו-שכבתי, ישן וחדש, והתנאים להעלאת פריט לתפריט החדש הפכו לדבר שונה לגמרי ממה שהיה.

בינתיים מנגנון שיוך הקבצים והרחבת המעטפת מתחתיו עדיין עולם COM והרישום הישן. מפתח סיומת מצביע על ProgID, הפועל של ה-ProgID מחזיק שורת פקודה, והרחבה מורכבת יותר רצה כשרת COM בתוך-תהליך (DLL) שנטען לסייר — המבנה הזה לא השתנה יותר מעשרים שנה. אם לא מכירים גם את היסוד שלא השתנה וגם את התפריט ש-Windows 11 פיצלה לשניים, אי אפשר לבודד «התפריט לא מופיע», «הוסתר» או «מופיע פעמיים».

המאמר מיועד לאנשי IT בחברות קטנות ובינוניות ולמפתחי Windows שמטפלים באפליקציות עסקיות. הוא קושר בתמונה אחת את המבנה התלת-שכבתי של שיוך קבצים, אזהרות הרחבות מעטפת קלאסיות, איך לכוון לתפריט ההקשר החדש של Windows 11, ורישום המתקין, ניקוי ופתרון תקלות.

1. השורה התחתונה קודם

  • היסוד של תפריט ההקשר ושל שיוך הקבצים הוא מבנה הרישום התלת-שכבתי «מפתח סיומת → ProgID → פועל». מפתח הסיומת הוא מצביע ל-ProgID, ה-ProgID הוא המהות, ו-shell\<verb>\command תחתיו מחזיק את שורת הפקודה.1
  • HKEY_CLASSES_ROOT (HKCR) אינה כוורת עצמאית; היא תצוגה ממוזגת של HKLM\Software\Classes ו-HKCU\Software\Classes. כותבים רישום לכל המשתמשים ל-HKLM ורישום לפי משתמש ל-HKCU, ומתייחסים ל-HKCR כקריאה בלבד.2
  • אפליקציית ברירת המחדל (זו שנפתחת בלחיצה כפולה) מתוכננת להיבחר בידי המשתמש, ותוכנית לא יכולה לגנוב אותה. מערכת ההפעלה מגנה על בחירת המשתמש; מה שמתקין יכול לעשות הוא להירשם כמועמד.3
  • הרחבת מעטפת קלאסית היא DLL COM בתוך-תהליך שנטען לסייר. קריסה או השהיה בהרחבה מתפשטות לסייר כולו (ולאפליקציות אחרות שמשתמשות במעטפת); סביבת 64 סיביות דורשת DLL של 64 סיביות; ומימוש בקוד מנוהל אינו נתמך.45
  • ב-Windows 11 תפריט ההקשר התפצל לשניים. הפקודות היחידות שמופיעות בתפריט החדש הן אלה שנרשמו עם IExplorerCommand ועם זהות חבילה; הרחבות IContextMenu קלאסיות מועברות לתפריט הישן תחת «הצג אפשרויות נוספות» (Shift+F10).67
  • הנתיב הרשמי להעלאת פקודה מותאמת לתפריט החדש הוא לרשום DLL מקורי שמממש IExplorerCommand במניפסט MSIX (desktop4:FileExplorerContextMenus). אפליקציה שאינה יכולה להפוך ל-MSIX יכולה לקבל זהות בלבד עם חבילה דלילה (MSIX עם מיקום חיצוני).78
  • אם כל מה שרוצים הוא «לפתוח עם האפליקציה הזו», שיוך ופועל סטטי עדיין מספיקים. אין צורך ב-DLL של הרחבת מעטפת, ומיקרוסופט עצמה כותבת במפורש «בחרו בשיטה הפשוטה ביותר שעומדת בדרישות (פועל סטטי)».9
  • אחרי רישום או שינוי מודיעים ב-SHChangeNotify(SHCNE_ASSOCCHANGED); בהסרת התקנה מוחקים את ה-ProgID אך לא מוחקים את ערך ברירת המחדל של מפתח הסיומת — זה המדריך הרשמי. אינטגרציית מעטפת כוללת גם את עיצוב הניקוי.110

במשפט אחד: עולם השיוכים והפעלים לא השתנה; רק אופן הצגת התפריט התפצל לשניים ב-Windows 11. להלן עולים מהיסוד.

2. איך פועל שיוך קבצים ── המבנה התלת-שכבתי מפתח סיומת → ProgID → פועל

2.1. קריאת המבנה התלת-שכבתי מתוך דוגמה אחת

מה שקורה בלחיצה כפולה על קובץ בסיומת נתונה נקבע בשלוש שכבות של מפתחות רישום.1

HKEY_CLASSES_ROOT
   .kmrpt                                  ← (1) מפתח הסיומת
      (Default) = KomuraSoft.Report.1      ←     מצביע שרק נותן שם ל-ProgID
      OpenWithProgids
         KomuraSoft.Report.1               ←     מועמד תחת «פתיחה באמצעות»
   KomuraSoft.Report.1                     ← (2) ProgID (מהות השיוך)
      (Default) = Komura Report document
      DefaultIcon
         (Default) = "C:\Program Files\KomuraSoft\Report.exe",0
      shell                                ← (3) רשימת פעלים
         open
            command
               (Default) = "C:\Program Files\KomuraSoft\Report.exe" "%1"
  • (1) מפתח הסיומת (.kmrpt) מצביע רק על שם ProgID כערך ברירת המחדל שלו. כתיבת פקודה כאן ישירות היא טעות.
  • (2) ה-ProgID (KomuraSoft.Report.1) הוא מהות השיוך; הוא מחזיק את שם התצוגה, הסמל ורשימת הפעלים.
  • (3) פועל הוא פעולה כמו «פתיחה» או «הדפסה», וערך ברירת המחדל של shell\open\command הוא שורת הפקודה שמופעלת בפועל.

ההפרדה הזו היא הסיבה שאפשר להצביע כמה סיומות (למשל .kmrpt ו-.kmrpt-file) לאותו ProgID, או להחליף את ה-ProgID בשדרוג האפליקציה.

המבנה התלת-שכבתי של שיוך קבציםמפתח הסיומת הוא מצביע שערך ברירת המחדל שלו נותן שם ל-ProgID; ה-ProgID הוא המהות שמחזיקה שם תצוגה, סמל ורשימת פעלים; וערך ברירת המחדל של command תחת הפועל הוא שורת הפקודה שמופעלת בפועלנותן שם ל-ProgID כברירת מחדלמפתח סיומת .kmrptProgID KomuraSoft.Report.1פועל (open ואחרים תחת shell)ערך ברירת המחדל של commandReport.exe מופעלמחזיק גם שם תצוגה ו-DefaultIcon

איור 1: מפתח הסיומת הוא מצביע, ה-ProgID הוא המהות, ו-command של הפועל הוא שורת הפקודה שמופעלת בפועל.

2.2. HKCR היא «תצוגה ממוזגת» ── לאן כותבים משנה את המשמעות

הדוגמה למעלה מוצגת תחת HKEY_CLASSES_ROOT (HKCR), אבל HKCR אינה מיקום אחסון פיזי; היא תצוגה ממוזגת של HKLM\Software\Classes ו-HKCU\Software\Classes. אם אותו מפתח קיים בשניהם, צד HKCU מנצח.2

HKCR היא תצוגה ממוזגתHKCR היא Classes של HKLM ושל HKCU מונחות זו על זו; אם אותו מפתח קיים בשניהם HKCU מנצחת; כותבים רישום ל-HKLM או ל-HKCU במפורש ומתייחסים ל-HKCR כקריאה בלבדHKLM\\Software\\Classes (כל המשתמשים)HKCR (תצוגה ממוזגת)HKCU\\Software\\Classes (לפי משתמש)אם אותו מפתח קיים, HKCU מנצחתמתייחסים אליה כקריאה בלבד (לאישור)

איור 2: HKCR היא איך נראות Classes של HKLM ושל HKCU יחד; תמיד מציינים אחד מהם כיעד כתיבה.

יעד כתיבה משמעות הרשאות נדרשות
HKLM\Software\Classes רישום משותף לכל המשתמשים מנהל
HKCU\Software\Classes רישום למשתמש הזה בלבד אין
כתיבה ישירה ל-HKCR מנותבת לפי היכן כבר חי המפתח הקיים תלוי

בפועל, הפיצול הבטוח הוא תמיד לכתוב רישום ל-HKLM או ל-HKCU במפורש, ולהתייחס ל-HKCR כקריאה בלבד (לאישור). גם היחס להפניית רישום WOW64 ראוי לסידור. נתוני שיוך ישירות תחת HKLM\Software\Classes כמו מפתחות סיומת ו-ProgID משותפים בין תצוגות הרישום 32 סיביות ו-64 סיביות מאז Windows 7, כך שמתקין 32 סיביות שכותב אותם אינו בורח לצד Wow6432Node. חלק ממפתחות-המשנה של רישום COM כמו Classes\CLSID, לעומת זאת, מופנים, וכשרושמים הרחבת מעטפת (COM בתוך-תהליך) פיצול הכתיבה 32 / 64 סיביות חשוב. פרטים ב-“Registry 32-bit/64-bit Redirection and Virtualization Pitfalls — Wow6432Node and the "The Value I Wrote Isn’t There" Problem”.

2.3. רישום מצד האפליקציה ── App Paths, Applications, RegisteredApplications

יש גם שלושה סוגי רישום מצד האפליקציה, שמתאימים לצד הקובץ (סיומת ו-ProgID).11

  • App Paths (HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths): רישום שמאפשר ל-ShellExecuteEx להפעיל לפי שם קובץ ההפעלה בלבד. מיקרוסופט ממליצה על כך כי אין צורך לזהם את משתנה הסביבה PATH.
  • Applications (HKCR\Applications\<app.exe>): מגדיר את דרך הפתיחה כברירת מחדל כשמוסרים קובץ שרירותי תחת «פתיחה באמצעות», ואת שם התצוגה של האפליקציה (FriendlyAppName).
  • RegisteredApplications + Capabilities: מכריז על הסיומות וסוגי MIME שהאפליקציה יכולה לטפל בהם, והוא הרישום שגורם לה להופיע כמועמדת בדף הגדרות אפליקציות ברירת המחדל של Windows.

רוב הייעוצים מסוג «האפליקציה שלנו לא מופיעה ברשימת אפליקציות ברירת המחדל» הם מקרים שבהם נרשם ה-ProgID והושמט רישום Capabilities הזה.

שלושת סוגי הרישום מצד האפליקציהרישום מצד האפליקציה יש לו שלושה סוגים ── App Paths, Applications ו-RegisteredApplications ── האחראים בהתאמה להפעלה לפי שם קובץ בלבד, לדרך הפתיחה כברירת מחדל תחת פתיחה באמצעות, ולהופעה בדף אפליקציות ברירת המחדלרישום מצד האפליקציהApp PathsApplicationsRegisteredApplicationsהפעלה לפי שם קובץ בלבדברירת מחדל תחת פתיחה באמצעותמופיע בדף אפליקציות ברירת המחדלנדרשת הכרזת Capabilities

איור 3: יש שלושה סוגי רישום מצד האפליקציה, והופעה כמועמדת לאפליקציות ברירת מחדל דורשת רישום Capabilities.

2.4. אפליקציית ברירת המחדל שייכת למשתמש ── הגנת UserChoice

כתיבת ProgID כערך ברירת המחדל של מפתח הסיומת אינה הופכת אותו לבדה לאפליקציית ברירת המחדל. תוצאת בחירה מפורשת של המשתמש תחת «פתיחה באמצעות» וכדומה נשמרת ב-HKCU\...\Explorer\FileExts\<extension>\UserChoice, ופתרון השיוך מעדיף את הצד ההוא.

והנקודה החשובה היא שWindows אינה תומכת בשינוי תכנותי של אפליקציית ברירת המחדל. הגדרות אפליקציית ברירת המחדל מתוכננות להיעשות בידי המשתמש דרך ממשק ההגדרות של המערכת; נתוני UserChoice מעורפלים, ומנהל התקן סינון (UCPD.sys) חוסם כתיבה מאפליקציות. בסביבה מנוהלת, מדיניות קבוצתית / MDM היא האמצעי הרשמי.3

זה שכלים כמו SetUserFTA, ש«מחקים את הגיבוב וכותבים מחדש», היו בשימוש הוא הצד השני של ההגנה הזו. מה שצריך לשים במתקין של אפליקציה פנימית אינו גניבת ברירת המחדל, אלא השלושה (א) רישום נכון של ה-ProgID והפעלים, (ב) הוספת עצמכם ל-OpenWithProgIds, ו-(ג) במידת הצורך, הפניה לדף ההגדרות.

פתרון אפליקציית ברירת מחדל והגנת UserChoiceתוצאת בחירה מפורשת של המשתמש נשמרת ב-UserChoice ומועדפת בפתרון השיוך; UCPD.sys חוסם כתיבה מחדש מאפליקציות, ולכן מה שמתקין יכול לעשות הוא להירשם כמועמד ולהפנות לדף ההגדרותמועדףUCPD.sys חוסםUserChoice (בחירת המשתמש)פתרון שיוךערך ברירת המחדל של מפתח הסיומתכתיבה מחדש מאפליקציהעבודת המתקיןרישום ה-ProgID והפעליםהוספה ל-OpenWithProgIdsהפניה לדף ההגדרות

איור 4: פתרון השיוך מעדיף את בחירת המשתמש (UserChoice), ומערכת ההפעלה מגנה עליה מכתיבה מחדש של אפליקציות.

3. פעלים שאינם «פתיחה» ── print, edit, runas ופעלים מותאמים

פועל אינו רק open. פעלים תקניים שמערכת ההפעלה מכירה את משמעותם כוללים גם edit, print, play ו-preview מלבד open, ופועל תקני מקבל אוטומטית שם תצוגה שעוקב אחרי אזור מערכת ההפעלה. הפועל כברירת מחדל בלחיצה כפולה נקבע בסדר: ערך ברירת המחדל של מפתח shell → הפועל הראשון ברישום → openopenwith.12

הסדר שבו נקבע הפועל כברירת מחדלהפועל כברירת מחדל בלחיצה כפולה הוא הראשון שנמצא בסדר ערך ברירת המחדל של מפתח shell, הפועל הראשון ברישום, open, openwithאם איןאם איןאם איןערך ברירת המחדל של מפתח shellהפועל הראשון ברישוםopenopenwith

איור 5: הפועל כברירת מחדל בלחיצה כפולה הוא הראשון שנמצא בסדר הזה.

כשרוצים להוסיף פעולה משלכם, רושמים פועל מותאם.

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                          ← פועל מותאם
         (Default) = Verify report (&V)   ← שם תצוגה בתפריט
         command
            (Default) = "C:\Program Files\KomuraSoft\Report.exe" /verify "%1"

שלוש עובדות קטנות שכדאי לדעת.

  • רושמים פועל בשם runas ומגדירים הפעלה מוגבהת השקולה ל-«הרצה כמנהל», והוא משמש גם כשממשק ממשפחת ShellExecute מציין runas.
  • שמים ערך ריק בשם Extended על מפתח הפועל והוא הופך לפועל מורחב שמוצג רק ב-Shift+לחיצה ימנית. נוח להסתרת פעולה מסוכנת שנדיר להשתמש בה.12
  • לחלק משיוכי אפליקציות ישנות עדיין יש תצורה ששולחת מסמך לתהליך קיים עם DDE (מפתח ddeexec), אבל הפעלת פועל דרך DDE היא כבר מורשת Deprecated. אין סיבה לכתוב אותה מחדש.12

תאונה נוספת שקורה הרבה היא ציטוט בשורת הפקודה. אם רכיב במחרוזת הפקודה יכול להכיל רווח, חייבים לעטוף אותו במירכאות. זה חל כמובן על נתיב EXE כמו C:\Program Files\..., ו%1 (נתיב הקובץ שנבחר) צריך תמיד להיכתב "%1". אי אפשר להבטיח שנתיב קובץ של משתמש אינו מכיל רווח. My Program.exe בלי מירכאות מתפרש כ-«הפעל את My עם הארגומנט Program.exe».13

תאונת הציטוט בשורת הפקודהפקודה בלי מירכאות נחתכת ברווח ומתפרשת בטעות כהפעלת My עם הארגומנט Program.exe, ולכן נתיב EXE שיכול להכיל רווח ו-%1 שמייצג את נתיב הקובץ שנבחר צריכים תמיד להיות עטופים במירכאותנחתכת ברווחפקודה בלי מירכאותמתפרשת בטעות כהפעלת EXE אחרפקודה במירכאותמופעלת כמתוכנןעוטפים את נתיב ה-EXE במירכאותעוטפים גם את %1 תמיד במירכאות

איור 6: פקודה בלי מירכאות נחתכת בטעות ברווח, לכן תמיד עוטפים את נתיב ה-EXE ואת %1 במירכאות.

מנגנון הרישום בלבד עד כאן (פועל סטטי) אפשר לממש בלי לכתוב אפילו DLL אחד, והוא אינו מסכן את יציבות הסייר. מיקרוסופט עצמה חוזרת ואומרת «לפני שכותבים הרחבת מעטפת, שקלו אם הפועל הסטטי הפשוט ביותר שעומד בדרישות יספיק».9

4. הרחבות מעטפת קלאסיות ── DLL שרץ בתוך הסייר

4.1. סוגי הרחבת מעטפת

דרישות שפועל סטטי אינו יכול למלא — «שנו את התפריט דינמית לפי הבחירה», «החליפו את הסמל או גיליון המאפיינים» — משתמשות במטפל הרחבת מעטפת. סוגים מייצגים להלן.4

מטפל ממשק עיקרי מה הוא יכול לעשות
מטפל תפריט הקשר IContextMenu + IShellExtInit הוספה ושליטה דינמית בפריטי תפריט
מטפל סמל / שכבת-על של סמל IExtractIcon / IShellIconOverlayIdentifier סמל לכל קובץ ושכבת-על
מטפל גיליון מאפיינים IShellPropSheetExt הוספת לשונית לגיליון המאפיינים
תמונה ממוזערת / infotip IThumbnailProvider / IQueryInfo תצוגת תמונה ממוזערת ותיאור ריחוף
גרירה ושחרור / מטפל וו העתקה IDropTarget / ICopyHook התערבות בשחרור או בהעתקה/העברה

כל אלה ממומשים כמחלקות COM ונרשמים ברישום לפי CLSID. רעיון COM עצמו מכוסה ב-“מה זה COM /‏ ActiveX /‏ OCX — הסבר מרוכז על ההבדלים והקשרים”.

4.2. מה פירוש להיות שרת COM בתוך-תהליך

מהות הרחבת מעטפת קלאסית היא שזו שרת COM בתוך-תהליך (DLL) שנטען לסייר (או לכל אפליקציה שפתחה דיאלוג קבצים משותף). כל אזהרה נובעת מכך.4

  • אם ההרחבה קורסת, הסייר נופל איתה. אם היא נתקעת, לחיצה ימנית קופאת כמה שניות. הנזק גם אינו מוגבל לסייר; הוא מגיע לכל אפליקציה שהציגה דיאלוג פתיחת קובץ.
  • בניית התפריט מתרחשת בשרשור ממשק המשתמש, לכן אסור לעשות עבודה איטית כמו גישה לרשת או קלט/פלט קבצים בזמן הצגת התפריט.
  • רושמים את מודל השרשורים כ-Apartment ככלל.
מבנה הנזק הנלווה של הרחבה בתוך-תהליךDLL של הרחבת מעטפת נטען לא רק לסייר אלא גם לתהליך של כל אפליקציה שפתחה דיאלוג קבצים, ולכן קריסה או תקיעה בהרחבה מתפשטות לכל התהליך המארחנטען בתוך-תהליךנטען בתוך-תהליךDLL הרחבת מעטפתהסיירכל אפליקציה שפותחת דיאלוגקריסה או תקיעה מתפשטותלא עושים עבודה איטית בזמן הצגה

איור 7: ה-DLL של ההרחבה רץ בתוך התהליך המארח, ולכן קריסה או תקיעה מתפשטות למארח כולו.

חוקרים ייעוץ כמו «הסייר קופא כשאני פותח תיקייה מסוימת» או «לחיצה ימנית לוקחת חמש שניות» ולא נדיר שהסיבה היא הרחבת מעטפת של צד שלישי ולא האפליקציה הפנימית. שיטות בידוד בפרק 8.

4.3. התאמת רוחב הסיביות ── סביבת 64 סיביות דורשת DLL של 64 סיביות

DLL בתוך-תהליך חייב להתאים לרוחב הסיביות של התהליך שטוען אותו. הסייר ב-Windows 64 סיביות הוא תהליך 64 סיביות, לכן DLL הרחבת מעטפת שנבנה רק כ-32 סיביות לעולם אינו נטען ולעולם אינו מופיע בתפריט. וגם אין שגיאה, ולכן זו סיבה קבועה ל-«רשמתי אבל זה לא מופיע». שילוב גוף אפליקציה 32 סיביות עם DLL הרחבת מעטפת 64 סיביות הוא תצורה לגיטימית, אבל צריך לשים לב שרישום COM מתפצל לפי רוחב סיביות (Wow6432Node). הפעלה מ-command של פועל היא EXE בתהליך נפרד, ולכן אינה כפופה למגבלה הזו (להשאיר אותו EXE 32 סיביות זה בסדר).

התאמת רוחב הסיביות של DLL הרחבת מעטפתDLL הרחבת המעטפת היחיד שסייר 64 סיביות יכול לטעון הוא בן 64 סיביות; DLL של 32 סיביות בלבד אינו מופיע בתפריט ואינו מייצר שגיאה; EXE שמופעל מפקודת פועל הוא תהליך נפרד ואינו כפוף למגבלהיכול לטעוןלא יכול לטעוןתהליך נפרדסייר 64 סיביותDLL הרחבת מעטפת 64 סיביותDLL של 32 סיביות בלבדלא מופיע בתפריט, בלי שגיאהEXE שמופעל מפועלבסדר להשאיר 32 סיביות

איור 8: ה-DLL היחיד שנטען לסייר 64 סיביות הוא DLL של 64 סיביות; EXE שמופעל מפועל אינו כפוף למגבלה הזו.

4.4. מדוע אסור לכתוב זאת בקוד מנוהל

אני מקבל לעיתים קרובות את השאלה «אפשר לכתוב הרחבת מעטפת ב-C#», אבל מיקרוסופט קבעה במפורש שכתיבת הרחבת מעטפת בתוך-תהליך בקוד מנוהל (.NET) אינה מומלצת ומחוץ לתמיכה.5

הסיבה היא טבע ההרחבה שנטענת לתהליך שרירותי. התנגשויות גרסת CLR (במיוחד מתחת ל-.NET Framework 4), בעיית הכניסה החוזרת של ה-CLR ללולאת ההודעות בזמן המתנה על נעילה, וחיי אובייקט לא-דטרמיניסטיים מאיסוף זבל שמתנגשים בחוזה ספירת ההפניות של COM הם סיבות מבניות לכך שאפליקציית המארח הופכת ללא יציבה. חלק מהסעיפים הוקלו ב-.NET Framework 4 ואילך וב-.NET מודרני, אבל העמדה הרשמית לא השתנתה.

הקו המעשי פשוט. כותבים הרחבה בתוך-תהליך ב-C++ מקורי. אם רוצים קוד מנוהל, עושים ממנו EXE רגיל שמופעל מפקודת הפועל, או הרחבה מחוץ-לתהליך שרצה בתהליך נפרד (מטפל תצוגה מקדימה וכדומה).5

שיפוט האם קוד מנוהל מותרהרחבה בתוך-תהליך שרצה בתוך הסייר נכתבת ב-C++ מקורי ככלל; אם רוצים קוד מנוהל עושים ממנו EXE רגיל שמופעל מפקודת פועל או הרחבה מחוץ-לתהליך שרצה בתהליך נפרדכןלארץ בתוך-תהליך?כותבים ב-C++ מקוריקוד מנוהל בסדרסיכון CLR / כניסה חוזרת הופך את המארח ללא יציבEXE שמופעל מפועלתצוגה מקדימה מחוץ-לתהליך

איור 9: הרחבה בתוך-תהליך היא C++ מקורי ככלל; קוד מנוהל מוגבל לתצורה שרצה בתהליך נפרד.

5. תפריט ההקשר החדש של Windows 11 ── התפריט שהתפצל לשניים

5.1. מה קרה

Windows 11 ריעננה את תפריט ההקשר של סייר הקבצים. גזירה, העתקה וכדומה הפכו לשורת סמלים למעלה; «פתיחה» ו-«פתיחה באמצעות» קובצו יחד למעלה; ופקודות שאפליקציה מוסיפה מקובצות מתחת לפקודות התקניות של המעטפת. כשאפליקציה אחת מוסיפה כמה פקודות, הן נאספות לתפריט נפתח (תת-תפריט) בשם האפליקציה.6

והנקודה המכרעת היא זו. הרחבות מעטפת קלאסיות מבוססות IContextMenu לא נמחקו; הן הועברו לצד התפריט הישן שנפתח ב-«הצג אפשרויות נוספות» (Shift+F10) וטוען את תפריט Windows 10 כפי שהוא.6 זהות ייעוץ הפתיחה «התפריט הוסתר» היא הפיצול הזה.

תפריט ההקשר ש-Windows 11 פיצלה לשנייםמה שנפתח ראשון בלחיצה ימנית הוא התפריט החדש; הפקודות היחידות שמופיעות שם הן אלה שנרשמו עם IExplorerCommand וזהות חבילה; הרחבות IContextMenu קלאסיות מועברות לתפריט הישן שנפתח בהצג אפשרויות נוספותהצג אפשרויות נוספות Shift+F10לחיצה ימנית על קובץהתפריט החדש (Windows 11)פקודות IExplorerCommand + זהותהתפריט הישן (תפריט Windows 10)הרחבות IContextMenu קלאסיותכמה פקודות נאספות לתפריט נפתח

איור 10: הפקודות היחידות שמופיעות בתפריט החדש הן פקודות IExplorerCommand + זהות; הרחבות קלאסיות מועברות לצד התפריט הישן.

5.2. הנתיב הרשמי לתפריט החדש ── IExplorerCommand + רישום מניפסט

יש דרך אחת להעלות פקודה מותאמת לתפריט החדש. מכינים DLL מקורי שמממש את ממשק IExplorerCommand, ומכריזים על שרת COM ועל הרחבת תפריט ההקשר במניפסט חבילת MSIX.7

<!-- Package manifest (excerpt) -->
<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>

Type של ItemType יכול לציין סיומת מסוימת, או * (כל הקבצים), Directory (תיקיות), או Directory\Background (רקע תיקייה). מתאימים את ה-DLL לארכיטקטורת הסייר (64 סיביות / ARM64).7

IExplorerCommand עצמו הוא ממשק שקיים מאז עידן Windows 7; מממשים כותרת (GetTitle), סמל (GetIcon), מצב מופעל / מושבת / מוסתר (GetState) והפעלה (Invoke). המתודות נקראות משרשור ממשק המשתמש, לכן גישה למשאבי רשת אסורה, ומתודות בניית תפריט צריכות לחזור במהירות. עבודה כבדה אחרי Invoke.147

מבנה המניפסט של רישום התפריט החדשהכרזת שרת COM במניפסט MSIX ממפה CLSID ל-DLL, והכרזת הרחבת תפריט הקשר קושרת את היעד והמימוש עם ItemType ו-Verb, כך שפקודה מותאמת מופיעה בתפריט החדשממפה CLSID ל-DLLמציין עם ItemType ו-Verbמניפסט MSIXהכרזת שרת COMהכרזת הרחבת תפריטDLL מימוש IExplorerCommandהפקודה מופיעה בתפריט החדשהיעד הוא סיומת, כל הקבצים וכדומה

איור 11: שתי הכרזות במניפסט קושרות את DLL המימוש ליעד, והפקודה מופיעה בתפריט החדש.

5.3. האפשרות לאפליקציה לא-ארוזה ── קבלת זהות בלבד עם חבילה דלילה

פתח המילוט כש«האפליקציה שלנו לא יכולה להיות מופצת אלא כ-MSI; MSIX בלתי אפשרי» הוא חבילה דלילה (MSIX עם מיקום חיצוני). חותמים MSIX קטן שהוא מניפסט בלבד, בלי גוף אפליקציה, ורושמים אותו בסוף המתקין הקיים. האפליקציה רוכשת אז זהות חבילה, ורישום המניפסט למעלה (= הופעה בתפריט החדש) הופך לאפשרי. זמינה מ-Windows 10 גרסה 2004 ואילך, והחבילה זקוקה לחתימה בתעודה מהימנה במחשב היעד.8

זרימת קבלת זהות עם חבילה דלילהאחרי שהמתקין הקיים מניח את גוף האפליקציה, רישום חבילה דלילה של מניפסט בלבד עם מיקום חיצוני נותן לאפליקציה זהות חבילה ומאפשר רישום מניפסט לתפריט החדשמתקין קייםהנחת גוף האפליקציהחבילה דלילהמניפסט בלבד, בלי גוףרישום עם מיקום חיצונירכישת זהות חבילהרישום לתפריט החדש הופך לאפשרינדרשת חתימה מהימנה

איור 12: רושמים חבילה דלילה שאינה מכילה גוף, עם מיקום חיצוני, והאפליקציה רוכשת זהות חבילה.

היתרון הגדול ביותר הוא שאין צורך להחליף את המתקין; זו התשובה המציאותית לאפליקציה שכבר יש לה נכס מתקין MSI/EXE. להשוואה עם מעבר מלא ל-MSIX ראו גם “איך בוחרים שיטת הפצה ליישום Windows - MSI/‏MSIX/‏ClickOnce/‏xcopy/עדכון עצמי”.

5.4. איך פעלי שיוך מופיעים בתפריט החדש

נקודה שקל לטעות בה: השיוכים של פרקים 2 ו-3 (ProgID ופועל) עדיין חיים בתפריט החדש. הפועל כברירת מחדל בלחיצה כפולה, «פתיחה», ומועמדי «פתיחה באמצעות» נפתרים מהשיוך ומוצגים בראש התפריט החדש. לכן אם כל מה שרוצים הוא «להיות מסוגלים לפתוח עם האפליקציה הזו», Windows 11 אינו דורש עבודה נוספת. מצד שני, שיוך אינו הרחבת תפריט כלל-תכליתית, ולכן אם רוצים פקודה מותאמת שרירותית בשכבה הראשונה של התפריט החדש צריך IExplorerCommand ועוד זהות — זה פיצול התפקידים.7

פיצול התפקידים בין שיוכים לתפריט החדששיוך ProgID ופועל עדיין משמש בתפריט החדש לפתרון הפועל כברירת מחדל, פתיחה ופתיחה באמצעות, ומוצג למעלה; העלאת פקודה מותאמת שרירותית לשכבה הראשונה של התפריט החדש דורשת IExplorerCommand וזהותשיוך (ProgID + פועל)פתרון ברירת מחדל / פתיחהראש התפריט החדשאין עבודה נוספת ב-Win11פקודה מותאמתIExplorerCommand+זהותהשכבה הראשונה של התפריט החדש

איור 13: שיוכים עדיין מטפלים בפתרון משפחת «פתיחה» בתפריט החדש; רק פקודה מותאמת דורשת IExplorerCommand ועוד זהות.

6. טבלת החלטה מעשית ── איזו משלוש האפשרויות לבחור

מארגנים את מה שיש עד כאן לבחירה משולשת מעשית.

מה רוצים להשיג האמצעי המומלץ איך זה נראה ב-Windows 11 העבודה והעלות הנדרשות
(א) להפעיל את האפליקציה הפנימית בלחיצה כפולה או «פתיחה» שיוך + פועל סטטי (רישום רישום בלבד) משולב ב-«פתיחה» וב-«פתיחה באמצעות» בתפריט החדש רישום רישום של המתקין בלבד. אין DLL, אין דרישת חתימה נוספת
(ב) להעלות פקודה מותאמת לקובץ/תיקייה שנבחרו לתפריט החדש מימוש IExplorerCommand + רישום מניפסט MSIX. אפליקציה לא-ארוזה מקבלת זהות בחבילה דלילה השכבה הראשונה של התפריט החדש (כמה פקודות נאספות לתפריט נפתח בשם האפליקציה) DLL C++ מקורי + זהות חבילה + חתימת קוד
(ג) להמשיך להשתמש בהרחבת IContextMenu קלאסית קיימת להשאיר כרגע כמו שהוא (לא לבחור לפיתוח חדש) צד התפריט הישן בלבד, תחת «הצג אפשרויות נוספות» (Shift+F10) תחזוקת בנייה 64 סיביות ורישום COM. לתכנן מעבר מאוחר ל-(ב)

שתי נקודות שיפוט. ראשית, אל תביאו (ב) או (ג) לדרישה ש-(א) ממלאת. ברגע שכותבים הרחבת מעטפת לוקחים אחריות על יציבות הסייר. שנית, (ג) הוא רק «לא שבור»; כחוויית משתמש הוא נשאר צעד גרוע יותר. ככל שפקודה בשימוש תכוף יותר בפעילות יומיומית, כך גדול יותר התשואה על מעבר ל-(ב).

איך לבחור בין שלוש האפשרויותאם כל מה שרוצים הוא הפעלה בלחיצה כפולה או פתיחה, שיוך ופועל סטטי מספיקים; להעלאת פקודה מותאמת לתפריט החדש משתמשים ב-IExplorerCommand ורישום מניפסט MSIX; אם אי אפשר להפוך ל-MSIX מעניקים זהות בחבילה דלילה; משאירים הרחבת IContextMenu קלאסית קיימת בצד התפריט הישן כרגעכןלאכןכןלאלאהאם פתיחה מספיקה?שיוך + פועל סטטימותאם בתפריט החדש?אפשר להפוך ל-MSIX?IExplorerCommand+MSIXזהות חבילה דלילהלהשאיר קלאסי כרגעצד התפריט הישן בלבדאין DLL, סיכון קטן

איור 14: בוחרים בין פועל סטטי, IExplorerCommand ועוד זהות, והשארת הקלאסי, לפי הדרישה.

7. פריסה ורישום בפועל ── מתקין, חבילה דלילה, ניקוי

7.1. HKLM או HKCU

מתאימים לצורה של המתקין. לכל המשתמשים (מונח תחת Program Files, הרשאות מנהל) הוא HKLM\Software\Classes; התקנה לפי משתמש (בלי העלאה) היא HKCU\Software\Classes. מערבבים אותם ומייצרים פניות מסוג «א יכול לפתוח אבל ב לא יכול». להרחבת מעטפת שכוללת רישום CLSID, Reg-Free COM — שמסיר את הצורך ברישום הרישום עצמו — הוא אפשרות תקפה לשימוש COM בתוך האפליקציה, אבל אי אפשר ליישם אותו על הרחבת מעטפת שהסייר טוען, ולכן צריך את הרישום הישיר (“מה זה Reg-Free COM - שימוש ב-COM בלי רישום”).

7.2. אחרי שינוי, מודיעים ── SHChangeNotify

אחרי שרושמים, משנים או מוחקים שיוך, מודיעים על אירוע SHCNE_ASSOCCHANGED עם SHChangeNotify. מדלגים על זה והסייר עלול לא להבחין בשינוי עד הפעלה מחדש.110

// Call once after changing associations, e.g. from an installer custom action
SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, nullptr, nullptr);

7.3. רישום והסרת חבילה דלילה

רישום והסרת חבילה דלילה הם עבודת המתקין. רושמים אחרי הנחת הקבצים; מסירים לפני מחיקת הקבצים.8

# At install time: after placing the files, register the install folder as the external location
Add-AppxPackage -Path "C:\Program Files\KomuraSoft\KomuraReport.identity.msix" `
                -ExternalLocation "C:\Program Files\KomuraSoft"

# At uninstall time: remove the package registration before deleting the files
Remove-AppxPackage <package full name>

נקודה לשמירה: Add-AppxPackage רושם עבור המשתמש שהריץ אותו. אם קוראים לו מפעולה מותאמת של MSI לכל-המחשב, שרצה תחת LocalSystem, זה אינו מעניק זהות למשתמש שהתקין, ולכן מגדירים אותו לרוץ תחת התחזות למשתמש. גם אז, הרישום תחת התחזות הוא רק עבור המשתמש שהריץ את ההתקנה הזו. במחשב שמשמש כמה משתמשים, למשתמשים אחרים ולמשתמשים שנוצרים אחר כך אין זהות חבילה, והפקודה אינה מופיעה בתפריט החדש. כדי שכל משתמש ישתמש בה, מספקים מנגנון כמו בדיקת רישום החבילה שלכם בהפעלה הראשונה ורישום אם חסר (רישום לפי משתמש), וכוללים הסרה מכל משתמש שיש לו רישום בתוכנית הסרת ההתקנה. השתקפות רישום מניפסט עשויה גם לדרוש הפעלה מחדש של הסייר (או יציאה).7

סדר רישום והסרת חבילה דלילהבזמן התקנה רושמים את החבילה הדלילה אחרי הנחת הקבצים; בזמן הסרת התקנה מסירים את הרישום לפני מחיקת הקבצים; שמים לב שהרישום תקף רק למשתמש שהריץ אותוהתקנההנחת הקבציםרישום החבילה הדלילההסרת התקנההסרת רישום החבילהמחיקת הקבציםהרישום תקף רק למשתמש הרץ

איור 15: רושמים אחרי הנחת הקבצים, מסירים לפני מחיקת הקבצים, ושמים לב שהרישום הוא לפי המשתמש הרץ.

7.4. ניקוי בהסרת התקנה ── מה למחוק ומה להשאיר

לניקוי בהסרת התקנה יש קו מדריך רשמי ברור.1

  • מוחקים: את כל מפתח ה-ProgID הפנימי, רישום Capabilities/RegisteredApplications, רישום CLSID של הרחבת המעטפת, החבילה הדלילה (Remove-AppxPackage).
  • משאירים: ערך ברירת המחדל של מפתח הסיומת (.kmrpt). ההמלצה הרשמית היא לא למחוק אותו גם אם הוא עדיין מצביע על ה-ProgID הפנימי. לשפוט אחרי התקנה אם אפליקציה אחרת לקחה את ברירת המחדל קשה, ו-Windows פשוט מתעלמת מ-ProgID ערך-ברירת-מחדל שאינו רשום, כך שהשארתו אינה מזיקה באמת.
  • קוראים ל-SHChangeNotify(SHCNE_ASSOCCHANGED) גם בסוף הניקוי.

רוב בעיות «הסרנו התקנה ועדיין מופיעות שאריות בתפריט» הן דליפה בעיצוב הניקוי הזה.

עיצוב הניקוי בהסרת התקנהבהסרת התקנה מוחקים את מפתח ה-ProgID הפנימי, רישום CLSID והחבילה הדלילה; משאירים את ערך ברירת המחדל של מפתח הסיומת כי ProgID לא-רשום מתעלמים ממנו; מודיעים על השינוי ב-SHChangeNotify בסוף הניקויהסרת התקנהמוחקיםמשאיריםרישום ProgID ו-CLSIDחבילה דלילהערך ברירת המחדל של מפתח הסיומתמתעלמים מ-ProgID לא-רשוםמודיעים ב-SHChangeNotify בסוף

איור 16: מוחקים את הרישום הפנימי, משאירים את ערך ברירת המחדל של מפתח הסיומת, ומודיעים על השינוי בסוף הניקוי.

8. פתרון תקלות ── חסר, כפול, כבד

8.1. זה לא מופיע בתפריט

מבודדים בסדר הזה.

  1. באיזה תפריט מסתכלים: רישום בסגנון קלאסי מופיע רק בצד התפריט הישן תחת Shift+F10. בודקים קודם את שניהם.
  2. רוחב סיביות: DLL הרחבת מעטפת של 32 סיביות בלבד אינו נטען לסייר 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. הסייר כבד או קורס

כשלחיצה ימנית איטית, או שתיקייה מסוימת קורסת, קודם ממפים את הרחבות המעטפת המותקנות. מפרטים הרחבות שאינן של מיקרוסופט בכלי כמו ShellExView של NirSoft, משביתים זמנית את החשודות, וחפשים בינארית כדי לזהות את ה-DLL האשם. בקריסה, «Faulting module» במציג האירועים הוא גם רמז. אם ההרחבה הפנימית הייתה הסיבה, חושדים בקלט/פלט סינכרוני או בגישה לרשת בנתיב בניית התפריט (סעיפים 4.2 ו-5.2).

זיהוי ה-DLL האשם כשזה כבד או קורסמפרטים הרחבות מעטפת שאינן של מיקרוסופט ב-ShellExView, משביתים זמנית את החשודות וחפשים בינארית כדי לזהות את ה-DLL האשם; בקריסה מודול התקלה במציג האירועים הוא גם רמזמיפוי הרחבות מעטפתפירוט אלה שאינן של מיקרוסופטהשבתה זמנית וחיפוש בינאריזיהוי ה-DLL האשםבקריסהבדיקת מודול התקלה

איור 19: משביתים זמנית הרחבות שאינן של מיקרוסופט וחפשים בינארית; בקריסה משתמשים גם במציג האירועים.

8.4. Windows Sandbox נוח לאימות

אימות אינטגרציית מעטפת מבוסס על אישור «התקנה בסביבה נקייה → הפעלה → הסרת התקנה → אפס שאריות». הנוח כאן הוא Windows Sandbox (Pro/Enterprise/Education): כל הפעלה מביאה Windows חדש חד-פעמי תוך שניות, כך שאפשר להריץ בדיקות רישום וניקוי של המתקין כמה שרוצים. סוגרים והכול נעלם, ולכן זה מתאים גם לחקירת רישום שאריות.15

9. סיכום

  • שיוך קבצים הוא המבנה התלת-שכבתי «מפתח סיומת → ProgID → פועל», ו-HKCR היא תצוגה ממוזגת של Classes של HKLM/HKCU. מציינים את יעד הכתיבה במפורש, ותמיד עוטפים %1 במירכאות.
  • אפליקציית ברירת המחדל מתוכננת להיבחר בידי המשתמש ואי אפשר לשנות אותה מתוכנית. עבודת המתקין היא להירשם נכון כמועמד.
  • הרחבת מעטפת קלאסית היא DLL COM בתוך-תהליך שנטען לסייר. קריסה או השהיה מתפשטות לכלל; נדרשות 64 סיביות; קוד מנוהל אינו נתמך; המימוש ב-C++ מקורי הוא הכלל.
  • ב-Windows 11 תפריט ההקשר התפצל לשניים. העלאת פקודה מותאמת לתפריט החדש דורשת IExplorerCommand ועוד מניפסט MSIX; IContextMenu קלאסי מועבר לצד «הצג אפשרויות נוספות».
  • לאפליקציה שאינה יכולה להפוך ל-MSIX, קבלת זהות עם חבילה דלילה (MSIX עם מיקום חיצוני) היא התשובה המציאותית.
  • אם כל מה שרוצים הוא «לפתוח עם האפליקציה הזו», שיוך ופועל סטטי עדיין מספיקים. להתחיל מהאמצעי הפשוט ביותר הוא גם המדריך הרשמי.
  • אחרי רישום, שינוי או מחיקה מודיעים ב-SHChangeNotify; בהסרת התקנה מוחקים את ה-ProgID ומשאירים את ערך ברירת המחדל של מפתח הסיומת. Windows Sandbox נוח לאימות.

אם החלפת מחשב ל-Windows 11 גרמה לכם להבחין ש«התפריט הוסתר», קודם מאשרים איזה מבין (א), (ב) ו-(ג) בטבלת ההחלטה של פרק 6 זה. אמורים להיות מסוגלים להעריך את היקף העבודה במקום.

מאמרים קשורים

תחומי ייעוץ קשורים

KomuraSoft LLC מטפלת בתכנון ובמימוש של שיוך קבצים, תפריטי הקשר והרחבות מעטפת לאפליקציות עסקיות; כיוון לתפריט ההקשר החדש של Windows 11 (מעבר ל-IExplorerCommand, הכנסת חבילה דלילה); סקירת רישום וניקוי של מתקין קיים; וחקירת הסיבה לסייר כבד או קורס. אפשר להתחיל מההחלטה מה לעשות עם «התפריט שהוסתר תחת הצג אפשרויות נוספות».

קישורי עיון

  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. על כך ששינוי אפליקציית ברירת המחדל מתוכנן להיעשות רק דרך ממשק ההגדרות של המערכת; נתוני הגדרות משתמש מעורפלים ומוגנים בכתיבה במנהל התקן סינון (UCPD.sys); שינוי מבוסס-רישום אינו נתמך; ושימוש במדיניות קבוצתית / MDM בסביבה מנוהלת.  2

  4. Microsoft Learn, Working with Shell Extensions. על סוגי מטפל הרחבת מעטפת; על כך שהרחבה היא DLL COM בתוך-תהליך שנטען לסייר (ולתהליכים שמארחים את המעטפת) כך שקריסה או תקיעה מתפשטות לסייר כולו; רישום עם ThreadingModel=Apartment; ובחינת חלופה פשוטה יותר לפני הרחבת מעטפת.  2 3

  5. Microsoft Learn, Guidance for Implementing In-Process Extensions. על כך שמיקרוסופט אינה ממליצה ואינה תומכת במימוש הרחבת מעטפת בתוך-תהליך בקוד מנוהל; סיבות כוללות התנגשויות גרסת CLR, כניסה חוזרת וחיי אובייקט לא-דטרמיניסטיים; וקוד מנוהל מקובל להרחבה מחוץ-לתהליך (מטפל תצוגה מקדימה, או הפעלה מ-shell\verb\command).  2 3

  6. Windows Developer Blog, Extending the Context Menu and Share Dialog in Windows 11. על עיצוב תפריט ההקשר החדש של Windows 11; הרחבה דרך IExplorerCommand ועוד זהות אפליקציה; מיקום «פתיחה» ו-«פתיחה באמצעות» למעלה; איסוף כמה פקודות לתפריט נפתח בשם האפליקציה; וטעינת הרחבות IContextMenu קלאסיות כתפריט Windows 10 תחת «הצג אפשרויות נוספות» (Shift+F10).  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; שמירה על מתודות בניית תפריט מהירות; כיסוי אפליקציה לא-ארוזה בחבילה דלילה; שלפעמים נדרשת הפעלה מחדש של הסייר כדי שהרישום ייכנס לתוקף; וששיוך קבצים אינו הרחבת תפריט כלל-תכליתית.  2 3 4 5 6 7 8

  8. Microsoft Learn, Grant package identity by packaging with external location. על קבלת זהות חבילה ברישום חבילת מיקום חיצוני (חבילה דלילה) בלי לשנות את המתקין הקיים; זמינות מ-Windows 10 גרסה 2004 ואילך; ותכונות Windows שדורשות זהות (רישום תפריט הקשר, הודעות וכדומה) הופכות לשימושיות.  2 3

  9. Microsoft Learn, Choosing a Static or Dynamic Shortcut Menu Method. על בחירת שיטת הפועל הסטטי הפשוטה ביותר שעומדת בדרישות; IContextMenu החזק ביותר אבל גם המורכב ביותר ומסווג לצד הלא-מומלץ; ו-IExplorerCommand/IExplorerCommandState השיטה המומלצת.  2

  10. Microsoft Learn, SHChangeNotify function. על איך להרים את אירוע SHCNE_ASSOCCHANGED שמודיע למערכת על שינוי שיוך קבצים, ועל השימוש בו כדי שהמעטפת תבחין בשינוי.  2

  11. Microsoft Learn, Application Registration. על כך שרישום קובץ הפעלה דרך מפתח-המשנה App Paths מומלץ; תפקיד מפתח-המשנה Applications; רישום פעלים דרך SystemFileAssociations; ועדיפות ה-ProgID והמידע הקשור כשאפליקציית ברירת המחדל משתנה. 

  12. Microsoft Learn, Creating Shortcut Menu Handlers. על איך לרשום פועל סטטי; הסדר שבו נקבע הפועל כברירת מחדל (ערך ברירת מחדל → פועל ראשון → Open → Open With); שמות תצוגה של פעלים תקניים מסופקים בידי מערכת ההפעלה; פעלים מורחבים דרך Extended; שיוך לפקודות DDE הוא Deprecated; ואזהרות הפניית WOW64 בסביבת 64 סיביות.  2 3

  13. Microsoft Learn, Verbs and File Associations. על כך שפועל הוא פעולה שמשמשת גם את ShellExecuteEx; רכיבים במחרוזת פקודה שיכולים להכיל רווח צריכים להיות עטופים במירכאות, ו-“%1” תמיד נכתב במירכאות; ורישום הליך ברירת מחדל תחת HKCR\Applications. 

  14. Microsoft Learn, IExplorerCommand interface. על הרכב המתודות GetTitle, GetIcon, GetState, Invoke, EnumSubCommands וכדומה; המתודות נקראות בשרשור ממשק המשתמש ולכן אסור להן לתקשר עם משאבי רשת; וזמינות מ-Windows Vista ואילך. 

  15. Microsoft Learn, Windows Sandbox. על היכולת להפעיל סביבת Windows מבודדת חד-פעמית תוך שניות, כל השינויים נזרקים כשסוגרים אותה, התאמתה לבדיקות תוכנה ואימות מתקין, וזמינות ב-Pro/Enterprise/Education. 

מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מדוע פריט תפריט ההקשר של האפליקציה שלנו ב-Windows 11 מופיע רק תחת "הצג אפשרויות נוספות"?
כי ב-Windows 11 תפריט ההקשר של סייר הקבצים התפצל לשתי שכבות, ישנה וחדשה. הפקודות היחידות שיכולות להופיע בתפריט החדש הן כאלה שמממשות את ממשק IExplorerCommand ורשומות במניפסט חבילת MSIX (= יש להן זהות חבילה). הרחבות מעטפת קלאסיות מבוססות IContextMenu הועברו לתפריט הישן שנפתח ב-"הצג אפשרויות נוספות" (Shift+F10). ההרחבה עצמה לא שבורה, ולכן היא ממשיכה לעבוד כרגע, אבל אם רוצים אותה בתפריט החדש צריך הגירה ל-IExplorerCommand ואריזה כ-MSIX או הענקת זהות בחבילה דלילה.
האם המתקין יכול לקבוע את האפליקציה שלנו כאפליקציית ברירת המחדל לקובץ (האפליקציה שנפתחת בלחיצה כפולה)?
לא. בחירת אפליקציית ברירת המחדל מתוכננת להיות פעולה של המשתמש, ו-Windows אינה תומכת בשינוי אפליקציית ברירת המחדל מכל מקום שאינו ממשק ההגדרות של המערכת. מידע UserChoice ששומר את בחירת כל משתמש מעורפל, וכן מנהל התקן סינון (UCPD.sys) מגן עליו מכתיבה של אפליקציות. מה שמתקין יכול לעשות הוא לרשום ProgID ופעלים, להוסיף את עצמו ל-OpenWithProgIds כדי להופיע כמועמד תחת "פתיחה באמצעות", ולהפנות את המשתמש לדף הגדרות אפליקציות ברירת המחדל. המימוש הנכון אינו לגנוב את ברירת המחדל, אלא להיות מוכנים להיבחר.
מותר לכתוב הרחבת מעטפת בקוד מנוהל כמו C#?
מיקרוסופט קבעה במפורש שכתיבת הרחבת מעטפת בתוך-תהליך (מטפל תפריט הקשר, מטפל סמל וכדומה) בקוד מנוהל אינה מומלצת ואינה נתמכת. ההרחבה נטענת לסייר ולתהליך של כל אפליקציה שפותחת דיאלוג קבצים משותף, ולכן התנגשויות גרסת CLR, כניסה חוזרת וחיי אובייקט לא-דטרמיניסטיים הופכים את אפליקציית המארח ללא יציבה. המימוש ב-C++ מקורי הוא הכלל. EXE רגיל שמופעל מפקודת הפועל, או הרחבה מחוץ-לתהליך כמו מטפל תצוגה מקדימה שרצה בתהליך נפרד, תקינים בקוד מנוהל.
מהי חבילה דלילה (MSIX עם מיקום חיצוני)?
חבילת MSIX קטנה שאינה מכילה קבצי אפליקציה, רק מניפסט (מידע זהות). לאפליקציה שמותקנת בדרך הרגילה עם מתקין קיים (MSI, Inno Setup וכדומה) רושמים אותה עם Add-AppxPackage -ExternalLocation שמצביע לתיקיית ההתקנה, והאפליקציה רוכשת זהות חבילה ויכולה להשתמש בתכונות שדורשות זהות, כמו רישום בתפריט ההקשר החדש של Windows 11 והודעות toast. זמינה מ-Windows 10 גרסה 2004 ואילך, והחבילה זקוקה לחתימת קוד מהימנה במחשב היעד. זו האפשרות המציאותית כשרוצים תמיכה בתפריט החדש בלי להעביר את כל שיטת ההפצה ל-MSIX.
מה לעשות כשפריט תפריט הקשר מופיע פעמיים, או לא נעלם?
קודם מבודדים את הסיבה לפי התפריט שבו הוא מופיע: התפריט החדש או הישן (הצג אפשרויות נוספות). התצוגה הכפולה הטיפוסית היא שרישום רישום קלאסי ורישום מניפסט MSIX מתקיימים יחד, או שנשאר רישום ProgID או CLSID של הרחבה בהסרת התקנה. אחרי שינוי שיוכים חשדו גם ב-SHChangeNotify(SHCNE_ASSOCCHANGED) שפוספס; מיד אחרי רישום חבילה חשדו בהפעלה מחדש של הסייר שפוספסה. אם זה עדיין לא נפתר, השביתו זמנית הרחבות שאינן של מיקרוסופט ב-ShellExView וחפשו בינארית כדי לזהות את ה-DLL האשם.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג