public static ActionResult JsonJpathSched(Session session)
        {
            AssemblyName me = typeof(JsonJPath).Assembly.GetName();

            session.Log($"Initialized from {me.Name} v{me.Version}");

            List <JsonJPathCatalog> catalogs = new List <JsonJPathCatalog>();;

            using (View jsonView = session.Database.OpenView("SELECT `PSW_JsonJPath`.`File_`, `PSW_JsonJPath`.`Component_`, `PSW_JsonJPath`.`FilePath`, `PSW_JsonJPath`.`JPath`, `PSW_JsonJPath`.`Value`, `PSW_JsonJPath`.`Formatting`, `PSW_JsonJPath`.`ErrorHandling` FROM `PSW_JsonJPath`"))
            {
                jsonView.Execute(null);

                foreach (Record rec in jsonView)
                {
                    using (rec)
                    {
                        JsonJPathCatalog ctlg      = new JsonJPathCatalog();
                        string           fileId    = rec[1] as string;
                        string           component = rec[2] as string;
                        string           filePath  = rec[3] as string;
                        string           jpath     = rec[4] as string;
                        string           value     = rec[5] as string;
                        int?formatting             = rec[6] as int?;
                        int?errorHandling          = rec[7] as int?;
                        ctlg.JPathObfuscated = session.Obfuscate(jpath);
                        ctlg.ValueObfuscated = session.Obfuscate(value);
                        ctlg.JPath           = session.Format(jpath);
                        ctlg.Value           = session.Format(value);
                        bool isHidden = !ctlg.Value.Equals(ctlg.ValueObfuscated);

                        if ((formatting != null) && Enum.IsDefined(typeof(JsonFormatting), (int)formatting))
                        {
                            JsonFormatting jsonFormat = (JsonFormatting)formatting;
                            switch (jsonFormat)
                            {
                            default:
                                break;

                            case JsonFormatting.String:
                                ctlg.Value = JsonConvert.ToString(ctlg.Value);
                                break;

                            case JsonFormatting.Boolean:
                                if (string.IsNullOrWhiteSpace(ctlg.Value))
                                {
                                    ctlg.Value = JsonConvert.False;
                                }
                                else if (bool.TryParse(ctlg.Value, out bool b))
                                {
                                    ctlg.Value = b ? JsonConvert.True : JsonConvert.False;
                                }
                                else if (int.TryParse(ctlg.Value, out int i) && (i == 0))
                                {
                                    ctlg.Value = JsonConvert.False;
                                }
                                else
                                {
                                    ctlg.Value = JsonConvert.True;
                                }
                                break;
                            }
                            if (!isHidden)
                            {
                                ctlg.ValueObfuscated = ctlg.Value;
                            }
                        }

                        // Sanity checks
                        if (string.IsNullOrWhiteSpace(component))
                        {
                            session.Log("Component must be supplied");
                            return(ActionResult.Failure);
                        }
                        if (string.IsNullOrWhiteSpace(fileId) == string.IsNullOrEmpty(filePath))
                        {
                            session.Log("Either File_ or FilePath must be supplied");
                            return(ActionResult.Failure);
                        }

                        if (string.IsNullOrEmpty(fileId))
                        {
                            ctlg.FilePath = session.Format(filePath);
                        }
                        else // Get component by file Id
                        {
                            ctlg.FilePath = session.Format($"[#{fileId}]");
                        }

                        if (errorHandling != null)
                        {
                            ctlg.ErrorHandling = (ErrorHandling)errorHandling;
                        }

                        ComponentInfo ci = session.Components[component];
                        if (ci == null)
                        {
                            session.Log($"Component '{component}' not present in package");
                            return(ActionResult.Failure);
                        }
                        // Path will be empty if component is not scheduled to do anything. We'll check that only if action is relevant.

                        switch (ci.RequestState)
                        {
                        case InstallState.Default:
                        case InstallState.Local:
                        case InstallState.Source:
                            if (string.IsNullOrWhiteSpace(ctlg.FilePath))
                            {
                                session.Log("Can't get target path for file");
                                return(ActionResult.Failure);
                            }

                            session.LogUnformatted($"Will replace JSON token matching JPath '{ctlg.JPathObfuscated}' with '{ctlg.ValueObfuscated}' in file '{ctlg.FilePath}'");
                            catalogs.Add(ctlg);
                            break;

                        default:
                            session.Log($"Component '{ci.Name}' action isn't install, or repair. Skipping JPath");
                            continue;
                        }
                    }
                }
            }

            if (catalogs.Count > 0)
            {
                XmlSerializer srlz = new XmlSerializer(catalogs.GetType());
                using (StringWriter sw = new StringWriter())
                {
                    srlz.Serialize(sw, catalogs);
                    session["JsonJpathExec"] = sw.ToString();
                    session.DoAction("JsonJpathExec");
                }
            }

            return(ActionResult.Success);
        }
        public static ActionResult JsonJpathSched(Session session)
        {
            AssemblyName me = typeof(JsonJPath).Assembly.GetName();

            session.Log($"Initialized from {me.Name} v{me.Version}");

            List <JsonJPathCatalog> catalogs = new List <JsonJPathCatalog>();;

            using (View jsonView = session.Database.OpenView("SELECT `PSW_JsonJPath`.`File_`, `File`.`Component_`, `PSW_JsonJPath`.`JPath`, `PSW_JsonJPath`.`Value`"
                                                             + " FROM `PSW_JsonJPath`, `File`, `Component`"
                                                             + " WHERE `PSW_JsonJPath`.`File_`=`File`.`File` AND `File`.`Component_`=`Component`.`Component`"
                                                             ))
            {
                jsonView.Execute(null);

                foreach (Record rec in jsonView)
                {
                    using (rec)
                    {
                        JsonJPathCatalog ctlg = new JsonJPathCatalog();
                        ctlg.FileId = rec[1] as string;
                        string component = rec[2] as string;
                        string jpath     = rec[3] as string;
                        string value     = rec[4] as string;
                        ctlg.JPath = session.Format(jpath);
                        ctlg.Value = session.Format(value);

                        // Sanity checks
                        if (string.IsNullOrWhiteSpace(ctlg.FileId))
                        {
                            session.Log("File_ not supplied");
                            return(ActionResult.Failure);
                        }
                        ComponentInfo ci = session.Components[component];
                        if (ci == null)
                        {
                            session.Log("File '{0}' not present in package", ctlg.FileId);
                            return(ActionResult.Failure);
                        }
                        // Path will be empty if component is not scheduled to do anything. We'll check that only if action is relevant.
                        ctlg.FilePath = session.Format(string.Format("[#{0}]", ctlg.FileId));

                        switch (ci.RequestState)
                        {
                        case InstallState.Default:
                        case InstallState.Local:
                        case InstallState.Source:
                            if (string.IsNullOrWhiteSpace(ctlg.FilePath))
                            {
                                session.Log("Can't get target path for file '{0}'", ctlg.FileId);
                                return(ActionResult.Failure);
                            }

                            session.LogObfuscated($"Will replace JSON token matching JPath '{jpath}' with '{value}' in file '{ctlg.FilePath}'");
                            catalogs.Add(ctlg);
                            break;

                        default:
                            session.Log($"Component '{ci.Name}' action isn't install, or repair. Skipping JPath for file '{ctlg.FileId}'");
                            continue;
                        }
                    }
                }
            }

            if (catalogs.Count > 0)
            {
                XmlSerializer srlz = new XmlSerializer(catalogs.GetType());
                using (StringWriter sw = new StringWriter())
                {
                    srlz.Serialize(sw, catalogs);
                    session["JsonJpathExec"] = sw.ToString();
                }
            }

            return(ActionResult.Success);
        }