如何将system()命令输出流到任何变量

时间:2013-09-12 08:40:40

标签: c windows stream

我创建了一个C程序,它将运行一些system()命令并将输出保存到C驱动器的特定文件夹中的.txt文件(程序将在具有启动权限的域客户端上运行) ,我将从那里过滤数据并在输出控制台屏幕上显示它。

一切都运行良好,但我无法为那些在其他驱动器中安装了操作系统的PC(例如 D:E:等)设计它,因为它们在C:驱动器中不会包含此特定文件夹。由于组策略,我无法在其他任何地方写入临时.txt文件。

有没有方法可以将这些数据直接传输到任何数组变量中?我经历了popen()函数,但它需要定义一个非常大的不可预测大小的数组(因为system()命令的输出可能非常大)。例如,将HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall的注册表项导出到.txt文件中。它的大小可能高达50KB或更大。

    reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall C:\\..(somewhere)....\\reg_output.txt

还有一些类似的命令具有大输出。我还不知道Win API编程,因此我使用的是系统命令。写作.txt可以有一个简单的替代方法吗?


@Megharaj! 正如您使用

    char line[100];
    fp = popen("ifconfig eth0", "r");
    fgets(line, 100, fp);

我必须使用

    char reg_output[100000];
    fp=popen("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall ????","r");
    fgets(line,100000,fp);

我在哪里导出注册表值? (由于用于导出它的DOS命令需要将其写入文件),与我正在使用的以下代码相比。

分配100000的空间不确定它是否容易出错。并且分配太高的值也会影响启动时的内存(我不确定但是这样猜测)。

使用文件处理时,我将其作为:

    char line[5000];   FILE* fp_reg;  int ch,n=0;
    system("reg export HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\uninstall c:\\registries.txt");
    fp_reg=fopen("c:\\registries.txt","r");
    while((ch=fgetc(fp_reg))!=EOF)
    {
        if(isalnum(ch) || ch=='\n')  //allow only alpha numeric & '\n' to pass to array
        { line[n]=ch;
          if(ch=='\n')
          {    filter_for_software(line,n);  //Send the array for filtering function
               n=0;   // Reset the array 'line'
          }
          n++;                
        }    
    }

(我没有从源代码复制代码,因为我坐在不同的PC上。但代码几乎与此类似。如果您复制此代码并运行,可能会出现一些错误。) 这样,我从文件中取出每一行并发送它以进行过滤以获得“已安装软件的名称”。我怎么用'popen()'来做,这样我就可以拿起一条线并将它扔到一个函数上。 Plz也为此编写了一些代码。

4 个答案:

答案 0 :(得分:1)

在linux中使用系统命令中的值我使用popen,我只是给出了一段时间我写的代码示例,通过系统命令“ifconfig eth0”获取pc的ip地址字符串/文件。见例子

    void get_my_ip(char *ip_mac_address)
{
    FILE *fp,*output;
    char *start=NULL; 
    char *end=NULL;
    char line[100];
    output=fopen("my_ip_address.txt", "w");
    if(output == NULL) {
        printf("error creating outputfile\n");
        return -1; 
    }

    printf("program to self query the ip address\n");   
    fp = popen("ifconfig eth0", "r");
    fgets(line, 100, fp);
    start=strstr(line, CHECK_STRING_MAC);
    start = start + 7;
    fwrite(start, 1, 17, output); start = NULL;
    fgets(line, 100, fp);
    start=strstr(line, CHECK_STRING_IP);
    start = start + 10;
    fwrite(start, 1, 14, output);
    fclose(output); 
    pclose(fp);
    if( access("my_ip_address.txt", F_OK ) != -1 ) {
        printf("found file having ip address\n");
        output=fopen("my_ip_address.txt", "r");
        fgets(ip_mac_address, 32, output);
    }
    else
        printf("unabe to find file with ip address\n");
    fclose(output);
    printf("my ip and mac address adress is %s \n",ip_mac_address);

}

答案 1 :(得分:1)

如果要将输出存储在数组中,则必须分配适当大小的数组。没有办法解决这个问题。

但如果使用popen,则无需执行此操作。你得到一个FILE *句柄,只需要读取小部分的输出并随时处理它。

  

从那里我将过滤数据并在输出控制台屏幕上显示它。

你是怎么做到的?用shell还是用C?如果在C中,那么您将读取system ed命令的输出,就像读取txt文件一样。唯一的区别是您需要使用pclose而不是fclose来关闭它,因此使用文本文件进行关闭只会有好处。

如果在shell中,那么你可以启动你使用的程序,再次调用popen,这次是"w"(写入)方向,并将一个管道的输出写入另一个管道的输入。但是,在这种情况下,您可能首先使用匿名管道调用shell。 ; - )

<强> 编辑:

您自己的回答清楚地表明您的要求与您的想法完全不同。如果它坚持写入文件,则无法通过管道和reg export读取popen的输出。

您可以尝试将文件写入临时文件夹;您应该被允许在那里创建文件,否则Windows将无法正常工作。只需将“%TEMP%\ reg.out”之类的内容指定为文件,然后从那里读取数据。

如果这不起作用,那么reg export就不顺利了。但您可以使用某些Windows API函数直接查询注册表。这是starting point

或者,您可能希望了解使用PowerShell的可能性。您可能会感兴趣question

答案 2 :(得分:0)

您可以使用Windows中的某些API创建临时文件,并将数据存储在其中。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363875(v=vs.85).aspx

链接中有一个C ++示例,您应该能够根据您的情况进行调整。

答案 3 :(得分:0)

所以,我准备了代码,以便在读取模式下将DOS命令的输出流式传输到文件指针并逐行检查:

    char array_sys[200];  FILE *fp_sys;   int ch,n=0;
    fp=popen("systeminfo","r");  //runs a DOS command & read it with a file pointer
    if(fp_sys==NULL)     printf("can't open file\n"); 
    while((ch=fgetc(fp_sys))!=EOF)  //READ CHARACTERS FROM FILE POINTER UNTIL FILE ENDS
    { 
            array_sys[n]=ch;     //ASSIGN CH TO EACH ELEMENT OF ARRAY    
            n++;                 //INCREMENT ELEMENTS OF ARRAY:-arr_sys
            if(ch=='\n')         //IF ELEMENTS MEET A NEW LINE CHARACTER
            { 
                    disp_date(array_sys,n);  //PASS ARRAY TO FUNCTION:-disp_date
                    n=0;                     //RESET THE ARRAY
            }   
    }

现在,这就是我在函数中处理数组以获取操作系统名称的方法。

    void disp_date(char array_sys[],int ind)
    { 
       char os_name[9]={"OS Name:"};
       if(strstr(array_sys,os_name)) //IF 'OS NAME' IS PRESENT IN ARRAY
       {  
            printf("%s",array_sys);  //PRINT THE ARRAY
       }
    }