Пример #1
0
        /// <summary>
        /// This splits the app's arguments into a string[].  Works for "regular" apps and ClickOnce apps.
        /// It handles a regular argument string passed to a regular exe (result does not include the exe path),
        /// a query string passed to a ClickOnce app's URI, or a query string passed to a ClickOnce app's .appref-ms file.
        /// </summary>
        public static string[] GetArgs(bool keepQuotes = false)
        {
            using (Log.InfoCall())
            {
                string[] args = null;

                if (ApplicationDeployment.IsNetworkDeployed)
                {
                    // This means we were called via the ClickOnce shortcut or URL.

                    Log.Info("ApplicationDeployment.IsNetworkDeployed = true.");
                    args = GetClickOnceArgs(keepQuotes);
                }
                else
                {
                    Log.Info("ApplicationDeployment.IsNetworkDeployed = false.");
                    Log.Info("Command line: ", Environment.CommandLine);
                    args = ArgParserTX.SplitCommandLine(Environment.CommandLine, keepQuotes).Skip(1).ToArray();
                }

                return(args ?? new string[0]);
            }
        }
Пример #2
0
        // Parses the command line and sets public fields/properties including IsHelpWanted and ErrorMessage.
        // If canDisplayMsg is true, a message box will be displayed if an error is found or the -help switch is found.
        // Otherwise, the caller should display any error found and/or call ShowHelp().
        // Returns true if no error was found, false if the ErrorMessage property was set.
        public static bool ParseCommandLine(bool canDisplayMsg)
        {
            using (Log.InfoCall())
            {
                string[] args = ArgParserTX.GetArgs(keepQuotes: false);

                foreach (string arg in args)
                {
                    Log.Debug("Got argument: ", arg);

                    // Arguments that start with - or / are switches.
                    // Others are "non-switches".

                    char switchFlag = arg[0];

                    if (switchFlag == '-' || switchFlag == '/')
                    {
                        // It's a switch.
                        // In general switches can have optional values, like "-switch:value".  ParseSwitch() sets switchPart
                        // and valuePart.  If the syntax is incorrect, ParseSwitch() returns false and sets
                        // msg to an error message.

                        string switchPart;
                        string valuePart;
                        string msg;

                        if (ArgParserTX.ParseSwitch(arg, out switchPart, out valuePart, out msg))
                        {
                            switch (switchPart.ToLower())
                            {
                            case "?":
                            case "h":
                            case "help":
                                IsHelpWanted = true;
                                break;

                            case "s":
                            case "server":
                                if (valuePart.NullOrWhiteSpace())
                                {
                                    SetError("The '{0}{1}' switch requires a value (i.e. the server name).".Fmt(switchFlag, switchPart));
                                }
                                else if (ServerName == null)
                                {
                                    if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                                    {
                                        ServerName = ArgParserTX.PercentDecode(valuePart);
                                    }
                                    else
                                    {
                                        ServerName = valuePart;
                                    }
                                }
                                else
                                {
                                    SetError("Two or more server names have been specified: '{0}' and '{1}'.".Fmt(ServerName, valuePart));
                                }
                                break;

                            case "ff":
                            case "filefilter":
                                if (valuePart.NullOrWhiteSpace())
                                {
                                    SetError("The '{0}{1}' switch requires a value (i.e. a file name filter).".Fmt(switchFlag, switchPart));
                                }
                                else if (FileFilter == null)
                                {
                                    if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                                    {
                                        FileFilter = ArgParserTX.PercentDecode(valuePart);
                                    }
                                    else
                                    {
                                        FileFilter = valuePart;
                                    }
                                }
                                else
                                {
                                    SetError("Two or more file filters have been specified: '{0}' and '{1}'.".Fmt(FileFilter, valuePart));
                                }
                                break;

                            default:
                                SetError("Unrecognized switch: {0}{1}".Fmt(switchFlag, switchPart));
                                break;
                            } // switch (switchPart)
                        }     // Valid switch format
                        else
                        {
                            // Some fundamental error in the format of a "-switch:value" pair
                            // such as the presence of "-switch:" with no value.

                            SetError(msg);
                        }
                    } // Found switch arg
                    else
                    {
                        // It's a non-switch.  This program allows a single non-switch to specify the file to view.

                        if (FilePath == null)
                        {
                            FilePath = arg;
                        }
                        else
                        {
                            SetError("More than one <FilePath> argument was specfied.  Are quotes needed?\n\n  First: {0}\n  Second: {1}".Fmt(FilePath, arg));
                        }
                    }
                } // foreach arg

                if (FilePath != null)
                {
                    if (FilePath.EndsWith(".application", StringComparison.OrdinalIgnoreCase))
                    {
                        // Assume this means we were launched via our own TracerX-Viewer.application file, when means don't actually have a file arg.
                        FilePath = null;
                    }
                    else
                    {
                        // If this app is installed as a ClickOnce app and the user double-clicks a
                        // file, the FilePath argument will be a URI such as
                        // "file:///c:\logs\may%20have%20blanks.tx1". That is, any blanks will be
                        // percent-encoded. We can construct a Uri object from the string and get the
                        // Url.LocalPath property.

                        Uri    uri;
                        string localPath = FilePath;

                        if (Uri.TryCreate(FilePath, UriKind.Absolute, out uri))
                        {
                            localPath = uri.LocalPath;
                        }

                        // Constructing a FileInfo is the best way I know
                        // to check if the file path syntax is valid.

                        try
                        {
                            FileInfo test = new FileInfo(localPath);
                            FilePath = localPath;
                        }
                        catch (Exception ex)
                        {
                            // Use the original argument in the error message.

                            SetError("Invalid file path syntax:\n\n  {0}".Fmt(FilePath));
                        }
                    }
                }

                if (IsHelpWanted || ErrorMessage != null)
                {
                    // Clear any args that were found so they are not acted on.

                    ServerName = null;
                    FilePath   = null;

                    if (canDisplayMsg)
                    {
                        ShowHelp(ErrorMessage);
                    }
                }
                else
                {
                    Log.Info("AppArgs.FilePath = ", FilePath);
                    Log.Info("AppArgs.ServerName = ", ServerName);
                }

                return(ErrorMessage == null);
            } // using Log
        }
