C# 如何确保通过另一个可执行文件打开一个可执行文件?
有一个巧妙的小技巧,你可以使用它,让操作系统永远不会锁定C# 如何确保通过另一个可执行文件打开一个可执行文件?,c#,windows,C#,Windows,有一个巧妙的小技巧,你可以使用它,让操作系统永远不会锁定.dll的/.exe需要运行的.exe 假设我们的目录如下所示: >opener.exe >actualProgram.exe >dependency.dll private void LaunchApplication() { ProcessStartInfo start = new ProcessStartInfo(); //you could pass in arguments here if you wanted st
.dll
的/.exe
需要运行的.exe
假设我们的目录如下所示:
>opener.exe
>actualProgram.exe
>dependency.dll
private void LaunchApplication()
{
ProcessStartInfo start = new ProcessStartInfo();
//you could pass in arguments here if you wanted
start.Arguments = string.Empty;
//your EXE name
start.FileName = @"c:\your_program.exe";
start.WindowStyle = ProcessWindowStyle.Normal;
start.CreateNoWindow = true;
Process p = Process.Start(start);
while (0 == (int)p.MainWindowHandle)
{
System.Threading.Thread.Sleep(100);
}
processHandle = p.MainWindowHandle;
label1.Text = processHandle.ToString();
//the launched program will receive this message as a signal that it can continue
SendNotifyMessage(processHandle, 99999, UIntPtr.Zero, IntPtr.Zero);
}
我们还可以在其中添加更多的逻辑,我们可以使用这些逻辑来实际替换/更新actualProgram.exe
,尽管进程的实例正在打开。试试看:当通过“opener”加载依赖项和“实际”程序时,您将能够删除/修改/替换依赖项和“实际”程序。显然,这有其好处,即使更新更容易
但在“actual.exe”中,如何确保它是通过另一个可执行文件加载的,并且知道它是在没有对.exe
进行锁定的情况下加载的?如果有人只是加载“actual.exe”,即不通过“opener”,我希望确保进程立即退出
暗示
将命令行参数传递给actualProgram.exe
,让它知道它是由启动器启动的。(在oleksii对OP的评论中也提出)
在启动器中设置可由子进程继承的环境变量
使用记录在案的方法之一获取父进程id,并使用该方法获取有关启动进程的信息。(当然,如果父进程终止,Windows可以自由地将PID重新分配给新进程。)
在启动程序中创建一个内存映射文件/命名管道/等,用于将信息传递给子级
在子对象中手动加载和卸载库引用。如果它们是.Net程序集,则可以使用AssemblyResolve
事件,将文件从磁盘加载到字节数组中,并使用Assembly.Load(byte[],byte[])
重载
注意:只要在修改/移动/删除程序集之前手动或在运行时加载所有程序集,就可以了。此外,加载DLL后更改DLL可能对正在运行的进程没有影响。我说可能在这两种情况下都是这样,因为通常在运行时不使用库是一个好主意,特别是在您没有手动加载它们的情况下
另见:
在应用程序启动后向其发送自定义消息如何?启动的代码如下:
>opener.exe
>actualProgram.exe
>dependency.dll
private void LaunchApplication()
{
ProcessStartInfo start = new ProcessStartInfo();
//you could pass in arguments here if you wanted
start.Arguments = string.Empty;
//your EXE name
start.FileName = @"c:\your_program.exe";
start.WindowStyle = ProcessWindowStyle.Normal;
start.CreateNoWindow = true;
Process p = Process.Start(start);
while (0 == (int)p.MainWindowHandle)
{
System.Threading.Thread.Sleep(100);
}
processHandle = p.MainWindowHandle;
label1.Text = processHandle.ToString();
//the launched program will receive this message as a signal that it can continue
SendNotifyMessage(processHandle, 99999, UIntPtr.Zero, IntPtr.Zero);
}
您正在运行的应用程序将需要一个简短的自定义windows消息处理程序来监视“保持活动”信号
private bool allowedToLive=false;
//我们要等多久信号?应在<1秒内到达
私有int-TimeoutSeconds=1;
private DateTime appStartTime=DateTime.Now;
受保护的覆盖无效WndProc(参考消息m)
{
基准WndProc(参考m);
//收到这个特别的信息意味着我们可以活下去。
如果(!allowedToLive)
{
allowedToLive=(m.Msg==99999);
如果(!allowedToLive&&(TimeoutSeconds是一种有趣的方法,以前从未见过。我想如果它不是安全关键的,您可以在actualProgram.exe
中看到一个参数,opener.exe
将提供该参数。如果用户只需单击actualProgram.exe
它应该检查该参数是否存在并退出[在此处插入您的操作]。例如:opener=>actualProgram calledByOpener
在actualProgram
中有一个if(args[0]!=“calledByOpener”)exit-1;
有一些防止偶然误用的保护措施,如oleksii建议的,但您无法保护自己不受某些人的影响,这些人决定强制您的应用程序运行(对于初学者,他们可以分解代码,移除保护措施,然后重新组装)。如果您只是想阻止某人从Explorer或cmd启动actual.exe
,请将其重命名为类似于userdata.dat
,并将您的开启器重命名为actual.exe
。该名称不会阻止应用程序域加载它,但会阻止Explorer或cmd打开它。而且会阻止大多数用户使用它如果你选择了正确的名字,你就不会去戳它。