ActiveX / OCX: להשאיר, לעטוף או להחליף

· עודכן בתאריך: · · COM, ActiveX, OCX, .NET, פיתוח Windows, modernization

היסטוריית עדכונים (גרסה ראשונה, פורסמה בתאריך 12 Mar 2026)
פרסום ראשון
לצטט את המאמר הזה(DOI: 10.5281/zenodo.22173380)

מאמר זה מאוחסן בארכיון Zenodo. להלן גם ה-DOI שתמיד מפנה לגרסה האחרונה וגם ה-DOI המקובע לגרסה שאתם קוראים.

Go Komura (2026). ActiveX / OCX: להשאיר, לעטוף או להחליף. KomuraSoft LLC. https://doi.org/10.5281/zenodo.22173380 https://comcomponent.com/he/blog/activex-ocx-keep-wrap-replace-decision-table/

DOI (הגרסה האחרונה)
10.5281/zenodo.22173380
DOI (הגרסה הזו)
10.5281/zenodo.22173381

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

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

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

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

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

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

תוכן עניינים

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

ב-diagram, solid line מציינת relation שתמיד מתקיים ו-dashed line מציינת relation מותנה (התנאים מופיעים בהסבר של כל relation ב-detail page). הרשימה המלאה של ה-relations (סה”כ 24, כולל evidence ו-certainty) וההגדרות של ה-concepts המרכזיים נמצאות ב-detail page של ה-knowledge map (ביפנית). Data: JSON-LD / Turtle

1. קודם כל, המסקנות

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

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

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

בסדר הזה, קל בהרבה לקבל החלטה.

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

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

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

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

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

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

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

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

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

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

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

מונח הגייה / שם מלא משמעות
CLSID Class ID GUID שמזהה באופן ייחודי את המימוש (המחלקה) של רכיב COM. גם registration ב-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 ב-Registry כדי שיהיה אפשר להשתמש בו מ-COM
AxHost — מחלקת בסיס לאירוח פקד ActiveX בתוך Windows Forms
AxImp ActiveX Control Importer כלי שמייצר מ-OCX assembly עוטף עבור Windows Forms
in-proc / out-of-proc בתוך ה-process / מחוץ ל-process האם זה רץ באותו process כמו הקורא (DLL או OCX), או ב-process נפרד (שרת EXE)
LocalServer — צורה שבה שרת COM רץ כ-EXE ב-process נפרד. מאפשרת לעבור את חומת ה-bitness ולבודד קריסות
Reg-Free COM / side-by-side COM ללא registration מנגנון שפותר COM לפי מידע שכתוב במניפסט של האפליקציה, בלי registration ב-Registry
רישיון design-time / runtime בזמן פיתוח / בזמן ריצה בפקדים של vendors, לפעמים הטיפול ברישיון שונה בין הדבקה על המסך במחשב הפיתוח לבין הרצה אצל הלקוח
adapter / facade — טיפוס תכנוני שמחליף API ישן ומפורט ב-API גס ונוח יותר
STA / MTA Single / Multi Threaded Apartment מודל ה-threading של COM. קובע מאיזה thread מותר לקרוא

3. טבלת ההחלטה

3.1. סקירה

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

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

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

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

3.2. החלטה להשאיר

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

דרך עטיפה מה עושים ראשון הסבר מפורט
host ב-WinForms + AxHost ב-Visual Studio, לחיצה ימנית על ה-Toolbox ← “Choose Toolbox Items” ← בוחרים את היעד בלשונית “COM Components”. בשורת פקודה: aximp המלכודות שב-registration וב-bitness בפיתוח COM/OCX/ActiveX
helper EXE של 32bit / LocalServer רושמים את ה-EXE של 32bit כשרת COM, וקוראים לו מצד ה-64bit ב-out-of-proc COM שימושי — מקרה של קריאה ל-DLL 64bit מאפליקציית 32bit
Reg-Free COM כותבים file ו-comClass במניפסט של האפליקציה, ופותרים בלי registration ב-Registry מהו Reg-Free COM — מנגנון להשתמש ב-COM ללא registration
צוהר תאימות 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, ב-Registry נכנס נתיב ה-EXE תחת HKEY_CLASSES_ROOT\CLSID\{CLSID}\LocalServer32. שרת EXE שנבנה עם ATL או MFC לרוב תומך, כמוסכמה, ב-self-registration וב-unregister עם MyServer.exe /regserver ו-/unregserver. אבל בגלל שהתצוגה ב-Registry נחלקת לפי bitness, חשוב תמיד לזכור ש-EXE של 32bit נרשם בצד ה-32bit של ה-Registry.

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

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

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

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

  • להפוך לשיטות בגרגר גס
  • לא לתת לקוד המסך לגעת ישירות ב-OCX
  • לתעד את הלוג הנדרש בכשל בגבול עצמו
  • לקבוע בגבול את האחריות ל-timeout, ניסיון חוזר והמרת exceptions
  • לבנות כך שגם התחליף העתידי יוכל להתחלף עם אותו 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 ללא registration, כולל שלבים מפורטים.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

כלומר:

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

איור 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, או רכיב שנושא spec

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

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

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

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

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

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

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

4.2. 32bit / 64bit וגבול ה-process

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

4.4. STA / message loop / callback

