Running command-line programs from LoadRunner

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.

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
/*
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…

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

3 Responses to “Running command-line programs from LoadRunner”

  1. [...] My Load Test Performance Testing with a LoadRunner focus « Running command-line programs from LoadRunner [...]

  2. Stuart Moncrieff says:

    Could try this…
    echo y | DEL /P

  3. Chris says:

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

Leave a Reply