איך מתייחסים היום ל-ActiveX /‏ OCX — טבלת החלטה: לשמר, לעטוף או להחליף

· עודכן בתאריך: · · COM, ActiveX, OCX, .NET, פיתוח Windows, מודרניזציה

פרויקטים שבהם עולות המילים ActiveX /‏ OCX, בדרך כלל האווירה קצת כבדה.

  • אפליקציית VB6 או C++‏ /‏ MFC ישנה עדיין בשימוש
  • ה-SDK של ציוד תעשייתי או מכשיר מדידה מציע רק OCX
  • אתר פנים-ארגוני שמניח ActiveX, ואי אפשר לצאת ממצב IE
  • רוצים לעבור מ-32bit ל-64bit, אבל OCX בודד מסרב

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

המאמר הזה מסדר בסדר קל לקבלת החלטה, מה לבחור כשמוצאים ActiveX /‏ OCX — לשמר, לעטוף או להחליף.

המקרים הרלוונטיים הם, לדוגמה:

  • אפליקציות desktop קיימות מסוג VB6 /‏ MFC /‏ WinForms
  • מעבר הדרגתי ל-C# /‏ .NET
  • מסכי legacy שכוללים WebBrowser / מצב IE
  • אפליקציות Windows שכוללות פקדי ActiveX של ספקים

תוכן עניינים

  1. קודם כול, המסקנה (במשפט אחד)
  2. ActiveX /‏ OCX במאמר הזה
  3. קודם כול, טבלת ההחלטה
    • 3.1. התמונה הכוללת
    • 3.2. החלטה לשמר
    • 3.3. החלטה לעטוף
    • 3.4. החלטה להחליף
    • 3.5. תלות בדפדפן נשקלת בנפרד
  4. נקודות שקל לטעות בהן
    • 4.1. רכיב UI, או רכיב שנושא מפרט
    • 4.2. ‏32bit /‏ 64bit וגבול התהליכים
    • 4.3. רישום, הפצה, הרשאות, רישיונות
    • 4.4. STA / לולאת הודעות / callback
    • 4.5. יש בדיקות? אפשר לצפות?
  5. המלצות לפי דפוסים אופייניים
    • 5.1. אפליקציית desktop פנים-ארגונית שיציבה כרגע
    • 5.2. רוצים להעביר OCX‏ 32bit לצד 64bit
    • 5.3. מסך שמניח IE /‏ WebBrowser
    • 5.4. ActiveX עם בקרת התקן או מפרט ייחודי
  6. אנטי-דפוסים נפוצים
  7. רשימת בדיקה להתחלת מעבר
  8. חלוקה גסה בין המצבים
  9. סיכום
  10. סוג ההתייעצות שמתאים לזה
  11. מקורות

מפת הידע של המאמר

בפועל, ActiveX משמש כמילה שמתייחסת לבקר מבוסס COM ולנכסים שסביבו, ו-OCX הוא הקובץ שמכיל את הישות הזו בפועל. ‏OCX שפועל in-proc חייב להתאים בהרכב הביטים (32bit/‏64bit) לתהליך המארח, וכדי לחצות את המגבלה הזו עוברים לתהליך נפרד כמו COM LocalServer שעוקף את חומת ה-bitness. בצד הדפדפן, גוף Microsoft Edge עצמו לא מחזיק ActiveX, וגם WebView2 לא יכול לרשת כמו שהוא תלות ב-ActiveX או סקריפט שמניח DOM של IE, ולכן מצב IE ממוקם כאמצעי הארכת חיים. אמצעי העטיפה כוללים אירוח כ-Windows Forms דרך AxHost ו-Aximp, פתרון ללא רישום ברג’יסטרי דרך Reg-Free COM, ורישום OCX דרך regsvr32 — כל אלה מניחים כתשתית מזהים ומידע טיפוסים כמו CLSID, ‏ProgID וספריית הטיפוסים.

מפת הידע של ההחלטה בין להשאיר, לעטוף או להחליף ActiveX/‏OCXתרשים שמראה ש-ActiveX ו-OCX מבוססים על COM; את אילוץ אי-ההתאמה ב-bitness ואת העקיפה שלו באמצעות תהליך נפרד; את יחסי אי-ההתאמה עם תלות בדפדפן (‏Edge, ‏מצב IE, ‏WebBrowser, ‏WebView2); ואיך אמצעי העטיפה (‏AxHost/‏Aximp/‏Reg-Free COM/‏LocalServer) קשורים ל-CLSID, ל-ProgID ולספריית הטיפוסים.משתמש במממש אתמחייבמחייבמצמצםמשתמש במשתמש במממש אתמחייבמחייבמחייבמחייבמחייבמחייבאינו מתיישב עםמשתמש במשתמש באינו מתיישב עםיורש אתמחייבמחייבמוגדר באמצעותמשתמש במחייבActiveXOCX‏COM (Component Object Model)מודל ה-apartment של COM‏ (STA/MTA)דרישת התאמת bitness‏COM LocalServer (שרת COM בתהליך נפרד)AxImp(ActiveX Control Importer)AxHostWindows FormsCLSID(Class ID)ProgID(Programmatic Identifier)Visual Basic 6.0(VB6)ספריית טיפוסים (TLB)מצב IEMicrosoft Edgeפקד WebBrowserMicrosoft Edge WebView2‏Reg-Free COM (COM ללא רישום)regsvr32MFC(Microsoft Foundation Classes)WebView2 Runtime

בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 24, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle

1. קודם כול, המסקנה (במשפט אחד)

  • כשרואים ActiveX /‏ OCX, השאלה הראשונה שצריך לשאול היא לא “האם זה ישן”, אלא מה הרכיב הזה בעצם אחראי עליו
  • אם זה סתם רכיב UI, ההחלפה יחסית קלה
  • אם הוא נושא בקרת התקן, דוחות, פורמט קובץ ייחודי או הרגלי הפעלה ישנים — בטוח יותר קודם לעטוף מאשר לממש מחדש ישר
  • אם הוא יציב ב-desktop ותחום השינוי בו קטן, גם ההחלטה לשמר סבירה לגמרי
  • תלות ב-ActiveX בדפדפן אפשר להאריך חיים, אבל העתיד שלה דל — עדיף להסתכל מתוך עדיפות להחלפה
  • אי אפשר לטעון OCX‏ 32bit לתוך תהליך 64bit ישירות. זו מגבלה שלא עוברים בכוח רצון
  • חיכוך שאינו טכני — רישום, DLL תלויים, הרשאות מנהל, רישיונות, STA /‏ MTA — נוטה להיות המכשול הגדול
  • גם “סתם לכתוב הכול מחדש” וגם “להקפיא לנצח כי זה מפחיד” הן בחירות עם שיעור תקלות גבוה

בקיצור, סדר ההחלטה הוא:

  1. מה יש בתוך ה-OCX הזה
  2. האם צריך להשתמש בו באותו תהליך
  3. האם זה נתקע ב-32bit /‏ 64bit, רישום או תלות בדפדפן
  4. האם צריך קודם ליצור גבול הניתן לבדיקה, ורק אז להחליף

