Why are my scripts/vusers failing?

What are the possibilities in Vugen?

1. The application that you are replaying against is not running.

Simple? But it does happen, as such, when it fails on replay, take some time and try logging into the application manually and perform the business processes.

2. There were changes to the application.
There were changes to the application in aspect that had affected the script. For a 3-tier architecture, anything could have changed such as the following:

a. Presentation layer: where links or buttons are removed,
b. Application layer: where methods are changed or removed,
c. Database layer: where calls or tables are changed or removed.
d. Architecture level: where proxies or load balancers are changed or removed.

As such, verify with the application and infrastructure team if there were any changes made. You may have to re-script or amend the script accordingly to the changes.

3. There are dynamic values that need to be correlated.
This is common in applications. They are usually in the form of Session IDs or returned values based on parameterization. You have two options here:

a. Use the auto-correlation feature to detect any dynamic values (which I don’t usually use) or,
b. Perform manual correlation by recording two scripts of the same business process. From the two scripts, compare the recording logs and the APIs that had been generated for the differences.

4. The parameterization may be causing the problem.
The parameterization may be causing the problem in the following manner:

a. Insufficient records: ensure that you have sufficient records for the replay, especially in iterations.
b. Incorrect records: verify with the application or database team that you are holding on the valid values to be passed in as parameters. Parameterization may also result in different set of data being returned by the server as mentioned previously in (3). If that happens, correlate the value accordingly.
For (1) to (4), it’s recommended to turn on Full Extended Log (all options enabled: Advanced Trace, Parameter Substitution, Data Returned From Server) in the Runtime Settings (Vugen) to verify the data that is been transmitted between the server and the client (script). Through this, you can find out what and where that could have gone wrong in the replay.

What are the possibilities in Controller?

5. Does it happen at the start of the scenario execution? 
We are focusing on the script only and leaving out the load testing setups. If the script/vuser fail at the start of the execution, verify the script again in Vugen, and if it still fails; it’s a script problem where you have to re-work from the previous point (1) to (4).

6. Does it fail on a particular Load Generator (LG)?
This may be caused by inconsistent LG across the load testing environment. As such, ensure the following in order for the script to run properly (but not limited to the list):

a. Folder directories that the script may be accessing to (particularly for file upload and download business processes).
b. Java settings like JVM and CLASSPATHs that can affect Java LoadRunner scripts.
c. All LGs have the same version as the Controller (e.g. LR9.0 across all LGs in the load testing environment).

7. Does it happen at the middle of the scenario execution? 

