Everyone should already know that you can run a command-line program from a LoadRunner script using the system() function. If you have used this, you would already know that things become a little awkward when need to capture the output of the program.

The common solution is to pipe the output of the command to a file (i.e. system(“my_command > output_file.txt”)), and then read the contents of the file. This is clunky and awkward, and not safe when multiple virtual users are writing to the same file.

A much better solution is to run all your command-line (DOS) programs using the popen() function. Read on for examples…

The popen() function works exactly the same as fopen(), except that instead of opening a stream to a file, you are opening a stream to a command line program. After calling popen(), you can just use the file stream functions (fscanf, fread, etc) as normal.

/*
Documentation on popen can be found here: http://www.mkssoftware.com/docs/man3/popen.3.asp
*/
#define BUFFER_SIZE 10240 // 10 KB

Action()
{
    long fp; // file/stream pointer
    int count; // number of characters that have been read from the stream.
    char buffer[BUFFER_SIZE]; // allocate memory for the output of the command.

    /*
     * Running a simple command, and printing the output
     */

    // "VER" outputs the version of Windows that is running.
    fp = popen("VER", "r");
    if (fp == NULL) {
        lr_error_message("Error opening stream.");
        return -1;
    }

    count = fread(buffer, sizeof(char), BUFFER_SIZE, fp); // read up to 10KB
    if (feof(fp) == 0) {
        lr_error_message("Did not reach the end of the input stream when reading. Try increasing BUFFER_SIZE.");
        return -1;
    }
    if (ferror(fp)) {
        lr_error_message ("I/O error during read."); 
        return -1;
    } 
    buffer[count] = NULL;

    lr_output_message("The Windows version is: %s", buffer);
    pclose(fp);
    return 0;
}

Here is an example, where each output row is saved to an element of a LoadRunner parameter array…

extern char* strtok(char *token, const char *delimiter); // Explicit declaration required for functions that do not return an int.

#define BUFFER_SIZE 10240 // 10 KB

Action()
{
    long fp; // file/stream pointer
    int count; // number of characters that have been read from the stream.
    char buffer[BUFFER_SIZE]; // allocate memory for the output of the command.
    char * token;
    char param_buf[10]; // buffer to hold the parameter name.
    int i;

    /*
     * Running a command, and splitting the output into separate parameters for each element.
     */ 

    // "DIR /B" gives a "bare" directory listing (in this case, of the files in the VuGen script directory).
    fp = popen("DIR /B", "r");
    if (fp == NULL) {
        lr_error_message("Error opening stream.");
        return -1;
    }

    count = fread(buffer, sizeof(char), BUFFER_SIZE, fp); // read up to 10KB
    if (feof(fp) == 0) {
        lr_error_message("Did not reach the end of the input stream when reading. Try increasing BUFFER_SIZE.");
        return -1;
    }
    if (ferror(fp)) {
        lr_error_message ("I/O error during read."); 
        return -1;
    }
    buffer[count] = NULL;

    // Split the stream at each newline character, and save them to a parameter array.
    token = (char*) strtok(buffer, "\n"); // Get the first token 

    if (token == NULL) { 
        lr_error_message ("No tokens found in string!"); 
        return -1; 
    }

    i = 1;
    while (token != NULL) { // While valid tokens are returned 
        sprintf(param_buf, "output_%d", i);
        lr_save_string(token, param_buf);
        i++;
        token = (char*) strtok(NULL, "\n"); 
    }
    lr_save_int(i-1, "output_count");

    // Print all values of the parameter array.
    for (i=1; i<=lr_paramarr_len("output"); i++) {
        lr_output_message("Parameter value: %s", lr_paramarr_idx("output", i));
    }

    pclose(fp);
 
    return 0;
}

Note that the popen() function is no good for controlling interactive command-line programs (that depend on user input), but it is certainly a very nice way of running command line programs from a LoadRunner script.

Β 

Published On: August 23, 2010Tags: ,

