#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. Гениально! Ваш код устраняет проблему, и перетаскивание теперь работает! 🙂 Большое вам спасибо