拖放- c#应用程序的拖放在内存中调用时不起作用

本文关键字:拖放 调用 不起作用 内存 应用程序 | 更新日期: 2023-09-27 17:53:25

我制作了一个名为MemoryLauncher的应用程序,它将另一个应用程序的可执行文件的二进制文件拉入内存并运行它。MemoryLauncher的目的是允许我在更新可用时覆盖其他程序的。exe,而不必担心另一个用户运行并锁定程序。这对我来说非常有效,除了一件事:拖放。我已经创建了一个设备管理器程序,MemoryLauncher将执行,该程序需要拖放功能,但当. exe被调用到内存中时,它似乎被禁用了。如果我正常启动设备管理器,那么拖放功能就可以正常工作。我认为这可能是由于特权的提升,所以我尝试将以下代码添加到设备管理器和MemoryLauncher中,但没有运气:

ChangeWindowMessageFilterEx(this.Handle, WM_DROPFILES, MSGFLT_ADD, IntPtr.Zero);
ChangeWindowMessageFilterEx(this.Handle, WM_COPYDATA, MSGFLT_ADD, IntPtr.Zero);
ChangeWindowMessageFilterEx(this.Handle, WM_COPYGLOBALDATA, MSGFLT_ADD, IntPtr.Zero);

下面是MemoryLauncher程序的代码,它实际获取另一个应用程序的二进制文件并运行它:

static class Program
    {
        private static string[] mainArgs;
        /// <summary>
        /// The main entry point for the application.
        /// </summary>
        [STAThread]
        static void Main(string[] args)
        {
            mainArgs = args;
            if (mainArgs.Length == 0)
                MessageBox.Show("Please run from shortcut or command line.", "MemoryLauncher.EXE");
            else
            {
                try
                {
                    if (mainArgs[0].Substring(mainArgs[0].Length - 1) != "''")
                        mainArgs[0] += "''";
                    byte[] bin = makeBinary(Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), mainArgs[0]), mainArgs[1]));
                    AppDomain ad = AppDomain.CurrentDomain;
                    ad.AssemblyResolve += new ResolveEventHandler(ad_AssemblyResolve);
                    Assembly assembly = Assembly.Load(bin);
                    MethodInfo method = assembly.EntryPoint;
                    if (method != null)
                    {
                        Object obj = assembly.CreateInstance(method.Name);
                        String[] argsToPass = null;
                        if (mainArgs.Length > 2 && mainArgs[2] == "/a")
                        {
                            argsToPass = new string[mainArgs.Length - 1];
                            for (int i = 3; i < mainArgs.Length; i++)
                                argsToPass[i - 3] = mainArgs[i];
                        }
                        if (argsToPass != null)
                            method.Invoke(obj, new object[] { argsToPass });
                        else
                            method.Invoke(obj, null);
                    }
                }
                catch (Exception e) { MessageBox.Show("ERROR: " + e.Message, "MemoryLauncher.EXE"); }
            }
        }
        static Assembly ad_AssemblyResolve(object sender, ResolveEventArgs resolveArgs)
        {
            //Load the assembly from the specified path.
            AssemblyName assemblyName = new AssemblyName(resolveArgs.Name);
            string folder = mainArgs[0];
            byte[] bin = makeBinary(Path.Combine(Path.Combine(Directory.GetCurrentDirectory(), folder), assemblyName.Name + ".dll"));
            return Assembly.Load(bin);
        }
        static byte[] makeBinary(string pathName)
        {
            FileStream fs = new FileStream(pathName, FileMode.Open);
            BinaryReader br = new BinaryReader(fs);
            byte[] bin = br.ReadBytes(Convert.ToInt32(fs.Length));
            fs.Close();
            br.Close();
            return bin;
        }
    }

拖放- c#应用程序的拖放在内存中调用时不起作用

我不知道你问题的确切答案,但这不是运行程序而不锁定它的最佳方式。
你应该使用。net的ShadowCopy特性,这是专门设计的。
我用它编写了以下启动器:

using System;
using System.IO;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Collections;
using System.Security.Policy;
[assembly: AssemblyVersion("1.1.0.0")]
namespace ShadowLauncher {
    static class Program {
        [STAThread]
        static int Main(string[] args) {
            if (args.Length == 0 || !File.Exists(args[0]))
                return 1;
            var assembly = args[0];
            var realArgs = new string[args.Length - 1];
            if (realArgs.Length > 0)
                Array.Copy(args, 1, realArgs, 0, realArgs.Length);
            var permissions = new PermissionSet(PermissionState.Unrestricted);
            AppDomain.CreateDomain(Path.GetFileNameWithoutExtension(assembly),
                AppDomain.CurrentDomain.Evidence,
                new AppDomainSetup {
                    ShadowCopyFiles = "true",
                    ConfigurationFile = assembly + ".config",
                    ApplicationBase = Path.GetDirectoryName(Path.GetFullPath(assembly))
                },
                permissions
            ).ExecuteAssembly(assembly, AppDomain.CurrentDomain.Evidence, realArgs);
            return 0;
        }
    }
}