22 Comments

  1. Stuart Moncrieff August 24, 2010 at 10:48 am

    From the Linux man page for popen (in stdio.h):

    “Since a pipe is by definition unidirectional, the type argument may specify only reading or writing, not both; the resulting stream is correspondingly read-only or write-only.”

    Assuming the you want to read from the stream opened by popen(), this is only a problem if the command line program is interactive.

    A dodgy work-around for this limitation might be to include input piped in from your original command. e.g.

    echo y | DEL /P
    
  2. Stuart Moncrieff August 24, 2010 at 2:56 pm

    Simon, you’re a genius! For reference, this is User Contributed Knowledge Base article 10058 “Controlling interactive DOS sessions”. The solution involves creating a batch file which calls the interactive command line utility and uses SET /P to prompt for input, and piping a text file containing the input parameters to the batch file. like… c:\>mybatch < inputparameters.txt See Simon's article for more information.

  3. Chris August 24, 2010 at 7:17 pm

    Nice one Stu! I will have to re-write my horrible command line vugen script tomorrow!

  4. soubhiks April 17, 2011 at 6:04 am

    hi,
    i loved the post above, but i have a question

    what if i had to write a script where i needed to write multiple vusers to write on the same file.
    i have a script where i need to record a small portion from the response for each of the vusers.. and i am finding it quite difficult to maintain the file..
    πŸ™

    thanks in advance

  5. SK November 15, 2011 at 2:34 am

    Nice one!
    Can I run multiple users on one machine using command line script?

  6. guy August 3, 2012 at 5:26 am

    Only problem is that it’s popup the CMD console while executing,?
    Any solution for this ??
    Thanks ?

    • Stuart Moncrieff December 2, 2013 at 10:22 am

      Yep. The black window that pops up when the command line program is run by popen() is really annoying. Unless I am debugging, I don’t run the VuGen script on localhost; I always run it on a remote load generator.

  7. Brian October 5, 2012 at 8:22 am

    Thanks for this! It almost does what I need. One question; Going by the first example, it seems we have to wait for the cmd to complete before any processing of the stream can be done? I would like to formant and print the stream as it happens, live. Is this possible? I hoping to run a perl script and use it’s output as data points in loadrunner.

    Thanks for any help!

    -Brian

  8. Kavi March 12, 2013 at 3:23 am

    Hi Stuart,
    Can u please provide your mailid for sending the queries.
    Need more clarifications regarding this topic

  9. Jean May 9, 2013 at 6:54 pm

    How to call java function from LR??

    • Stuart Moncrieff December 2, 2013 at 10:33 am

      You have several options if you need to call Java code from a LoadRunner script:

      1. Use the LoadRunner Java vuser type. Then calling your Java code is as simple as adding a jar file to your script and importing the correct package. Note that using the LoadRunner Java vuser type requires that you are licensed for either the Java Template vuser type or the Java Record-Replay vuser type.
      2. Wrap your Java code in a Java console program, and then invoke the Java command line program e.g. popen(“java com.example.myapp”);
        Note that this may be slow and CPU intensive if you are going to invoke Java very frequently.
      3. Wrap your Java code in a web application, and then call it via HTTP by using the LoadRunner web_url() function.
  10. Wonder August 22, 2013 at 7:12 am

    Stuart,
    I am using the Web (HTTP/HTML) protocol to record a script for the co. business process. I need to also access the print function and select the printer/ PDF writer from the Windows Print Popup option. The vugen script will not record any of the Windows Print option steps. I also tried the multiprotocol Microsoft Remote Desktop Protocol (RDP) and WEB protocol, but it does not work either, any suggestions?

    Thank you in advance!

  11. Chris September 20, 2013 at 2:23 pm

    Really nice work Stuart! Thank you!

  12. Stuart Moncrieff November 29, 2013 at 8:37 am

    AN IMPORTANT NOTICE
    ===================

    Someone has told me that it is not possible to capture the output of the command run with popen() when the LoadRunner Agent is running as a service. The Agent must be run as a process for this to work.

    • Sailu Dolly May 25, 2016 at 11:28 pm

      Hi Stuart,

      Thank you very much for the details on command line functions. All your suggestions and codes worked were very much helpful is developing the Vuser script. I am now facing an issue when trying to run the script for multiple Users from 2 load Generators. The stream is not getting opened after 2044 times. Could you please let me know what could be the issue.
      After the script gets executed for 2044 times in total by all users, the users are failing with the error “Failed opening stream”. Could you please help.

      Thanks,
      Dolly

  13. Scott Turner February 6, 2014 at 2:28 pm

    I have used this many a time now to troubleshoot issues within a HP SaaS project where all i have access to is the SaaS interface and some networking issue has occurred on a loadgenerator deployed in Africa, Australia or USA. I have even created scripts to restart loadrunner service or the box itself. However there is a run command that you need in the SaaS interface to enable the command to work. Just giving acknowledgement to my source πŸ™‚

  14. Sunil February 12, 2014 at 6:38 pm

    Good Article Stuart..let me try

  15. Anand July 24, 2014 at 10:51 am

    Hi Stuart,

    Nice explanation Thanks . I have one clarification. I am using popen to run command line program , but each time i execute i get multiple console prompting up.Is there any way where we can disable the consoles. Maximum say 5 users will be used for this each may run say 500 times so more consoles are popped up during the test. Please suggest how to handle/overcome this.

    Thanks in advance

  16. Raj January 22, 2015 at 5:01 pm

    Thanks for this! It almost does what I need. One question; Going by the first example, it seems we have to wait for the cmd to complete before any processing of the stream can be done? I would like to formant and print the stream as it happens, live. Is this possible? I hoping to run a perl script and use it’s output as data points in loadrunner.

    Thanks for any help!

    Do you have any answer to this question?

  17. Jothiswaran Ramachandran February 13, 2016 at 1:57 am

    Thanks Stuart! Using intermediate files really is clunky and awkward πŸ™‚

  18. raghav July 15, 2016 at 2:29 am

    how capture the command prompt text using load runner?
    we tried with system command for passing the commands to the command prompt but unable to read the text from command prompt.
    Please help us.

  19. Rahul September 17, 2016 at 1:47 pm

    Hi Stuart, We have recorded a windows batch application using VB script, but while trying to run in controller and try to run with multiple concurrent users, we face following problems,
    1. At any point of time, only one batch files or script runs and remaining scripts/users fails
    2. It seems while we try to run with 5 Vusers concurrently, the window focus remains only one window at a time, out of 5 vusers only 1 is able to perform operation.
    We have huge no of concurrent no of users around 400 to simulate in performance testing,but due to above issue, we are unable to move ahead. It would be great if you help us here. Thanks for your help in advance.

Comments are closed.