Пример #3
0
        // Sets properties from command line args.  May set ErrorMessage.
        private static void ParseArgs()
        {
            string[] args = ArgParserTX.GetArgs(keepQuotes: false);

            foreach (string arg in args)
            {
                Log.Debug("Got argument: ", arg);

                // Arguments that start with - or / are switches.
                // Others are "non-switches".

                char switchFlag = arg[0];

                if (switchFlag == '-' || switchFlag == '/')
                {
                    // The arg is a switch.
                    // Switches can be bare such as "-switchpart" or have values such as "-switchpart:valuepart".
                    // ParseSwitch() checks the syntax of the switch argument and sets switchPart
                    // and valuePart.  If the syntax is incorrect, ParseSwitch() returns false and sets
                    // msg to an error message.

                    string switchPart;
                    string valuePart;
                    string msg;

                    if (ArgParserTX.ParseSwitch(arg, out switchPart, out valuePart, out msg))
                    {
                        switch (switchPart.ToLower())
                        {
                        case "?":
                        case "h":
                        case "help":
                            SetBool(ref _isHelpWanted, switchPart, valuePart);
                            break;

                        case "i":
                        case "install":
                            SetBool(ref _isInstall, switchPart, valuePart);
                            break;

                        case "u":
                        case "uninstall":
                            SetBool(ref _isUninstall, switchPart, valuePart);
                            break;

                        case "c":
                        case "console":
                            SetBool(ref _isConsoleApp, switchPart, valuePart);
                            break;

                        case "impersonate":
                            SetBool(ref _isImpersonate, switchPart, valuePart);
                            break;

                        case "p":
                        case "port":
                            SetInt(ref _port, switchPart, valuePart);
                            break;

                        case "r":
                        case "retry":
                            SetInt(ref _retryInterval, switchPart, valuePart);
                            break;

                        default:
                            SetError("Unrecognized switch: {0}{1}".Fmt(switchFlag, switchPart));
                            break;
                        } // switch (switchPart)
                    }     // Valid switch format
                    else
                    {
                        // Some fundamental error in the format of a "-switch:value" pair
                        // such as the presence of "-switch:" with no value.

                        SetError(msg);
                    }
                } // Found switch arg
                else
                {
                    // It's a non-switch.

                    SetError("The following argument is not a switch and is therefore invalid.\n{0}".Fmt(arg));
                }
            } // foreach arg
        }
