C++ Нет вывода из popen

tl;dr — Не удается записать выходные данные команд, использующих RPC, на удаленный сервер с использованием любого языка программирования, который я пытаюсь использовать, даже если эти команды возвращаются в командную строку при вводе вручную

У меня есть функция, которая использует fpipe для запуска команды netsh для отображения статистики с нашего DHCP-сервера. Я использую ту же технику чтения буфера fpipe в другом месте своей программы, и она работает нормально, но здесь я вообще не получаю вывода:

РЕДАКТИРОВАТЬ: я упрощаю свой код до фрагмента, который больше соответствует концепции. На самом деле это всеобъемлющий исходный файл .cpp, который по-прежнему воспроизводит проблему.

#include <iostream>
#include <string>
#include <stdio.h>  // for _popen() and _pclose()
using namespace std;

    int main()
    {
        char buff[512];
        buff[0]=0;
        string cmd="netsh dhcp server 192.168.200.15 scope 192.168.200.0 show clients 1";
        FILE *fpipe = _popen(cmd.c_str(),"r");
        if(fpipe==NULL) cout<<"Failed to open"<<endl; else cout<<"Opened pipe successfully";
        while(fgets(buff,sizeof(buff),fpipe)!=NULL) cout<<buff<<endl;
        _pclose(fpipe);
    }

Единственный вывод, который я получаю:

Opened pipe successfully

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

Так куда это идет? Почему ничего никогда не попадает в мой буфер?

Кроме того, изменение строки «cmd» с команды netsh на команду «dir» успешно выводит вывод dir.

РЕДАКТИРОВАТЬ: даже system(cmd.c_str()); ничего не выводит!

EDIT: Любопытно, что cmd="netsh dump"; на самом деле выводит нормально, а cmd="netsh dhcp server... - нет. Что-то странное с тем, как CMD маршрутизирует текст netsh или... что-то в этом роде? Здесь вне моей зоны комфорта.

EDIT: это, очевидно, проблема за пределами C++, потому что, когда я нахожусь в оболочке Python 2.7 (кстати, это 64-разрядная версия Windows 7), я пробую это:

>>> import subprocess
>>> subprocess.call('dir', shell=True)
 Volume in drive C has no label.
 Volume Serial Number is 2E2B-B34F

 Directory of C:\MyDir

09/30/2013 01:24 PM  <DIR>       .
09/30/2013 01:24 PM  <DIR>       ..
09/20/2013 10:11 AM          45  test.txt
             1 File(s)       45 bytes
             2 Dir(s)   162,260,246,528 bytes free
0
>>> subprocess.call('netsh dhcp server 192.168.200.15 scope 192.168.200.0 show clients 1', shell=True)
0
>>>

person armani    schedule 20.09.2013    source источник
comment
Вот что нужно проверить. Нужны ли привилегии root для netsh? И запускаете ли вы свою программу с соответствующими привилегиями? Пользователь? Разрешения? Как насчет замены netsh на /path/netsh? Правильно ли настроены ваши среды PATH и LIBPATH для cmd?   -  person Bitdiot    schedule 27.09.2013
comment
Нет, я могу запустить netsh в обычном режиме с неадминистративной командной строкой cmd и в любом случае запустить программу C++ в командной строке с повышенными правами. Если бы переменные пути не были настроены правильно, я бы увидел вывод ошибки либо в STDOUT, либо в STDERR... а также другая команда netsh (дамп netsh) выводилась нормально. Просто netsh dhcp... не работает.   -  person armani    schedule 28.09.2013
comment
производит ли string cmd="netsh dhcp server 192.168.200.15 scope "+scopes[x]+" show clients 1 > out.txt" вывод в соответствующем файле?   -  person t7bdh3hdhb    schedule 30.09.2013
comment
@ t7bdh3hdhb Файл out.txt создается, но он пуст. Размер ноль байт.   -  person armani    schedule 30.09.2013


Ответы (4)


Может быть, вывод идет в STDERR, а не в STDOUT?

Попробуйте это в конце вашей системной команды -> «2>&1».

Например: ФАЙЛ *p = popen("g++ main.cpp -o main", "r");

