0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
1
.NET 3.x

Как получить строку с ошибкой при запуске стороннего приложения?

27.09.2016, 20:19. Показов 1770. Ответов 20
Метки нет (Все метки)

Уважаемые программисты , прошу подсказать по теме. Создана программка, которая меняет в текстовом файле данных стороннего приложения некоторые поля и запускает это приложение с параметром в виде этого файла (это автоматизация инженерного расчета). Запускается все в отдельном потоке с помощью "System.Diagnostics.Process.Start", обрабатывается событие Exited и по результатам заново меняется файл данных и заново запускается процесс. И т.д. до получения необходимого результата.
Вопрос! Как получать ошибку запущенного стороннего приложения (все стандартно - приложение возвращает в систему "0" если завершилось нормально или какую-то другую цифру в зависимости от ошибки в приложении), Мне нужно отлавливать эту строку чтобы правильно обработать ситуацию.
Как это сделать в net?
Заранее спасибо!
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
27.09.2016, 20:19
Ответы с готовыми решениями:

При запуске приложения на турецкой системе программа вываливается с ошибкой
В чем может быть проблема? При запуске приложения на турецкой системе программа вываливается с...

Получить данные из стороннего приложения
Приложение просто отображает таблицу, в которой периодически меняются текстовые данные. Пытался...

Записать строку в окно стороннего приложения
Здравствуйте, столкнулся с подобной задачей. Необходимо найти программу, чтоб сделать её активной....

Получить координаты окна стороннего приложения
Здравствуйте дорогие форумчане, встал вопрос как получить координаты СТОРОННЕЙ программы , при...

20
Эксперт .NET
5340 / 4132 / 1187
Регистрация: 12.10.2013
Сообщений: 11,981
Записей в блоге: 2
27.09.2016, 20:25 2
Цитата Сообщение от forem0st Посмотреть сообщение
Как это сделать в net?
Использовать код завершения процесса.
1
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
27.09.2016, 22:23  [ТС] 3
Спасибо insite2012, это я читал, но мне так и не удалось получить ни чего кроме "0"(см. картинку). Я моделировал разные ошибки в стороннем приложении но ExitCode все время ноль. Хотя его разработчик утверждает, что код ошибки каждый раз выдается и он разный! Как проверить не знаю и вопрос про правильный перехват остается не решенный.
Миниатюры
Как получить строку с ошибкой при запуске стороннего приложения?  
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
27.09.2016, 22:30  [ТС] 4
Возможно дело в том, что я пытаюсь получить его в событии Exited и код ещё не сгенерирован сторонней программой? Но не делать же мне такой же костыль, как в примере из MSDN?!
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
27.09.2016, 22:42 5
forem0st, запускайте дочерний процесс в отдельном потоке / таске и ожидайте его завершения с помощью метода WaitForExit.
После возвращения управления Вашему коду экземпляр класса Process гарантированно будет иметь правильный ExitCode.
1
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
27.09.2016, 23:00  [ТС] 6
bax_tang, то есть мне надо создать метод запускающий мой process, запускать этот метод в отдельном потоке с WaitForExit ? Просто если я сделаю WaitForExit к самому process то весь интерфейс будет долго и нудно висеть!
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
28.09.2016, 08:33 7
Лучший ответ Сообщение было отмечено forem0st как решение

Решение

Да, совершенно верно, нужен отдельный метод, внутри которого процесс будет создаваться, и затем через WaitForExit этот метод будет ожидать завершения процесса - чтобы гарантированно получить его ExitCode.
Собственно, именно для этого и нужен фоновый поток - чтобы интерфейс приложения при выполнении такой длительной операции не повисал.

Добавлено через 2 часа 42 минуты
forem0st, я бы реализовал вышеописанный функционал как-то так (.NET 4.5):

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
 
public class SomeYourClass
{
    /* some other code */
    