ActiveX / OCX הוא לא סתם קריאת DLL. לפעמים יש לו הנחות על מודל ה-threading של COM ועל ה-message loop.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

בפועל, נוח יותר מבנה שכולא ב-process 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 בגרגר גס.

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

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

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

כאן, לפני שרצים לכתוב helper EXE משלנו, יש שלב אחד שכדאי לבדוק קודם.

אם ה-OCX / DLL הזה הוא שרת COM מסוג in-proc, כלומר כזה שאפשר לרשום ב-InprocServer32, אפשר להעלות אותו על process ה-surrogate שמגיע עם Windows ולהוציא אותו כ-Local Server מסוג out-of-proc. מצמידים ל-CLSID ערך AppID, כותבים במפתח ה-AppID הזה DllSurrogate עם מחרוזת ריקה — וזה הכול, בלי שורת קוד אחת מצידנו. שלבי ה-registration מרוכזים ב-3.5 של המלכודות שב-registration וב-bitness בפיתוח COM/OCX/ActiveX.

אבל surrogate לא מוחק את הפער ב-bitness. מה שנעלם הוא רק המגבלה שחייבים לרוץ באותו process; הקריאות הופכות ל-out-of-proc, והעלות של marshaling ושל תקשורת בין-process נשארת במלואה.

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

מצב מה בוחרים הסיבה
automation object שמסתפק בקריאות לשיטות ובאירועים קודם surrogate ה-registration לבדו כבר הופך אותו ל-out-of-proc, ואין קוד לכתוב
הטיפוסים שעוברים ניתנים ל-marshaling דרך IDispatch או דרך proxy / stub רשומים קודם surrogate הטיפול במעבר הגבול כבר קיים
ל-CLSID הזה כבר יש registration של EXE, למשל LocalServer32 אין ל-surrogate תפקיד כאן הפעלת שרת ה-EXE או השירות תמיד מקבלת עדיפות
רוצים להשתמש בו כפקד ויזואלי שמדביקים על טופס והוא מצייר לחשוב על מבנה אחר ההנחה היא שהחלון נמצא בתוך ה-process של ה-host
קריאות קטנות בתדירות גבוהה, ותיווך ישיר שלהן יוצא כבד helper EXE משלנו צריך שכבה משלנו שתאגד אותן ל-API בגרגר גס
ל-interface ייחודי אין marshaler helper EXE משלנו מהר יותר להכין proxy / stub או לקבוע בעצמנו את הטיפוסים בגבול
רוצים להחזיק בעצמנו את סדר האתחול, החיבור מחדש, ה-timeout והלוג helper EXE משלנו אורך החיים של process ה-surrogate נתון בידי COM

כלומר, surrogate הוא המהלך המינימלי ששווה לנסות ראשון, וה-EXE שלנו הוא המהלך למי שרוצה לתכנן את הגבול בעצמו. השורה בטבלה של 3.1 — “רוצים לטעון OCX 32bit לתוך process 64bit ישירות ← לעטוף / שינוי מבנה” — לא משתנה. פשוט תקראו את ה”לעטוף” הזה כמשהו שיש בתוכו שני שלבים.

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

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

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

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

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

נכתוב גם את הטיפול הקונקרטי בצד הארכת החיים. IE mode הוא לא משהו ש”פועל מעצמו כשמתקינים 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 mode נכשל.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

6. anti-patterns נפוצים

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

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

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

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

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

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

7. checklist להתחלת מעבר

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

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

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

8. איך בוחרים בפועל

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

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

9. סיכום

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

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

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

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

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

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

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

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

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

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

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

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

  • רוצים למפות אילו OCX-ים באמת צריך להחליף
  • רוצים לקבע קודם רק את נקודות התקיעה של 32bit / 64bit
  • רוצים לעבור ל-.NET, אבל לשמר רק את כניסת ה-COM
  • רוצים להשוות בין הארכת חיים לנסיגה עבור ActiveX שה-vendor שלו סיים תמיכה
  • רוצים לראות מאיפה אפשר להתחיל לקלף את התלות ב-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/
  • Microsoft Learn: DllSurrogate
    • https://learn.microsoft.com/en-us/windows/win32/com/dllsurrogate
  • Microsoft Learn: Registering the DLL Server for Surrogate Activation
    • https://learn.microsoft.com/en-us/windows/win32/com/registering-the-dll-server-for-surrogate-activation
  • 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 ללא registration
    • /he/blog/what-is-reg-free-com/
  • KomuraSoft Blog: המלכודות שב-registration וב-bitness בפיתוח COM/OCX/ActiveX
    • /en/blog/2026/04/15/001-com-ocx-activex-pitfalls-visual-studio-bitness-admin-rights/
  • KomuraSoft Blog: מדריך היציאה ממערכת שתלויה ב-IE mode
    • /en/blog/2026/04/25/003-ie-mode-internal-web-system-life-extension-and-exit/
  • KomuraSoft Blog: אחרי IE mode, האם WebView2 מספיק? — המגבלה שבה ActiveX לא פועל, ותכנון מעבר ריאלי
    • /en/blog/webview2-embed-web-ui-in-windows-apps/

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

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

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

שאלות נפוצות

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

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

פרופיל הכותב

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

Go Komura

מנהל KomuraSoft LLC

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

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

חזרה לבלוג