吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 620|回复: 10
收起左侧

[已解决] 如何使用反射来执行加载项dll里的按钮事件?

 关闭 [复制链接]
zhanglei1371 发表于 2023-12-13 13:24
本帖最后由 zhanglei1371 于 2023-12-14 08:17 编辑

我用vs创建了一个vsto项目,添加了一个按钮和测试代码: 0001.jpg
在Excel里也能正常点击,出现消息框。

我尝试用反射来执行这个按钮事件,再次新建一个新的vsto工程,代码如下:
Assembly a = Assembly.LoadFrom("E:\\TestVsto\\bin\\Debug\\TestVsto.dll");
        Type t = a.GetType("TestVsto.Ribbon1");
        MethodInfo m = t.GetMethod("Button1_Click", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Static);
        if (m != null)
        { //已经成功执行到这里;
                m.Invoke(t, new[] {sender, e}); //此处出错;
        }
错误信息如下:
0005.jpg
多次修改,始终都是这个错误提示。
不知该如何修改,望高人能解惑,谢谢!
-----------------------------------------------------
感谢@周易和@cdj68765 的帮助,问题已解决!

测试文件:https://wwi.lanzoup.com/iA3js1hqvz0b

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

610100 发表于 2023-12-13 13:33
本帖最后由 610100 于 2023-12-13 13:45 编辑

似乎是方法名搞错了?应该是button不是Button吧?另外参数改成null,null呢?
周易 发表于 2023-12-13 14:00
本帖最后由 周易 于 2023-12-14 09:09 编辑

非静态方法需要实例才能调用。

Activator.CreateInstance(type);

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
610100 + 1 + 1 我很赞同!

查看全部评分

 楼主| zhanglei1371 发表于 2023-12-13 20:23
周易 发表于 2023-12-13 14:00
[md]非静态方法需要实例才能调用。

```cs

谢谢回答,不过测试未通过。
可以测试下我发的源码:Object obj = Activator.CreateInstance(type);这句就出错了:
错误信息:System.Reflection.TargetInvocationException:“调用的目标发生了异常。”
NullReferenceException: 未将对象引用设置到对象的实例。
周易 发表于 2023-12-13 21:08
zhanglei1371 发表于 2023-12-13 20:23
谢谢回答,不过测试未通过。
可以测试下我发的源码:Object obj = Activator.CreateInstance(type);这句 ...
  1. 针对错误本身:创建实例需要自行处理构造函数参数。
  2. 如果目标程序集已经加载,那么GetField获取实例字段要比自行创建实例更符合现实场景。请明确一下需求。
 楼主| zhanglei1371 发表于 2023-12-13 21:33
周易 发表于 2023-12-13 21:08
[md]1. 针对错误本身:创建实例需要自行处理构造函数参数。
2. 如果目标程序集已经加载,那么`GetField` ...

哦,我的目的就是希望能通过反射来运行vsto加载项的Button1按钮,就是实例里的,您可以下载附件看看。
我现在有点怀疑,是否ribbon对象无法反射区执行按钮?
周易 发表于 2023-12-13 22:01
zhanglei1371 发表于 2023-12-13 21:33
哦,我的目的就是希望能通过反射来运行vsto加载项的Button1按钮,就是实例里的,您可以下载附件看看。
...

要调用方法的话非常简单。但是这么做意义不明。如果不考虑参数的话伪代码如下。实现是肯定可以实现的但是为什么要实现?

using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
    class Program
    {
        public delegate void ButtonClickDelegate();

        static void Main(string[] args)
        {
            Assembly assembly = Assembly.LoadFrom(@"TestVsto.dll");
            Type type = assembly.GetType("TestVsto.Ribbon1");
            MethodInfo method = type.GetMethod("Button1_Click", BindingFlags.Instance | BindingFlags.NonPublic);
            RuntimeHelpers.PrepareMethod(method.MethodHandle);
            IntPtr ptr = method.MethodHandle.GetFunctionPointer();
            ButtonClickDelegate del = (ButtonClickDelegate)Marshal.GetDelegateForFunctionPointer(ptr, typeof(ButtonClickDelegate));
            del();
        }
    }
}

免费评分

参与人数 3吾爱币 +5 热心值 +3 收起 理由
ps122 + 1 + 1 谢谢@Thanks!
zhanglei1371 + 2 + 1 谢谢@Thanks!
cdj68765 + 2 + 1 我很赞同!

查看全部评分

 楼主| zhanglei1371 发表于 2023-12-14 06:06
本帖最后由 zhanglei1371 于 2023-12-14 08:15 编辑
周易 发表于 2023-12-13 22:01
[md]要调用方法的话非常简单。但是这么做意义不明。如果不考虑参数的话伪代码如下。实现是肯定可以实现的 ...

谢谢大佬回复,已成功实现!

点评

可以把最终的解决方案放出来以供参考吗。  发表于 2023-12-14 09:40
ps122 发表于 2023-12-14 11:12
周易 发表于 2023-12-13 22:01
[md]要调用方法的话非常简单。但是这么做意义不明。如果不考虑参数的话伪代码如下。实现是肯定可以实现的 ...

大佬,如果考虑参数的话又该怎么处理?
 楼主| zhanglei1371 发表于 2023-12-14 17:26
周易 发表于 2023-12-13 21:08
[md]1. 针对错误本身:创建实例需要自行处理构造函数参数。
2. 如果目标程序集已经加载,那么`GetField` ...

感谢大佬的代码,已实现反射调用ribbon按钮事件。
测试发现win10完美通过。win7在调试时可能会存在问题,但是非调试模式就没问题了。
成品地址:
https://wwi.lanzoup.com/itd4P1hwd7zg
001.jpg
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2025-1-10 12:21

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表