拖放- 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;
}
}
我不知道你问题的确切答案,但这不是运行程序而不锁定它的最佳方式。
你应该使用。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;
}
}
}