VB – Working with PuTTY

26 11 2009

I tried for a very long time to use VB .NET to simultaneously control multiple PuTTY windows, reading the text from the window, and sending the same text command to all current open windows.

Let me save you a lot of time.

Cant. Be. Done.

There. I said it – i’d have saved myself so much time if only I was told that. I’m not talking about using a StreamWriter here (because I know it’s possible this way), i’m talking having PuTTY windows open completely standalone, and having an application writing to the windows.

Let’s elaborate –

Ok so techincally you can ‘read’ what’s been processed, and that’s via the method of logging the output from the PuTTY terminal into a text file, then using your app to open the text file and read whats happening. You can’t use screen grabbing methods (i.e. user32 GetWindowText API) because PuTTY is a console application. *Note – if anyone wants me to go into detail on how you do this, leave a comment and i’ll do it.

Now, the harder part – writing to multiple windows.

The only viable method I found was to activate a window (by active, I mean set focus – you can activate a window without it having focus, but this is no good), and then send the keys using..


My.Computer.Keyboard.SendKeys("example text to send to window")

Also, the easiest method to activate a window is by doing:


AppActivate(ProcessID)

…however this has it’s flaws, such as failing when activating windows which are minimized.

This works, activate -> send text -> activate -> send text -> activ…. you get the idea.

Now, what if you have a large quantity of windows you wish to send text to? This isn’t a very good way to do it. Most people will tell you to use the SendMessage API or PostMessage API, however because it’s a console window, they don’t work – at best you’ll change the window title because your posting the message to the wrong hWnd.

Take a step back, lets look at Notepad. Notepad (in Win XP at least) has 2 window handles we’re interested in, the actual text area, called ‘Edit’ and the status bar ‘msctls_statusbar32’.

To send text to the ‘Edit’ box, we need to enumerate through the child handles to find the edit box, and use the SendMessage API to send to each of those window handles at the same time.

This quick and dirty example below is in C#, however it’s fundamentally the same code in VB.

Hook our DLL:

[DllImport("user32.dll")] private static extern int SendMessage(IntPtr hWnd, int uMsg, Int32 wParam, string lParam);

Where iPID is my array holding each process ID for the notepad windows:

for (int i = 0; i < iPID.Length; i++)
{
// Set ChildHandle to the window handle for the 'Edit' box
IntPtr ChildHandle = FindWindowEx(Process.GetProcessById(iPID[i]).MainWindowHandle, new IntPtr(0), "Edit", null);
// Call the SendMessage API to send the text to the ChildHandle variable
SendMessage(ChildHandle, 0x000C, 0, textBox1.Text + System.Environment.NewLine);
}

..now, looking back at PuTTY – You’ve got 5 window handles;

– PuTTY
– Layered WS2 Provider
– MSCTFIME UI
– IME
– IME

(that’s not a typo, there’s 2x IME)

Without going into detail, SendMessage to any of those window handles, and the text won’t send. I know what your thinking, send it to the PuTTY handle. Nope – Window Title, it’s a console window!

Now then, I know it *IS* possible to do – somehow, just not via these methods. If you do know a different way to do this, let me know in the comments… please!

Still want to get this to work but having the same trouble as me? Download PuTTY Connection Manager. It’ll save you so much time.





C# – RichTextBox Syntax Highlighting

26 11 2009

There’s a few different methods to make your application apply syntax highlighting, this method below works for me, and although there’s many better, and more efficient ways it can be done, this is simple. Really simple.

First off, you need a reference for RegularExpressions –

using System.Text.RegularExpressions;

…and you’ll need to create a Rich Text Box, and either a button or menu item – you can have this working on a timer or a ‘TextChanged’ function, but it requires a bit more work, and can get very messy with large sections of text.

We need to declare regular expression strings to a variable that we’ll be searching for, it’s easiest to place it in the ‘global declaration’ area.. So right after:

public partial class Form1 : Form
{

Create your variable declaration:


public Regex keyWordsBlue = new Regex("if |then |else |fi |true |while |do |done |set |export |bool |break |case |class |const |for |foreach |goto |in |void |if\n|then\n|else\n|fi\n|true\n|while\n|do\n|done\n|set\n|export\n|bool\n|break\n|case\n|class\n|const\n|for\n|foreach\n|goto\n|in\n|void\n");

This is basically saying anything between the quotes, delimited by a pipe(|) symbol will get highlighted.

I’ve picked some common protected function words in Unix for my example. Since I don’t want *every* occurance of this to be highlighted, i’ve made it so the word requires a space or a return (new line \n) character after it, which 99% of the time it will have.

The next bit will apply the highlighting. Personally I prefer to have this in a button, or menu item – if you want this to run on ‘TextChanged’ or via a timer, you’ll need to edit it ever so slightly.

Remember to create this in a seperate function, so you can call it from different places as/when required.

        private void ApplySyntaxHighlighting()
        {

            // Select all and set to black so that it's 'clean'
            rtbText.SelectAll();
            rtbText.SelectionColor = Color.Black;

            // Then unselect and scroll to the end of the file
            rtbText.ScrollToCaret();
            rtbText.Select(rtbText.Text.Length, 1);

            // Start applying the highlighting... Set a value to selPos
            int selPos = rtbText.SelectionStart;

            foreach (Match keyWordMatch in keyWordsBlue.Matches(rtbText.Text))
            {
                // Select the word..
                rtbText.Select(keyWordMatch.Index, keyWordMatch.Length);
                // Change it to blue
                rtbText.SelectionColor = Color.Blue;
                // Set it to bold for this example
                rtbText.SelectionFont = new Font(rtbText.SelectionFont, FontStyle.Bold);
                // Move cursor back to where it was
                rtbText.SelectionStart = selPos;
                // Change the default font color back to black.
                rtbText.SelectionColor = Color.Black;
            }
        }

Now, in your button or menu item, you need to call the function with “ApplySyntaxHighlighting();” – i.e.


private void applySyntaxHighlightingToolStripMenuItem_Click(object sender, EventArgs e)
{
ApplySyntaxHighlighting();
}

Once you’ve added some different regular expression strings, it should start looking a bit like this:

Example

P.S – The expression I used for the comment line was:


public Regex keyWordsGreenComment = new Regex(@"\#.*?\n");