[Win10][.NET Desktop] Migrate Framework project to Core3.1

Overview

Since netcore 3.0, dotnet has moved many things like netcore, even the Winform and WPF of windows gui have been moved over, it seems to abandon the rhythm of the framework, and the latest vs is still supported in a major update Netcore's windows form designer has been added, and the project organization in netcore has also changed a lot. The most important thing is that you can generate multiple versions of the library at the same time by configuring the project file (I only learned about it recently, ashamed).

Preview

This time I relocated a previous Windows 10 Toast Notification module. This module is not very large, but the tools used in it are not very commonly used. I encountered a problem during the relocation:

The COM registration method was removed by the Net Core team! I went to the git of the NetCore team and found that many classes under System.Runtime.InteropServices have been deleted, and there is an answer ( link ) that I don't know who it is , and I feel that this method should not be added again.


var regService = new RegistrationServices();
regService.RegisterTypeForComClients(
    typeof(T),
    RegistrationClassContext.LocalServer,
    RegistrationConnectionType.MultipleUse);

With the function I currently use, I think the function of this method is to register a type in COM, so that you can obtain an instance of this type through GUID in other processes to perform certain operations.
Of course, the answer above is also The alternative solution is to use RunningObjectTable to implement type registration. I don’t know if my application environment is special or something.

[DllImport("Ole32.dll")]
public static extern void GetRunningObjectTable(int reserved,out IRunningObjectTable pprot);

[DllImport("Ole32.dll")]
static extern int CreateClassMoniker([In] ref Guid rclsid, out IMoniker ppmk);

IMoniker moniker;
IRunningObjectTable rot;
GetRunningObjectTable(0, out rot);
CreateMoniker([你的一个类型的GUID的ref],out moniker);
rot.Register(1, obj, moniker);

//这样调用成功了以后好像没有什么用

Well, I can only find the source code of RegisterTypeForComClients. After finding the source code, I just stayed ( ref ):

[System.Security.SecurityCritical]  // auto-generated
[ResourceExposure(ResourceScope.None)]
[MethodImplAttribute(MethodImplOptions.InternalCall)]
private static extern int RegisterTypeForComClientsExNative(Type t, RegistrationClassContext clsContext, RegistrationConnectionType flags);

//遇见这种方法在 NET 中就很难受了,因为 framework 的 clr 没有开源,而这个类刚好又是被core删掉的类,所以就没法找了
//不过这里官方给了个提示 CoRegisterClassObject ,不过很可惜,这个方法的第二个参数没什么资料,这个也是卡了最久的地方
//只能在 PInvoke上找到 
[DllImport("ole32.dll")]
static extern int CoRegisterClassObject(
[MarshalAs(UnmanagedType.LPStruct)] Guid rclsid,
[MarshalAs(UnmanagedType.IUnknown)] object pUnk,
uint dwClsContext,
uint flags,
out uint lpdwRegister);

// IUnknown 也是一个 COM 类型

However, after almost a day of investigation, I finally found a use case on the git of excel DNA with some gains , so the relocation work was carried out.


        [ComImport]
        [Guid(gstrIClassFactory)]
        [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
        internal interface IClassFactory
        {
    
    
            // For HRESULTs use 
            [PreserveSig]
            HRESULT CreateInstance([In] IntPtr pUnkOuter,
                                [In] ref IID riid,
                                [Out] out IntPtr ppvObject);

            [PreserveSig]
            HRESULT LockServer([In, MarshalAs(UnmanagedType.VariantBool)] bool fLock);

            //        HRESULT STDMETHODCALLTYPE CreateInstance( 
            //        /* [unique][in] */ IUnknown *pUnkOuter,
            //        /* [in] */ REFIID riid,
            //        /* [iid_is][out] */ void **ppvObject) = 0;

            //    virtual /* [local] */ HRESULT STDMETHODCALLTYPE LockServer( 
            //        /* [in] */ BOOL fLock) = 0;
        }

Then it inherits this interface to implement a class and returns the instance ( ref ) of the type you want to create in CreateInstance. The
last difference is in exceldna, and the last one that passes in CoRegisterClassObject is

Marshal.GetIUnknownForObject(factory);

Obtained IUnknown interface, but this is not easy to use here, and it is easy to pass in this factory class directly

Finally, my project ToastHelper
code cloud
Github
is a tool library for your net desktop app to send win10 style notifications

Guess you like

Origin blog.csdn.net/q886yes/article/details/106970233