如何确保通过另一个可执行文件打开可执行文件?

时间:2015-08-19 13:13:59

标签: c# windows

有一个巧妙的小技巧,你可以用来永远不让操作系统锁定.dll / .exe的{​​{1需要运行。

让我们说我们的目录如下:

>opener.exe
>actualProgram.exe
>dependency.dll

作为一个基本的例子,我们可以这样做:

.exe

我们还可以在其中添加更多逻辑,尽管正在打开该进程的实例,但我们可以使用它来实际替换/更新namespace Opener { class Program { static void Main(string[] args) { AppDomain domain = AppDomain.CurrentDomain; AppDomain newDomain = AppDomain.CreateDomain( domain.FriendlyName, domain.Evidence, domain.BaseDirectory, domain.RelativeSearchPath, true, // "shadow copy" files: copy rather than lock domain.SetupInformation.AppDomainInitializer, domain.SetupInformation.AppDomainInitializerArguments ); string assembly = System.Reflection.Assembly.GetExecutingAssembly().Location + "\\..\\actualProgram.exe"; newDomain.ExecuteAssembly(assembly, args); } } } 。试一试:你将能够删除/修改/替换依赖项和"实际的"通过"开启者"加载程序。显然这有其好处,即更新更容易。

但是在你的" actual.exe"中,你怎么能确定它是通过另一个可执行文件加载的,并且知道它是在actualProgram.exe没有锁定的情况下加载的?如果有人要加载" actual.exe",即不是通过"开启者",我想确保该过程立即退出。

提示?

2 个答案:

答案 0 :(得分:2)

  1. 将命令行参数传递给actualProgram.exe,让它知道它是由启动器启动的。 (在Oleksii的评论中也提出了建议)
  2. 在启动器中设置一个可由子进程继承的环境变量。
  3. 使用其中一种记录的方法获取父进程ID,并使用该方法获取有关启动进程的信息。 (当然,如果父进程终止,Windows可以自由地将PID重新分配给新进程。)
  4. 创建一个内存映射文件/命名管道/ etc。在发射器中,可用于将信息传递给孩子。
  5. 手动加载和卸载子项中的库引用。如果它们是.Net程序集,则可以使用AssemblyResolve事件,将文件从磁盘加载到字节数组中并使用Assembly.Load(byte[], byte[])重载。
  6. 注意:只要在修改/移动/删除它们之前手动或由运行时加载所有程序集,您可能就可以了。此外,在加载DLL后更改DLL 可能对正在运行的进程没有影响。我可能在两种情况下都说过,因为在运行时将库单独保留通常是个好主意,特别是如果你没有手动加载它们。

    另见:

答案 1 :(得分:0)

如何在启动后向应用程序发送自定义消息? 启动的代码将是这样的:

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;
//how long will we wait for the signal?  should arrive in < 1 second
private int TimeoutSeconds = 1;
private DateTime appStartTime = DateTime.Now;

protected override void WndProc(ref Message m)
{
  base.WndProc(ref m);
  //receiving the special message means we are allowed to live.
  if(!allowedToLive)
  {
    allowedToLive = (m.Msg == 99999);
    if (!allowedToLive && (TimeoutSeconds <= DateTime.Now.Subtract(appStartTime).Seconds))
    {
      //times up.  quit.
      Application.Exit();
    }
  }
}

如果您不想依赖Windows消息的时间,您可以更改目标程序以启动,但实际上在收到自定义消息之前不会开始执行任何操作。