/// <summary>
        /// Load identifiers for external games from screenshots.vdf
        /// </summary>
        /// <param name="SteamId">Steam user identifier</param>
        /// <param name="shortcutGames">Found games listed as pairs of {gameName, gameId} </param>
        /// <returns></returns>
        private bool LoadShortcutGames(long SteamId, out Dictionary <string, int> shortcutGames)
        {
            bool   result   = false;
            string filePath = string.Format(Properties.Resources.ScreenshotsFilePath, Settings.Instance().SteamPath, Profile.ID64toDirName(SteamId));

            shortcutGames = new Dictionary <string, int>();

            StreamReader reader = null;

            try
            {
                reader = new StreamReader(filePath, false);
                TextVdfFileNode dataRoot = TextVdfFileNode.Load(reader, true);

                VdfFileNode appsNode = dataRoot.GetNodeAt(new string[] { "shortcutnames" }, false);

                foreach (KeyValuePair <string, VdfFileNode> shortcutPair in appsNode.NodeArray)
                {
                    string strId = shortcutPair.Key;

                    ulong ulongId;
                    if (ulong.TryParse(strId, out ulongId))
                    {
                        int    gameId   = (int)(ulongId >> 32);
                        string gameName = (string)shortcutPair.Value.NodeData;
                        shortcutGames.Add(gameName, gameId);
                    }
                    else
                    {
                        Program.Logger.Write(LoggerLevel.Warning, GlobalStrings.GameData_ErrorParsingScreenshots, (string)shortcutPair.Value.NodeData);
                    }
                }
                result = true;
            }
            catch (FileNotFoundException e)
            {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorOpeningConfigFileParam, e.ToString());
            }
            catch (IOException e)
            {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_LoadingErrorSteamConfig, e.ToString());
            }

            if (reader != null)
            {
                reader.Close();
            }

            return(result);
        }
        /// <summary>
        /// Loads category info from the given steam config file.
        /// </summary>
        /// <param name="filePath">The path of the file to open</param>
        /// <returns>The number of game entries found</returns>
        public int ImportSteamFile(string filePath, SortedSet <int> ignore, bool ignoreDlc)
        {
            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_OpeningSteamConfigFile, filePath);
            TextVdfFileNode dataRoot;

            try {
                using (StreamReader reader = new StreamReader(filePath, false)) {
                    dataRoot = TextVdfFileNode.Load(reader, true);
                }
            } catch (ParseException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorParsingConfigFileParam, e.Message);
                throw new ApplicationException(GlobalStrings.GameData_ErrorParsingSteamConfigFile + e.Message, e);
            } catch (IOException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorOpeningConfigFileParam, e.Message);
                throw new ApplicationException(GlobalStrings.GameData_ErrorOpeningSteamConfigFile + e.Message, e);
            }

            VdfFileNode appsNode = dataRoot.GetNodeAt(new string[] { "Software", "Valve", "Steam", "apps" }, true);
            int         count    = GetDataFromVdf(appsNode, ignore, ignoreDlc);

            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_SteamConfigFileLoaded, count);
            return(count);
        }
        /// <summary>
        /// Writes category information out to a steam config file. Also saves any other settings that had been loaded, to avoid setting loss.
        /// </summary>
        /// <param name="path">Full path of the steam config file to save</param>
        public void SaveSteamFile(string filePath, bool discardMissing)
        {
            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_SavingSteamConfigFile, filePath);

            TextVdfFileNode fileData = new TextVdfFileNode();

            try {
                using (StreamReader reader = new StreamReader(filePath, false)) {
                    fileData = TextVdfFileNode.Load(reader, true);
                }
            } catch (Exception e) {
                Program.Logger.Write(LoggerLevel.Warning, GlobalStrings.GameData_LoadingErrorSteamConfig, e.Message);
            }

            VdfFileNode appListNode = fileData.GetNodeAt(new string[] { "Software", "Valve", "Steam", "apps" }, true);

            if (discardMissing)
            {
                Dictionary <string, VdfFileNode> gameNodeArray = appListNode.NodeArray;
                if (gameNodeArray != null)
                {
                    foreach (KeyValuePair <string, VdfFileNode> pair in gameNodeArray)
                    {
                        int gameId;
                        if (!(int.TryParse(pair.Key, out gameId) && Games.ContainsKey(gameId)))
                        {
                            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_RemovingGameCategoryFromSteamConfig, gameId);
                            pair.Value.RemoveSubnode("tags");
                        }
                    }
                }
            }

            foreach (Game game in Games.Values)
            {
                if (game.Id > 0) // External games have negative identifier
                {
                    Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_AddingGameToConfigFile, game.Id);
                    VdfFileNode gameNode = (VdfFileNode)appListNode[game.Id.ToString()];
                    gameNode.RemoveSubnode("tags");
                    if (game.Category != null || game.Favorite)
                    {
                        VdfFileNode tagsNode = (VdfFileNode)gameNode["tags"];
                        int         key      = 0;
                        if (game.Category != null)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode(game.Category.Name);
                            key++;
                        }
                        if (game.Favorite)
                        {
                            tagsNode[key.ToString()] = new TextVdfFileNode("favorite");
                        }
                    }
                }
            }

            Program.Logger.Write(LoggerLevel.Verbose, GlobalStrings.GameData_CleaningUpSteamConfigTree);
            appListNode.CleanTree();

            Program.Logger.Write(LoggerLevel.Info, GlobalStrings.GameData_WritingToDisk);
            TextVdfFileNode fullFile = new TextVdfFileNode();

            fullFile["UserLocalConfigStore"] = fileData;
            try {
                FileInfo f = new FileInfo(filePath);
                f.Directory.Create();
                FileStream fStream = f.Open(FileMode.Create, FileAccess.Write, FileShare.None);
                using (StreamWriter writer = new StreamWriter(fStream)) {
                    fullFile.Save(writer);
                }
                fStream.Close();
            } catch (ArgumentException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigBadPath, e);
            } catch (IOException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_FailedToSaveSteamConfigFile + e.Message, e);
            } catch (UnauthorizedAccessException e) {
                Program.Logger.Write(LoggerLevel.Error, GlobalStrings.GameData_ErrorSavingSteamConfigFile, e.ToString());
                throw new ApplicationException(GlobalStrings.GameData_AccessDeniedSteamConfigFile + e.Message, e);
            }
        }