Saturday, March 20, 2010

Win XP Explorer Context Menu: Open and Run in CMD

From time to time I still have to use software running in DOS command.com-like window. If such a program was started from Explorer, the cmd window would disappear with all the information as soon as the program has ended. To avoid that it is necessary, first, to start command window by running cmd.exe, then change directory to the one you need to run the program from and finally start the program. Luckily, there are ways to speed it up.

A partial solution for the problem would be at least an ability to open command window in a required directory and there are many known ways to do that. For example, Add Command Prompt Here Shortcut to Windows Explorer has a comprehensive list of such variants. My choice was to edit Windows registry file.

Note: Editing the registry file is dangerous and good practice is to try every change you are going to do in a virtual machine first.

Copy the following text into a text file:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\Directory\shell\Open in cmd]
@="Open in cmd"

[HKEY_CLASSES_ROOT\Directory\shell\Open in cmd\command]
@="cmd.exe /k cd %1"
save the file with "reg" extension, then double click it to install the new keys. You can download the OpenDirInCmd.reg file ready for using.

In addition, I created an option which is slightly different from the previous one. It opens command prompt window by right click on any file in a directory:
Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\*\shell\Open in cmd]
@="Open in cmd"

[HKEY_LOCAL_MACHINE\SOFTWARE\Classes\*\shell\Open in cmd\command]
@="cmd.exe /k"
It's in the file OpenInCmd.reg.

A close variant for running an executable file in cmd window is "Send to Toys" from http://www.gabrieleponti.com. It adds an option "Command Prompt" to the context menu "Send To". Using it on exe file ends up with open cmd window in corresponding directory and the chosen exe file name typed in the prompt, so the only move left to run the program is to press Enter. I personally decided to mess a little bit directly with the registry:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\exefile\shell\Run in cmd]

[HKEY_CLASSES_ROOT\exefile\shell\Run in cmd\command]
@="cmd.exe /k \"%1\""
I put it in the file RunInCmd.reg. Right click on an exe file, then choose "Run in cmd" option - it opens cmd window, runs the program from its directory and the cmd window stays open after the program termination:


Similarly for batch files:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\batfile\shell\Run in cmd]

[HKEY_CLASSES_ROOT\batfile\shell\Run in cmd\command]
@="cmd.exe /k \"%1\""
I saved it in the file RunBatInCmd.reg.

One thing which can be helpful: in order to see what really comes with the parameter "%1" just insert "echo" command before it:
Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\exefile\shell\Run in cmd]

[HKEY_CLASSES_ROOT\exefile\shell\Run in cmd\command]
@="cmd.exe /k echo \"%1\""
It's in the file RunInCmdecho.reg.

So the main problem is solved, but for the sake of curiosity I'm still looking for a context menu option when right click is done on empty space in Explorer - tweaking "Directory\Background\..." in the registry has not helped yet.
Read more...

Saturday, March 6, 2010

COM Port Connection Automation - Python and CSharp

Many control and measurement devices support RS232 serial interface for communication what easily allows automation. It is pretty convenient when software can find out on its own what device is connected to what COM port. It is the case especially when the port is not a physical one with a fixed number, but a virtual representation in system and its number may change from one connection to another. Some of Fluke and Agilent multimeters, Arroyo temperature controllers and many other devices using similar to USB FTDI chips connection approach can be examples of that.

Finding a COM port device automatically can be done in the two following steps:
  1. Find all available COM ports in system. In Python it can be a function like this:
    import serial

    def COMportScan():
    """scans for available COM ports."""
    availableCOMports = []
    for i in range(256):
    try:
    COMport = serial.Serial(i)
    availableCOMports.append(COMport.portstr)
    COMport.close()
    except serial.SerialException:
    pass
    return availableCOMports

    The same thing in C Sharp:
    using System.IO.Ports;

    string[] availableCOMports;
    availableCOMports = SerialPort.GetPortNames();

  2. Among the available ports find the port which is connected to a particular device. Any device interface command with predictable response can be used for that, for example, for Fluke 189 DMM it can be Identification "ID" command:

    With Python a solution can look like this:
    def ReadDataString(self):
    strData = ''
    cycles = 0
    char = self.comport.read()
    while (char != chr(13) and cycles < 100):
    strData = strData + char
    char = self.comport.read()
    cycles += 1
    return strData

    def readFlukeID(self):
    strFlukeID = ''

    self.comport.write("ID" + chr(13))
    char = self.comport.read() # Read out '0'
    char = self.comport.read() # Read out chr(13)
    self.m_strFlukeID = self.ReadDataString()
    return self.m_strFlukeID

    Similarly with C# :
    public string ReadDataString()
    {
    string strData = "";
    int cycles = 0;
    char[] ch = new char[1];

    try
    {
    COMPort.Read(ch, 0, 1);

    while ((ch != '\r') && (cycles < 100))
    {
    strData += ch;
    COMPort.Read(ch, 0, 1);
    cycles += 1;
    }
    }
    catch (TimeoutException) { }

    return strData;
    }

    public string ReadFlukeID()
    {
    string strFlukeID = "";
    COMPort.WriteLine("ID\r");
    COMPort.Read(ch, 0, 1); // Read out '0';
    COMPort.Read(ch, 0, 1); // Read out chr(13);
    strFlukeID = ReadDataString();
    return strFlukeID;
    }
Read more...