DO WANT ERRORS:
Ever get sick of having to constantly change command line arguments for programs that run on the command line? Wish you could just create a nice, easy to use user interface for a program? Well, I'll show you a few functions that will make it easier to do so.
At the bottom of this tutorial is an attachment; "tutorial.zip". Inside you will find my example program that runs on the command line. This is the program I will be creating a user interface for in this particular tutorial.
What does the program do?
All the command line program does is perform ROT-5 (Caesar) encoding on all the command line arguments it is given and output them to the standard output. However it's a pain to go and change the command line arguments and then restart the program each time just to get the encoding, so let's make an interface that enables us to change the command line arguments easily, and read whatever the program sends back.
What is the aim here?
In layman terms we want to create another program that:
Modify the command line arguments to the program.
Runs the program
Redirects the standard output to itself so it can display it to the user.
???
Profit.
Okay, hopefully everyone knows what the aim is, now we need to begin making our program. I'm going to write some very generic functions that you can use for just about any project that has the same purpose as this one (interfacing with a command line program).
First off, create a new Windows Application project, call it whatever you want and press okay.
Now, press F7 to go to the code window (if you're using Visual Basic/Studio) and we'll begin with a simple structure.
StandardResponse
a very simple structure to hold the standard error and standard output from the process.
[highlight=vb.net]
Public Structure StandardResponse
Public Output As String 'holds the std output for this response
Public [Error] As String 'holds the std err for this response
Public Sub New(ByVal o As String, ByVal e As String)
'very simple constructor to set the output and error
Me.Output = o
Me.Error = e
End Sub
End Structure
[/highlight]
CaptureResponse
this is the core function to the program, it will accept a few arguments and then send us back whatever the program responded with. Here's the method signature:
[highlight=vb.net]
Public Shared Function CaptureResponse(ByVal filePath As String, ByVal args As String, Optional ByVal maxWait As Integer = Integer.MaxValue, Optional ByVal workingDir As String = "") As StandardResponse
End Function
[/highlight]
Okay, CaptureResponse takes 4 arguments, what are they?
filePath - The path to our command-line program.
args - a string containing all the arguments to pass to the program. This function assumes the args have already been formatted prior to the function call.
maxWait - Optional, if manually set restricts how long our program will wait for the process to finish executing (in milliseconds). It's a good idea to set this in case of infinite loops within our called process.
workingDir - The working directory for the program. This is optional, but if set this directory will become the relative path for the program. Don't worry, if you don't know what the working directory is you probably won't need to change it.
Time to fill out this function. We're going to need to set up a process, execute it, trap the output and return it to the caller. Comments are included
[highlight=vb.net]
If ( String.IsNullOrEmpty(workingDir) ) Then workingDir = IO.Path.GetDirectoryName(filePath) 'if no working directory was set, make it the directory where the filePath resides.
Dim cmdProc As New Process() 'create a new instance of the process class.
Dim pInfo As New ProcessStartInfo(filePath, args) 'construct a new ProcessStartInfo, and set the file path and arguments of the process we wish to start.
pInfo.WorkingDirectory = workingDir 'set the working directory.
pInfo.UseShellExecute = False 'we do not wish to use ShellExecute to run this process, as that means we cannot redirect the standard output/error
pInfo.CreateNoWindow = True 'we don't want this process to create its own window, we just want it to run hidden, send us its output and then shutdown.
pInfo.RedirectStandardOutput = True 'obviously we do wish to redirect the standard output.
pInfo.RedirectStandardError = True 'we also do want to redirect the standard error, in case something goes wrong.
cmdProc.StartInfo = pInfo 'set our processes start info to what we just configured.
cmdProc.Start() 'begin the process.
cmdProc.WaitForExit(maxWait) 'stall our program until the process exits or maxWait is reached.
'after this point, the process "cmdProc" has exited.
Dim response As New StandardResponse() 'create an empty StandardResponse using the default constructor.
Using stdOutReader As IO.StreamReader = cmdProc.StandardOutput
response.Output = stdOutReader.ReadToEnd() 'read the standardoutput to the end and assign it to our "response" structure.
End Using
Using stdErrReader As IO.StreamReader = cmdProc.StandardError
response.Error = stdErrReader.ReadToEnd() 'same as above, but this time assign it to the "Error" variable.
End Using
Return response 'return our response
[/highlight]
And that's the CaptureResponse function completed! If you don't understand some of the comments or how some stuff works, feel free to post in the thread and I'll do my best to answer your questions.
Our CaptureResponse code should now look like this:
[highlight=vb.net]
Public Shared Function CaptureResponse(ByVal filePath As String, ByVal args As String, Optional ByVal maxWait As Integer = Integer.MaxValue, Optional ByVal workingDir As String = "") As StandardResponse
If (String.IsNullOrEmpty(workingDir)) Then workingDir = IO.Path.GetDirectoryName(filePath) 'if no working directory was set, make it the directory where the filePath resides.
Dim cmdProc As New Process() 'create a new instance of the process class.
Dim pInfo As New ProcessStartInfo(filePath, args) 'construct a new ProcessStartInfo, and set the file path and arguments of the process we wish to start.
pInfo.WorkingDirectory = workingDir 'set the working directory.
pInfo.UseShellExecute = False 'we do not wish to use ShellExecute to run this process, as that means we cannot redirect the standard output/error
pInfo.CreateNoWindow = True 'we don't want this process to create its own window, we just want it to run hidden, send us its output and then shutdown.
pInfo.RedirectStandardOutput = True 'obviously we do wish to redirect the standard output.
pInfo.RedirectStandardError = True 'we also do want to redirect the standard error, in case something goes wrong.
cmdProc.StartInfo = pInfo 'set our processes start info to what we just configured.
cmdProc.Start() 'begin the process.
cmdProc.WaitForExit(maxWait) 'stall our program until the process exits or maxWait is reached.
'after this point, the process "cmdProc" has exited.
Dim response As New StandardResponse() 'create an empty StandardResponse using the default constructor.
Using stdOutReader As IO.StreamReader = cmdProc.StandardOutput
response.Output = stdOutReader.ReadToEnd() 'read the standardoutput to the end and assign it to our "response" structure.
End Using
Using stdErrReader As IO.StreamReader = cmdProc.StandardError
response.Error = stdErrReader.ReadToEnd() 'same as above, but this time assign it to the "Error" variable.
End Using
Return response 'return our response
End Function
[/highlight]
Yeah, it's a bit long.
Now, we need to test the code. I will be using my "tutorial.exe" file (found in "tutorial.zip" at the bottom of this page)
I'm going to add a textbox, a richtextbox and a button to my form, and rename them to txtArgs, txtOutput and btnRun respectively.
My button code will be as follows.
[highlight=vb.net]
Private Sub btnRun_Click(ByVal sender As Object, ByVal e As EventArgs) Handles btnRun.Click
Dim tutLocation As String = "C:\Users\Jason_2\Documents\tutorial.exe" 'location of my tutorial.exe
Dim cmdLineArgs As String = txtArgs.Text 'the arguments I wish to pass to tutorial.exe.
txtLog.Text = "Beginning to capture output" + Environment.NewLine 'add some text
Dim tutResponse As StandardResponse = CaptureResponse(tutLocation, cmdLineArgs) 'capture the output, note that I omitted the last 2 "optional" arguments, letting them sort themselves out.
txtLog.Text += "Standard Output:" + Environment.NewLine + tutResponse.Output + Environment.NewLine 'append the std output to the log.
txtLog.Text += "Standard Error:" + Environment.NewLine + tutResponse.Error + Environment.NewLine 'append the std error to the log.
txtLog.Text += "Finished capturing output.." 'done
End Sub
[/highlight]
Now all you need to do is fill in some words in txtArgs, and press btnRun to see what happens!
Try it out with txtArgs empty and see if the standard error reports anything to you!
And yeah, that's about all to this tutorial. Just a very basic tutorial on how to start interfacing with programs that run on the command line.
Hope someone gets something out of this.
Cheers,
Jason.
tutorial scan: [x]
You can win the rat race,Originally Posted by Jeremy S. Anderson
But you're still nothing but a fucking RAT.
++Latest Projects++
[Open Source] Injection Library
Simple PE Cipher
FilthyHooker - Simple Hooking Class
CLR Injector - Inject .NET dlls with ease
Simple Injection - An in-depth look
MPGH's .NET SDK
eJect - Simple Injector
Basic PE Explorer (BETA)
Blubb1337 (08-29-2011)
I seen something like this posted somewhere else I smell leach : o
You can win the rat race,Originally Posted by Jeremy S. Anderson
But you're still nothing but a fucking RAT.
++Latest Projects++
[Open Source] Injection Library
Simple PE Cipher
FilthyHooker - Simple Hooking Class
CLR Injector - Inject .NET dlls with ease
Simple Injection - An in-depth look
MPGH's .NET SDK
eJect - Simple Injector
Basic PE Explorer (BETA)