Click here to Skip to main content
15,881,709 members
Articles / Programming Languages / XSLT
Article

WinDos Tool

Rate me:
Please Sign up or sign in to vote.
4.64/5 (21 votes)
26 Oct 20079 min read 50.1K   1.6K   60   2
A tool for executing any DOS command using property editors
WinDos using the prompt WinDos running a command

Introduction

This is a tool for constructing and executing DOS commands. The idea of this tool is to be able to assemble any DOS command as a Windows dialog, with editors/dialogs for specific command parameters. For example, if a DOS command accepts a directory parameter, you can use a directory dialog.

The benefit of this is to make complex DOS commands easy, without the hassle of creating and saving a whole bunch of un-maintainable BAT files. Some help is also displayed for the selected command or parameter and, lastly, commands are organized into categories. The list of commands can be saved as or loaded from an XML file for having different sets and sharing commonly used commands with others.

Usage

Using Commands

When you start the tool, a default (sample) command list appears, as well as the command line (DOS). A startup command list file can be specified in the configuration file.

WinDos default view

You can select a command from the list and expand it to show and edit its parameters. Note that different parameter types have different editors for them.

Run button Click on the Run button to run the command in DOS. In the status bar, a preview of the command (that will be executed) is displayed.
Zoom button

The Zoom button can be used to zoom in to a command or, if you are already zoomed in, back to the list.

Edit button The Edit button can be used to start editing the current selection. See the next section.
FileOpen button The File Open button is for opening an XML file with commands.
FileSave button The File Save button is for saving the command list to an XML file.
FileSave button The Descriptions button shows or hides the description of the selected item.

The header and title bar show the name for the current command.

Editing Commands

To start editing commands, click on the Edit button. A second property grid appears that shows the properties of the selected command. The next screenshot illustrates this (note that the screenshot is zoomed in on the command):

WinDos viewing details of a property

Two extra buttons appear in edit mode:

Add button Click on the Add button to add a new command (when viewing the command list) or a parameter (when in the zoomed in view).
Delete button Click on the Delete button to delete the selected item.

The General properties are the same for each property. They mostly have to do with displaying the property and are hopefully self-explanatory. The most important property is the "Type," which determines the behavior of the property. This includes the default value and the editor(s) for the property. Expanding the Type property shows editable properties specific to the selected type.

In the example picture, the Directory property of the Dir command is of type DirectoryPropertyType, which makes it selectable via a directory dialog. The Format property defines how the value is translated to the command value (in this case, the value is quoted).

Property Types

The property types form an important part of this tool. They determine the types of data a user can enter. Currently, this tool contains the following property types:

Simple types
BooleanUser can select true/false. The Boolean value is mapped to a command string.
StringUser can enter text. Text can be formatted for the command string.
Dialog types
DirectoryUser can select a directory. The directory path can be formatted for the command string.
FileUser can select a file. The filename can be formatted for the command string.
List types
ListUser can select an item from a list. Each item has a display and command value.
CheckListUser can select multiple items from a list. Each item has a display and command value. There is a format string and a delimiter string.
Composite types
CommandA command contains other properties. There is a format string and a delimiter string.

I hope to enlarge and optimize this list. Last but not least, commands can be copied and pasted. Use a right mouse click on the Commands property grid to select Copy or Paste.

  • Copy will copy the selected property or command.
  • Paste will paste a copied property or command to the current CommandList.

I hope this explains the basic use. Play around to get a feel of how everything works. Note that the tool itself is not very useful, but having a command set that you can use often is. It takes a little bit of time to create a command; the benefit is you can use it again and again. I've supplied a default set to play around with.

Using the Code

Some goals I had in the code design were to have a flexible model and to limit the amount of code needed to add a new property type. In fact, this project really does not need much code at all. This is due to the functionality already built into .NET. First, a small diagram. This diagram shows the basic setup, including two property types: a command and a directory parameter.

WinDos global class model

CommandList

The container of all commands and parameters is the CommandList. It implements ICustomTypeDescriptor to be able to define our own properties at runtime. It does this by wrapping the supplied CommandProperty instances by a CommandPropertyDescriptor. Note that in the tool, the main PropertyGrid shows these runtime properties. The details grid shows the selected CommandProperty as it is, i.e. as standard properties of a class. CommandList contains command properties and exists in different functions:

  • It serves as the global command list (containing commands). In the most simple setup, this is the only CommandList.
  • It serves as a command (containing parameters).
  • It serves as a complex command parameter.

By nesting CommandLists, an item can be a complete batch.

CommandProperty

Any part of a command (being a command or parameter) is encapsulated in a CommandProperty. This is a sealed class that contains the general properties, such as Name and Category.