Пример #4
0
        public static void StartNewViewer(string file = null, string server = null)
        {
            using (Log.InfoCall())
            {
                // If this is a ClickOnce app we can't just
                // call Process.Start(Application.ExecutablePath) because the new process won't use the
                // same application settings file as the current process.  To use the same settings file we need to
                // start the new process via the same shortcut that started the current process.
                // Here we try to determine that shortcut.

                DeploymentDescription clickOnceInfo = Instance;
                string arguments = "";

                Log.Info("file = ", file);
                Log.Info("server = ", server);
                Log.Info("clickOnceInfo = ", clickOnceInfo);

                if (clickOnceInfo == null)
                {
                    // Not a ClickOnce app.  Just invoke the .exe directly.

                    if (file != null)
                    {
                        arguments = "\"" + file + "\"";
                    }

                    if (!server.NullOrWhiteSpace())
                    {
                        arguments += " -server:\"" + server + "\"";
                    }

                    Process.Start(System.Windows.Forms.Application.ExecutablePath, arguments);
                }
                else
                {
                    // We're a ClickOnce app. Invoke process via the ClickOnce shortcut.  In this case the argument string cannot
                    // have embedded spaces or double-quotes. Use the '&' char where we would normally use a space to separate
                    // the arguments and percent-encode each individual argument in case they contain spaces or '&'s.

                    if (file != null)
                    {
                        //arguments = "%22" + file + "%22"; // Truncated at first blank.
                        //arguments = "\"" + file + "\""; // Quotes are removed, embedded blanks look like multiple args.
                        //arguments = "file:" + ArgParser.PercentEncode(file); // Invalid URI and invalid file.
                        //arguments = "-file:\"" + file + "\""; // Truncated at first quote.

                        // The Uri class will correctly percent-encode the file path so there are no embedded spaces.

                        Uri uri = new Uri(file);
                        arguments = uri.AbsoluteUri;
                    }

                    if (!server.NullOrWhiteSpace())
                    {
                        arguments += "&-server:" + ArgParserTX.PercentEncode(server);
                    }

                    Log.Info("argument string: ", arguments);
                    Process.Start(clickOnceInfo.Shortcut, arguments);
                }
            }
        }