If it is the case, it may be caused by anything but unlikely script problems (since the script/vuser have already started running successfully at the start of the run in (5). When this happens, the Application under Test (AUT) maybe under load and unable to process all requests from the scripts/vusers and therefore returning errors to them. You can verify this with the following.

a. Manually log into your AUT again and verify if it is still running or experiencing any lags.
b. Reduce the amount of vusers being generated in the scenario and re-run the test. If a reduced amount results in an error-free or non-script related errors, you are sure that the AUT is under load.

The above should be sufficient for you to troubleshoot script/vuser problems in Vugen and Controller. However, take note that it may not be limited to those and it will be advisable to carefully work the problem step-by-step to eliminate and possibilities

Difference between HTML, URL and GUI Mode Recording

HTML Mode:

Default and recommended recording mode.

Records HTML action in the context of the current Web page so that all we see on a web page will be recorded in a single function which makes it easier to read.

Advantage of this mode is that it generates a script that is intuitive to the reader in terms of what is the form requesting (in a form of entire web page).

Best for browser applications.

URL Mode:

Instructs VuGen to record all requests and resources from the server. It automatically records every HTTP resource as URL steps.

Generates a script that has all known resources downloaded for your viewing which works good with non-HTML applications such as applets and non-browser applications (e.g. Win32 executables).

Having everything together creates another problem of overwhelming low-level information and making the script unintuitive. Difficult to read.

When there are unrecognizable requests made to the server in Web (HTTP/HTML) protocol, they are recorded as web_custom_request. However, in URL-mode, this can be selected to allow recording to default to web_custom_request.

GUI Mode:

Introduced with Web (Click & Script) protocol.

GUI-mode option instructs VuGen to record all editable fields in an object or non-browser applications. What it does is to detect the fields that have been edited and generate the scripts accordingly.

Concept similar to functional testing when objects are detected at theGUI-level. When reading the script, it allows easier reading as the script is based on the GUI presented to the real user. Easier to read in context of the object.

Best for applets and non-browser applications.

Difference between Loadrunner and performance center


LoadrunnerPerformance Center
Loadrunner is a industry standard enterprise level load testing toolPerformance Center is a web enabled load testing tool
Resource management (VuGen scripts, scenarios and results) is local to the person, who is using the loadrunner tool on his local machineResource management is centralized, since it is web enabled
If there are multiple performance test engineers using the shared lab, there is lot of dilemma how to reserve the lab for a specific load testUsing performance center the lab machines can be reserved for a time slot
Using load runner optimum usage of virtual users licenses is a problem, if more than one load tester is involvedVirtual users can be reserved based on the time slot. So the user licenses can be optimally used in this case
A single load test at a time can be initiated from a loadrunner controllerMultiple load tests can be executed simultaneously using performance center
Versioning of the resources is not possibleVersion of the resources is possible through performance center
Locally accessible platformA Web-based, 24x7, globally accessible platform
Assets can be shared only on the local projectsLoad test assets (VuGen scripts, results) can be shared across the project
Monitoring will help identify infrastructure issuesInfrastructure topology definition and monitoring to help identify infrastructure issues
There is no traceability in loadrunnerPerformance requirements and defect traceability
There is no direct integration with HP Application Lifecycle Management and Business Availability CenterIntegration with HP Application Lifecycle Management and Business Availability Center
Loadrunner is good, if you have a small load testing team sitting in one locationPerformance center is good, if you have a large distrbuted load testing team sitting in different locations

Performance Center Interview Questions-Enough stuff on PC

1. Tell something about performance center?
2. Which of the cases performance center will be chosen over loadrunner?
3. What are the types of access sites available in performance center?
4. What is a user site in performance center?
5. What is host in performance center?
6. Can one system act as a controller and load generator in performance center?
7. What is a timeslot in performance center?
8. What is the significance of using the time slots in performance center?
9. How to create Vuser Scripts in performance center?
10. What are the steps followed to upload VuGen scripts in performance center?
11. How to create test scripts directly in performance center?
12. What is a monitor profile in performance center?
13. How to add monitor graphs from performance center?
14. What is auto start viewer in performance center?
15. How to configure auto start viewer in performance center?
16. What is the significance of options in performance center?
17. Where the settings for Transaction Data and Server Resource Monitors will be set in performance center?
18. What are the run time settings can be set in performance center options?
19. How to set the time out settings for load generator and vuser in performance center?
20. What is the debug information settings can be set in performance center options?
21. How multiple ip address allocation per process or thread can be set in performance center?
22. How to switch from one project to the other without logging out from performance center?
23. How to create a new load test in performance center?
24. How to enable spoofer in performance center?
25. How to pause a scheduler at load test start in performance center?
26. What are the options available in assigning the load generators to groups in performance center?
27. How to set and change the group size by number in performance center?
28. What is the advantage of using group size by percentage option in performance center?
29. How to add multiple groups in performance center load test?
30. What is the significance of using start time options in performance center scheduler?
31. What is the significance of using schedule options in performance center scheduler?
32. What is the significance of using run mode options in performance center scheduler?
33. What are the actions available in performance center global schedule?
34. What is the significance of using each action in performance center global schedule?
35. How to add monitors in performance center load test?
36. What do search results module displays in performance center?
37. How to change personal information in performance center?
38. What and where to see recently run load tests in performance center?
39. What and where to see currently run load tests in performance center?
40. What and where to see next reserved timeslots in performance center?
41. What and where to see the dash board section of performance center?
42. How to set service level agreements in performance center?
43. What are the types of service level agreements available in performance center?
44. How to download the load test results from performance center?
45. How to analyze the results in performance center?
46. What are the reports generated by performance center?
47. How to upload test scripts directly from VuGen to performance center?
48. How to import the scripts from one project to other in performance center?
49. How to edit the uploaded scripts in performance center?
50. How to import the monitors from one project to other in performance center?
51. What are the prerequisites to import the scripts and monitor profiles in performance center?
52. How to add more monitors to the existing monitor profile in performance center?
53. How to add a project to be part of auto start viewer in performance center?
54. What is the difference between the project and load test in performance center?
55. How to assign virtual load generators to the groups in performance center?
56. How to analyze the load test results from analyzer in performance center?
57. How to publish the load test results to dashboard in performance center?
58. What is the prerequisite to publish the load test results to dashboard in performance center?
59. What are the details displayed after the load test is published to dashboard in performance center?

Difference between Thick Client and Thin Client

Thick Client Vs Thin Client:

Thin Client
Thick Client
Mostly it is a web based client. Will be accessed through a common client called browser
It will be accessible through client software which is installed locally
Business logic will be there in middleware’s or application servers.
Business logic will be installed in the local machine.
When the URL is accessed most of the business logic will be executed on the server. And some client side processing and rendering happens within the browser.
When the client get installed all the business logic of the application installed locally
Thin client uses stateless connections. For each request connection will be opened and after the response it will be closed
Thick client uses dedicated connections
Thin clients are slower in response
• Connection needs to be opened explicitly for each request
• Pages needs to be downloaded from presentation layer
• Data needs to be retrieved from the DB
• Business logic related processing will be happening in the middle wares or application servers
Thick clients are faster in response
• most of the processing happens locally
• Connections will be closed only explicit logouts
Thin clients will be used by the external users. Ex: Bank customers
Thick clients will be used by the internal users most of the times: Ex: Bank employees and customer support executives

ORACLE NCA protocol

This is part 1 of an article which discusses some of the mechanisms for performance testing Oracle Applications / Oracle Forms using LoadRunner. This is far from an in-depth article but will, we hope, help performance testers get started with testing Oracle Applications and act as a reference resource. The article as a whole covers two key areas that seem to present the most issues, Object Names and Connect issues, as well as some other issues that we at Testing Performance have come across when delivering our Performance Testing Services. Part 1 covers Object Names issues.

Object Names 

One of the first issues you will come across when recording an Oracle Application is that Oracle objects are recorded by a number rather than a name. These numbers are dynamic and cannot be relied upon when playing back a script, i.e. the object cannot be found by LoadRunner as its “number” has changed.

Here is an example of objects recorded by their object number (this is part of a login script that was recorded using Oracle Applications 11i protocol against an Oracle Forms application):

nca_edit_set(“31”, ”USERNAME”);

nca_obj_type(“31”, ‘\t’, 0);

nca_edit_set(“32”, (”PASSWORD”));

nca_obj_type(“32”, ‘\t’, 0);

nca_edit_set(“33”, ”TRAINING”);

nca_button_press(“34”);


This script refers to four objects 31, 32, 33 and 34. If these objects do not change their number between recording and execution then the script should run OK. However these numbers are subject to change for example if a new field is added on the form between object 33 and object 34 then the nca_button_press(“34”) would fail as would now probably known as 35. To get round this issue Oracle offers the “RECORD=NAMES” method which associates a name to each object rather than a number. The name is very much more likely to remain static.

Here is the same example as above except the objects were recorded by their object name (this is part of a login script that was recorded using Oracle Applications 11i protocol against an Oracle Forms application):

nca_edit_set(“LOGON_INFO_USER_NAME”, ”USERNAME”);

nca_obj_type(“LOGON_INFO_USER_NAME”, ‘\t’, 0);

nca_edit_set(“LOGON_INFO_USER_PASSWORD”,(”PASSWORD”));

nca_obj_type(“LOGON_INFO_USER_PASSWORD”,(””, ‘\t’, 0);

nca_edit_set(“LOGON_INFO_USER_DATABASE”,(””,”TRAINING”);

nca_button_press(“LOGON_INFO_CONNECT_BUTTON”);
....
By default, in all the engagements that I have been involved in at least, Record=Names is not enabled. So how do you enable Record=Names? Here are four methods for achieving this, three of which require a configuration change and one which is very simple. I have found that finding the correct method is very much a “suck it and see” methodology.

Before trying the following just make sure that your installation records numbers instead of names by recording a simple logon script.

Method 1: Append to URL 

This is very much the simplest method and should be tried first.

Below is the Start Recording dialog presented when recording using the Oracle Applications 11i protocol. The URL in this case is:

http://apps.acme.co.uk:7778/forms/frmservlet?config=2001

Try appending record=names to the end of the URL, for example:

http://apps.acme.co.uk:7778/forms/frmservlet?config=2001&record=name

Note if record=names is the first parameter to be added to the url then you will need a question mark before it eg:

http://apps.acme.co.uk:7778/forms/frmservlet?record=names

If however there are one or more parameters already in the url then you will need the ampersand prefix eg:

http://apps.acme.co.uk:7778/forms/frmservlet?config=2001&record=names
Now try and record a simple login script, if the object numbers are replaced by object names then you are in business. You should also notice that the record=names flag is appended to the connect_server statement.

Note: This method worked with the following configuration:
Oracle Forms version: 1012002

LR Protocol: Oracle Applications 11i

LR Version: 9.5

Jinitiator version: 1.3.1.28 (not overly important)

Method 2: Set record=names in startup file 


This method requires a change to the HTML startup file on the forms server. Tracking which file to change can be a bit tricky if someone has renamed the appropriate file, which they are quite entitled to do. The file you are looking for is the one that is called when the forms applet starts. This file holds configuration details for the forms applet. By default the name of the file is basejini.htm.

The file contains a number of configuration entries. The line you are interested in is something like this:

[param name="”serverArgs" fndnam="APPS”" /] Note there may be a number of entries which replace the ellipses (…) above.

Append record=names as the last argument i.e.: [param name="”serverArgs" fndnam="APPS" record="names”" /]

>

Note: there is a space between the fndnam=APPS argument and record=names.

Now try and record a simple login script, if the object numbers are replaced by object names then you are in business. Note: This method worked with the following configuration:

Oracle Forms version: 60824

LR Protocol: Oracle Applications 11i

LR Version: 9.5
Jinitiator version: 1.1.8.16 (not overly important) 

Method 3: Set value in formsweb file and HTML start-up file 

I have had to use this method less often than the previous two methods. This method should be used if the HTML start-up file references the Forms CGI configuration file. This method requires two files to be changed.

The Forms CGI configuration file in question is formsweb.cfg (it may have been renamed but probably not).

You will need to add a new entry in this file under the USER PARAMETERS in the section: “Values for Forms applet parameters”. Add the following as the last entry in this section:

xrecord=names

Your file should look something like this:

connectMode=socket

serverHost=serv1.acme.co.uk

xrecord=names
;
4) Parameters fo Jinitiator

In the HTML start-up file basejini.htm (or whatever its name has been changed to) there are a number of configuration entries. The lines you are interested in go something like this:

[param name="”serverArgs" fndnam="APPS”" /] Note there may be a number of entries which replace the ellipses (…) above.

Append record=%xrecord% as the last argument i.e.: [param name="”serverArgs" fndnam="APPS" record="%xrecord%”" /]

Note 1: there is a space between the fndnam=APPS argument and record=%xrecord%.

Note 2: there may be more than one entry in the HTML start-up file that needs to be changed

Method 4: Oracle Applications record=names flagoracle nca pop up handle: 
We will see step-by-step procedure of how to handle the pop-up windows while using Oracle NCA protocol: 
Put the title of the pop-up window in nca_obj_statusfunction.
Find out where the pop-up is occurring, put the handling statement below it.
The handling statement could benca_popup_message_press or nca_message_box_press.To find out which function is suitable for your script, record a script using data that generates that popup window, click on the button and check which function gets recorded. 

Example:

This piece of code will trigger a pop-up:


nca_set_window( "PopUpObjects");

nca_lov_retrieve_items("PopUpObjects",1,20);

nca_lov_select_item("PopUpObjects","POP UP NOTIFICATIONS"); 
If title of the window is “Warning”, put it inside the nca_obj_status function. The code would be something like-

int status;

status=nca_obj_status("Warning");

if (status = = 0)

nca_popup_message_press("Warning","OK");

// nca_message_box_press("Forms",1); Any one of them

LoadRunner License Information

LoadRunner License Information
To preview your license key information, click
Start > Programs > Mercury LoadRunner > LoadRunner. Mercury
LoadRunner opens. Click the License button. The License Information
dialog opens.



The LoadRunner License Information dialog displays the following
information:
Chapter 1 • Introduction
License Keys: Displays the available license keys, as well as a summary of all
the available license keys.
License Key Information
Type: Displays the type of license available for the license key you selected.
The following types of licenses are available:
➤ Permanent: The license never expires.
➤ Time Limited: The license is limited by a start date and an expiration
date.
➤ Temporary:  The license is granted for a pre-defined number of days after
product installation.
➤ VUD-based: The license is limited by a number of Virtual User Days
(VUDs). A VUD license enables the user to use the product an unlimited
number of times within a period of 24 hours.
Note: If a user has a VUD-based license for 1000 Vusers and the maximum
number of concurrently running Vusers within a 24-hour period is 300, the
following day the user will be able to run the remaining 700 Vusers.
➤ Plugged: The license requires a dongle.
License Validity: Displays the time limitation of the selected license key. 
Vuser Types: Displays a list of Vuser protocols available for the selected 
license key. 
Monitors: Displays the server monitors available for the selected license key.
Host ID: Displays an ID for a specific machine. To receive a license key for a
specific machine, contact Mercury’s Customer Support.

To modify the current license information:




Click Start > Programs>MercuryLoadRunner>LoadRunner to open the 
Mercury LoadRunner window, and then click the License button. The
LoadRunner License Information dialog box opens. 

Click the New License button. The New LoadRunner License dialog box
opens. 

Enter the new license number exactly as it was given to you and click OK. If
your license is limited for a specific amount of time, LoadRunner issues a
message accordingly. 

Click OK to close the New LoadRunner License dialog

LoadRunner VuGen scripting - How to automatically download file from server and save it to local disk?

LoadRunner records file transferring from server and does not record file saving.

What to do, if you have to save transferred file to local disk?
Continue reading, and you will get the solution :)

You can download file from a server with the web_url function.
See an example:

Image downloading:
web_url("logo.gif",
"URL=http://www.google.com/intl/en_ALL/images/logo.gif",
"Resource=1",
"RecContentType=image/gif",
"Snapshot=t1.inf",
LAST);

This code downloads Google's logo image:

To save this image as file to local disk, we have to perform these steps:
Capture image from server's response
Save captured data to local disk

How to capture image from server's response?

Use web_reg_save_param function with the following boundaries - "LB=\r\n\r\n", "RB=". These boundaries allows to capture the whole data from a body of server's response. Function will look like:
web_reg_save_param("prmLogoImage", "LB=\r\n\r\n", "RB=", LAST);

This function should be placed before web_url function. After execution, prmLogoImage parameter will contain GIF-file.

I will clarify briefly the meaning of boundaries - "LB=\r\n\r\n" and "RB=".
Please, read the basic concepts of HTTP protocol, read Request message section:

HTTP response consists of the following:
Headers, such as HTTP/1.1 200 OK or Content-Length: 3473
An empty line
A message body, containg text of requested page or file

So, Header and Message body should be separated by empty line.
First CRLF (that is, a carriage return (CR = "\r") followed by a line feed (LF = "\n")) ends last header, and second CRLF ( = "\r\n") creates empty line. All data, followed by second CRLF, are treated as message body.
To summarize - "LB=\r\n\r\n" says "start capturing from the beginning of message body", empty right boundary "RB=" says "capture data till the end of message".

Open LoadRunner and enable logging of data, returned by server:


Then execute script containing initial web_url function, and open Replay log:


As you see, Replay log contains "\r\n\r\n" at the end of server's response.
Also, pay attention, that server returns the length of file to be downloaded (Content-Length: 8558).

Save captured data to local disk
Saving captured binary data (in our case, GIF file) requires additional step - we have to determine the length (= size) of captured data.

Tips: The simplest way - strlen function - is not correct. Imagine, that that captured data contains embedded NULL characters ('\0'):
"123\0qwe"
The real size of captured data = 7 bytes ('1', '2', '3', '\0', 'q', 'w', 'e').
But strlen function will return value 3, because it counts bytes before the first NULL character ('\0').

To calculate size of captured data use lr_eval_string_ext function:
lr_eval_string_ext ("{prmLogoImage}", strlen("{prmLogoImage}") /* = 14*/, &szBuf, &nLength, 0, 0,-1);

lr_eval_string_ext function copies captured data into szBuf array and places a size of captured data into nLength variable. That's easy, I hope :) If not, Help will help :)

Tips: There is another way to get known the size of file to be downloaded. Remember, that server returned the length of file (Content-Length: 8558). So, you can extract this value using Correlation.

And the last action is to save binary data from szBuf array into a local file. I used standard fwrite function from C programming language:
fwrite(szBuf, len, 1, hFile);

Well, please see the whole source code:

Click the block to expand the source code:
int WriteDataToFile(char *szFileName, const char *szBuf, int len)
{
int hFile;

hFile = fopen(szFileName,"wb");
.....

Execute the source code, and you will see, that new file will be created and saved automatically - "C:\LogoImage.gif". And this is what we needed - Google's logo image.

How to record a file saving, performed by user from browser page?

The problem:
This is a frequently asked question - why file downloading from a browser page (right mouse click, then "Save Target As...") was not recorded in LoadRunner VuGen script?

The difference between functional and load testing:Actually, LoadRunner records a file transferring only, not downloading!
This is the principal difference between functional and load testing! I will describe it.
Functional testing is done from a user's viewpoint.


What does a user see? It sees windows, dialogs, UI cotrols.
For example, user can see downloaded html-page in a browser, or as plain text in a telnet session.
In this case, data transferring is the same (HTTP protocol), while data representation varies (browser or telnet session).
LoadRunner performs Load testing, i.e. it records and emulates data transferring between client and server. Data transferring only, not data displaying for user!
For the above example, html-page can be downloaded directly from web-server. Another variant - page can be downloaded from FTP-server (even using Secured FTP protocol - FTPS), and then data will be passed to browser. User will see the same page.
In this case, data representation is the same (browser page), while data transferring varies (HTTP or FTPS protocols).

So, remember the simple rule:

LoadRunner does not record client side activities!

Tips: That's why LoadRunner does not show browser windows during load testing.
Note: Please, do not tell me, that VuGen shows Run-Time Viewer during replay :)
The run-time viewer was developed specifically for script debugging. There is no dependency between data representations in Run-Time Viewer and in a real browser (for detailed info read Mercury Support Knowledge Base (http://kb-web.mercury.com, requires login), topic 14094 "What are the limitations of the Run-Time Viewer").

LoadRunner - how to convert a plain text to URL format

The task - How to convert a plain text string to URL-format in LoadRunner?

Several days ago I faced with a simple task - it was needed to convert a passed parameter (which was in a plain text form) to URL-format. In other words, I had to convert:
string "ab" to the same string "ab"
string "a b" to the string "a%20b"
string "a b_c%" to "a%20b%5Fc%25"
and so on ...

The cause - Why it was needed?
LoadRunner script contained parameters, which should be passed to URL directly. Some my parameters contained special characters like spaces (" "), quotes ("), percentage ("%"), asterisks ("*") and others. To be processed correctly by a browser and a web server, these characters should be translated and passed as their hex-codes.
For example:
a space character (" ") has hex-code 0x20, so it should be passed as "%20"
underline character (" ") has hex-code 0x5F, so it should be passed as "%5F"
The ways on how to perform the task.
To perform this task I decided to use LoadRunner's web_convert_param function. I didn't know at that time that this function does not satisfy my requirements. So, I was reluctant to write my own function EncodePlainToURL. Well, let's see both solutions.
web_convert_param function.

As Help says, web_convert_param function converts HTML to a URL or plain text.
So, I wrote this code:
char sIn[] = "t es%d$ + eprst_"; That means that space (" ") was converted to a plus ("+"). I expected to see "%20" instead of a plus character.

Actually, it seems that "+" and "%20" are twins. For example Google uses a plus to encode a space within a search query. For example, if the query is "some text", then the URL will be: http://www.google.com/search?hl=en&q=some+text&btnG=Google+Search

I was tried to encode spaces (and others special characters) to their hex-codes.
That's why the following function was written:


EncodePlainToURL function.

The logic is simple enough:
If the current character is a digits or an alphabetic letter, then pass it "as is"
Otherwise the current character is a special one. So, hex-code should be written in this case This is a code of EncodePlainToURL function:/* * EncodePlainToURL converts a plain text string to an URL-form string. * * Parameters: sIn - input string to be encoded to URL format * sOut - output buffer * Note: the size of "sOut" parameter should be at least equal to triple size * of "sIn" parameter plus one character(for end-terminator '\0') 

 Examples:
 "a" -> "a" * "a b" -> "a%20b" * "a b_cc:\/c%" -> "a%20b%5Fcc%3A%2Fc%25" */ 

char *EncodePlainToURL(const char *sIn, char *sOut) 
{
 int i; 
 char cCurChar; 
 char sCurStr[4] = {0}; 
 sOut[0] = '\0'; for (i = 0; cCurChar = sIn[i]; i++) 
 {
 // if this is a digit or an alphabetic letter

 if (isdigit(cCurChar) || isalpha(cCurChar)) 
 {
 // then write the current character "as is" 
 sprintf(sCurStr, "%c", cCurChar); } 
 else
 { 
 // else convert it to hex-form. "_" -> "%5F" 
 sprintf(sCurStr, "%%%X", cCurChar);
 }
 // append current item to the output string 
 strcat(sOut, sCurStr);
 } 
 return sOut; 
}
 The example of usage is: 
char sIn[] = "t es%d$ + eprst_"; char sOut[100];
 lr_output_message("%s", EncodePlainToURL(sIn, sOut));
 Execute the code, and see the result: 
The input string "t es%d$ + eprst_" was converted to "t%20es%25d%24%20%2B%20eprst%5F".