Most important, it has the property Type, which defines the actual behavior. The property must be a subclass of IPropertyType (more specifically, BasePropertyType, since I haven't been able to XML-serialize an interface type). The Type property uses a Type Converter (PropertyTypeConverter) to show all the known types, so the user can select one from a dropdown list. Once a selection is made, the property value is instantiated with a new instance of the selected type.

IPropertyType

The IPropertyType descendent is where the "action is at." This class must provide the following functionality:

  • The Default value (this will determine the type of the value, as well).
  • The value to use in the DOS command line (FormatValue), based on the user entered value.

Optionally, you can add to this:

  • A value editor (an EditorType) for dialogs or controls.
  • A value type converter (a ConverterType) for lists or type conversions.

This may sound complicated, but in practice this is simpler than it seems. To prove my point, let's have a look at the DirectoryPropertyType.

C#
public class DirectoryPropertyType: BasePropertyType {
    string format = "\"{0}\"";

    [Description("Format string for the directory command.")]
    public string Format {
        get {  return format; }
        set { format = value; }
    }
    public override object Default {
        get {
            return string.Empty;
        }
    }
    public override Type EditorType {
        get {
            return typeof(DirectoryEditor);
        }
    }
    public override string FormatValue(object value) {
        return value == null ? string.Empty : string.Format(Format, value);
    }
}

This class has one property Format whose value it uses in the FormatValue method to return the value to use in the DOS command. This class overrides EditorType to supply the editor for choosing a directory. The editor looks like this:

C#
public class DirectoryEditor: UITypeEditor {
    public override object EditValue(ITypeDescriptorContext context,
        IServiceProvider provider, object value) {
        FolderBrowserDialog dialog = new FolderBrowserDialog();
        if (value != null && value.ToString().Length > 0) {
            string path = Path.GetFullPath(value.ToString());
            if (!Directory.Exists(path))
                throw new InvalidOperationException();
            dialog.SelectedPath = path;
        }
        if (dialog.ShowDialog() == DialogResult.OK)
            value = dialog.SelectedPath;
        return value;
    }
    public override UITypeEditorEditStyle 
           GetEditStyle(ITypeDescriptorContext context) {
        return UITypeEditorEditStyle.Modal;
    }
}

These two classes are all that is needed to be able to have a directory selection in any DOS command.

And the Rest...

There are a lot of other classes and pieces of functionality worth mentioning. I've tried to put comments in all classes and members, so you may find it useful to run the source through NDoc (much easier to browse than source code).

Points of Interest

The XML file is the XML-serialized CommandList. Reading an XML file of an older version of this application may cause problems if some classes have changed (a universal problem). A solution is to provide an XSL style sheet for transforming to newer versions. The property form and the command prompt are separate processes and behave as such. It would be nice if they acted more as a unit (e.g. by both coming to the foreground if one is activated). I have no (elegant) solution for this. Some design choices:

  • Classes that have no use outside of another have been made private inner classes. This applies to most ConverterType and EditorType classes. Some of these inner classes have a type dependency on their parent class.
  • Classes follow loose-coupling rules. This means they have simple interfaces. It also means you end up with more classes.
  • The design follows basic design-pattern principles.

I would have liked to use the standard verb mechanism to show the actions (add command, add parameter). Unfortunately, the PropertyGrid does not display verbs at runtime.

Evolution and Credits

I use CodeProject very often and your articles helped me numerous times, including in building this particular tool. So, thank you CodeProject and thank you Internet ;-)

Initially, my command prompt was a textbox talking to an invisible command prompt, similar to the setup of ShellControl by S. Senthil Kumar. He has an excellent textbox control for capturing input/output. I rewrote this somewhat to keep the process alive, so the command context would stay alive (such as the current directory) and use threads for async processing. But then I ran into all sorts of problems trying to exactly emulate the behavior of the command prompt (such as a seemingly mundane task as handling special keys like CTRL-C).

For me, the prime point was to have the exact functionality, and this turned out to be more of a drama than I bargained for. Eventually, I got fed up and decided the best direction was to use the command prompt as it is. This reduced my problem to sending commands to the (separate) command prompt. The current solution will not win any beauty-prizes, but at least it is but a few lines of code (and therefore easy to maintain).

For the property editor logic, I looked at the excellent article Bending the .NET PropertyGrid to Your Will by Tony Allowatt. Again, it was not exactly what I wanted, but it helped me understand some key points. Last but not least, I say thanks to my colleague and friend Koen Muilwijk. He helped with several parts of this little exercise, being the critic that he is. ;-)

Known Bugs

On some machines, an exception is generated at startup while accessing the process' MainWindowHandle. The message is "Couldn't get process information from remote machine," and is caused by the line System.Diagnostics.PerformanceMonitor.GetData(String item). Process uses the PerformanceCounter to determine a number of process properties. The exception happens because the account does not have the proper privileges to access this counter. I do not have a solution yet for this problem except to try to "upgrade" your account. If this situation happens, the application will quit.

History

This is the first version, so I'll call it the 1.0 beta. The amount of history this tool will get most likely depends on the reactions I get. I'll be grateful for any constructive comments or code improvements you have. My personal "wish list" includes:

  • Command management
  • Better integration with the command prompt
  • More/improved PropertyTypes
  • Regular expressions for validations and replacements

Again, comments are welcome. Thank you for reading and/or trying this.

  • 20 February, 2006 -- Original version posted
  • 26 October, 2007 -- Demo and source downloads updated

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Architect Independer
Netherlands Netherlands
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
GeneralVS2005 Errors Pin
omzig25-Oct-07 5:49
omzig25-Oct-07 5:49 
GeneralRe: VS2005 Errors Pin
msmits25-Oct-07 19:22
msmits25-Oct-07 19:22 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.