Introduction
This project is a full featured DOSKey control, (like what is built into Windows XP Command Prompt).
We are all familiar with the DOSKey utility found in console applications or from the Command Prompt. The DOSKey control has the handy command history that is navigated via the Up/Down arrow keys. This feature prevents us from having to retype some lengthy commands over and over. Once a command has been entered, it is inserted into the DOSKey command history queue.
Did you know that DOSKey has a history window that will popup when the F7 key is hit? This gives a detailed view of where your commands are and allows you to navigate to the desired command and execute it. Also once the F7 key stroke has popped up the history window, you can hit F9 and enter the indexed selection from the history list and execute that command.
I've taken these features and placed similar functionality into this DOSKey control. I've taken all of the good features and added some enhancements to make a solid control for any command driven application. I've included a test application that simulates some command driven application that receives commands from the DOSKey control and simulates some execution engine.
Features
- Persistent Most Recent Used (MRU) circular command queue (size is configurable).
- Persistent MRU list - Spans application scope (history stored in the registry).
- Command Validation - Only valid commands will be added to the MRU queue (a very nice feature).
- Unneeded or unwanted commands can be deleted from the DOSKey History Command Picker dialog box.
- Commands from the DOSKey History Command Picker may be routed directly to your executor or to the text box for modifications.
- No command duplicates. If the same command is already in the list, it is moved to the Most Recent Used position.
- Hitting the Escape key will reset the DOSKey navigation back to the Most Recent Used item in the history queue.
- Hitting the Enter key when the DOSKey control's edit box is empty will place the Most Recent Used item into the edit box.
Using the Code
The DOSKey control is a DLL that needs to be placed in the same folder as your executable. The demo project has that already done for you. For you to place the DOSKey control in a different project, you should add it to your Toolbox. First compile the DOSKey control, then open up the Toolbox and right click, then select "Choose Item".
Use the browse button in the "Choose Toolbox Items" dialog to navigate to DOSKey.dll, then press the Open button.
This will add DOSKey.dll into the Toolbox so that the control can be dragged from the Toolbox into the Form.
Configuring the DOSKey Control
There are some properties and events that must be defined in order for the DOSKey control to fully function properly. First we'll start off with the properties.
Properties
CtrlWidth
property is controlled by the Form design view and adjusts as the control is stretched to fit into the Form in the desired location. HistoryLength
property is the length of the DOSKey's MRU history queue. The allowed range is set to 1 - 100 by the read only properties HistroyLengthMin
and HistoryLengthMax
. HistroyLengthMin
and HistoryLengthMax
: These are read only, but they can be changed in the source code. RegistryCompanyName
and RegistryMruName
define the location in the registry where the MRU data is to be stored. Here is the path used in this example: My Computer\HKEY_CURRENT_USER\Software\ST Howard\DosKeyMRU.
The registry is the best place to store the history since the XML and data file persistence methods are too slow and throw exceptions on rapid command entry.
Now for the events (delegates):
Events
IsDOSKeyValidCommand
(command validation) event, if connected, will be executed before the DOSKeyNewEntry
event. This way only valid commands will be accepted and placed into the command history. If the IsDOSKeyValidCommand
is not connected then all commands are assumed to be valid and are placed into the command history. DOSKeyNewEntry
is the event that gets fired whenever a new command has been entered in the control. This is what the owner of the DOSKey control uses to receive all the commands from the control.
Here is the code for the delegates and events:
<summary />public delegate void DOSKeyHandler(string str);
</summary />
[Category("DOSKey Configuration"),
Description("Sent when the user hits the enter key inside the textBox.")]
public event DOSKeyHandler DOSKeyNewEntry;
<summary /></summary />public delegate bool DOSKeyCommandValid(string str);
</summary />
[Category("DOSKey Configuration"),
DefaultValue("true"),
Description("Used to receive notification that the command entered has valid syntax.")]
public event DOSKeyCommandValid IsDOSKeyValidCommand;
Here is the implementation using these delegates and events:
private void InsertCallDelegate(string str)
{
if (IsDOSKeyValidCommand != null)
{
if (IsDOSKeyValidCommand(str) != true)
{
textBox.SelectAll();
return;
}
}
InsertMruItem(str);
SaveDosKeyHistoryToRegistry();
textBox.Focus();
textBox.SelectAll();
iDosKeyIndex = 0;
if (DOSKeyNewEntry != null)
{
DOSKeyNewEntry(str);
}
}
Command Validation
The default command validation in this example only allows commands that start off with: "cmd "
, "mem "
, "option "
, and "test "
. There are no other qualifications on the input. Your own data validation should be added which fully qualifies your command set.
str.ToLower();
str.Trim();
if (str.StartsWith("cmd ") || str.StartsWith("option ") ||
str.StartsWith("mem ") || str.StartsWith("test "))
{
return true;
}
Use of the Ctrl Key with the DOSKey Control
The history dialog box can be popped up by holding the Ctrl key down and then pressing the Up arrow key. This can be easier than hitting just the F7 key to open the history dialog box. The greatest benefit of all is when you've navigated through the history queue for a few entries and haven't found the desired item. Holding down the Ctrl key and pressing the Up arrow will open the history dialog box and have the current item in the history queue selected. This turns out to be a very nice feature when the history queue is large.
The Ctrl key is also used to pull an item from the history dialog box to the DOSKey control's edit window for tweaking. To do this, you hold the Ctrl key down and press the Enter key. This action places the item into the DOSKey's edit box for modifications. This way you're able to modify the command before executing it.
Points of Interest
Using the Registry
Reading the history from the registry.
private int ReadDosKeyHistoryFromRegistry()
{
int iRegCnt = 0;
string strDosKeyItem;
RegistryKey regCurrUser_software = null;
RegistryKey regMRU = null;
try
{
regCurrUser_software = Registry.CurrentUser.OpenSubKey("Software", true);
string strSubKey = strRegCompanyName + "\\" + strRegDosKey;
regMRU = regCurrUser_software.OpenSubKey(strSubKey);
if (regMRU == null)
{
regCurrUser_software.Close();
return 1;
}
iRegCnt = regMRU.ValueCount;
for (int i = 0; i < iRegCnt; i++)
{
strDosKeyItem = string.Format("{0}{1}", strMruName, i);
String s = (String)regMRU.GetValue(strDosKeyItem,
"null - Oh Crap, someone's read from an empty or corrupted list!");
aList.Insert(0, s);
}
}
catch
{
regCurrUser_software.Close();
regMRU.Close();
return -1;
}
regCurrUser_software.Close();
regMRU.Close();
return 0;
}
Saving the history queue to the registry. It is easier to delete the old key and save a new one instead of sorting the change and then saving.
private int SaveDosKeyHistoryToRegistry()
{
string strDosKeyItem;
RegistryKey regCurrUser_software = null;
RegistryKey regMRU = null;
try
{
regCurrUser_software = Registry.CurrentUser.OpenSubKey("Software", true);
string strSubKey = strRegCompanyName + "\\" + strRegDosKey;
regMRU = regCurrUser_software.CreateSubKey(strSubKey);
regCurrUser_software.DeleteSubKeyTree(strSubKey);
regMRU = regCurrUser_software.CreateSubKey(strSubKey);
for (int i = 0; i < aList.Count; i++)
{
strDosKeyItem = string.Format("{0}{1}", strMruName, i);
regMRU.SetValue(strDosKeyItem, (string)aList[(aList.Count - 1) - i],
RegistryValueKind.String);
}
}
catch
{
regCurrUser_software.Close();
regMRU.Close();
return -1;
}
regCurrUser_software.Close();
regMRU.Close();
return 0;
}
Acknowledgements
I'd like to thank Bob Powell for the tips on how to get the DOSKey icon to show up in the Toolbox. He has a nice web site with tips and tricks that you should visit.
Thanks also to Eric Woodruff for his NDoc interface into the Sandcastle XML document builder.
I’ve been involved in the disk drive industry since 1986 in test development and R&D (FW - firmware). I hold bachelor degrees in Electronics, Computer Science and Mathematics.