Пример #5
0
        // Parses the command line and sets public fields/properties including IsHelpWanted and ErrorMessage.
        // If canDisplayMsg is true, a message box will be displayed if an error is found or the -help switch is found.
        // Otherwise, the caller should display any error found and/or call ShowHelp().
        // Returns true if no error was found, false if the ErrorMessage property was set.
        public static bool ParseCommandLine(bool canDisplayMsg)
        {
            using (Log.InfoCall())
            {
                string[] args = ArgParserTX.GetArgs(keepQuotes: false);

                foreach (string arg in args)
                {
                    Log.Debug("Got argument: ", arg);

                    // Arguments that start with - or / are switches.
                    // Others are "non-switches".

                    char switchFlag = arg[0];

                    if (switchFlag == '-' || switchFlag == '/')
                    {
                        // It's a switch.
                        // In general switches can have optional values, like "-switch:value".  ParseSwitch() sets switchPart
                        // and valuePart.  If the syntax is incorrect, ParseSwitch() returns false and sets
                        // msg to an error message.

                        string switchPart;
                        string valuePart;
                        string msg;

                        if (ArgParserTX.ParseSwitch(arg, out switchPart, out valuePart, out msg))
                        {
                            switch (switchPart.ToLower())
                            {
                            case "?":
                            case "h":
                            case "help":
                                IsHelpWanted = true;
                                break;

                            case "s":
                            case "server":
                                if (valuePart.NullOrWhiteSpace())
                                {
                                    SetError("The '{0}{1}' switch requires a value (i.e. the server name).".Fmt(switchFlag, switchPart));
                                }
                                else if (ServerName == null)
                                {
                                    if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                                    {
                                        ServerName = ArgParserTX.PercentDecode(valuePart);
                                    }
                                    else
                                    {
                                        ServerName = valuePart;
                                    }
                                }
                                else
                                {
                                    SetError("Two or more server names have been specified: '{0}' and '{1}'.".Fmt(ServerName, valuePart));
                                }
                                break;

                            case "ff":
                            case "filefilter":
                                if (valuePart.NullOrWhiteSpace())
                                {
                                    SetError("The '{0}{1}' switch requires a value (i.e. a file name filter).".Fmt(switchFlag, switchPart));
                                }
                                else if (FileFilter == null)
                                {
                                    if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                                    {
                                        FileFilter = ArgParserTX.PercentDecode(valuePart);
                                    }
                                    else
                                    {
                                        FileFilter = valuePart;
                                    }
                                }
                                else
                                {
                                    SetError("Two or more file filters have been specified: '{0}' and '{1}'.".Fmt(FileFilter, valuePart));
                                }
                                break;

                            default:
                                SetError("Unrecognized switch: {0}{1}".Fmt(switchFlag, switchPart));
                                break;
                            } // switch (switchPart)
                        }     // Valid switch format
                        else
                        {
                            // Some fundamental error in the format of a "-switch:value" pair
                            // such as the presence of "-switch:" with no value.

                            SetError(msg);
                        }
                    } // Found switch arg
                    else
                    {
                        // It's a non-switch.  This program allows a single non-switch to specify the file to view.

                        if (FilePath == null)
                        {
                            FilePath = arg;
                        }
                        else
                        {
                            SetError("More than one <FilePath> argument was specfied.  Are quotes needed?\n\n  First: {0}\n  Second: {1}".Fmt(FilePath, arg));
                        }
                    }
                } // foreach arg

                if (FilePath != null)
                {
                    if (FilePath.EndsWith(".application", StringComparison.OrdinalIgnoreCase))
                    {
                        // Assume this means we were launched via our own TracerX-Viewer.application file, which means we don't actually have a file arg.
                        FilePath = null;
                    }
                    else
                    {
                        // If this app is installed as a ClickOnce app and the user double-clicks a
                        // file, the FilePath argument will be a URI such as
                        // "file:///c:\logs\may%20have%20spaces.tx1"
                        // or
                        // "file://server/share/has%20space%20and%20%25.tx1".
                        // That is, it will be percent-encoded.  However, we want a regular
                        // file path that is NOT percent-encoded.
                        // We can construct a Uri object from the string and get the
                        // Url.LocalPath property to do that.  If FilePath is not a valid URI
                        // we may need to percent-decode it ourselves but we must not
                        // percent-decode it twice because the original file name may contain the % char.

                        Uri    uri;
                        string localPath = null;

                        if (FilePath.StartsWith("file://", StringComparison.InvariantCultureIgnoreCase) && Uri.TryCreate(FilePath, UriKind.Absolute, out uri))
                        {
                            localPath = uri.LocalPath;
                            Log.Debug("Converted URI '", FilePath, "' to\n", localPath);
                        }
                        else if (System.Deployment.Application.ApplicationDeployment.IsNetworkDeployed)
                        {
                            // This is a ClickOnce app.  It was probably invoked via the command line or Process.Start() using the .appref-ms file.
                            // In that scenario we require the file path to be percent-encoded (also the switch arguments).
                            localPath = ArgParserTX.PercentDecode(FilePath);
                            Log.Debug("PercentDecode(\"", FilePath, "\") returned\n", localPath);
                        }
                        else
                        {
                            // Since this is not a ClickOnce app, regular command line syntax applies.  The FilePath
                            // need not be percent-encoded, though the user should have enclosed it in quotes, that are
                            // gone now, if it contains blanks.
                            localPath = FilePath;
                            Log.Debug("Using FilePath as is: ", FilePath);
                        }

                        // Constructing a FileInfo is the best way I know
                        // to check if the file path syntax is valid.

                        try
                        {
                            FileInfo test = new FileInfo(localPath);

                            // If no exception we have a valid path (syntax).
                            FilePath = localPath;
                        }
                        catch (Exception ex)
                        {
                            // Use the original argument in the error message.

                            SetError("Invalid file path syntax:\n\n  {0}".Fmt(FilePath));
                        }
                    }
                }

                if (IsHelpWanted || ErrorMessage != null)
                {
                    // Clear any args that were found so they are not acted on.

                    ServerName = null;
                    FilePath   = null;

                    if (canDisplayMsg)
                    {
                        ShowHelp(ErrorMessage);
                    }
                }
                else
                {
                    Log.Info("AppArgs.FilePath = ", FilePath);
                    Log.Info("AppArgs.ServerName = ", ServerName);
                }

                return(ErrorMessage == null);
            } // using Log
        }