בסדר הזה, קל בהרבה לסדר את זה.

סדר ההחלטהתרשים המראה שהסדר לבדיקה הוא מה יש בתוך ה-OCX, האם צריך אותו תהליך, האם 32bit או 64bit או רישום או תלות בדפדפן חוסמים, והאם צריך ליצור גבול הניתן לבדיקה לפני שמחליפים.מה יש בתוך ה-OCXהאם צריך אותו תהליךהאם bitness, רישום או דפדפן חוסמיםליצור גבול לפני שמחליפים

איור 1: לא “האם זה ישן” — בסדר הזה קל יותר לסדר את ההחלטה בין לשמר, לעטוף או להחליף.

2. ActiveX /‏ OCX במאמר הזה

קודם כול, נבהיר איך נעשה שימוש במילים במאמר הזה.

מילה המשמעות במאמר הזה
‏COM מודל הרכיבים הבינארי-תואם של Windows. ממשקים ציבוריים, רישום, מודל ה-Apartment וכדומה הם הבסיס שלו
‏ActiveX /‏ OCX בעבודה בפועל, המונחים משמשים לרוב יחד לציון פקדים מבוססי COM ונכסים סביבם. כולל בעיקר פקדי UI מסוג .ocx ורכיבים שמוטמעים ב-IE / container
תלות ב-WebBrowser /‏ IE גם אם זה לא ActiveX ממש, זה כולל דפדפן מוטמע או אינטגרציה שמניחים “עולם IE”. מבחינת ההחלטה, זו בעיה קרובה מאוד

בהגדרה מדויקת, ActiveX ו-‏COM אינם אותו הדבר. אבל הנקודות שמקשות בעבודה בפועל דומות מאוד.

  • האם ה-32bit /‏ 64bit מתאימים
  • איך מפיצים את הרישום וה-DLL התלויים
  • באיזה host / container זה רץ
  • האם STA, לולאת הודעות או callback לא חוסמים
  • האם לא נשארה תלות בדפדפן

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

נקודות שמקשות בעבודה בפועלתרשים המראה שגם אם ActiveX ו-COM אינם אותו הדבר במדויק, הנקודות שמקשות בעבודה בפועל דומות מאוד: התאמת bitness, הפצת רישום ו-DLL, זהות ה-host, והנחות STA ו-callback שמובילות לפעמים לתלות בדפדפן.מקרה ActiveX / OCXהאם bitness מתאיםהפצת רישום ו-DLL תלוייםבאיזה host זה רץהנחות STA ו-callbackהאם נשארה תלות בדפדפן

איור 2: גם אם ActiveX ו-COM שונים בהגדרה מדויקת, הנקודות שמקשות בעבודה בפועל מתרכזות באזור הזה.

בנוסף, נסכם מראש את הקיצורים שיופיעו בהמשך כמובנים מאליהם. גם אם בפרק 7, ברשימת הבדיקה, כתוב “למפות ProgID ו-CLSID”, בלי להבין את זה קשה להתקדם.

מונח הגייה / שם מלא משמעות
CLSID Class ID GUID שמזהה באופן ייחודי את המימוש (המחלקה) של רכיב COM. גם רישום ברישום (registry) נשען על הערך הזה
ProgID Programmatic Identifier שם קריא לבני אדם שמוצמד ל-CLSID. מחרוזת כמו Excel.Application
IID Interface ID GUID שמזהה ממשק COM באופן ייחודי. שונה מ-CLSID
TLB Type Library קובץ שמחזיק בפורמט בינארי מידע טיפוסים כמו ממשקים, שיטות וטיפוסי ארגומנטים. בזכות זה אפשר לקרוא “עם טיפוסים” מ-VB6 או מ-‏.NET
RegAsm Assembly Registration Tool כלי שמגיע עם .NET Framework. רושם assembly של .NET ברישום כדי שיהיה אפשר להשתמש בו מ-COM
AxHost מחלקת בסיס לאירוח פקד ActiveX בתוך Windows Forms
AxImp ActiveX Control Importer כלי שמייצר מ-OCX assembly עוטף עבור Windows Forms
in-proc / out-of-proc בתוך התהליך / מחוץ לתהליך האם זה רץ באותו תהליך כמו הקורא (DLL או OCX), או בתהליך נפרד (שרת EXE)
LocalServer צורה שבה שרת COM רץ כ-EXE בתהליך נפרד. מאפשרת לעבור את חומת ה-bitness ולבודד קריסות
Reg-Free COM / side-by-side COM ללא רישום מנגנון שפותר COM לפי מידע שכתוב במניפסט של האפליקציה, בלי רישום ברישום
רישיון design-time / runtime בזמן פיתוח / בזמן ריצה בפקדים של ספקים, לפעמים הטיפול ברישיון שונה בין הדבקה על המסך במחשב הפיתוח לבין הרצה אצל הלקוח
adapter / facade טיפוס תכנוני שמחליף API ישן ומפורט ב-API גס ונוח יותר
STA / MTA Single / Multi Threaded Apartment מודל התהליכונים של COM. קובע מאיזה ת’רד מותר לקרוא

3. קודם כול, טבלת ההחלטה

3.1. התמונה הכוללת

אם מסתכלים על הטבלה הזו קודם, רוב הכיוון כבר נקבע.

מצב הבחירה הראשונה הסיבה
תלות ב-ActiveX בדפדפן נטייה להחליף Edge עצמו לא תומך ב-ActiveX, ומצב IE ממוקם כאמצעי הארכת חיים
ב-desktop, ה-OCX יציב ותחום השינוי קטן נטייה לשמר עלות הפירוק עכשיו לרוב גדולה יותר
רוצים רק לעבור ל-.NET בסביבה, אבל התנהגות הפקד לא ברורה נטייה לעטוף קודם לסדר את הגבול בטוח יותר
רוצים לטעון OCX‏ 32bit לתוך תהליך 64bit ישירות לעטוף / שינוי מבנה זה גבול שאי אפשר לעבור ב-in-proc
נעשה בו שימוש רק כרכיב UI, ויש תחליף נטייה להחליף לרוב מספיקה החלפה של השטח
ספק סיים תמיכה, חתימה, רישום או DLL תלויים גורמים תקלה כל פעם נטייה להחליף עלות התפעול כבר מתגלה כחוב טכני
כולל בקרת התקן, דוחות או פרוטוקול ייחודי נטייה לעטוף קודם צריך לקבע את ההתנהגות, אחרת עלות ההחלפה לא ניתנת לחיזוי
תרשים ההחלטה המלא - לשמר, לעטוף או להחליףתרשים המראה שההסתעפות הראשונה היא תלות בדפדפן, ואם כן עדיפות להחלפה כי מצב IE הוא רק הארכת חיים; אחרת בודקים אם זה בעיקר רכיב UI עם תחליף שקול ואז שוקלים החלפה או קודם עטיפה; אם לא, בודקים אם יש בקרת התקן או מפרט ייחודי ואז קודם עוטפים ומכינים בדיקות; ואם לא, בודקים אם רישום, bitness או הפצה כואבים ואז בוחנים מחדש את המבנה, אחרת ההחלטה לשמר סבירה.כןלאכןכןלאלאכןלאכןלאיש ActiveX / OCXתלות בדפדפן?עדיפות להחלפה — מצב IE הוא רק הארכת חייםבעיקר רכיב UI?יש תחליף שקול?לשקול החלפהקודם לעטוף ולסדר את הגבוליש בקרת התקן, מפרט ייחודי או לוגיקת דוחות?קודם לעטוף — להכין בדיקות ואז להחליף בהדרגהרישום, bitness או הפצה כואבים?בחינה מחדש של המבנה — לשקול out-of-proc, חיבור לתהליך נפרד או Reg-Free COMגם ההחלטה לשמר ריאלית

