5 / 5 / 1
Регистрация: 25.10.2013
Сообщений: 230
1

Запустить внешнее консольное приложение и вернуть результат

07.05.2016, 01:26. Показов 5210. Ответов 4
Метки нет (Все метки)

Здравствуйте. Подскажите, пожалуйста, как можно запустить внешнее консольное приложение без создания окна и вернуть результат? Например вызвав ping.exe получить вывод в своей программе.
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.05.2016, 01:26
Ответы с готовыми решениями:

Как запустить внешнее консольное приложение и получить то, что будет выведено на экран?
Есть программка которая распознает капчу, когда я ее запускаю из командной строки выводится...

Запустить внешнее приложение, передать ему параметры и получить результат
Здравствуйте. Проблема такая: RunCommand(exe_name,,output); Думаю, что такое exe_name и...

Как java-приложение может попросить OS запустить внешнее приложение?
Как java-приложение может попросить OS запустить внешнее приложение?

Как из Vb.Net запустить внешнее приложение
Помогите пожалуйста новичку. Мне нужно из vb.net запустить Crystal Reports (не компонент vb) и...

4
29 / 29 / 18
Регистрация: 20.12.2010
Сообщений: 119
07.05.2016, 15:35 2
Лучший ответ Сообщение было отмечено DarkMasterW как решение

Решение

перед выводом будет небольшая задержка(из-за ping)
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
#include <cstdio>
#include <iostream>
#include <stdexcept>
#include <string>
 
std::string exec(const char* cmd) {
    char buffer[128];
    std::string result = "";
    FILE* pipe = _popen(cmd, "r");
    if (!pipe) throw std::runtime_error("popen() failed!");
    while (!feof(pipe)) {
        if (fgets(buffer, 128, pipe) != NULL)
            result += buffer;
    }
    _pclose(pipe);
    return result;
}
 
int main() {
 
    std::cout << exec("ping 8.8.8.8");
 
    std::cin.get();
    return 0;
}
2
5 / 5 / 1
Регистрация: 25.10.2013
Сообщений: 230
24.05.2016, 15:48  [ТС] 3
Что произойдет при открытии pipe и невыполнении чтения? При большом потоке данных и отсрочке чтения, насколько я понимаю, все должно падать в буфер ОС. Есть какие-то стандарты поведения, объем буфера и т.д.?
0
29 / 29 / 18
Регистрация: 20.12.2010
Сообщений: 119
24.05.2016, 16:35 4
Насколько я понял при вызове popen создается pipe (i/o поток), размером по-умолчанию в 65536 байт (размер зависит от реализации в ОС), реальный размер можно получить через fcntl с F_GETPIPE_SZ. Чтение из pipe это по сути чтение из стандартного потока вывода команды cmd. Если чтение не произведено, то при закрытии pipe буфер будет очищен.
http://man7.org/linux/man-pages/man3/popen.3.html про чтение
http://man7.org/linux/man-pages/man7/pipe.7.html смотри главу "Pipe capacity" и "I/O on pipes and FIFOs"
http://man7.org/linux/man-pages/man2/fcntl.2.html глава "Changing the capacity of a pipe"
В винде все примерно тоже самое.
1
5 / 5 / 1
Регистрация: 25.10.2013
Сообщений: 230
24.05.2016, 22:21  [ТС] 5
Потребовалась двусторонняя связь. Вечер убит вникуда... В rw открыть pipe, как я понял невозможно, нужно через создание процесса создавать два pipe'а. Шаг в сторону и одни грабли:
С пингом работает, но если используем netsh /?\r\n в качестве параметра, то вернет "команда не найдена", хотя должно вывести хелп.
При этом если в атрибутах запуска присутствует флаг STARTF_USESTDHANDLES, то сразу после запуска netsh будет завершен, хотя он должен остаться висеть и ожидать команды. Убираем флаг STARTF_USESTDHANDLES, в процессах висит, но при этом теряем связь через pipe.
Использование WriteFile не привело к каким-либо результатам вообще.

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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
CStringA ExecCmd(
    const char* cmd              // [in] command to execute
    )
{
    CStringA strResult;
    HANDLE hPipeRead, hPipeWrite;
 
    SECURITY_ATTRIBUTES saAttr = { sizeof(SECURITY_ATTRIBUTES) };
    saAttr.bInheritHandle = TRUE;   //Pipe handles are inherited by child process.
    saAttr.lpSecurityDescriptor = NULL;
 
    // Create a pipe to get results from child's stdout.
    if (!CreatePipe(&hPipeRead, &hPipeWrite, &saAttr, 0))
        return strResult;
 
    STARTUPINFO si = { sizeof(STARTUPINFO) };
    si.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
    si.hStdOutput = hPipeWrite;
    si.hStdError = hPipeWrite;
    si.wShowWindow = SW_HIDE;       // Prevents cmd window from flashing. Requires STARTF_USESHOWWINDOW in dwFlags.
 
    PROCESS_INFORMATION pi = { 0 };
 
    BOOL fSuccess = CreateProcessA(NULL, (LPSTR)cmd, NULL, NULL, TRUE, CREATE_NEW_CONSOLE, NULL, NULL, &si, &pi);
    if (!fSuccess)
    {
        CloseHandle(hPipeWrite);
        CloseHandle(hPipeRead);
        return strResult;
    }
 
    //Sleep(5000);
    //char buf_write[] = "/?\r\n\0";
    //DWORD dwWrite = 0;
    //if (!::WriteFile(hPipeWrite, buf_write, strlen(buf_write), &dwWrite, NULL) || !dwWrite)
    //  cout << "write error" << endl;
    //cout << "dwWrite" << dwWrite << endl;
 
    bool bProcessEnded = false;
    for (; !bProcessEnded;)
    {
        // Give some timeslice (50ms), so we won't waste 100% cpu.
        bProcessEnded = WaitForSingleObject(pi.hProcess, 50) == WAIT_OBJECT_0;
 
        // Even if process exited - we continue reading, if there is some data available over pipe.
        for (;;)
        {
            char buf[1024];
            DWORD dwRead = 0;
            DWORD dwAvail = 0;
 
            if (!::PeekNamedPipe(hPipeRead, NULL, 0, NULL, &dwAvail, NULL))
                break;
 
            if (!dwAvail) // no data available, return
                break;
 
            if (!::ReadFile(hPipeRead, buf, min(sizeof(buf) - 1, dwAvail), &dwRead, NULL) || !dwRead)
                // error, the child process might ended
                break;
 
            buf[dwRead] = 0;
            strResult += buf;
        }
    } //for
 
    CloseHandle(hPipeWrite);
    CloseHandle(hPipeRead);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return strResult;
} //ExecCmd
 
 
void main(){
    std::cout << "result: \n" << ExecCmd("netsh");
    _getch();
    return;
}
Прошу помочь...
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.05.2016, 22:21
Помогаю со студенческими работами здесь

Запустить консольное приложение в Windows 7
Всем привет. Я написал консольное приложение на Visual C++ 2008 Express по минимизации логических...

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

Запустить и скрыть консольное приложение
Всем привет. У меня есть функция для запуска программ function StartProccess(filepath: string;...

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


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

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

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru