예제 #1
0
        /// <summary>
        /// Loads the profile with items from the given XML string. See the
        /// <see cref="sXmlXpath"/>, <see cref="sXmlKeyKey"/> and
        /// <see cref="sXmlValueKey"/> properties to learn what XML tags are
        /// expected.
        /// </summary>
        /// <param name="asXml">
        /// An XML document as a string.
        /// </param>
        /// <param name="aeLoadAction">
        /// The action to take while loading profile items.
        /// See <see cref="tvProfileLoadActions"/>
        /// </param>
        public void LoadFromXml(
            
            String asXml
            , tvProfileLoadActions aeLoadAction
            )
        {
            if ( tvProfileLoadActions.Overwrite == aeLoadAction )
            {
                this.Clear();
            }

            XmlDocument loXmlDoc = new XmlDocument();
                        loXmlDoc.LoadXml(asXml);

            foreach ( XmlNode loNode in loXmlDoc.SelectNodes(this.sXmlXpath) )
            {
                String lsKey = loNode.Attributes[this.sXmlKeyKey].Value;
                String lsValue = loNode.Attributes[this.sXmlValueKey].Value.StartsWith(Environment.NewLine)
                        ? loNode.Attributes[this.sXmlValueKey].Value.Substring(Environment.NewLine.Length
                                , loNode.Attributes[this.sXmlValueKey].Value.Length - 2 * Environment.NewLine.Length)
                        : loNode.Attributes[this.sXmlValueKey].Value;

                switch ( aeLoadAction )
                {
                    case tvProfileLoadActions.Append:
                    case tvProfileLoadActions.Overwrite:

                        this.Add(lsKey, lsValue);
                        break;

                    case tvProfileLoadActions.Merge:

                        this.bSaveEnabled = false;

                        int liIndex = this.IndexOfKey(lsKey);

                        if ( -1 != liIndex )
                        {
                            // Set each entry with a matching key to the given value.

                            foreach ( DictionaryEntry loEntry in this.oOneKeyProfile(lsKey, false) )
                            {
                                this.SetByIndex(this.IndexOfKey(loEntry.Key.ToString()), lsValue);
                            }
                        }
                        else
                        {
                            // Don't add keys that contain '*'.
                            if ( -1 == lsKey.IndexOf('*') )
                                this.Add(lsKey, lsValue);
                        }
                        break;
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Loads the profile with items from the given "command line" string.
        /// </summary>
        /// <param name="asCommandLine">
        /// A string (not a string array) of the form:
        /// <see langword='-Key1=one -Key2=2 -Key3 -Key4="we have four"'/>.
        /// </param>
        /// <param name="aeLoadAction">
        /// The action to take while loading profile items.
        /// See <see cref="tvProfileLoadActions"/>
        /// </param>
        public void LoadFromCommandLine(
            
            String asCommandLine
            , tvProfileLoadActions aeLoadAction
            )
        {
            if ( null == asCommandLine )
                return;

            // Remove any leading spaces or tabs so that mccSplitMark becomes the first char.
            asCommandLine = asCommandLine.TrimStart(' ');
            asCommandLine = asCommandLine.TrimStart('\t');

            if ( -1 != asCommandLine.IndexOf('\n') )
            {
                // If the command line is actually already line delimited, then we're practically done.
                // The use of all known line delimiters allows for passing profiles between environments.
                this.LoadFromCommandLineArray(asCommandLine.Replace("\r\n", mccSplitMark.ToString())
                        .Replace("\n", mccSplitMark.ToString()).Split(mccSplitMark), aeLoadAction);
            }
            else
            {
                StringBuilder lsbNewCommandLine = new StringBuilder();

                char lcCurrent = '\u0000';
                bool lbQuoteOn = false;

                for ( int i = 0; i <= asCommandLine.Length - 1; i++ )
                {
                    char    lcPrevious;
                            lcPrevious = lcCurrent;
                            lcCurrent = asCommandLine[i];
                            if ( '\"' == lcCurrent )
                            {
                                lbQuoteOn = ! lbQuoteOn;
                            }

                    if ( lbQuoteOn || '-' != lcCurrent || '=' == lcPrevious )
                    {
                        // The "|| '=' == lcPrevious" allows for negative numbers.
                        lsbNewCommandLine.Append(lcCurrent);
                    }
                    else if ( '\\' == lcPrevious )
                    {
                        lsbNewCommandLine.Remove(lsbNewCommandLine.Length - 1, 1);
                        lsbNewCommandLine.Append(lcCurrent);
                    }
                    else
                    {
                        lsbNewCommandLine = new StringBuilder(lsbNewCommandLine.ToString().Trim() + mccSplitMark + "-");
                    }
                }

                //Cleanup any remaining tabs.
                lsbNewCommandLine.Replace('\t', ' ');

                //The first occurrence of the separator must be removed.
                this.LoadFromCommandLineArray(lsbNewCommandLine.ToString()
                        .TrimStart(mccSplitMark).Split(mccSplitMark), aeLoadAction);
            }
        }
예제 #3
0
        /// <summary>
        /// Loads the profile with items from the given "command line"
        /// string array.
        /// </summary>
        /// <param name="asCommandLineArray">
        /// A string array of the form: <see langword='-Key1=one'/>, <see langword='-Key2=2'/>,
        /// <see langword='-Key3'/>, <see langword='-Key4="we have four"'/>.
        /// </param>
        /// <param name="aeLoadAction">
        /// The action to take while loading profile items.
        /// See <see cref="tvProfileLoadActions"/>
        /// </param>
        public void LoadFromCommandLineArray(
            
            String[] asCommandLineArray
            , tvProfileLoadActions aeLoadAction
            )
        {
            if ( tvProfileLoadActions.Overwrite == aeLoadAction )
            {
                this.Clear();
            }

            if ( null != asCommandLineArray )
            {
                String lsBlockKey = null;
                String lsBlockValue = null;
                Hashtable loMergeKeysMap = new Hashtable();

                foreach ( String lsItem in asCommandLineArray )
                {
                    if ( !lsItem.TrimStart().StartsWith("-") )
                    {
                        if ( null != lsBlockKey )
                        {
                            lsBlockValue += lsItem + Environment.NewLine;
                        }

                        // If an item does not start with a "-"
                        // and is not within a block, ignore it.
                    }
                    else
                    {
                        String lsKey;
                        String lsValue;
                        Object loValue;
                        int liPos = lsItem.IndexOf("=");

                        if ( -1 == liPos )
                        {
                            lsKey = lsItem.Trim();
                            loValue = true;
                        }
                        else
                        {
                            lsKey = lsItem.Substring(0, liPos).Trim();
                            lsValue = lsItem.Substring(liPos + 1).Trim();

                            if ( lsValue.StartsWith("\"") && lsValue.EndsWith("\"") )
                            {
                                if ( lsValue.Length < 2 )
                                    loValue = "";
                                else
                                    loValue = lsValue.Substring(1, lsValue.Length - 2);
                            }
                            else
                            {
                                // This is intentionally not trimmed.
                                loValue = lsItem.Substring(liPos + 1);
                            }
                        }

                        lsValue = loValue.ToString();

                        if ( null != lsBlockKey )
                        {
                            if ( mcsEndBlockMark == lsValue && lsBlockKey == lsKey )
                            {
                                lsBlockKey = null;
                                loValue = lsBlockValue;
                            }
                            else
                            {
                                lsBlockValue += lsItem + Environment.NewLine;
                            }
                        }
                        else if ( mcsBeginBlockMark == lsValue )
                        {
                            lsBlockKey = lsKey;
                            lsBlockValue = null;
                        }

                        if ( null == lsBlockKey )
                        {
                            switch ( aeLoadAction )
                            {
                                case tvProfileLoadActions.Append:
                                case tvProfileLoadActions.Overwrite:

                                    this.Add(lsKey, loValue);
                                    break;

                                case tvProfileLoadActions.Merge:

                                    // Only disable saving after merges if the "bSaveSansCmdLine" switch is turned off.
                                    // Likewise, only after merges do we bother to check for command line keys to remove.
                                    if ( !this.bSaveSansCmdLine )
                                        this.bSaveEnabled = false;

                                    int liIndex = this.IndexOfKey(lsKey);

                                    // Replace wildcard keys with the first key match, if any.
                                    lsKey = ( -1 == liIndex ? lsKey : this.sKey(liIndex) );

                                    if ( loMergeKeysMap.ContainsKey(lsKey) )
                                    {
                                        // Set the search index to force adding this key.
                                        liIndex = -1;
                                    }
                                    else
                                    {
                                        if ( -1 != liIndex )
                                        {
                                            // Remove all previous entries with this key (presumably from a file).
                                            this.Remove(lsKey);

                                            // Set the search index to force adding this key with its overriding value.
                                            liIndex = -1;
                                        }

                                        // Add to the merge key map to prevent any further removals of this key.
                                        loMergeKeysMap.Add(lsKey, null);
                                    }

                                    if ( -1 == liIndex )
                                    {
                                        // Don't add keys that contain '*'.
                                        if ( -1 == lsKey.IndexOf('*') )
                                            this.Add(lsKey, loValue);
                                    }
                                    break;
                            }
                        }
                    }
                }
            }
        }
예제 #4
0
        /// <summary>
        /// Loads the profile with items from the given text file.
        /// <p>
        /// If <see cref="bUseXmlFiles"/> is true, text files will be read assuming
        /// standard XML "configuration file" format rather than line delimited
        /// "command line" format.
        /// </p>
        /// </summary>
        /// <param name="asPathFile">
        /// The path/file location of the text file to load. This value will
        /// be used to set <see cref="sLoadedPathFile"/> after a successful load.
        /// </param>
        /// <param name="aeLoadAction">
        /// The action to take while loading profile items.
        /// See <see cref="tvProfileLoadActions"/>
        /// </param>
        public void Load(
            
            String asPathFile
            , tvProfileLoadActions aeLoadAction
            )
        {
            // If asPathFile is not null, check existence. Otherwise check for the existence
            // of one of several default filenames. Returned null means none exist.
            String  lsPathFile = this.sFileExistsFromList(this.sRelativeToProfilePathFile(asPathFile));
            String  lsFilnameOnly = Path.GetFileNameWithoutExtension(this.sExePathFile);
            String  lcsLoadingMsg = lsFilnameOnly + " loading, please wait ...";

            if ( null == lsPathFile )
            {
                if ( null == asPathFile )
                {
                    lsPathFile = this.sDefaultPathFile;
                }
                else
                {
                    lsPathFile = asPathFile;
                }

                if ( tvProfileFileCreateActions.PromptToCreateFile == this.eFileCreateAction )
                {
                    // If the EXE is not already in a folder with a matching name and if the
                    // EXE is not already installed in a typical installation folder, proceed.
                    if ( !this.bInOwnFolder && !this.bInstalledAlready )
                    {
                        String lsNewPath = Path.Combine(
                                Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory), lsFilnameOnly);
                        String lsMessage = String.Format(( Directory.Exists(lsNewPath)
                                ? "an existing folder ({0}) on your desktop"
                                : "a new folder ({0}) on your desktop" ), lsFilnameOnly);

                        if ( DialogResult.OK == MessageBox.Show(String.Format(@"
            For your convenience, this program will be copied
            to {0}.

            Depending on your system, this may take several seconds.

            Copy and proceed from there?

            "
                                    , lsMessage), "Copy EXE to Desktop?", MessageBoxButtons.OKCancel, MessageBoxIcon.Question) )
                        {
                            if ( null != mttvMessageBox )
                            {
                                moAppLoadingWaitMsg = Activator.CreateInstance(mttvMessageBox);
                                mttvMessageBox.InvokeMember("ShowWait", BindingFlags.InvokeMethod, null, moAppLoadingWaitMsg
                                                            , new object[]{null, lcsLoadingMsg, 250});
                            }

                            String lsNewExePathFile = Path.Combine(lsNewPath, Path.GetFileName(this.sExePathFile));

                            if ( !Directory.Exists(lsNewPath) )
                                Directory.CreateDirectory(lsNewPath);

                            File.Copy(this.sExePathFile, lsNewExePathFile, true);

                            ProcessStartInfo    loStartInfo = new ProcessStartInfo(lsNewExePathFile);
                                                loStartInfo.WorkingDirectory = Path.GetDirectoryName(lsNewExePathFile);
                            Process             loProcess = Process.Start(loStartInfo);

                            //this.bExit = true;        // This was moved outside the block after disabling the other show below.
                        }

                        this.bExit = true;
                    }

                    //if ( !this.bExit )
                    //{
                    //    if ( !this.bInOwnFolder && DialogResult.Cancel == MessageBox.Show(String.Format(
                    //                  "The profile file for this program can't be found ({0}).\n\n"
                    //                + "Create it and proceed anyway?", lsPathFile)
                    //                        , "Create Profile File?"
                    //                , MessageBoxButtons.OKCancel, MessageBoxIcon.Question) )
                    //    {
                    //        this.bExit = true;
                    //    }
                    //}
                }

                // Although technically the file was not loaded (since it doesn't exist yet),
                // we consider it empty and we set the property to allow for subsequent saves.
                if ( !this.bExit )
                    this.sLoadedPathFile = lsPathFile;
            }
            else
            {
                if ( null != mttvMessageBox )
                {
                    moAppLoadingWaitMsg = Activator.CreateInstance(mttvMessageBox);
                    mttvMessageBox.InvokeMember("ShowWait", BindingFlags.InvokeMethod, null, moAppLoadingWaitMsg
                                                , new object[]{null, lcsLoadingMsg, 250});
                }

                String  lsFileAsStream = null;
                        this.UnlockProfileFile();

                        StreamReader loStreamReader = null;

                        try
                        {
                            loStreamReader = new StreamReader(lsPathFile);
                            lsFileAsStream = loStreamReader.ReadToEnd();
                        }
                        catch (IOException ex)
                        {
                            if ( !ex.Message.Contains("being used by another process") )
                            {
                                // Wait a moment ...
                                System.Threading.Thread.Sleep(200);

                                // Then try again.
                                if ( null != loStreamReader )
                                    loStreamReader.Close();

                                loStreamReader = new StreamReader(lsPathFile);
                                lsFileAsStream = loStreamReader.ReadToEnd();
                            }
                        }
                        finally
                        {
                            if ( null != loStreamReader )
                                loStreamReader.Close();
                        }

                        if ( !this.bLockProfileFile(lsPathFile) )
                        {
                            this.bExit = true;
                            return;
                        }

                int liDoOver = 1;

                do
                {
                    // mbUseXmlFiles is intentionally used here (instead of "this.bUseXmlFiles") to avoid side effects.
                    if ( mbUseXmlFiles )
                    {
                        try
                        {
                            this.LoadFromXml(lsFileAsStream, aeLoadAction);

                            // The profile file format is as expected. No do-over is needed.
                            liDoOver = 0;

                            if ( !this.bUseXmlFiles )
                            {
                                lsPathFile = this.sReformatProfileFile(lsPathFile);
                            }
                        }
                        catch
                        {
                            // mbUseXmlFiles is intentionally used here (instead of "this.bUseXmlFiles") to avoid side effects.
                            mbUseXmlFiles = false;
                        }
                    }

                    // mbUseXmlFiles is intentionally used here (instead of "this.bUseXmlFiles") to avoid side effects.
                    if ( !mbUseXmlFiles )
                    {
                        if ( lsFileAsStream.Length > 11 )
                        {
                            // Look for the XML tag only near the top (an XML document could be embedded way below).
                            if ( -1 == lsFileAsStream.IndexOf("<?xml versi", 0, 11) )
                            {
                                // The profile file format is as expected. No do-over is needed.
                                liDoOver = 0;

                                // The default file format is line delimited "command line" format.
                                // The use of all known line delimiters allows for passing profiles between environments.
                                this.LoadFromCommandLineArray(lsFileAsStream.Replace("\r\n", mccSplitMark.ToString())
                                        .Replace("\n", mccSplitMark.ToString()).Split(mccSplitMark), aeLoadAction);

                                if ( this.bUseXmlFiles )
                                {
                                    lsPathFile = this.sReformatProfileFile(lsPathFile);
                                }
                            }
                            else
                            {
                                // mbUseXmlFiles is intentionally used here (instead of "this.bUseXmlFiles") to avoid side effects.
                                mbUseXmlFiles = true;
                            }
                        }
                    }
                }
                while ( liDoOver-- > 0 );

                this.sLoadedPathFile = lsPathFile;
            }

            // If it doesn't already exist, create the file.
            if ( !this.bExit
                    && !File.Exists(lsPathFile)
                    && tvProfileFileCreateActions.NoFileCreate != this.eFileCreateAction )
            {
                this.Save(lsPathFile);

                // In this case, consider the file loaded also.
                this.sLoadedPathFile = lsPathFile;
            }
        }