איור 3: ההסתעפות הראשונה היא תלות בדפדפן, ואחר כך הכיוון נקבע לפי רכיב UI, קיום תחליף, או מפרט שהרכיב נושא.

מכאן נסקור כל דפוס בתורו.

3.2. החלטה לשמר

רק בגלל שזה ActiveX /‏ OCX, זה לא אומר שזה מיד מועמד להחלפה. אם מתקיימים תנאים כאלה, לרוב זול יותר פשוט לשמר:

  • טווח השימוש סגור, וסביבת התפעול (הפצה פנים-ארגונית, צירוף לציוד וכדומה) קבועה
  • הפקד יציב גם כרגע, ודרישות השינוי לא גדולות
  • הספק עדיין פעיל, או שיש יכולת תחזוקה מינימלית בבית
  • זה לא תלוי בדפדפן, ונשלם בתוך ה-host הקיים ב-desktop
  • אין צורך לשנות בינתיים את הנחת ה-32bit /‏ 64bit

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

  • לתעד בכתב את מערכת ההפעלה הנתמכת, ה-bitness, ה-DLL התלויים הנדרשים ושלבי הרישום
  • להעביר התקנה, רישום וביטול רישום לסקריפט או למתקין, ולא להסתמך על פתק ידני
  • להכין smoke test בסביבה נקייה
  • לרכז את הקריאות לפקד במקום אחד ככל האפשר, במקום לפזר אותן בכל האפליקציה

הכי גרוע הוא להמשיך 10 שנים עם “זה עובד אז לא נוגעים”, עד ששום אחד כבר לא יכול להסביר את ההנחות. ככל שבוחרים לשמר, הפיכת ההנחות לגלויות הופכת חשובה יותר.

הפיכת ההנחות לגלויות כחלק מההחלטה לשמרתרשים המראה שההחלטה לשמר אינה הזנחה אלא כוללת תיעוד ההנחות, הפיכת שלבי הרישום לסקריפט, הכנת smoke test בסביבה נקייה, וריכוז הקריאות במקום אחד.ההחלטה לשמרתיעוד ההנחות בכתבהפיכת שלבי הרישום לסקריפטהכנת smoke testריכוז הקריאות במקום אחד

איור 4: לשמר זה לא להזניח — ככל שבוחרים לשמר, כדאי יותר לחשוף את ההנחות.

3.3. החלטה לעטוף

בעבודה בפועל, זו הבחירה שדורשת הכי הרבה עבודה.

“לעטוף” כאן משמעו לכלוא את ה-ActiveX /‏ OCX בתוך גבול צר, ולהראות אותו לסביבה כ-API חדש או כרכיב מסך חדש.

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

המבנה של הבחירה לעטוףתרשים המראה שכליאת ה-ActiveX / OCX בתוך גבול צר והצגתו לסביבה כ-API או כרכיב מסך חדש מונעים את הצרה הכפולה של חפירת מפרט ושחזור תקלות שנובעת ממימוש מחדש מלא לפני שההתנהגות ברורה.ActiveX / OCXכליאה בתוך גבול צרהצגה כ-API חדשהסביבה רואה רק את הצוהר החדשהימנעות מחפירת מפרט ומשחזור כפול

איור 5: “לעטוף” הוא בידוד הרכיב הישן ובניית צוהר חדש, כשלב מקדים לפני מימוש מחדש מלא.

יש כמה תבניות לעטיפה.

דרך עטיפה מתאים ל נקודות לבדוק
host ב-WinForms +‏ AxHost /‏ AxImp הטמעה במסך desktop קיים, השארת מעט מסכים בלבד STA, אירועים, תלות בזמן עיצוב, רישיון
helper EXE של 32bit /‏ COM LocalServer / גישור לתהליך נפרד רוצים לעבור ל-64bit, לבודד קריסות תקשורת בין-תהליכית, סדר עלייה, ניטור, פריסה
צוהר תאימות COM בצד ה-‏.NET רוצים לשמר את קוראי ה-COM הקיימים אבל לעדכן את הפנים IID /‏ CLSID /‏ TLB / שיטת רישום /‏ bitness

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

דרך עטיפה מה עושים ראשון הסבר מפורט
host ב-WinForms +‏ AxHost ב-Visual Studio, לחיצה ימנית על ה-Toolbox ← “Choose Toolbox Items” ← בוחרים את היעד בלשונית “COM Components”. בשורת פקודה: aximp המלכודות שברישום וב-bitness בפיתוח COM/OCX/ActiveX
helper EXE של 32bit /‏ LocalServer רושמים את ה-EXE של 32bit כשרת COM, וקוראים לו מצד ה-64bit ב-out-of-proc COM שימושי — מקרה של קריאה ל-DLL‏ 64bit מאפליקציית 32bit
Reg-Free COM כותבים file ו-comClass במניפסט של האפליקציה, ופותרים בלי רישום ברישום מהו Reg-Free COM — מנגנון להשתמש ב-COM ללא רישום
צוהר תאימות COM בצד ה-‏.NET חושפים את צד ה-‏.NET כ-COM, ובמידת הצורך מייצרים TLB עם dscom איך משתמשים ב-DLL‏ .NET 8 מ-VBA עם טיפוסים — חשיפת COM ו-dscom TLB

מריצים את aximp מתוך Developer Command Prompt של Visual Studio.

aximp C:\path\to\MyControl.ocx

בעזרת זה נוצרים שני קבצים: runtime callable wrapper מסוג COM, ועוטף עבור Windows Forms שיורש מ-AxHost. שימו לב ששם הקובץ נקבע לפי ה-ProgID, לא לפי שם הקובץ המקורי. בדוגמה מהתיעוד של Microsoft, מ-msdxm.ocx יוצאים MediaPlayer.dll ו-AxMediaPlayer.dll. מוסיפים את השני כהפניה, ומדביקים את AxMediaPlayer על הטופס.

