C++ popen无输出

3

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

但是,如果我将该命令复制/粘贴到另一个命令提示符窗口中,它就能成功运行并立即输出许多行。

那么它去哪了?为什么我的缓冲区里面没有任何东西?

此外,将"netsh"更改为"dir"命令的字符串将成功输出dir的输出。

编辑:即使是system(cmd.c_str());也没有输出!

编辑:奇怪的是,cmd="netsh dump";实际上可以正常输出,但是cmd="netsh dhcp server...却不能。CMD路由netsh文本的方式有点奇怪,或者是其他问题?这已经超出了我的舒适区了。

编辑:显然,这是一个超出C++范畴的问题,因为当我在Python 2.7 shell中(顺便说一下,这是Windows 7 64位系统)时,我尝试了以下操作:

>>> 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
>>>

以下是需要检查的内容。netsh需要root权限吗?您是否使用适当的特权运行程序?用户?权限?将netsh替换为/path/netsh如何?您的PATH和LIBPATH环境是否正确设置为cmd? - Bitdiot
不,我可以在非管理员的cmd提示符下正常运行netsh,并在提升的cmd提示符下运行C++程序。如果路径变量没有正确设置,我应该会在STDOUT或STDERR中看到错误输出...另外,其他netsh命令(netsh dump)也正常输出。只有"netsh dhcp..."无法工作。 - armani
string cmd="netsh dhcp server 192.168.200.15 scope "+scopes[x]+" show clients 1 > out.txt" 这行代码会将输出写入到对应文件吗? - t7bdh3hdhb
@t7bdh3hdhb out.txt文件已创建,但是它是空的。大小为零字节。 - armani
4个回答

1
也许输出是发送到 STDERR 而非 STDOUT? 在您的系统命令结尾处尝试添加 " 2>&1"。 例如: FILE *p = popen("g++ main.cpp -o main", "r"); 尝试这样写: FILE *p = popen("g++ main.cpp -o main 2>&1", "r");

不,那没有改变任何东西。猜得不错,不过。 - armani

0

尝试将您的 _popen 替换为:

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

也许你仍然需要完全指定读取模式。

还要使用错误检查来检查 _popen 是否起作用:

if(fpipe == NULL)
    cout<<"Failed to open"<<endl;

我没有收到“无法打开”消息,所以看起来fpipe变量得到了一些东西。也许只是为了格式化而输出的空格,但并没有通过RPC从DHCP服务器检索的netsh数据在命令窗口中显示。 - armani

0
你确定这个命令是正确的吗? 我猜你在使用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 server 192.168.200.15 scope 192.168.16.0 show clients 1 未找到以下命令:dhcp server 192.168.200.15 scope 192.168.16.0 show clients 1。

netsh dhcp server 192.168.200.15 scope 192.168.144.0 show clients 1 未找到以下命令:dhcp server 192.168.200.15 scope 192.168.144.0 show clients 1。

netsh dhcp server 192.168.200.15 scope 192.168.155.0 show clients 1 未找到以下命令:dhcp server 192.168.200.15 scope 192.168.155.0 show clients 1。

netsh dhcp server 192.168.200.15 scope 192.168.200.0 show clients 1 未找到以下命令:dhcp server 192.168.200.15 scope 192.168.200.0 show clients 1。


该命令肯定没问题;正如之前提到的,当我将该命令复制/粘贴到单独的命令提示符窗口中时,它可以正常执行并填充我的屏幕与DHCP客户端信息。你可能在你的网络上没有一个IP为192.168.200.15的DHCP服务器,所以这很可能是你收到该错误的原因。 - armani
同意!但是你能看一下这个程序吗?它可以执行命令并打印输出。 - a_secenthusiast
我刚刚在这里尝试了一下,得到了相同的输出(也就是说,除了通过“cout<<cmd<<endl”看到它在哪个命令上之外,没有任何输出)。 - armani

0

这可能是权限问题吗?如果netsh dhcp ...命令需要管理员权限才能正常工作,那么问题可能是应用程序在运行时未继承管理员权限,因此无法成功完成命令。当然,在这种情况下,它似乎应该输出一些STDERR内容,但我不确定...


我可以在普通的非管理员用户帐户的CMD提示符中成功运行netsh命令。此外,我通常使用提升的命令提示符编译和运行C++程序。所以这不是问题所在。 - armani

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接