[Win10][.NET Desktop] 迁移 Framework 项目至 Core3.1

概述

由于自 netcore 3.0 以来,dotnet 将许多东西都在往 netcore 上般,甚至连 windows gui 的 Winform 和 WPF 都搬了过去,这看起来要放弃framework 的节奏啊,而且最新的vs还在大更新中支持了 netcore 的 windows 窗体设计器,而且 netcore 中的项目组织方式也变化了许多,最主要的就是可以通过配置项目文件同时生成多版本的库(最近才知道,惭愧啊)。

预览

这次搬迁的是以前的一个Windows 10 Toast Notification 模块,这个模块不是很大,但里面用的工具类不是很常用,搬迁时就碰到了一个问题:

COM 注册方法被 Net Core 团队移除了 !去看 NetCore 团队的 git 发现 System.Runtime.InteropServices 下的好多类都被删除了,而且有一个也不知道是谁的回答(link),感觉应该不会再添加回去这个方法了。


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

以我目前用到的功能,我觉得这个方法的作用就是将一个类型注册到COM中,使你可以在其他进程中通过GUID去获得一个这个类型的实例进行某种操作
当然,上面的回答中也给了代替解决方法 就是用 RunningObjectTable 来实现类型的注册,也不知道是不是我这个应用环境比较特殊还是怎么的,

[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);

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

好吧,我只能去找 RegisterTypeForComClients 的源码,找到源码后我直接呆了(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 类型

不过在差不多查了一天以后,终于还是有些收获的 在 excel Dna 的 git 上发现了其一个使用实例,因此就进行了搬迁工作。


        [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;
        }

然后是继承这个接口实现一个类 并在 CreateInstance 中返回你要创建类型的实例 (ref
最后有一点不同的是在 exceldna 中,最后传入 CoRegisterClassObject 的是

Marshal.GetIUnknownForObject(factory);

获得的IUnknown接口,但在我这里这个不好使,而直接传入这个工厂类是好使的

最后我的项目 ToastHelper
码云
Github
是让你的 net desktop app 发送win10样式通知的工具库

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值