В моем приложении пользователь может выбирать различные файлы и исполняемые файлы с помощью OpenFileDialog
.Из пути выбранного файла создается ProcessModel
и добавляется к ObservableCollection
.
План состоит в том, что пользователь может выбирать различные файлы и программы и добавлять их в список в приложении.Затем программное обеспечение должно открывать - а затем закрывать - выбранные файлы, как только происходит определенное событие (в этом случае жест пользователя, захваченный камерой).
ProcessModel
содержит несколько свойств для разных параметров, но те, которые важны для моего вопроса, задаются в конструкторе следующим образом:
public ProcessModel(string path)
{
ProcessName = Path.GetFileNameWithoutExtension(path);
processExtension = Path.GetExtension(path);
ProcessPath = path;
instances = new List<Process>();
}
Что я хочу сделать с каждым ProcessModel
означает, что в случае запуска определенного события в приложении я хочу запустить связанный процесс.Кроме того, я хочу отслеживать, сколько экземпляров одних и тех же процессов было запущено, а также иметь возможность закрыть их с помощью другого события.Чтобы добиться этого, я слушаю событие Process.Exited
и соответственно обрабатываю свой список экземпляров.Прежде чем перейти к реальной проблеме, вот методы, которые я использую (все в моем классе ProcessModel
):
создание и запуск нового процесса:
/// <summary>
/// Starts a new instance of the current process
/// </summary>
public void StartNewInstance()
{
try
{
Process newInstance;
if (processExtension == GenDefString.ExecutableExtension)
{
newInstance = new Process();
newInstance.StartInfo.UseShellExecute = false;
newInstance.StartInfo.FileName = ProcessPath;
newInstance.Start();
}
else
{
newInstance = Process.Start(ProcessPath);
}
newInstance.EnableRaisingEvents = true;
newInstance.Exited += OnProcessExited;
instances.Add(newInstance);
UpdateNrOfInstances();
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
остановка последнего экземплярав списке:
/// <summary>
/// stops the last instance int he list
/// </summary>
public void StopLastInstance()
{
if (instances.Count < 1) return;
try
{
var instanceToDelete = instances.Last();
instanceToDelete.Exited -= OnProcessExited;
instanceToDelete.CloseMainWindow();
instanceToDelete.Close();
instances.RemoveAt(instances.Count - 1);
UpdateNrOfInstances();
}
catch(Exception e)
{
MessageBox.Show(e.Message);
}
}
метод, который прослушивает событие закрытия процесса (внешне):
/// <summary>
/// Trigger Status changed Event was raised
/// </summary>
/// <param name="source"></param>
/// <param name="e"></param>
public void OnProcessExited(object source, EventArgs e)
{
var process = source as Process;
if (process == null) return;
instances.Remove(process);
UpdateNrOfInstances();
}
Обновление количества текущих экземпляров в GUI:
/// <summary>
/// Sets the value for the number of instances (used for GUI update)
/// </summary>
private void UpdateNrOfInstances()
{
NrOfInstancesRunning = instances.Count;
}
Как вы можете видеть в методе StartNewInstance()
, я проверяю, относится ли расширение к исполняемому файлу или связанному с программным файлом (GenDefString.ExecutableExtension
- это строка, содержащая @ ". Exe").Все работает как задумано, однако, если, например, пользователь помещает два разных файла .pdf
, второй процесс немедленно прекращается, потому что мой pdf-просмотрщик уже был запущен ProcessModel
, связанным с первым файлом .pdf
.
В этом случае мне нужно обращаться с вещами по-другому.Насколько я понимаю, у меня есть способы сделать это:
- Заставить каждый недавно запущенный процесс в свое собственное Окно: я не считаю это хорошей идеей в дополнение к тому, чтобы не знать, какчтобы добиться этого со всеми различными типами программного обеспечения.
- Информирование пользователя о том, что происходит и почему в соответствующем элементе 0 экземпляров, когда файл явно открыт.Я предпочитаю это, и мой подход заключается в получении информации из аргумента
source
метода OnProcessExited()
.
Итак, мой вопрос: как я могу различить, если выход из процесса произошел из-за описанного случая?
РЕДАКТИРОВАТЬ: Мой текущий подход будет отслеживать идентификаторы процесса, однако яИнтересно, есть ли лучшее решение, может быть, уже реализованное для класса процессов
EDIT2: Для лучшего понимания полный проект можно найти здесь.