    public void RunProcess()
    {
        // как-то формируем параметры запуска процесса
        Dictionary<string, string> runParams = ...; 
        
        // создаём экземпляр runner-a
        ProcessRunner runner = new ProcessRunner(@"<path_to_your_exe>.exe", runParams);
        
        // запускаем фоновую задачу и цепляем к ней продолжение, которое запустится
        // после завершения задачи и позволит отреагировать на exit code внешнего процесса
        Task.Run(new Func<int>(runner.StartAndWait)).ContinueWith(new Action<Task<int>>(AnalyzeExitCode));
    }
 
    private void AnalyzeExitCode(Task<int> runTask)
    {
        int exitCode = runTask.Result;
        
        // тут каким-либо образом анализируем exit code внешнего процесса
    }
}
 
public class ProcessRunner()
{
    private string ExeFilePath;
    private Dictionary<string, string> RunParameters;
    
    public ProcessRunner(string exeFilePath, Dictionary<string, string> parameters)
    {
        ExeFilePath = exeFilePath;
        RunParameters = parameters;
    }
    
    public int StartAndWait()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo(ExeFilePath)
        {
            // заполняем поля класса ProcessStartInfo из RunParameters
        };
        
        Process externalProc = Process.Start(startInfo);
        
        externalProc.WaitForExit();
        
        return externalProc.ExitCode;
    }
}


Добавлено через 2 минуты
Вот ведь... только сейчас обратил внимание на заголовок темы - .NET 3.x... а нет никакой возможности подняться на версию повыше? чисто на Thread-ах реализовать такое будет потруднее.
1
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
28.09.2016, 08:50  [ТС] 8
Цитата Сообщение от bax_tang Посмотреть сообщение
я бы реализовал вышеописанный функционал как-то так (.NET 4.5):
Спасибо. Возможность перейти на 4.5 есть. Тем более нужно еще реализовывать вывод графика, а сhart от Microsoft только Net 4 и выше.
Сердечно благодарю за пример кода!
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
28.09.2016, 08:52 9
Лучший ответ Сообщение было отмечено forem0st как решение

Решение

forem0st, переписал на использование делегатов в асинхронном режиме, должно работать начиная с .NET 3.5:

Кликните здесь для просмотра всего текста

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
using System;
using System.Collections.Generic;
using System.Diagnostics;
 
public class SomeYourClass
{
    /* some other code */
    
    public void RunProcess()
    {
        // как-то формируем параметры запуска процесса
        Dictionary<string, string> runParams = ...; 
        
        // создаём экземпляр runner-a
        ProcessRunner runner = new ProcessRunner(@"<path_to_your_exe>.exe", runParams);
        
        // создаём экземпляр делегата, запускаем его асинхронно и цепляем к нему callback продолжения
        Func<int> runFunction = new Func<int>(runner.StartAndWait);
        runFunction.BeginInvoke(new AsyncCallback(AnalyzeExitCode), runFunction);
    }
 
    private void AnalyzeExitCode(IAsyncResult result)
    {
        Func<int> runFunction = result.AsyncState as Func<int>;
        if (runFunction != null)
        {
            int exitCode = runFunction.EndInvoke(result);
            
            // тут каким-либо образом анализируем exit code внешнего процесса
        }
    }
}
 
public class ProcessRunner()
{
    private string ExeFilePath;
    private Dictionary<string, string> RunParameters;
    
    public ProcessRunner(string exeFilePath, Dictionary<string, string> parameters)
    {
        ExeFilePath = exeFilePath;
        RunParameters = parameters;
    }
    