מה aximp מייצרתרשים המראה שהעברת OCX ל-aximp מייצרת שני קבצים — DLL עוטף מסוג COM ו-DLL עוטף שיורש מ-AxHost — כשהאחרון מתווסף כהפניה ומודבק על הטופס, ושם הקובץ נקבע לפי ProgID.ה-OCX היעדהרצת aximpDLL עוטף מסוג COMDLL עוטף שיורש מ-AxHostהוספה כהפניה והדבקה על הטופסשם הקובץ נקבע לפי ProgID

איור 6: הפלט של aximp הוא שני DLL, ומה שמדביקים על הטופס הוא העוטף שיורש מ-AxHost.

עבור Reg-Free COM, המניפסט הצדדי של האפליקציה במינימום נראה כך:

<?xml version="1.0" encoding="utf-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
  <assemblyIdentity type="win32" name="MyApp" version="1.0.0.0" />
  <file name="MyControl.ocx">
    <comClass
      clsid="{01234567-89AB-CDEF-0123-456789ABCDEF}"
      threadingModel="Apartment"
      progid="MyCompany.MyControl.1" />
  </file>
</assembly>

בשיטת ה-LocalServer, ברישום נכנס נתיב ה-EXE תחת HKEY_CLASSES_ROOT\CLSID\{CLSID}\LocalServer32. שרת EXE שנבנה עם ATL או MFC לרוב תומך, כמוסכמה, ברישום עצמי וביטול רישום עם MyServer.exe /regserver ו-/unregserver. אבל בגלל שהתצוגה ברישום נחלקת לפי bitness, חשוב תמיד לזכור ש-EXE של 32bit נרשם בצד ה-32bit של הרישום.

רישום LocalServer ותצוגת הרישוםתרשים המראה שבשיטת LocalServer נרשם נתיב ה-EXE תחת LocalServer32 מתחת ל-CLSID, שאפשר לרשום עצמית עם המוסכמה של regserver, אבל תצוגת הרישום נחלקת לפי bitness ו-EXE של 32bit נרשם בצד ה-32bit.32bit64bitשרת EXEרישום נתיב תחת LocalServer32מה ה-bitness של ה-EXE?רישום בתצוגת ה-32bitרישום בתצוגת ה-64bit

איור 7: יעד הרישום של LocalServer נקבע לפי תצוגת הרישום שמחולקת לפי bitness.

מה שחשוב במיוחד הוא לא להעתיק בעטיפה 200 שיטות מה-API הישן כמו שהן. אם עושים את זה, פשוט מייבאים את המגבלות הישנות לקוד החדש.

כשעוטפים, שימת לב לדברים האלה עוזרת מאוד:

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

יש גם מקרים שבהם רוצים לשמר רק את כניסת ה-COM בצד ה-‏.NET החדש. במקרה כזה, מבנה של “לעדכן את הפנים תוך שמירה על חוזה ה-COM בלבד” הוא ריאלי. עם זאת, לא בטוח שמספיק “סתם RegAsm” בתחושה של תקופת ה-‏.NET Framework. הטיפול הנוכחי ב-COM host, ב-TLB, ב-bitness וב-Registry-Free COM של ‏.NET כדאי לתכנן מראש — זה נוח יותר בהמשך. פרטים על זה נמצאים ב-איך משתמשים ב-DLL‏ .NET 8 מ-VBA עם טיפוסים — חשיפת COM ו-dscom TLB וב-מהו Reg-Free COM — מנגנון להשתמש ב-COM ללא רישום, כולל שלבים מפורטים.

אחריות שנקבעת בגבולתרשים המראה שכשעוטפים הופכים לשיטות בגרגר גס, לא נותנים לקוד המסך לגעת ישירות ב-OCX, קובעים בגבול את אחריות הלוג, ה-timeout וההמרה, ובונים כך שגם התחליף העתידי יוכל להתחלף עם אותו interface.הגבול בעטיפהשיטות בגרגר גסתיעוד לוג בגבולtimeout והמרת חריגותצוהר אחיד להחלפה עתידיתלא להעתיק 200 שיטות ישנות

איור 8: הערך של העטיפה הוא ריכוז האחריות בגבול; העתקה נאמנה של ה-API הישן לא מייצרת את הערך הזה.

3.4. החלטה להחליף

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

כדאי להסתכל מתוך עדיפות להחלפה במקרים כאלה:

  • ה-ActiveX משמש רק כרכיב UI
  • הספק הוציא ממשיך ל-‏.NET /‏ WPF /‏ WebView2
  • תלות בדפדפן או הנחת IE מעכבות
  • נתקעים כל פעם ברישום, חתימה, הרשאות מנהל או הגדרות אבטחה
  • יש בדיקות או תרחישי עסקיים שאפשר לאמת בהם מימוש חלופי

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

אם מחליפים, מתחילים מה-UI.

  • grid
  • לוח שנה
  • עץ (tree)
  • חלק תצוגת דפדפן
  • סיוע קלט פשוט

אלה יחסית קלים להחלפה. מצד שני, יש דברים שנראים כמו UI אבל התוכן שלהם עשיר:

  • ActiveX של ספק לבקרת התקן
  • פקד שמשולב עם הדפסה או יצירת דוחות
  • פקד שכולל קריאה וכתיבה של פורמט קובץ ייחודי
  • פקד עם הנחות של callback ב-COM וסביב ת’רדים

אם מפספסים את ההבדל הזה, הערכת המאמץ מתפרקת בבת אחת.

ההבחנה בהחלטה להחליףתרשים המראה שאם השימוש הוא רק רכיב UI עם תחליף קל להחליף, אך אם הוא נושא מפרט כמו בקרת התקן, דוחות, פורמט ייחודי או הנחות ת'רד, זריקה מיידית הופכת לבוץ ועדיף לעבור להחלטה לעטוף.רק ישנוּת השטחנושא גוש מפרטמה יש מאחורי המראה?קל להחליףזריקה מיידית הופכת לבוץעברו להחלטה לעטוף

איור 9: האם זה מתאים להחלפה נקבע לפי ההבחנה בין “ישנוּת השטח” לבין “עושר התוכן”.

3.5. תלות בדפדפן נשקלת בנפרד

זה בעצם קטגוריה נפרדת לגמרי.

בשונה מ-OCX ב-desktop, ל-ActiveX בדפדפן יש סיבה חלשה למדי להמשיך ולפתח אותו.

הסיבה פשוטה: תשתיות הדפדפנים המודרניים לא הופכות את זה לזירה מרכזית. ‏Microsoft Edge עצמו לא תומך ב-ActiveX. מצד שני, מצב IE משמש כשכבת תאימות שמפעילה מנוע מסדרת IE עבור אתרים שהוגדרו, ומריצה חלק מתכונות IE כולל ActiveX.

כלומר:

  • אפשר להאריך חיים כדי שזה יעבוד עכשיו
  • אבל כתכנון ארוך טווח, העתיד לא רחב
