Building a GUI for a CLI Application
CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 1 of 3 123 LastLast
Results 1 to 15 of 35

Thread: Building a GUI for a CLI Application

  1. #1
    Join Date
    Sep 2009
    Posts
    23

    Building a GUI for a CLI Application

    Just a little background for you guys - Ive dabbled around in C# for awhile now and have started writing a few apps as side-projects, or things Ive wanted but havent been able to find. With that being said, Im not the best coder out there, and Im well aware of that. However, Im more than willing to learn, and Im doing everything I can to figure these things out on my own.

    Now, on to the problem at hand.

    Im trying to create a GUI for a CLI (command-line interface) program called iphone_tunnel. Long story short, the application hooks an Apple DLL and "tunnels" any TCP port over the iPhone's USB cable. This is incredibly handy for copying files or for VNC, as you dont need a (slow, vs hardwired) wireless connection.

    The syntax of the program is this:
    "iphone_tunnel [iPhone Port] [Local Port]"

    For example, if I wanted to SSH to the device, I would use:
    "iphone_tunnel 22 22"

    And then use 127.0.0.1 / localhost as the address to connect to.



    Since Im trying to teach myself C#, I decided I wanted to create a pretty little GUI for the console app, and came up with this:


    This is the code I have so far (Im using Visual C# 2008 Express w/ .NET 3.5 SP1):
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace iPhone_Tunnel_GUI
    {
        public partial class Form1 : Form
        {
            string exeFile = @"iphone_tunnel.exe";
            Process p = new Process();
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void startButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Started")
                {
                    if (!File.Exists(exeFile))
                    {
                        MessageBox.Show("Please make sure iphone_tunnel.exe is in the same directory as this GUI.");
                    }
                    p.StartInfo.FileName = exeFile;
                    p.StartInfo.Arguments = "22 22";
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.RedirectStandardOutput = true;
                    //p.StartInfo.CreateNoWindow = true;
                    //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
                    p.Start();
                    outputBox.Text = p.StandardOutput.ReadToEnd();
                    //p.WaitForExit();
                    statusLabel.ForeColor = Color.Green;
                    statusLabel.Text = "Started";
                }
            }
    
            private void stopButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Stopped")
                {
                    p.Close();
                    statusLabel.ForeColor = Color.Red;
                    statusLabel.Text = "Stopped";
                }
            }
        }
    }
    Some parts may be redundant or unnecessary, but Id like to get a working version first, and clean it up and tweak later. For example, Ive set the arguments for the program to always be "22 22" so that I can get the app loading/logging part working, before delving into something else. What I plan on having is a predefined list of common ports, and a radio box that lets you fill in custom ports, with different ports for the iPhone and the local port.

    For example - I run a VNC server on my laptop, but I also want to VNC into the phone - so I start the program with the arguments "5900 5500" so that I can connect to port 5500 on my computer, and that is translated to port 5900 on the phone.

    Now, for the problem:
    When I press Start, a console window opens with a flashing cursor (this is iphone_tunnel.exe opening). The program is running, because I can SSH into the device; but the text that normally shows up in a console window doesnt show up in the window that pops up. Aswell, the GUI freezes up solid until I CTRL+C, or close the console window that pops up.

    I want to click Start, have the log of the application show up in the text box, and keep the app responsive, so I can then hit Stop when I want to.

    Im pretty sure the code is stopping at this line:
    "outputBox.Text = p.StandardOutput.ReadToEnd();"
    because once I CTRL+C, only then does the label change to "Started".

    Where should I begin? Thanks!

  2. #2
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Hi, the problem you're experiencing is the iphone_tunnel.exe you're loading must finish executing before it can continue to the next line of code.

    Try following this MSDN using the BeginOutputReadLine instead of ReadToEnd

    http://msdn.microsoft.com/en-us/libr...treadline.aspx

    The SortOutputHandler gets run each time a new line is read from the process so you can update your UI in there with the new data.

    Code:
            private static void SortOutputHandler(object sendingProcess, 
                DataReceivedEventArgs outLine)
            {
                // Collect the sort command output.
                if (!String.IsNullOrEmpty(outLine.Data))
                {
                    // Add the text to the collected output.
                    outputBox.Text += outLine.Data;
                }
            }
    You'll need to run this in a new thread to keep it form blocking the UI. When i can home i can try to show you a better example, don't have much time to write one up for you atm since i'm at work. But maybe this will give you a head start.

  3. #3
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    I dont quite understand the concept of "running this in a new thread" but Im working on it.

    Im reading the link you posted and tried the block you posted instead of theirs, but I get the following error:
    "An object reference is required for the non-static field, method, or property 'iPhone_Tunnel_GUI.Form1.outputBox'"

    This occurs on this line:
    "outputBox.Text += outLine.Data;"

    However, if I change it from "private static void" to "private void" the error goes away.

    Still havent tested the full code tho. Thanks for the offer, Ill check back later and see what youve posted, if I cant figure it out by then.

  4. #4
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    Hmm, apparently there isnt an Edit button, so I have to double-post.

    Ive gotten a bit further. This is the code I have so far:
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    
    namespace iPhone_Tunnel_GUI
    {
        public partial class Form1 : Form
        {
            string exeFile = @"iphone_tunnel.exe";
            Process p = new Process();
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void startButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Started")
                {
                    if (!File.Exists(exeFile))
                    {
                        MessageBox.Show("Please make sure iphone_tunnel.exe is in the same directory as this GUI.");
                    }
                    p.StartInfo.FileName = exeFile;
                    p.StartInfo.Arguments = "22 22";
                    p.StartInfo.UseShellExecute = false;
                    p.StartInfo.RedirectStandardOutput = true;
                    //p.StartInfo.CreateNoWindow = true;
                    //p.StartInfo.WindowStyle = ProcessWindowStyle.Hidden; 
                    p.OutputDataReceived += new DataReceivedEventHandler(OutputHandler);
                    p.Start();
                    p.BeginOutputReadLine();
                    //outputBox.Text = p.StandardOutput.ReadToEnd();
                    //p.WaitForExit();
                    statusLabel.ForeColor = Color.Green;
                    statusLabel.Text = "Started";
                }
            }
            private void OutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
            {
                // Collect the sort command output.
                if (!String.IsNullOrEmpty(outLine.Data))
                {
                    // Add the text to the collected output.
                    outputBox.Text += outLine.Data;
                }
            }
    
            private void stopButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Stopped")
                {
                    p.Close();
                    statusLabel.ForeColor = Color.Red;
                    statusLabel.Text = "Stopped";
                }
            }
        }
    }
    A couple things - the program now runs when I hit Start, and the GUI doesnt freeze. However, when I connect to the phone, I dont see the output of the program, either in the GUI or in the console window that pops up. Another issue Ive noticed is when I hit stop, it doesnt kill the console window (and app), which I assumed would be taken care of by "p.Close();".

  5. #5
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Process.Close() only frees the resources that are being used by the process object. Try using p.Kill(). Ideally the program would have some message you can send it to exit instead of using p.Kill(), Killing a process should be the last resort.

  6. #6
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    The only way to close the program when its run from the command line was CTRL+C, or closing the window (killing the process). Is it possible to send a "CTRL+C" or "^C" command. I tried p.Kill(); and that seems to work
    Last edited by SpikedCola; September 1st, 2009 at 08:42 PM.

  7. #7
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Ok well i made a pretty basic example of what i'm talking about. I made a new thread to start the process in and used the Asynchronous method of reading the data so I could write to the textbox as new data was read. Keep in mind this example doesn't account for thread synchronization or error handling its merely a bare bones type solution that will help you get started.

    Let me know if you have any questions, I didn't really comment much but I think most of it will make sense.
    Attached Files Attached Files

  8. #8
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    Thanks! Ive never touched multithreading before but it doesnt look as complicated as I thought it would be.

    I ported your code over to my project, but I still dont get any text being put in the text box.

    Here is the code:
    Code:
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
    using System.Threading;
    using System.Diagnostics;
    
    namespace iPhone_Tunnel_GUI
    {
        public partial class Form1 : Form
        {
            string exeFile = @"iphone_tunnel.exe";
            private CLIProcess process = null;
            string args = "22 22";
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void startButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Started")
                {
                    if (!File.Exists(exeFile))
                    {
                        MessageBox.Show("Please make sure iphone_tunnel.exe is in the same directory as this GUI.");
                    }
                    outputBox.Text = String.Empty;
    
                Thread t = new Thread(StartProcess);
                t.Start();
                    statusLabel.ForeColor = Color.Green;
                    statusLabel.Text = "Started";
                }
            }
    
            private void stopButton_Click(object sender, EventArgs e)
            {
                if (statusLabel.Text != "Stopped")
                {
                    process.Exit();
                    statusLabel.ForeColor = Color.Red;
                    statusLabel.Text = "Stopped";
                }
            }
    
            public void StartProcess(Object state)
            {
                process = new CLIProcess(exeFile, args);
                process.OutputDataReceived += processData;
                process.Start();
            }
    
            private void processData(Object sender, DataReceivedEventArgs e)
            {
                if (outputBox.InvokeRequired)
                {
                    outputBox.Invoke(new MethodInvoker(delegate()
                    {
                        outputBox.Text += e.Data;
                    }));
                }
            }
        }
    }
    And Ive attached both my project folder (GUI) and the original command-line app (CLI - the extension is actually zip but it says bz2 - you may need to rename it to zip to get your archiving program to open it; mine didnt care) so that you can test it. If you run the CLI app like this:
    "iphone_tunnel 80 80"
    and then open a browser and try to go to http://127.0.0.1 you will see two lines of text show up in the program (there are usually more but if you dont have an iPhone plugged in thats as far as it will go).

    Then, copy the files from the CLI archive into the debug folder of the GUI project and try running it; youll see what I mean about not getting any text out of it (but the app does run properly, so Im almost there!)
    Attached Files Attached Files

  9. #9
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Ok i'll take a look at it in a bit.

  10. #10
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    Also, if it helps, here is the source of the CLI app.
    Attached Files Attached Files

  11. #11
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Your example works for me.

    If the CLI outputs any data it gets displayed in your textbox. I had to modify the arguments to "80 80" from "22 22" to see anything show up though. Once you get the interface working where it changes the arguments with what you type in I think you should be good. When i type in 80 80 i get the message.

    "bind error!"

  12. #12
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    I just tested again and the only text that shows up in the box is error text, not normal text.

    "Bind error" means it couldnt bind that port, so youre probably running some sort of HTTP server Id assume.

    I assumed you didnt have an HTTP server running. Try modifying the arguments for "8080 8080", which should be unused, then try to make a connection to 127.0.0.1:8080 - if it works for you Ill make a video of it not working for me

    EDIT Just to show you whats happening to me (and to show that Im not crazy), here is a screenshot of the app being run with the GUI (no text shown) and a VNC connection opened [I modified the arguments to be "5900 5500" for VNC]:


    And here is how its supposed to look (the text shows up when i initiate the VNC connection):
    Last edited by SpikedCola; September 2nd, 2009 at 03:47 PM.

  13. #13
    Join Date
    Jul 2006
    Posts
    297

    Re: Building a GUI for a CLI Application

    Yup because you're sending the wrong arguments.

    VNC box you show is port 5500 you're sending 22

    When i start the CLI manually with "22 22" nothing shows up.
    When i start the CLI manually with "80 80" i get "bind error!"
    When i start the CLI manually with "8080 8080" i get

    Code:
    new connection !
    MobileDevice: AMDeviceNotificationSubscribe:
     AMDeviceNotificationSubscribe = -402653085
    callback error !
    I can reproduce each of these with your application if i change the args

    Code:
    string exeFile = @"iphone_tunnel.exe";
            private CLIProcess process = null;
            string args = "8080 8080";
    Make sure to change String args because right now you have it hard-coded at "22 22" so it will only ever run with those ports.

  14. #14
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    Ive changed the hardcoded args to reflect the changes - it is set for the correct ports. When I manually run the CLI with args 22 22 I have text show up. Ive changed the ports in the app and I have a connection being made on the proper ports, the text just doesnt show up (if I was on the wrong port like you said I wouldnt get as far as I did with VNC - if I typed in the password it would have continued, and it did)

    See here:
    http://img196.imageshack.us/img196/8818/86885950.png
    Last edited by SpikedCola; September 2nd, 2009 at 09:37 PM.

  15. #15
    Join Date
    Sep 2009
    Posts
    23

    Re: Building a GUI for a CLI Application

    So to recap:

    Running the CLI app directly, with proper args - Output seen in command window
    Running the GUI, with proper args - No output seen in command window that pops up, or in text box
    Running the GUI, with invalid/in-use/whatever args - Error text seen in text box

    Is it possible that the output stream is only updated or displayed in the text box when the app closes? Im not sure why error text shows up but normal text doesnt, and the only difference I can think of is that error text occurs, and then the program closes, whereas normal text occurs but the program remains open.

Page 1 of 3 123 LastLast

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  


Windows Mobile Development Center


Click Here to Expand Forum to Full Width

This is a CodeGuru survey question.


Featured


HTML5 Development Center