    public int StartAndWait()
    {
        ProcessStartInfo startInfo = new ProcessStartInfo(ExeFilePath)
        {
            // заполняем поля класса ProcessStartInfo из RunParameters
        };
        
        Process externalProc = Process.Start(startInfo);
        
        externalProc.WaitForExit();
        
        return externalProc.ExitCode;
    }
}
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
28.09.2016, 09:23  [ТС] 10
Цитата Сообщение от bax_tang Посмотреть сообщение
переписал на использование делегатов в асинхронном режиме, должно работать начиная с .NET 3.5
Спасибо! Изучу оба варианта. Вечером попробую реализовать и сообщу о результатах.
P.S.
опять, блин, эти делегаты. Второй год пытаюсь понять - зачем мне это надо?
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
29.09.2016, 22:46  [ТС] 11
bax_tang. Как и обещал, вечером проверил (ничего что через день))). Вариант номер 2, тот что под дот3 полностью рабочий и я получаю то, что нужно (правильный код ошибки). Проблема решена!
Если есть время прошу пояснить - почему используются встроенный делегат Func, а не объявляются свой? Еще я ни черта не понял зачем там нужен
Цитата Сообщение от bax_tang Посмотреть сообщение
Dictionary<string, string>
и заменил его на то, что понимаю - String[], который потом превращаю в строку командой String.Join(" ", ...
Плюс ещё в коде под вторым спойлером ошибочка (или опечатка). Вот это
Цитата Сообщение от bax_tang Посмотреть сообщение
C#
1
2
3
4
ProcessStartInfo startInfo = new ProcessStartInfo(ExeFilePath)
 {
    // заполняем поля класса ProcessStartInfo из RunParameters
 };
наверное нужно заменить на что-то такое:
C#
1
2
3
4
ProcessStartInfo startInfo = new ProcessStartInfo(ExeFilePath);
startInfo. ... = ... ;
startInfo. ... = ... ;
...// заполняем поля класса ProcessStartInfo из RunParameters
а то интеллесенс ругается сильно .
А в целом спасибо! Уважуха, респект и т.п. )))
Первый пример попробую позже.
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
29.09.2016, 23:00 12
1. Func<int> - "зачем добавлять что-то ещё, когда в платформе уже есть готовое универсальное?"
2. Dictionary мне показался более наглядно описывающим сущность "параметры запуска" (ключ - значение)
3. "опечатка" у ProcessStartInfo - это другой вариант синтаксиса инициализации объекта (предыдущие версии платформы его могут не поддерживать)
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
29.09.2016, 23:34  [ТС] 13
bax_tang по третьему пункту примерно так и понял... Зря я на 3.5 начал делать, теперь проблемки. Буду потом ещё вопросы задавать - как версию повышать (уже пробовал, просто так не повышается - ругается на что-то)? ...
Про "ключ - значение". Имеете в виду, использовать строку как параметр, а ключ как порядковый номер параметра? Не могу оценить - на сколько это нужно?..
Вижу вы новичок на форуме. Желаю Вам рейтинга как у модератора и всех благ!
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
30.09.2016, 05:49 14
forem0st, скопируйте сюда сообщение об ошибке при повышении версии до 4.5 - посмотрю, что может быть не так
про ключ - значение - имелось в виду "название параметра" - "значение параметра"
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
30.09.2016, 10:58  [ТС] 15
bax_tang, ошибка вот. Но я вроде понял, что дело в сторонней библиотеки скомпилированной под младшую версию.
Теперь придется копаться в исходниках (библиотека открытая) и перекомпилировать. Кстати! Не знаете - как без костылей реализовать распаковку cab-файла в C#? А то пользоваться чужой (хоть и свободной) библиотекой не комильфо...
0
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
30.09.2016, 11:00  [ТС] 16
Вот картинка с ошибкой
Миниатюры
Как получить строку с ошибкой при запуске стороннего приложения?  
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
30.09.2016, 12:38 17
forem0st, да, очевидно, придётся перекомпилировать библиотеку под .NET более высокой версии.
По поводу второго вопроса - на мой взгляд, самый "бескостыльный" способ - это использовать из NuGet стандартную сборку от Microsoft для работы с .cab - файлами.
1
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
01.10.2016, 09:40  [ТС] 18
bax_tang,
"бескостыльный" способ - это использовать из NuGet стандартную сборку от Microsoft для работы с .cab
Подключил эту библиотеку. Настали светлые времена . Спасибо за наводку. Я очень долго её искал...

