November 26, 2009

Accessing Command Line Arguments In WPF

public partial class App : Application
{
    protected override void OnStartup(StartupEventArgs sea)
    {
        CommandLine.Instance.SetArguments(sea.Args);
        base.OnStartup(sea);
    }
}

public class CommandLine
{
    private CommandLine()
    {}

    private static readonly CommandLine instance = new CommandLine();

    public static CommandLine Instance
    {
        get { return instance; }
    }

    public IEnumerable Arguments
    {
        get { return args; }
    }

    public void SetArguments(string[] args)
    {
        this.args = args ?? new string[0];
    }

    private string[] args = new string[0];
}
then to use
private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            foreach (string arg in CommandLine.Instance.Arguments)
            {
                if (arg.ToUpper() == "/C")
                {
                    if (System.Windows.Forms.Clipboard.ContainsText())
                    {
                        tbCode.Text = System.Windows.Forms.Clipboard.GetText();
                    }
                }
            }

        }
Doh!
Even easier:
string[] arguments = Environment.GetCommandLineArgs();
When processing command line args using Environment.CommandLineArgs(), found that the system automatically matches " in an argument. So if you have a path that contains a spaces, as long as that path is wrapped with " marks, the path will not be parsed into multiple arguments but rather appear as a single argument. eg.:
-myArg:C:\Program Files\MyProgram\Something.exe
will get parsed as multiple arguments:
  • -myArg:C:\Program
  • Files\MyProgram\Something.exe
whereas
-myArg:"C:\Program Files\MyProgram\Something.exe"
will get parsed as a single argument:
  • -myArg:C:\Program Files\MyProgram\Something.exe

Have also noticed that carriage return line feeds can get sucked into a command line argument. Perhaps a "Trim()" should be applied to each argument string before it is processed to be sure this whitespace is removed. Here is a sample command line parser:
internal class CommandLineParser
{
    public string Drive { get; set; }
    public string TrueCryptFile { get; set; }
    public string KeyFile { get; set; }

    const string DrivePrefix = "-D";
    const string TrueCryptFilePrefix = "-T";
    const string KeyFilePrefix = "-K";

    public void CommandLineArgs(string[] args)
    {
        //string[] args = Environment.GetCommandLineArgs();
        Debug.WriteLine("Args:" + string.Join(",", args));
        int ix = 0;
        foreach (string arg in args)
        {
            Debug.WriteLine("arg[" + ix++.ToString() + "]=\'" + arg + "\'");
        }
        foreach (string rawArg in args)
        {
            // Get rid of whitespace chars at the beginning and end
            string arg = rawArg.Trim(); 
            if (arg.Length < 2)
              continue;
            string argument = (arg[0] == '/') ? "-" + arg.Substring(1) : arg;
            int end = argument.IndexOf(':');
            if ((end == -1) && ((end + 1) >= argument.Length))
                continue;
            if (argument.ToUpper().StartsWith(DrivePrefix))
            {
                Drive = argument.Substring(end + 1).Substring(0, 1) + ":";
            }
            else if (argument.ToUpper().StartsWith(TrueCryptFilePrefix))
            {
                TrueCryptFile = argument.Substring(end + 1);
            }
            else if (argument.ToUpper().StartsWith(KeyFilePrefix))
            {
                KeyFile = argument.Substring(end + 1);
            }
        }
        Debug.WriteLine("Processed command line args:");
        Debug.WriteLine("Drive=\"" + Drive + "\"");
        Debug.WriteLine("TrueCryptFile=\"" + TrueCryptFile + "\"");
        Debug.WriteLine("KeyFile=\"" + KeyFile + "\"");
    }
}

// and tester (not really finished)
class CommandLineParserTester
{
    public void TestCommandLineParser()
    {
        CommandLineParser clp = new CommandLineParser();
        clp.CommandLineArgs(new string[] { 
            @"-D:M",
            @"-T:F:/Temp/truecrypt.tc",
            @"-K:F:/Temp/truecrypt.keyfile" });
        Assert(clp.Drive == "M:");
        Assert(clp.TrueCryptFile == @"F:/Temp/truecrypt.tc");
        Assert(clp.KeyFile == @"F:/Temp/truecrypt.keyfile");
    }
}

No comments: