Вот ситуация.
У меня есть приложение, которое по всем причинам и задачам я должен рассматривать как черный ящик.
Мне нужно иметь возможность открывать несколько экземпляров этого приложения, каждый с набором файлов. Синтаксис для открытия этого executable.exe file1.ext file2.ext
.
Если я запускаю executable.exe
x количество раз без аргументов, новые экземпляры открываются нормально.
Если я запускаю executable.exe file1.ext
, а затем executable.exe file2.ext
, то второй вызов открывает файл 2 в существующем окне, а не создает новый экземпляр. Это мешает остальной части моего решения и является проблемой.
Мое решение оборачивает это приложение и выполняет над ним различные операции управления, вот один из моих классов-оболочек:
public class myWrapper
{
public event EventHandler<IntPtr> SplashFinished;
public event EventHandler ProcessExited;
private const string aaTrendLocation = @"redacted";
//private const string aaTrendLocation = "notepad";
private readonly Process _process;
private readonly Logger _logger;
public myWrapper(string[] args, Logger logger =null)
{
_logger = logger;
_logger?.WriteLine("Intiialising new wrapper object...");
if (args == null || args.Length < 1) args = new[] {""};
ProcessStartInfo info = new ProcessStartInfo(aaTrendLocation,args.Aggregate((s,c)=>$"{s} {c}"));
_process = new Process{StartInfo = info};
}
public void Start()
{
_logger?.WriteLine("Starting process...");
_logger?.WriteLine($"Process: {_process.StartInfo.FileName} || Args: {_process.StartInfo.Arguments}");
_process.Start();
Task.Run(()=>MonitorSplash());
Task.Run(() => MonitorLifeTime());
}
private void MonitorLifeTime()
{
_logger?.WriteLine("Monitoring lifetime...");
while (!_process.HasExited)
{
_process.Refresh();
Thread.Sleep(50);
}
_logger?.WriteLine("Process exited!");
_logger?.WriteLine("Invoking!");
ProcessExited?.BeginInvoke(this, null, null, null);
}
private void MonitorSplash()
{
_logger?.WriteLine("Monitoring Splash...");
while (!_process.MainWindowTitle.Contains("Trend"))
{
_process.Refresh();
Thread.Sleep(500);
}
_logger?.WriteLine("Splash finished!");
_logger?.WriteLine("Invoking...");
SplashFinished?.BeginInvoke(this,_process.MainWindowHandle,null,null);
}
public void Stop()
{
_logger?.WriteLine("Killing trend...");
_process.Kill();
}
public IntPtr GetHandle()
{
_logger?.WriteLine("Fetching handle...");
_process.Refresh();
return _process.MainWindowHandle;
}
public string GetMainTitle()
{
_logger?.WriteLine("Fetching Title...");
_process.Refresh();
return _process.MainWindowTitle;
}
}
Мой класс-обертка работает нормально, пока я не начну предоставлять аргументы файла, и это неожиданное поведение экземпляра не заработает.
Я не могу изменить целевое приложение, и при этом у меня нет доступа к его источнику, чтобы определить, управляется ли этот экземпляр с помощью мьютексов или с помощью какой-либо другой функции. Следовательно, мне нужно определить, есть ли способ предотвратить просмотр нового экземпляра существующим. Есть ли у кого-нибудь предложения?
TLDR: как запретить приложению, ограниченному одним экземпляром, определить, что уже запущен экземпляр
Чтобы уточнить (после подозрительных комментариев), команда моей компании по исследованиям и разработкам написала executable.exe
, но у меня нет времени ждать их помощи в этом вопросе (у меня есть дни, а не месяцы) и у меня есть разрешение сделать все необходимое для доставки требуемая функциональность (в моем решении гораздо больше, чем упоминается в этом вопросе) быстро.
С некоторой декомпиляцией я вижу, что для поиска существующего экземпляра используется следующее.
Process[] processesByName = Process.GetProcessesByName(Process.GetCurrentProcess().ProcessName);
Есть ли способ возиться с этим коротким созданием нескольких копий приложения с разными именами? Я смотрел на переименование Process
на лету, но, видимо, это невозможно, если не писать эксплойты ядра ...