搜索
bottom↓
回复: 10

vb.net直接运行内存中的exe程序

[复制链接]

出0入0汤圆

发表于 2018-6-18 11:52:08 | 显示全部楼层 |阅读模式
本帖最后由 cnxh 于 2018-6-18 13:03 编辑

RunNewApp这个模块中的,调用method.Invoke语句
如果是c#编写的exe程序 method的值是{Void Main()},写成method.Invoke(Nothing, Nothing),可以正确运行
如果是VB.NET编写的exe程序 method的值是{Void Main(System.String[])},怎么写都是不能正确


'Path 是exe程序名称包含后设置成,嵌入式资源
Private Sub WriteResourceFile(ByVal Path As String)
        '内存运行exe程序
        Dim _projectName As String = Assembly.GetExecutingAssembly().GetName().Name.ToString()
        Dim Name As String = Assembly.GetExecutingAssembly().GetName().Name.ToString()
        Dim _stream As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(_projectName + "." & Path )
        Dim br As BinaryReader = New BinaryReader(_stream)
        Dim bin As Byte() = br.ReadBytes(Convert.ToInt32(_stream.Length))
        Dim a As Assembly = Assembly.Load(bin)
        method = a.EntryPoint '获得内存中可执行文件的入口点
        Dim thd As System.Threading.Thread
        Dim ts As System.Threading.ThreadStart '在线程上执行特定的方法
        ts = New System.Threading.ThreadStart(AddressOf RunNewApp)
        thd = New System.Threading.Thread(ts)
        thd.Start()

    End Sub

    Dim method As MethodInfo
    Private Sub RunNewApp()
         If method IsNot Nothing Then
            method.Invoke(Nothing, nothing)'此句完成已在内存的exe程序运行
        End If
    End Sub

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

 楼主| 发表于 2018-6-18 13:45:35 | 显示全部楼层
vb.net不能运行的毛病找到了,要运行的exe源文件工程必须和调试的工程在同一个工程项目内,当单一个exe程序不能运行,如果只有一个exe程序不知道怎么解决

出0入0汤圆

 楼主| 发表于 2018-6-18 13:48:18 | 显示全部楼层
本帖最后由 cnxh 于 2018-6-18 13:52 编辑

谁能改一下下面说的那个Runner类,public void Run(string assemblyPath)这个函数,复制过来有错误


