Перетаскивание приложения C # не работает при вызове в памяти

#c# #drag-and-drop

#c# #перетаскивание

Вопрос:

Я создал приложение под названием MemoryLauncher, которое извлекает двоичный файл исполняемого файла другого приложения в память и запускает его. Цель MemoryLauncher — позволить мне перезаписать .Бывшие версии других программ, когда доступно обновление, без необходимости беспокоиться о том, что другой пользователь запустит и заблокирует программу. У меня это работает действительно хорошо, за исключением одной вещи: перетаскивание. Я создал программу диспетчера устройств, которую будет выполнять MemoryLauncher, и для этой программы требуется функция перетаскивания, но, похоже, она отключена, когда .EXE вызывается в память. Если я запускаю диспетчер устройств нормально, то функция перетаскивания работает нормально. Я подумал, что, возможно, это связано с повышенными привилегиями, поэтому я попытался добавить следующий код в device mananager и 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 amp;amp; 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;
        }
    }
  

Комментарии:

1. Вы должны заменить makeBinary на File.ReadAllBytes .

Ответ №1:

Я не знаю точного ответа на ваш вопрос, но это не лучший способ запустить программу без ее блокировки.
Вам следует использовать .Функция теневого копирования Net, которая специально разработана для этого.
Я написал следующий лаунчер, используя его:

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

Комментарии:

1. Гениально! Ваш код устраняет проблему, и перетаскивание теперь работает! 🙂 Большое вам спасибо