המעמד של ActiveX בדפדפןתרשים המראה ש-Microsoft Edge עצמו לא מריץ ActiveX, ומצב IE מאפשר הארכת חיים כשכבת תאימות עבור אתרים שהוגדרו, אבל העתיד ארוך הטווח דל, ולכן עדיף להסתכל מתוך עדיפות להחלפה.ActiveX בדפדפןלא רץ ב-Edge עצמואפשר להאריך חיים במצב IEהעתיד ארוך הטווח דללהסתכל מתוך עדיפות להחלפה

איור 10: תלות ב-ActiveX בדפדפן — מפרידים בין הארכת חיים לבין תכנון קבוע, ומסתכלים מתוך עדיפות להחלפה.

אותו הדבר קורה גם לפקד WebBrowser שמוטמע באפליקציית Windows. ‏WebBrowser גורר אחריו את “עולם” ה-IE, ולכן אם רק רוצים להציג HTML, טבעי יותר להפוך את WebView2 למועמד הראשון לעבודה חדשה מהיום.

עם זאת, חשוב לזכור ש-WebView2 אינו רכיב חלופי מלא ל-WebBrowser.

  • סקריפטים שמניחים DOM של IE
  • תלות ב-ActiveX
  • הנחות סביב window.external
  • התנהגות שמניחה אזורי אבטחה או אינטראנט

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

מה לא עובר ל-WebView2תרשים המראה ש-WebView2 מתאים כמועמד ראשון אם רק רוצים להציג HTML, אבל הוא לא רכיב חלופי מלא, וסקריפטים שמניחים DOM של IE, תלות ב-ActiveX, הנחות window.external והתנהגות אזורי אבטחה לא עוברים כמו שהם.מ-WebBrowser ל-WebView2מועמד ראשון אם רק תצוגת HTMLמה שלא עובר כמו שהואסקריפטים עם DOM של IEתלות ב-ActiveXהנחות window.externalהתנהגות אזורי אבטחה

איור 11: WebView2 הוא רכיב חלופי למנוע הרינדור, אבל לא יורש את שטח החיבור של עולם ה-IE.

4. נקודות שקל לטעות בהן

4.1. רכיב UI, או רכיב שנושא מפרט

זו הנקודה החשובה ביותר.

grid או לוח שנה ישן — מתקדמים די רחוק רק בבדיקת תאימות המראה והאירועים. מצד שני, ל-ActiveX שנושא בקרת התקן, דוחות או פורמט ייחודי יש גוש מפרט מאחורי המראה.

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

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

מימוש מחדש מיידי של האחרון הופך כמעט תמיד לפרויקט חפירת מפרט. כאן בטוח יותר לעטוף קודם.

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

איור 12: ההבחנה החשובה ביותר. גם אם המראה זהה, האם מאחוריו יש גוש מפרט קובע את דרך ההתקדמות.

4.2. ‏32bit /‏ 64bit וגבול התהליכים

לרוב מפספסים את הנקודה הזו, אבל היא ממש מהותית.

OCX‏ ב-in-proc חייב להתאים ב-bitness לתהליך שטוען אותו. כלומר, אי אפשר לטעון OCX‏ 32bit לתוך אפליקציית 64bit ישירות.

האפשרויות הריאליות במקרה הזה הן בעצם השלוש האלה:

  • להשאיר בינתיים גם את אפליקציית ה-host כ-32bit
  • לכלוא בתהליך 32bit נפרד, ולהתחבר לצד ה-64bit דרך IPC או COM מסוג out-of-proc
  • להתחיל להחליף מהמקומות שאפשר להסיר בהם את התלות ב-OCX

כאן, ה-“מכיוון שזה Any CPU זה בטח יסתדר” בדרך כלל לא עובד. גם כשבונים חלון תאימות COM בצד ה-‏.NET החדש, המראה של קוד managed וה-bitness האמיתי של ה-COM host הם בעיות נפרדות. אם מתחילים בזה ברישול, יוצא הדבר המעצבן: ה-build עובר, אבל זה לא עובד אצל הלקוח.

שלוש האפשרויות ל-OCX 32bit ולמעבר ל-64bitתרשים המראה שמכיוון ש-OCX 32bit לא נטען ב-in-proc לתוך תהליך 64bit, שלוש האפשרויות הריאליות הן להשאיר את ה-host כ-32bit, לכלוא בתהליך 32bit נפרד ולהתחבר עם IPC או COM out-of-proc, או להחליף מהמקומות שאפשר להסיר בהם את התלות.OCX 32bit לא נטען ב-in-procהשארת ה-host כ-32bitכליאה בתהליך 32bit נפרדהחלפה מהמקומות שאפשרחיבור עם IPC או COM out-of-proc

איור 13: את חומת ה-bitness אי אפשר לעבור בכוח רצון; האפשרויות הריאליות מצטמצמות לשלוש אלה.

4.3. רישום, הפצה, הרשאות, רישיונות

טכנית אפשר לקרוא לזה, אבל זה מת בהפצה. זה קורה הרבה מאוד ב-ActiveX /‏ OCX.

המכשולים האופייניים הם בערך אלה:

  • ההנחה סביב regsvr32 תלויה באדם
  • מיקום ה-DLL התלויים לא מתועד במפורש
  • נדרשות הרשאות מנהל, אבל זה לא הוטמע בנוהל התפעול
  • רישיון design-time /‏ runtime של פקד הספק מחולק
  • עובד במחשב הפיתוח, אבל לא בסביבה נקייה

אלה עוצרים את הפרויקט גם בלי לגעת בשורת קוד אחת.

יש מקרים שבהם מבנה ללא רישום או פריסת side-by-side מקלים, אבל זה לא אבקת קסמים. צריך לוודא התאמה עם ה-container ועם שיטת ההפצה.

בקיצור, מעבר ActiveX /‏ OCX הוא לא רק מימוש, אלא גם תכנון הפצה. אם דוחים את זה, נופלים בגדול בסוף.

מכשולים שעוצרים בהפצהתרשים המראה שתלות אנושית ב-regsvr32, מיקום DLL לא מתועד, הרשאות מנהל שלא הוטמעו בנוהל, ורישיון מחולק בין design-time ל-runtime עוצרים את הפרויקט גם בלי לגעת בקוד.תכנון ההפצהregsvr32 תלוי באדםDLL תלויים לא מתועדיםהרשאות מנהל מחוץ לנוהלרישיון מחולק לשנייםעוצר גם בלי לגעת בקוד

איור 14: זה נקרא טכנית, אבל מת בהפצה — מכשול שמתכננים בנפרד מהמימוש עצמו.

4.4. STA / לולאת הודעות / callback

‏ActiveX /‏ OCX הוא לא סתם קריאת DLL. לפעמים יש לו הנחות על מודל התהליכונים של COM ועל לולאת ההודעות.

כדאי במיוחד לשים לב למקרים כאלה:

  • יציב רק בהנחת ת’רד ה-UI
  • הנחת STA, אבל קוראים לו ברשלנות מצד MTA
  • callback חוזר באמצע קריאה סינכרונית
  • ההנחה על ת’רד קבלת האירועים לא ברורה