在Windows上从内存中启动.net程序(C#程序从内存中启动)


2018年02月27日 22:58:42       
阅读数:244







  通常,我们的程序是保存在计算机的硬盘上的,程序的启动是通过操作系统将硬盘上的文件加载到内存中并进行执行的。然而,操作系统打开磁盘上的可执行文件后,该可执行文件就会处于被打开状态。这样会产生一个问题:你无法对这个可执行文件进行修改和删除等操作。另外,C#程序本身具有一定的开源性,因为当你拿到.net的exe或dll文件后,可以很轻松的通过一些软件对其反编译,得到源代码。而且反编译得到的源代码与编写该程序的源代码几乎一模一样(这是题外话)。如果我们启动了程序后不会锁定磁盘上的文件又该如何操作呢?

  基本思路:1.先将可执行文件读取放在正在执行的程序中的一个数据块中,比如读入一个字节型数组中。

       2.再将这个数组的数据当成程序来执行。

  针对Windows上的.net程序类型分别有不同的解决方案。

  注意:被启动的程序需要的dll(无论是C#编写的还是C++编写的),存放的位置应该相对第一个程序的位置放置。

控制台和Winform程序

  首先我们在需要启动程序的地方执行以下代码。
var bin = File.ReadAllBytes(@"被启动程序的绝对路径")
Assembly asm = Assembly.Load(bin);
method = asm.EntryPoint;
System.Threading.Thread thd;
System.Threading.ThreadStart ts;
ts = new System.Threading.ThreadStart(RunNewApp);
thd = new System.Threading.Thread(ts);
thd.Start();

  其中method是一个私有字段,其定义为
private MethodInfo method;

  其中RunNewApp方法的定义为
private void RunNewApp()
{
   if (method != null)
       method.Invoke(null, null);
}

应用举例:

  1.在一个Winform中启动另一个Winform程序。比如我们在第一个winform程序中添加一个按钮,按钮的事件就是上面的代码。

  2.在一个控制台中启动另一个控制台程序。

WPF程序

  如果使用上面的代码用一个WPF程序启动从内存中启动另一个WPF程序,是会出错的,我们可以采用如下方法。

  这里提供了一个Runner类,其代码如下:
using System;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows;

namespace 你的程序的名称空间
{
    public class Runner : MarshalByRefObject
    {
        public static AppDomain RunInOtherDomain(string assemblyPath)
        {
            var ownType = typeof(Runner);
            string ownAssemblyName = ownType.Assembly.FullName;
            var childDomain = AppDomain.CreateDomain(Guid.NewGuid().ToString());
            childDomain.Load(ownAssemblyName);
            var runner = (Runner)childDomain.CreateInstanceAndUnwrap(ownAssemblyName, ownType.FullName);
            runner.Run(assemblyPath);
            return childDomain;
        }

        public void Run(string assemblyPath)
        {
            var otherAssemblyBytes = File.ReadAllBytes(assemblyPath);
            var assembly = AppDomain.CurrentDomain.Load(otherAssemblyBytes);
            AppDomain.CurrentDomain.AssemblyResolve += (sender, args) =>
            {
                throw new NotImplementedException("Probably need to do some work here if you depend on other assemblies.");
            };
            Application.ResourceAssembly = assembly;
            var app = assembly.GetExportedTypes().Single(t => typeof(Application).IsAssignableFrom(t));
            MethodInfo main = app.GetMethod("Main", BindingFlags.Static | BindingFlags.Public);
            main.Invoke(null, null);
        }
    }
}

当你需要启动你的第二个程序时,只需要使用如下代码:
Runner.RunInOtherDomain(@"被启动程序的绝对路径");

总结

  这样做有一些好处:开发人员没有必要去把真正需要执行可执行文件保存在硬盘上,可以将其保存在服务器上(或者加密后保存程序),让硬盘上的一个小程序来下载(解密)真正的可执行文件,放在内存中,并进行执行;当需要更新(修复)程序时,就可以在不关闭源程序的基础上进行程序更新;保护自己的程序不受源码级泄露的威胁。

  当然,这样做也可能会带来一些安全隐患,对于用户而言:下载的程序的安全性是无法考量的,因为用户是在不知情的情况下直接下载并执行了未知程序。

出0入0汤圆

 楼主| 发表于 2018-6-18 14:11:54 | 显示全部楼层

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?注册

x

出0入93汤圆

发表于 2018-6-18 14:45:02 | 显示全部楼层
我只想问一句:杀软在打瞌睡么?

出0入0汤圆

 楼主| 发表于 2018-6-18 15:05:38 | 显示全部楼层
本帖最后由 cnxh 于 2018-6-18 15:25 编辑
takashiki 发表于 2018-6-18 14:45
我只想问一句:杀软在打瞌睡么?


杀软无提示,exe程序可以运行,好像控制台也看不到运行的进程,应该是和主程序是同一个进程,内存运行的exe关闭后,才跳出那几句运行exe的语句,
打开exe这句语句应该是阻塞的,这样做防止工程内需要运行的exe程序释放到硬盘时在运行,被拷贝

出0入0汤圆

 楼主| 发表于 2018-6-18 15:39:36 | 显示全部楼层
搞的我有点乱,有些自己写的exe程序又可以,不知道是不是有引用外部dll库和加密的原因

出0入22汤圆

发表于 2018-6-18 21:10:59 来自手机 | 显示全部楼层
看起来有点高大上啊。

出0入0汤圆

发表于 2018-6-18 22:13:19 | 显示全部楼层

我建议是断点到调用失败的地方,或者把识别出来的方法打印出来,看看有没有把目标找到。
要不仔细看看调试输出,看看有没有奇怪的地方

出0入0汤圆

发表于 2018-6-19 11:07:27 | 显示全部楼层
标题霸气! 不过还是建议改一下吧。

出0入0汤圆

 楼主| 发表于 2018-6-19 22:32:33 | 显示全部楼层
不好意思标题违规了码,我想不管有没有违规想改一下标题,找不到入口
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-25 13:11

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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