XML find and change node script

This is a script written in ruby designed to find a specified node in an XML file, and replace one value with another.

Usage example:
changenode /home/me/foo bar.xml name bob john will find all ‘name’ nodes in bar.xml and replace ‘bob’ with ‘john’

The code can be found on github here

JavaScript Map object implementation

The idea of this object is to mimic the API of the Map object in Java.

It can be used in the following way:

var myMap = new Map();
myMap.put('foo', 'bar');
var bar = myMap.get('foo');

I know this behaviour can also be attained by using an array in the following manner:

var myMap = [];
myMap['foo'] = 'bar';
var bar = myMap['foo'];

But I thought it interesting to implement it as a map too.

The code can be found on github here

Replace webapp in deployed tomcat

This script will quickly replace the webapp dir of a deployed webapp in tomcat. It scans at your current directory tree for an appropriate artifact.
It will look for a target subdirectory, and will try to find a .war file in it (assumes you’ve build your app with maven).

The script takes two parameters, ‘webapp’ and ‘dir’:

  • The first is the name of the webapp deployed in tomcat
  • The second is the dir to move into the deployed webapp

Usage examples:
ctw myapp mydir will copy mydir into the myapp webapp sitting in tomcat

NB: all parameters are case insensitive
The script can be found on github here

Copy to apache script

This script is designed to work with OS X and will copy the specified dir into the users local sites dir.
It looks for the specified dir, and if it exists copies it into apache. If the dir already exists in apache, it first deletes it.
The script takes one parameter, ‘dir’ which is the dir name.

Usage examples:
ca mywebapp copies dir mywebapp into $HOME/sites/mywebapp

NB: all parameters are case insensitive
The script can be found on github here

Copy to tomcat script

This script will quickly copy an app into tomcat by scanning at your current directory tree for an appropriate artifact.
It will look for a target subdirectory, and will try to find a .war file in it (assumes you’ve build your app with maven).

The script takes two parameters, ‘tomcat’ and ‘app’:

  • The first is asking whether to start/stop tomcat, it takes ‘Y’ or ‘N’ as options
  • The second is asking what to copy to tomcat. It has the options of ‘W’ or ‘C’. ‘W’ means copy the whole war, ‘C’ means copy just the compiled classes

Usage examples:
ct y c will stop/start tomcat and copies just compiled classes
ct n w will not stop/start tomcat and copies the war

NB: all parameters are case insensitive
This script requires the Generic tomcat script found on github here
The script can be found on github here

Generic tomcat script

This script makes it easy to control your main tomcat installation.
All you need to do is set the $CATALINA_HOME environment variable to the location of your tomcat installation.

The available switches are:

  • start starts tomcat
  • stop stops tomcat
  • restart stops then starts tomcat
  • kill kill -9′s tomcat process
  • tail tails tomcat log

Usage examples:
tomcat start starts tomcat
tomcat restart restarts tomcat

NB: all parameters are case insensitive
The script can be found on github here.

Introducing unix scripts

I’ve got several scripts that I use for doing useful things on unix.
They can be found on github here.
I’ll add some details about them individually in separate posts.

Date Driven Development (DDD)

I tweeted this as a joke, but thought it deserved a brief post:
A senior manager in the company arbitrarily pulls a date out of the air (normally the Friday just before an important golfing holiday) for when he needs a report. This means that a load of developers need to jump though hoops to write a system to produce the report, whilst having to continually deal with requirement changes and middle management customers that can’t actually make a decision about anything. When the system is delivered a week late, the senior manager is already playing golf and doesn’t care anymore, so all the developers are sacked.

More on TiddlyBlogger

Just a quick note to point out some work that’s been done “White Hat Marketer”

Check out the details here:

http://whitehat-marketer.com/blog/tiddlyblogger-with-permalinks-and-updates/

It basically includes the capability to update posts (rather than just create new ones), and also create permalinks.

C# Win32 messaging with SendMessage and WM_COPYDATA

I had a real pain recently where I wanted to control one windows app from another. I found some useful stuff on the net, but nothing that gave an end to end solution. So here’s what I came up with.

Firstly I’ll explain why this is useful. SendMessage is part of the Win32 API, and is used to send messages from one application to another. There are a set of predefined properties that the message can relate to, and these can be used to send messages to existing applications to perform all sorts of useful functions such as changing the font in notepad, or bringing a window to the fore. For more information of the wider use of the SendMessage function, have a look at:

http://www.autohotkey.com/docs/commands/PostMessage.htm

http://msdn.microsoft.com/en-us/library/ms644950(VS.85).aspx

The main use that I’m interested in is passing a specific instruction (via a string) from one app that I’ve written, to another one that I’ve written. This way I can effectively remote control one app from another (particularly useful if you want your main application to open a pop-up, and you don’t want to worry about the pop-up’s performance affecting the main application). Let’s now have a quick look at the SendMessage function:

SendMessage(int hWnd, int Msg, int wParam, int lParam)

hWnd – This is the window instance id of the application you want to send a message to. This id is retrieved using the FindWindow function

Msg – This is the type of message you want to send

wParam – Message specific data you pass in

wParam – Message specific data you pass in

Also used is the FindWindow function. This is to get the relevant window id:

FindWindow(String lpClassName, String lpWindowName)

lpClassName -The name of the class you want

lpWindowName – The name of the window that you want

To send a message that is a string, you need to use the WM_DATACOPY message property. The hard part is that you cannot just send the string as a parameter across. You need to send a pointer to the memory address of the string. If you just want to send an integer as a message you can use the WM_USER message property and send it as a value without a problem.

Below now is a brief listing of my MessageHelper.cs class, for the whole class file see:

http://craigcook.co.uk/samples/MessageHelper.cs.txt

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.InteropServices;
using System.Diagnostics;

public class MessageHelper
{
[DllImport("User32.dll")]
private static extern int RegisterWindowMessage(string lpString);

[DllImport("User32.dll", EntryPoint = "FindWindow")]
public static extern Int32 FindWindow(String lpClassName, String lpWindowName);

//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

//For use with WM_COPYDATA and COPYDATASTRUCT
[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, ref COPYDATASTRUCT lParam);

[DllImport("User32.dll", EntryPoint = "SendMessage")]
public static extern int SendMessage(int hWnd, int Msg, int wParam, int lParam);

[DllImport("User32.dll", EntryPoint = "PostMessage")]
public static extern int PostMessage(int hWnd, int Msg, int wParam, int lParam);

[DllImport("User32.dll", EntryPoint = "SetForegroundWindow")]
public static extern bool SetForegroundWindow(int hWnd);

public const int WM_USER = 0x400;
public const int WM_COPYDATA = 0x4A;

//Used for WM_COPYDATA for string messages
public struct COPYDATASTRUCT
{
public IntPtr dwData;
public int cbData;
[MarshalAs(UnmanagedType.LPStr)]
public string lpData;
}

public bool bringAppToFront(int hWnd)
{
return SetForegroundWindow(hWnd);
}

public int sendWindowsStringMessage(int hWnd, int wParam, string msg)
{
int result = 0;

if (hWnd > 0)
{
byte[] sarr = System.Text.Encoding.Default.GetBytes(msg);
int len = sarr.Length;
COPYDATASTRUCT cds;
cds.dwData = (IntPtr)100;
cds.lpData = msg;
cds.cbData = len + 1;
result = SendMessage(hWnd, WM_COPYDATA, wParam, ref cds);
}

return result;
}

public int sendWindowsMessage(int hWnd, int Msg, int wParam, int lParam)
{
int result = 0;

if (hWnd > 0)
{
result = SendMessage(hWnd, Msg, wParam, lParam);
}

return result;
}

public int getWindowId(string className, string windowName)
{

return FindWindow(className, windowName);

}
}

So now you can call the code to send a message like so:

MessageHelper msg = new MessageHelper();
int result = 0;
//First param can be null
int hWnd = msg.getWindowId(null, “My App Name”);
result = msg.sendWindowsStringMessage(hWnd, 0, “Some_String_Message”);
//Or for an integer message
result = msg.sendWindowsMessage(hWnd, MessageHelper.WM_USER, 123, 456);

Now all you need to do on the app that you want to receive the message is override the following function in the form class (obviously you can change what the responses are, and you’ll need to create constants for the parameters):

protected override void WndProc(ref Message m)
{
switch (m.Msg)
{
case WM_USER:
MessageBox.Show("Message recieved: " + m.WParam + " - " + m.LParam);
break;
case WM_COPYDATA:
COPYDATASTRUCT mystr = new COPYDATASTRUCT();
Type mytype = mystr.GetType();
mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
this.doSomethingWithMessage(mystr.lpData);
break;
}
base.WndProc(ref m);
}

Follow

Get every new post delivered to your Inbox.