בהתחלה זה מופיע כ”סיפור רפאים”: “לפעמים נתקע”, “לפעמים אירוע לא מגיע”. אבל בפועל, ברוב המקרים זו הפרת הנחה.

לכן, גם כשעוטפים וגם כשמחליפים, כדאי לקבע מראש באיזה ת’רד יוצרים, באיזה ת’רד קוראים, ואיפה מקבלים אירועים.

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

איור 15: “לפעמים זה נתקע” הוא לרוב הפרת הנחה — קיבוע מראש של הבטחות הת’רד מונע את זה.

4.5. יש בדיקות? אפשר לצפות?

ההחלפה קשה לא רק בגלל שהקוד ישן. אלא בגלל שאין קריטריון לכך ש“זה פעל אותו הדבר”.

עצם קיומם של אלה כבר עושה הבדל גדול:

  • smoke test לכל תרחיש הפעלה
  • דוגמאות קלט/פלט
  • צילומי מסך או דוגמאות דוחות
  • תבניות שגיאה והתנהגות צפויה
  • לוג בזמן timeout או כשההתקן לא מחובר

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

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

איור 16: קושי ההחלפה נקבע פחות לפי ישנות הקוד, ויותר לפי קיום אמצעי תצפית שיודע לומר “פעל אותו הדבר”.

5. המלצות לפי דפוסים אופייניים

5.1. אפליקציית desktop פנים-ארגונית שיציבה כרגע

ההמלצה: נטייה לשמר.

בתנאים כאלה, לרוב עדיף לא לקלף בכוח:

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

אבל לא משאירים את זה “עירום” — ריכוז מוקדי הקריאה בלבד ישתלם בהמשך.

כלומר, המדיניות היא כזו:

  • כרגע משמרים
  • אבל מסדרים רק את הגבול
  • כך שכשתידרש החלפה, אפשר יהיה להתחיל משם

המבנה בן שלוש השכבות הזה הכי פשוט.

5.2. רוצים להעביר OCX‏ 32bit לצד 64bit

ההמלצה: לעטוף / לשנות מבנה.

אם ניגשים לזה ישירות, נתקעים. כי אי אפשר לטעון OCX‏ 32bit לתוך תהליך 64bit ב-in-proc.

בפועל, נוח יותר מבנה שכולא בתהליך helper של 32bit או ב-LocalServer, ומתקשר עם אפליקציית ה-64bit דרך API בגרגר גס.

מבנה שבו helper של 32bit מגשר בין אפליקציית 64bit ל-OCXתרשים רצף המראה שאפליקציית .NET של 64bit פונה ל-helper או LocalServer של 32bit דרך API בגרגר גס, וזה קורא ב-in-proc ל-OCX של 32bit ומחזיר תוצאה מומרת בחזרה.OCX של 32bithelper / LocalServer של 32bitאפליקציית .NET 64bitOCX של 32bithelper / LocalServer של 32bitאפליקציית .NET 64bitפנייה עם API בגרגר גסקריאה ב-in-procתוצאה / אירועתוצאה מומרת

איור 17: OCX שכלוא ב-helper של 32bit, ואפליקציית ה-64bit משתמשת בו דרך API בגרגר גס.

הנקודה כאן היא לא לתווך את כל השיטות הקטנות כמו שהן. גבול בין-תהליכי מתעייף מהר אם שולחים דרכו הרבה קריאות קטנות.

  • להתקרב לגרגר של פעולה אחת = בקשה אחת
  • לעצב ערכי החזרה ושגיאות ליחידות בעלות משמעות
  • לתעד לוג בגבול

בצורה הזו, גם קל יותר בהמשך כשבאמת מחליפים את הפנים.

5.3. מסך שמניח IE /‏ WebBrowser

ההמלצה: עדיפות להחלפה.

זה תחום שבו “עובד עכשיו” ו”קל לתחזק גם בהמשך” לא בקלות מתלכדים. מצב IE עוזר מאוד לתאימות, אבל ההנחה עדיין נשארת מסדרת IE.

לכן, ברור יותר לחלק את החשיבה כך:

  • להאריך חיים במצב IE כדי לא לעצור פעילות פנים-ארגונית
  • אבל לא לבלבל בין הארכת חיים לתכנון קבוע
  • לבחור יעד החלפה מבין WebView2, Web טהור, או היברידי של UI native + Web

נכתוב גם את הטיפול הקונקרטי בצד הארכת החיים. מצב IE הוא לא משהו ש”פועל מעצמו כשמתקינים Edge” — הוא נפתח עם מנוע מסדרת IE רק אחרי שמציינים את האתר היעד במדיניות (policy). שלושה ערוצי הגדרה:

שיטה הגדרה הערה
רשימת אתרים ב-Group Policy של Microsoft Edge מגרסה 78 ואילך, ב-“Configure the Enterprise Mode Site List” מציינים את מיקום ה-XML של רשימת האתרים ב-Enterprise Mode הצורה הבסיסית ביותר
שימוש ברשימת ה-IE הישן מדיניות “Use the Enterprise Mode IE website list” של Internet Explorer אם קיימת מדיניות בצד Edge, היא תקבל עדיפות
הפניית כל האינטראנט הפעלת Group Policy של Microsoft Edge מגרסה 77 ואילך: “Send all intranet sites to Internet Explorer” הטווח רחב, ולכן זה לא תחליף למיפוי מסודר

התנאים המקדימים: עדכונים אחרונים ל-Windows ול-Edge, תבנית הניהול (template) של Microsoft Edge מותקנת, ותכונת Windows של Internet Explorer 11 מופעלת. אם אחד מאלה חסר, מצב IE נכשל.

בנוסף, במצב IE פועלים גם פקדי ActiveX וגם Browser Helper Object. כלומר, הארכת החיים באמת עובדת. בדיוק בגלל זה, אם ממשיכים להשתמש בזה בלי לקבוע תנאי סיום, אי אפשר להיחלץ. איך לקלף מוסבר ב-מדריך היציאה ממערכת שתלויה במצב IE.

אופן החשיבה על הארכת חיים במצב IEתרשים המראה שרק אחרי שמציינים את האתר היעד במדיניות, המצב נפתח כמצב IE, ואפשר להאריך חיים כולל ActiveX, אבל אם לא קובעים תנאי סיום ומשתמשים בזה כך, אי אפשר להיחלץ.ציון אתר יעד במדיניותנפתח במצב IEהארכת חיים כולל ActiveXשימוש עם תנאי סיוםבלי תנאי סיום אי אפשר להיחלץ

איור 18: הארכת החיים של מצב IE “באמת עובדת” — בדיוק בגלל זה כדאי להשתמש בה יחד עם תנאי סיום.

בפרט אם משתמשים בפקד WebBrowser רק כמציג HTML פשוט, עדיפות ההחלפה גבוהה.

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

