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

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. #C | הטמעת ממשקי COM במצב NativeAOT‏

#C | הטמעת ממשקי COM במצב NativeAOT‏

מתוזמן נעוץ נעול הועבר תכנות
9 פוסטים 3 כותבים 299 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • קומפיונטק מנותק
    קומפיונטק מנותק
    קומפיונט
    כתב ב נערך לאחרונה על ידי
    #1

    ב - 8 NET. שהושק לפני כמה ימים, במיקרוסופט פיתחו בין היתר את התכונה Native-AOT, למי שלא מכיר זה מאפשר לקמפל קוד #C לקוד מכונה מקורי, ללא קוד IL ובלי שימוש במנגנון JIT. יש בזה הרבה מעלות (אין צורך בזמן ריצה מותקן, זמן טעינה מהיר, ועוד) אבל יש גם קצת מגבלות, כרגיל.
    אחת הבעיות היא הטמעת ממשקי COM בקוד, ראיתי שיש הרבה דיבור על זה ברשת, אבל בתכל'ס אני לא מצליח ליישם את זה.

    אני לוקח לדוגמא את הקוד הבא:

    using System.Runtime.InteropServices;
    using static Taskbar;
    
    try
    {
        var taskbar = (ITaskbarList3)new TaskBarCommunication();
    
        Console.WriteLine("COM interface created successfully");
    }
    catch (Exception exception)
    {
        Console.WriteLine($"Error at creating COM interface: {exception}");
    }
    
    Console.ReadLine();
    
    static class Taskbar
    {
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        [Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
        public interface ITaskbarList3
        {
            // ITaskbarList
            [PreserveSig] void HrInit();
            [PreserveSig] void AddTab(IntPtr hwnd);
            [PreserveSig] void DeleteTab(IntPtr hwnd);
            [PreserveSig] void ActivateTab(IntPtr hwnd);
            [PreserveSig] void SetActiveAlt(IntPtr hwnd);
    
            // ITaskbarList2
            [PreserveSig] void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
    
            // ITaskbarList3
            [PreserveSig] void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
            [PreserveSig] void SetProgressState(IntPtr hwnd, int state);
        }
    
        [ComImport]
        [ClassInterface(ClassInterfaceType.None)]
        [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
        public class TaskBarCommunication { }
    }
    

    קובץ הפרויקט:

    <Project Sdk="Microsoft.NET.Sdk">
      <PropertyGroup>
        <OutputType>Exe</OutputType>
        <TargetFramework>net8.0</TargetFramework>
        <ImplicitUsings>enable</ImplicitUsings>
        <Nullable>enable</Nullable>
        <PublishAot>true</PublishAot>
        <BuiltInComInteropSupport>true</BuiltInComInteropSupport>
      </PropertyGroup>
    </Project>
    

    כשאני מריץ עם: dotnet run זה רץ בלי בעיות, אבל כשאני מקמפל עם dotnet publish זה זורק את החריג הבא:

    System.InvalidProgramException: Common Language Runtime detected an invalid program. The body of method 'Void TaskBarCommunication..ctor()' is invalid.
       at Internal.Runtime.TypeLoaderExceptionHelper.CreateInvalidProgramException(ExceptionStringID, String) + 0x40
       at Internal.Runtime.CompilerHelpers.ThrowHelpers.ThrowInvalidProgramExceptionWithArgument(ExceptionStringID, String) + 0x9
       at ComWithNativeAotSample.Taskbar.TaskBarCommunication..ctor() + 0x15
       at Program.<Main>$(String[] args) + 0x34
    

    משהו יכול להסביר לי איך אני אמור לשנות את הקוד כדי שזה יעבוד עם native-aot?

    תגובה 1 תגובה אחרונה
    0
    • dovidD מנותק
      dovidD מנותק
      dovid ניהול
      כתב ב נערך לאחרונה על ידי
      #2

      https://github.com/dotnet/runtimelab/issues/306
      https://github.com/dotnet/runtime/issues/69919

      מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

      בכל נושא אפשר ליצור קשר dovid@tchumim.com

      תגובה 1 תגובה אחרונה
      0
      • חגיח מנותק
        חגיח מנותק
        חגי
        כתב ב נערך לאחרונה על ידי
        #3
        פוסט זה נמחק!
        תגובה 1 תגובה אחרונה
        0
        • קומפיונטק מנותק
          קומפיונטק מנותק
          קומפיונט
          כתב ב נערך לאחרונה על ידי
          #4

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

          dovidD תגובה 1 תגובה אחרונה
          0
          • חגיח מנותק
            חגיח מנותק
            חגי
            כתב ב נערך לאחרונה על ידי חגי
            #5

            בסוף אחד הקישורים הם מציינים בהקשר הזה שהם מתחילים להוסיף תמיכה לcode generator עבור רכיבי COM, ניסית לבדוק אם זה פותר את השגיאה?
            https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#source-generated-com-interop

            קומפיונטק תגובה 1 תגובה אחרונה
            0
            • dovidD מנותק
              dovidD מנותק
              dovid ניהול
              השיב לקומפיונט ב נערך לאחרונה על ידי dovid
              #6

              @קומפיונט כתב ב#C | הטמעת ממשקי COM במצב NativeAOT‏:

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

              אתה לא כ"כ מכיר כי כתוב שמה שהם לא מתכוננים לתת תמיכה לCOM interop נכון לעכשיו (וזה נכתב כבר ב2020 וזה עדיין בתוקף).

              מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

              בכל נושא אפשר ליצור קשר dovid@tchumim.com

              קומפיונטק תגובה 1 תגובה אחרונה
              0
              • קומפיונטק מנותק
                קומפיונטק מנותק
                קומפיונט
                השיב לdovid ב נערך לאחרונה על ידי
                #7

                @dovid לא שמתי לב שזה כתוב שם, אבל אני יודע שאפשר ליישם ממשקי COM ב native-aot, בדקתי את קוד המקור של avalonia שתומכת ב native-aot באופן מלא, וראיתי שהם פיתחו תת פרויקט (MicroCom) שמחולל קוד לממשקי COM מקבצי idl. לא התעמקתי בזה כ"כ כי אני לא מכיר קבצי idl, בתכלס אני שואל מה הדרך הכי קלה ליישם ממשקי COM עם או בלי מיקרוסופט?

                תגובה 1 תגובה אחרונה
                0
                • קומפיונטק מנותק
                  קומפיונטק מנותק
                  קומפיונט
                  השיב לחגי ב נערך לאחרונה על ידי
                  #8

                  @חגי כתב ב#C | הטמעת ממשקי COM במצב NativeAOT‏:

                  בסוף אחד הקישורים הם מציינים בהקשר הזה שהם מתחילים להוסיף תמיכה לcode generator עבור רכיבי COM, ניסית לבדוק אם זה פותר את השגיאה?
                  https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotnet-8#source-generated-com-interop

                  ניסיתי גם את זה ונשאר עם אותה שגיאה (זה מגנרט קוד, אבל ב-native-aot זה זורק אותו חריג), אולי לא ממשתי את זה נכון (יש דרך אחרת לקבל מופע של ממשק COM?)

                  static partial class Taskbar
                  {
                      [GeneratedComInterface]
                      [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
                      [Guid("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF")]
                      public partial interface ITaskbarList3
                      {
                          // ITaskbarList
                          [PreserveSig] void HrInit();
                          [PreserveSig] void AddTab(IntPtr hwnd);
                          [PreserveSig] void DeleteTab(IntPtr hwnd);
                          [PreserveSig] void ActivateTab(IntPtr hwnd);
                          [PreserveSig] void SetActiveAlt(IntPtr hwnd);
                  
                          // ITaskbarList2
                          [PreserveSig] void MarkFullscreenWindow(IntPtr hwnd, [MarshalAs(UnmanagedType.Bool)] bool fFullscreen);
                  
                          // ITaskbarList3
                          [PreserveSig] void SetProgressValue(IntPtr hwnd, ulong ullCompleted, ulong ullTotal);
                          [PreserveSig] void SetProgressState(IntPtr hwnd, int state);
                      }
                  
                      [ComImport]
                      [GeneratedComClass]
                      [ClassInterface(ClassInterfaceType.None)]
                      [Guid("56FDF344-FD6D-11d0-958A-006097C9A090")]
                      public partial class TaskBarCommunication { }
                  }
                  
                  תגובה 1 תגובה אחרונה
                  0
                  • קומפיונטק מנותק
                    קומפיונטק מנותק
                    קומפיונט
                    כתב ב נערך לאחרונה על ידי
                    #9

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

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

                    public static partial class ComActivator
                    {
                        [LibraryImport("ole32")]
                        private static partial int CoCreateInstance(
                            ref Guid clsid,
                            nint pUnkOuter,
                            int dwClsContext,
                            ref Guid iid,
                            [MarshalAs(UnmanagedType.Interface)] out object pObj
                        );
                    
                        public static TInterface ActivateClass<TInterface>(Guid clsid, Guid iid)
                        {
                            Debug.Assert(iid == typeof(TInterface).GUID);
                    
                            var hResult = CoCreateInstance(ref clsid, default, 1, ref iid, out var obj);
                    
                            if (hResult < 0)
                            {
                                Marshal.ThrowExceptionForHR(hResult);
                            }
                    
                            return (TInterface)obj;
                        }
                    }
                    

                    ב. למחלקה ITaskbarList3 הוספתי את התכונה GeneratedComInterface

                    ג. ככה אני מקבל את האובייקט:

                    var clsid = Guid.Parse("56FDF344-FD6D-11D0-958A-006097C9A090"); // TaskBarList
                    var iid = Guid.Parse("EA1AFB91-9E28-4B86-90E9-9E9F8A5EEFAF"); // ITaskBarList3
                    
                    var taskbar = ComActivator.ActivateClass<ITaskbarList3>(clsid, iid);
                    

                    קישור שעזר לי: https://learn.microsoft.com/en-us/dotnet/standard/native-interop/tutorial-comwrappers

                    נ.ב. מצאתי עוד פתרון עם ComWrappers אבל הפתרון הראשון עובד מצויין אז השתמשתי בו.

                    תגובה 1 תגובה אחרונה
                    4

                    בא תתחבר לדף היומי!
                    • התחברות

                    • אין לך חשבון עדיין? הרשמה

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