Попробуйте так: ФАЙЛ *p = popen("g++ main.cpp -o main 2>&1", "r");

person SoulfreezerXP    schedule 24.09.2013
comment
Нет, это ничего не изменило. Хорошая догадка, однако. - person armani; 25.09.2013

Попробуйте заменить _popen на:

FILE *fpipe = _popen(cmd.c_str(),"rt");

Возможно, вам все же придется полностью указать режим чтения.

А также используйте проверку ошибок, чтобы проверить, сработал ли _popen:

if(fpipe == NULL)
    cout<<"Failed to open"<<endl;
person The Quantum Physicist    schedule 23.09.2013
comment
На выходе никаких изменений. Я также не получаю сообщение Failed to open, поэтому похоже, что переменная fpipe что-то получает. Возможно просто выведенные для форматирования болванки, а не данные netsh, которые извлекаются с DHCP-сервера через RPC для отображения в командном окне. - person armani; 24.09.2013

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

person MorbidFuzzball    schedule 27.09.2013
comment
Я могу запустить команду netsh в командной строке CMD обычной учетной записи пользователя, не являющейся администратором. Кроме того, я обычно компилирую и запускаю программу на C++ в командной строке с повышенными привилегиями. Так что это не так. - person armani; 28.09.2013

Вы уверены в команде? Я предполагаю, что вы используете Windows, так как были упоминания о «командной строке», когда я делаю netsh /? Я вообще не вижу подкоманды dhcp. Я вижу только dhcpclient. Даже с этой неправильной командой (я полагаю), я получаю вывод, что подкоманда недоступна. Вот код, я использую Cygwin. следовательно, функции _p* заменяются функциями p*.

#include <iostream>
#include <vector>
#include <string>
using std::cout;
using std::endl;
using std::string;
using std::vector;

#include <stdio.h>

int main(int argc, char* argv[])
{
    cout<<"Entered DHCPLookup() function"<<endl;
    vector<string> scopes;
    scopes.push_back("192.168.16.0");
    scopes.push_back("192.168.144.0");
    // some scopes omitted here
    scopes.push_back("192.168.155.0");
    scopes.push_back("192.168.200.0");
    char buff[512];
    for(int x=0;x<scopes.size();x++)
    {
        buff[0]=0;
        string cmd="netsh dhcp server 192.168.200.15 scope "+scopes[x]+" show clients 1";
        cout<<cmd<<endl;
        FILE *fpipe = popen(cmd.c_str(),"r");
        while(fgets(buff,sizeof(buff),fpipe)!=NULL) cout<<buff<<endl;
        pclose(fpipe);
    }
}

Вот результат

Введена функция DHCPLookup().

netsh dhcp-сервер 192.168.200.15 область 192.168.144.0 показать клиентов 1 Не удалось найти следующую команду: dhcp-сервер 192.168.200.15 область 192.168.144.0 показать клиентов 1.

netsh dhcp-сервер 192.168.200.15 область 192.168.155.0 показать клиентов 1 Не удалось найти следующую команду: dhcp-сервер 192.168.200.15 область 192.168.155.0 показать клиентов 1.

netsh dhcp-сервер 192.168.200.15 область 192.168.200.0 показать клиентов 1 Не удалось найти следующую команду: dhcp-сервер 192.168.200.15 область 192.168.200.0 показать клиентов 1.

person a_secenthusiast    schedule 30.09.2013
comment
Команда определенно в порядке; Как уже упоминалось, когда я копирую/вставляю команду в отдельное окно командной строки, она выполняется нормально и заполняет мой экран информацией о клиенте DHCP. Вероятно, в вашей сети нет DHCP-сервера с IP-адресом 192.168.200.15, поэтому, вероятно, вы получаете эту ошибку. - person armani; 30.09.2013
comment
Согласен! Но не могли бы вы взглянуть на программу, она также может выполнять команду и печатать вывод. - person a_secenthusiast; 30.09.2013
comment
Я только что попробовал это здесь и получил тот же результат (то есть никакого вывода, кроме просмотра того, какая команда включена через cout‹‹cmd‹‹endl - person armani; 30.09.2013