5.4. ActiveX עם בקרת התקן או מפרט ייחודי

ההמלצה: קודם לעטוף.

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

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

אם בונים מחדש רכיב מהסוג הזה רק בגלל “זה ממילא ישן”, יש סיכוי גבוה שבדיקות השטח יישרפו.

לכן, בטוח יותר להתחיל מכאן:

  1. לכלוא את הרכיב הקיים בתוך הגבול
  2. להוסיף לוג כדי לראות מה קורה
  3. לאסוף תרחישי בדיקה ותבניות ממכשיר אמיתי
  4. ורק אז לחתוך את הטווח הניתן להחלפה

זה לא מרשים, אבל בעבודה בפועל זה הכי יעיל.

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

איור 19: רכיב שנושא בקרת התקן או מפרט ייחודי — בסדר הזה בדיקות השטח פחות נשרפות.

6. אנטי-דפוסים נפוצים

אנטי-דפוס מה קשה בו תיקון ראשוני
כתיבה מחדש מלאה בגלל שיש ActiveX פספוס מפרט וניפוח מאמץ קודם מיפוי וחיתוך גבול
טעינת OCX‏ 32bit ישירות לתוך אפליקציית 64bit בלתי אפשרי עקרונית בידוד בצד ה-32bit או שינוי מבנה
קריאה ישירה ל-API של הפקד מתוך קוד המסך נוטה להפוך לבלתי-ניתן-להחלפה לעבור ל-adapter / facade
תפעול נוהל regsvr32 באופן ידני תקלה כל פעם עקב הבדל בין סביבות לשקול מתקין, סקריפט או מניפסט
להירגע כי יש מצב IE קל לבלבל בין הארכת חיים לתגובה קבועה לקבוע תוכנית החלפה ותנאי סיום
לא לתעד את ההתנהגות לפני ההחלפה אי אפשר לקבוע מתי זה הושלם להכין smoke test, דוגמאות נתונים ולוג

מבין אלה, שלושה נראים במיוחד בעבודה בפועל:

  1. ממהרים לכתיבה מחדש מלאה
  2. מזלזלים בחומת ה-bitness
  3. מפזרים API על פני כל האפליקציה

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

שלושת האנטי-דפוסים הנפוצים ביותרתרשים המראה שהימנעות משלושה דברים — מיהור לכתיבה מחדש מלאה, זלזול בחומת ה-bitness, ופיזור API על פני כל האפליקציה — מורידה משמעותית את שיעור התקלות.מיהור לכתיבה מחדש מלאההימנעות משלושת אלהזלזול בחומת ה-bitnessפיזור API על כל האפליקציהשיעור תקלות נמוך משמעותית

איור 20: מבין האנטי-דפוסים, שלושת אלה הכי נפוצים, וההימנעות מהם משפיעה הכי הרבה.

7. רשימת בדיקה להתחלת מעבר

בפרויקט ActiveX /‏ OCX, מוצלח יותר לעשות קודם מיפוי מלא ורק אז להיכנס למימוש. הסדר הוא בערך כך:

  1. למפות את ה-OCX /‏ DLL שנמצאים בשימוש
    • שם קובץ, גרסה, ProgID,‏ CLSID, ספק, קיום רישיון
  2. למפות איפה נעשה בהם שימוש
    • מסך, תכונה, דוח, התקן, batch, אינטגרציית Office וכדומה
  3. לבדוק את תנאי ה-bitness וה-host
    • 32bit /‏ 64bit,‏ in-proc /‏ out-of-proc, הנחת STA, תלות בדפדפן
  4. לבדוק את תנאי ההפצה
    • שיטת רישום, DLL תלויים, הרשאות מנהל, התקנה שקטה, שחזור בסביבה נקייה
  5. להכין smoke test
    • לא רק מסלול רגיל, גם כשל, חוסר חיבור ו-timeout
  6. ליצור גבול
    • adapter,‏ service,‏ facade, גישור לתהליך נפרד וכדומה
  7. לנסות ביחידה קטנה — מסך אחד, תכונה אחת, התקן אחד
  8. מהגבול שהצליח, להרחיב בהדרגה את לשמר / לעטוף / להחליף

אם מדלגים על השלבים האלה, בהמשך קשה אפילו להסביר “מה בכלל היה קשה”.

8. חלוקה גסה בין המצבים

מצב הבחירה הראשונה
שימוש פנים-ארגוני בלבד, יציב, שינוי קטן לשמר
רוצים רק ל-.NET-פיקציה סביבתית לעטוף
‏32bit /‏ 64bit מתנגשים לעטוף / לשנות מבנה
תלות ב-IE /‏ WebBrowser / ActiveX בדפדפן להחליף
רכיב UI פשוט עם תחליף להחליף
כולל בקרת התקן, דוחות או מפרט ייחודי לעטוף
נתקעים כל פעם ברישום או בהפצה לעטוף או להחליף

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

9. סיכום

איך מתייחסים ל-ActiveX /‏ OCX זה לא נושא שמחליטים לפי “זה legacy אז שונאים את זה”.

יש ארבע נקודות שצריך להסתכל עליהן קודם:

  1. האם הרכיב סתם UI, או ממשק גבול שנושא מפרט
  2. האם צריך להשתמש בו באותו תהליך
  3. האם 32bit /‏ 64bit, רישום, תלות בדפדפן או רישיון חוסמים
  4. האם אפשר לצפות בהתנהגות לפני ההחלפה

אם ארבעת אלה ברורים, בערך אפשר לסדר כך:

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

טכנולוגיית legacy היא לא נושא ללעג, אלא חפץ ממשי מלא היסטוריה וחוזים. עם זאת, כדי להתמודד עם החפץ הזה נדרש תכנון גבול.

כשלומדים לחשוב על “לשמר, לעטוף, להחליף” יחד, פרויקט ActiveX /‏ OCX הופך פתאום לבעיה שאפשר להתמודד איתה.

הסידור המסכםתרשים המראה שאם יציב וצפוי משמרים, אם רוצים לחדש רק את הסביבה עוטפים, אם רכיב UI או תלות בדפדפן מחליפים, ואם זה גוש מפרט קודם עוטפים ואז מחליפים בהדרגה.איך מתייחסים ל-ActiveX / OCXיציב וצפוי — לשמרחידוש הסביבה — לעטוףUI או תלות בדפדפן — להחליףגוש מפרט — לעטוף ואז להחליף בהדרגה

איור 21: אם ארבע נקודות ההסתכלות ברורות, לשמר / לעטוף / להחליף מסתדרים בצורה הזו.

10. סוג ההתייעצות שמתאים לזה

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