Добавлено через 1 час 0 минут
Покопался в этом NuGet (раньше как-то не обращал внимания) нашел Microsoft.Chart для версии .Net 3.5.1!

Добавлено через 1 минуту
bax_tang, образовалась проблема. Раньше у меня была реализована возможность прерывания процесса во время расчета. Теперь, когда Process.Start запрятан в другом потоке с WaitForExit у меня не получается выйти из расчета в любое время. Прошу дополнить Ваш код правильной функцией для прерывания процесса пользователем.
Спасибо!
0
.NET senior
437 / 355 / 137
Регистрация: 23.09.2016
Сообщений: 980
01.10.2016, 10:15 19
forem0st, добавьте в класс ProcessRunner private поле типа Process, в которое записывайте экземпляр созданного процесса перед вызовом WaitForExit. Также добавьте public метод с названием StopProcess, внутри которого для экземпляра процесса из поля класса будет вызываться метод Kill, например.
1
0 / 0 / 0
Регистрация: 06.07.2012
Сообщений: 27
01.10.2016, 17:56  [ТС] 20
bax_tang, я сделал так:
В классе ProcessRunner
Кликните здесь для просмотра всего текста
Код
  public class ProcessRunner
    {
        private string ExeFilePath;
        private String[] RunParameters;
        Process externalProc;

        public ProcessRunner(string exeFilePath, String[] parameters)
        {
            ExeFilePath = exeFilePath;
            RunParameters = parameters;
        }

        public int StartAndWait()
        {
            ProcessStartInfo startInfo = new ProcessStartInfo();
            startInfo.Arguments = String.Join(" ", RunParameters);
            startInfo.FileName = ExeFilePath;
            startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
            startInfo.UseShellExecute = false;
            startInfo.RedirectStandardError = true;
            startInfo.RedirectStandardOutput = true;
            externalProc = Process.Start(startInfo);
            externalProc.WaitForExit();
            return externalProc.ExitCode;
        }
        public int Stop()
        {
            externalProc.Kill();
            return 0;
        }
    }

В кнопке обработчика прерывания расчета
Кликните здесь для просмотра всего текста
Код
       private void button_Stop_Click(object sender, EventArgs e)
        {
            this.status_ProgressBar.Visible = false;
            this.status_ProgressBar.Value = 0;
            this.status_ProgressBar.Enabled = false;
            if (runner != null)
            {                
                Func<int> stopRuner = new Func<int>(runner.Stop);
                BeginInvoke(stopRuner);
                this.status.Text = "The calculation a customer is interrupted";
                return;
            }
        }

Расчет прерывается, но я все равно получаю код ошибки в метод "AnalyzeExitCode(IAsyncResult result)". Вопрос - все ли я сделал верно и, правильно ли это, что код ошибки все равно получается? Код ошибки совпадает с одним из задокументированных, но не совпадает действие, которое надо делать. Меня это не напрягает, я просто ввиду дополнительный переключатель и буду его проверять.
Но. Все ли я сделал правильно?
Спасибо!
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
01.10.2016, 17:56

Получить текст компонента стороннего приложения
Добрый день! Подскажите, пожалуйста, есть у меня чужая программа, точно знаю что написана на...

Получить дескриптор окна стороннего приложения и контекстного меню
Здравствуйте. Подскажите пожалуйста. Как можно словить дескриптор выскакивающего окна? в списке...

Получить содержимое и/или элементы окна стороннего приложения
Подскажите, возможно ли с помощью C# (в том числе winapi) получить сабж?

Как развернуть окно стороннего приложения при его запуске?
Здравствуйте. При запуске ресурса System.Diagnostics.Process.Start(&quot;chrome&quot;, &quot;http://...&quot;) окно...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.