לדוגמה, ההתייעצויות האלה מתאימות מאוד:

  • רוצים למפות אילו OCX-ים באמת צריך להחליף
  • רוצים לסדר קודם רק את נקודות התקיעה של 32bit /‏ 64bit
  • רוצים לעבור ל-‏.NET, אבל לשמר רק את כניסת ה-COM
  • רוצים להשוות בין הארכת חיים לנסיגה עבור ActiveX שהספק שלו סיים תמיכה
  • רוצים לראות מאיפה אפשר להתחיל לקלף את התלות ב-IE /‏ WebBrowser
  • רוצים להפריד קודם בבטחה מסך אחד, תכונה אחת

בפרויקט ActiveX /‏ OCX, לרוב איך חותכים את הגבול קובע יותר מהמימוש עצמו. כשלב מקדים לשיפוץ מלא, יש ערך רב כבר רק בסידור מצב קיים, השוואת מבנים ותכנון סדר המעבר.

11. מקורות

  • Microsoft Learn: AxHost Class (System.Windows.Forms)
    • https://learn.microsoft.com/ja-jp/dotnet/api/system.windows.forms.axhost
  • Microsoft Learn: Aximp.exe (Windows フォーム ActiveX コントロール インポーター)
    • https://learn.microsoft.com/ja-jp/dotnet/framework/tools/aximp-exe-windows-forms-activex-control-importer
  • Microsoft Learn: How to: Add ActiveX Controls to Windows Forms
    • https://learn.microsoft.com/en-us/dotnet/desktop/winforms/controls/how-to-add-activex-controls-to-windows-forms
  • Microsoft Learn: Expose .NET Core components to COM
    • https://learn.microsoft.com/en-us/dotnet/core/native-interop/expose-components-to-com
  • Microsoft Learn: Registration-Free COM Interop
    • https://learn.microsoft.com/en-us/dotnet/framework/interop/registration-free-com-interop
  • Microsoft Learn: Microsoft Edge に関してよく寄せられる質問
    • https://learn.microsoft.com/ja-jp/deployedge/microsoft-edge-frequently-asked-questions
  • Microsoft Learn: What is Internet Explorer (IE) mode?
    • https://learn.microsoft.com/en-us/deployedge/edge-ie-mode
  • Microsoft Learn: WebBrowser Class (System.Windows.Forms)
    • https://learn.microsoft.com/en-us/dotnet/api/system.windows.forms.webbrowser
  • Microsoft Learn: Introduction to Microsoft Edge WebView2
    • https://learn.microsoft.com/en-us/microsoft-edge/webview2/
  • KomuraSoft Blog: הידע הבסיסי למניעת תקיעה עם STA/MTA של COM
    • /he/blog/sta-mta-com-relationship/
  • KomuraSoft Blog: כשמשתמשים ב-DLL native של ‏C++ מתוך ‏C#, למה עדיף לבנות עוטף עם ‏C++/CLI
    • /he/blog/cpp-cli-wrapper-for-native-dlls/
  • KomuraSoft Blog: מקרה שבו COM שימושי — כשרוצים לקרוא ל-DLL‏ 64bit מאפליקציית 32bit
    • /he/blog/com-case-study-32bit-to-64bit/
  • KomuraSoft Blog: מה זה COM /‏ ActiveX /‏ OCX — הסבר מרוכז על ההבדלים והקשרים
    • /he/blog/what-is-com-activex-ocx/
  • KomuraSoft Blog: איך משתמשים ב-DLL‏ .NET 8 מ-VBA עם טיפוסים — חשיפת COM ו-dscom TLB
    • /he/blog/dotnet8-dll-typed-vba-com-dscom-tlb/
  • KomuraSoft Blog: מהו Reg-Free COM — מנגנון להשתמש ב-COM ללא רישום
    • /he/blog/what-is-reg-free-com/
  • KomuraSoft Blog: המלכודות שברישום וב-bitness בפיתוח COM/OCX/ActiveX
    • /en/blog/2026/04/15/001-com-ocx-activex-pitfalls-visual-studio-bitness-admin-rights/
  • KomuraSoft Blog: מדריך היציאה ממערכת שתלויה במצב IE
    • /en/blog/2026/04/25/003-ie-mode-internal-web-system-life-extension-and-exit/
  • KomuraSoft Blog: אחרי מצב IE, האם WebView2 מספיק? — המגבלה שבה ActiveX לא פועל, ותכנון מעבר ריאלי
    • /en/blog/webview2-embed-web-ui-in-windows-apps/

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

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

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

שאלות נפוצות

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

כדאי להחליף ActiveX /‏ OCX?
ההחלטה לא נשענת על "האם זה ישן", אלא על מה שהרכיב הזה בעצם אחראי עליו. אם זה רק רכיב UI ויש לו תחליף — מחליפים; אם הוא כולל בקרת התקן, דוחות או פורמט קובץ ייחודי — קודם עוטפים ומסדרים את הגבול; ואם הוא יציב ותחום השינויים בו קטן — גם החלטה לשמר אותו ריאלית. גם "סתם לכתוב הכול מחדש" וגם "להקפיא לנצח כי זה מפחיד" הן בחירות עם שיעור תקלות גבוה.
אפשר להשתמש ב-OCX‏ 32bit מתוך אפליקציית 64bit?
לא ב-in-proc. ה-OCX חייב להתאים ל-bitness של התהליך שטוען אותו — זו מגבלה עקרונית. שלוש האפשרויות הריאליות הן: להשאיר בינתיים גם את אפליקציית ה-host כ-32bit; לכלוא אותו בתהליך 32bit נפרד (helper EXE או COM LocalServer) ולהתחבר אל צד ה-64bit דרך IPC או COM מסוג out-of-proc; או להתחיל להחליף מהמקומות שבהם אפשר להסיר את התלות ב-OCX.
מה עושים עם תלות ב-ActiveX בדפדפן?
עדיף להסתכל על זה מתוך עדיפות להחלפה. Microsoft Edge עצמו לא תומך ב-ActiveX, ומצב IE (IE mode) ממוקם כאמצעי הארכת חיים בלבד. גם פקד WebBrowser גורר אותו "עולם" של IE, ולכן אם רק רוצים להציג HTML, ‏WebView2 הוא המועמד הראשון. עם זאת, WebView2 אינו רכיב חלופי מלא: סקריפטים שמניחים DOM של IE וההנחות סביב window.external לא עוברים כמו שהם.
מה זה אומר בפועל "לעטוף" ActiveX /‏ OCX?
לכלוא את ה-ActiveX /‏ OCX בתוך גבול צר, ולהראות אותו לסביבה כ-API חדש או כרכיב מסך. יש כמה תבניות: host ב-WinForms עם AxHost, גישור לתהליך נפרד עם helper EXE של 32bit או LocalServer, וחלון תאימות COM בצד ה-‏.NET. כשעוטפים, לא מעתיקים את ה-API הישן בהמוניו — הופכים אותו לשיטות בגרגר גס, קובעים בגבול את האחריות ללוג, timeout והמרת חריגות, ובונים כך שאפשר יהיה להחליף בעתיד גם את התחליף עם אותו interface.

פרופיל הכותב

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

Go Komura

מנהל KomuraSoft LLC

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

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

חזרה לבלוג