public void PlugInInfoCloneTest()
        {
            var pluginInfo = new ThePluginInfo
            {
                DeviceTypes = new List <TheDeviceTypeInfo>
                {
                    new TheDeviceTypeInfo {
                        Description = "DT1", Capabilities = new eThingCaps[] { eThingCaps.CameraSource, eThingCaps.EnergyMeter }, DeviceType = "TestDeviceType"
                    },
                },
            };
            var pluginInfoClone = pluginInfo.Clone();

            Assert.AreNotSame(pluginInfo.DeviceTypes, pluginInfoClone.DeviceTypes);
            Assert.AreEqual(pluginInfo.DeviceTypes.Count, pluginInfoClone.DeviceTypes.Count);
            int i = 0;

            foreach (var dt in pluginInfo.DeviceTypes)
            {
                Assert.IsTrue(dt.Description == pluginInfoClone.DeviceTypes[i].Description);
                Assert.IsTrue(dt.DeviceType == pluginInfoClone.DeviceTypes[i].DeviceType);
                Assert.AreNotSame(dt.Capabilities, pluginInfoClone.DeviceTypes[i].Capabilities);
                Assert.AreEqual(dt.Capabilities.Length, pluginInfoClone.DeviceTypes[i].Capabilities.Length);
                for (int j = 0; j < dt.Capabilities.Length; j++)
                {
                    Assert.IsTrue(dt.Capabilities[j] == pluginInfoClone.DeviceTypes[i].Capabilities[j]);
                }
            }
        }
        private void ShowKPI(int pFldOrder, string pLabel, string pUpdName, int MaxVal = 100, int AveVal = 50, string pUnits = "bytes")
        {
            TheNMIEngine.AddSmartControl(MyBaseThing, mMyForm, eFieldType.TileGroup, pFldOrder, 0, 0, null, null, new nmiCtrlTileGroup {
                ParentFld = 300, TileWidth = 6
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, mMyForm, eFieldType.SmartLabel, pFldOrder + 1, 0, 0, null, null, new nmiCtrlSmartLabel {
                ParentFld = pFldOrder, Text = pLabel, NoTE = true, TileFactorY = 2, TileHeight = 1, TileWidth = 5, ClassName = "cdeTileGroupHeaderSmall"
            });
            var tBut = TheNMIEngine.AddSmartControl(MyBaseThing, mMyForm, eFieldType.TileButton, pFldOrder + 2, 2, 0, "V-Tise", null, new nmiCtrlTileButton {
                ParentFld = pFldOrder, NoTE = true, TileFactorY = 2, TileHeight = 1, TileWidth = 1, ClassName = "cdeGlassButton"
            });

            tBut.RegisterUXEvent(MyBaseThing, eUXEvents.OnClick, $"But{pUpdName}", (sender, para) =>
            {
                TheThing tT = TheThingRegistry.GetThingByID(MyBaseEngine.GetEngineName(), $"ISO{MyBaseThing.cdeMID}:{pUpdName}");
                if (tT == null)
                {
                    TheKPIReport tRep = new TheKPIReport(null, MyPlugin);
                    TheThing.SetSafePropertyGuid(tRep, "RealSensorThing", MyBaseThing.cdeMID);
                    tRep.GetBaseThing().ID = $"ISO{MyBaseThing.cdeMID}:{pUpdName}";
                    MyBaseThing.GetProperty(pUpdName, true);
                    TheThing.SetSafePropertyString(tRep, "RealSensorProperty", pUpdName);
                    TheThing.SetSafePropertyNumber(tRep, "StateSensorMaxValue", MaxVal);
                    TheThing.SetSafePropertyNumber(tRep, "StateSensorAverage", AveVal);
                    TheThing.SetSafePropertyNumber(tRep, "StateSensorSteps", MaxVal / 15);
                    TheThing.SetSafePropertyString(tRep, "StateSensorValueName", pLabel);
                    TheThing.SetSafePropertyString(tRep, "StateSensorUnit", pUnits);
                    TheThing.SetSafePropertyString(tRep, "FriendlyName", MyBaseThing.FriendlyName);
                    TheThing.SetSafePropertyString(tRep, "ReportName", $"ISO-KPI: {MyBaseThing.FriendlyName} - {pLabel}");
                    TheThing.SetSafePropertyString(tRep, "ReportCategory", "ISO KPI Reports");
                    ThePluginInfo tI = MyPlugin.GetBaseEngine().GetPluginInfo();
                    if (tI != null)
                    {
                        TheThing.SetSafePropertyString(tRep, "SerialNumber", TheCommonUtils.CStr(tI.CurrentVersion));
                        TheThing.SetSafePropertyString(tRep, "VendorName", TheCommonUtils.CStr(tI.Developer));
                        TheThing.SetSafePropertyString(tRep, "ProductName", TheCommonUtils.CStr(tI.ServiceDescription));
                        TheThing.SetSafePropertyString(tRep, "ProductText", TheCommonUtils.CStr(tI.LongDescription));
                        TheThing.SetSafePropertyString(tRep, "VendorText", TheCommonUtils.CStr(tI.DeveloperUrl));
                        TheThing.SetSafePropertyString(tRep, "ProductID", TheCommonUtils.CStr(tI.cdeMID));
                    }
                    TheThingRegistry.RegisterThing(tRep);
                    MyBaseEngine.ProcessMessage(new TheProcessMessage(new TSM(MyBaseEngine.GetEngineName(), "REFRESH_DASH")));
                }
                else
                {
                    TheCommCore.PublishToOriginator((para as TheProcessMessage).Message, new TSM(eEngineName.NMIService, "NMI_TTS", tT.cdeMID.ToString()));
                }
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, mMyForm, eFieldType.SmartLabel, pFldOrder + 3, 0, 0, null, pUpdName, new nmiCtrlSingleEnded {
                ParentFld = pFldOrder, TileWidth = 2
            });
            TheNMIEngine.AddSmartControl(MyBaseThing, mMyForm, eFieldType.BarChart, pFldOrder + 4, 0, 0, null, pUpdName, new nmiCtrlBarChart()
            {
                ParentFld = pFldOrder, MaxValue = MaxVal, TileWidth = 4, NoTE = true, Foreground = "blue"
            });
        }
        //Who uses the .CDES File in the store? Moved into platform folder
        private static void WriteServiceInfo(ThePluginInfo tInfo, string storePath)
        {
            string tInfoFile;

            if (String.IsNullOrEmpty(storePath))
            {
                tInfoFile = TheCommonUtils.cdeFixupFileName($"store\\{tInfo.cdeMID}\\{tInfo.Platform}\\{tInfo.ServiceName}.CDES");
            }
            else
            {
                tInfoFile = Path.Combine(storePath, $"{tInfo.ServiceName}.CDES");
            }
            using (StreamWriter sr = new StreamWriter(tInfoFile))
                sr.Write(TheCommonUtils.SerializeObjectToJSONString <ThePluginInfo>(tInfo));
        }
        /// <summary>
        /// Creates an installation package for a plugin.
        /// </summary>
        /// <param name="tInfo">Meta information about the plug-in. (can be null, but then tPlace has to be specified)</param>
        /// <param name="tPlace">Additional information about the plug-in's presence in a market place (can be null, but then tInfo has to be specified)</param>
        /// <param name="outputDirectory">Path to a directory that will be used for temporary files as well as the generated installation package</param>
        /// <param name="bForce">Overwrites output files if they already exists.</param>
        /// <param name="packageFilePath">Path to the installation package within the outputDirectory.</param>
        /// <returns>null or empty string if successful. Error information on failure.</returns>
        public static string CreatePluginPackage(ThePluginInfo tInfo, TheServicesMarketPlace tPlace, string outputDirectory, bool bForce, out string packageFilePath)
        {
            packageFilePath = null;
            string tMetaFile = "";

            if (tInfo != null)
            {
                if (tInfo.Capabilities != null && tInfo.Capabilities.Contains(eThingCaps.Internal))
                {
                    return($"{tInfo.ServiceName} Is Internal Only");
                }
                if (String.IsNullOrEmpty(outputDirectory))
                {
                    tMetaFile = TheCommonUtils.cdeFixupFileName($"store\\{tInfo.cdeMID}\\{tInfo.Platform}\\");
                }
                else
                {
                    tMetaFile = $"{outputDirectory}\\store\\{tInfo.cdeMID}\\{tInfo.Platform}\\";
                }
                if (!Directory.Exists(tMetaFile))
                {
                    TheCommonUtils.CreateDirectories(tMetaFile);
                }
                WriteServiceInfo(tInfo, outputDirectory);

                string tgr = tMetaFile + "new\\";
                if (TheCommonUtils.IsOnLinux())
                {
                    tgr = tgr.Replace('\\', '/');
                }
                if (Directory.Exists(tgr))
                {
                    Directory.Delete(tgr, true);
                }

                if (tInfo.FilesManifest != null && tInfo.FilesManifest.Count > 0)
                {
                    foreach (string tFile in tInfo.FilesManifest)
                    {
                        if (tFile == null)
                        {
                            continue;
                        }
                        string tFinalFile = tFile;
                        try
                        {
                            if (tFile.StartsWith("@"))  //If a Manifest file starts with @ this function expects this syntax: "@<platform>@<FileName>"
                            {
                                var tC = tFile.Split('@');
                                if (tC.Length < 3)
                                {
                                    continue;
                                }
                                switch (tC[1])
                                {
                                case "net35":
                                    if (tInfo.Platform != cdePlatform.X32_V3)
                                    {
                                        continue;
                                    }
                                    break;

                                case "net40":
                                    if (tInfo.Platform != cdePlatform.NETV4_32 && tInfo.Platform != cdePlatform.NETV4_64)
                                    {
                                        continue;
                                    }
                                    break;

                                case "net45":
                                    if (tInfo.Platform != cdePlatform.X64_V3 && tInfo.Platform != cdePlatform.X32_V4)
                                    {
                                        continue;
                                    }
                                    break;

                                case "netstandard2.0":
                                    break;

                                default:
                                    if ((TheCommonUtils.CInt(tC[1]) > 0 && TheCommonUtils.CInt(tC[1]) != TheCommonUtils.CInt(tInfo.Platform)))
                                    {
                                        continue;
                                    }
                                    break;
                                }
                                tFinalFile = tC[2];
                            }
                            string src = TheBaseAssets.MyServiceHostInfo.BaseDirectory;
                            if (TheBaseAssets.MyServiceHostInfo.cdeHostingType == cdeHostType.IIS)
                            {
                                src += "bin\\";
                            }
                            src += tFinalFile;
                            if (TheCommonUtils.IsOnLinux())
                            {
                                src = src.Replace('\\', '/');
                            }
                            tgr = tMetaFile + "new\\" + tFinalFile;
                            if (TheCommonUtils.IsOnLinux())
                            {
                                tgr = tgr.Replace('\\', '/');
                            }
                            TheCommonUtils.CreateDirectories(tgr);
                            File.Copy(src, tgr, true);
                        }
                        catch (Exception e)
                        {
                            return(string.Format("Manifest File {0} could not be copied: {1}", tFile, e.ToString()));
                            //TheBaseAssets.MySYSLOG.WriteToLog(2, new TSM("ISMManager", string.Format("Manifest Filer {0} could not be copied.", tFile), eMsgLevel.l1_Error, e.ToString())); //Log Entry that service has been started
                        }
                    }
                }
            }
            else
            {
                tMetaFile = TheCommonUtils.cdeFixupFileName(string.Format("store\\{0}\\{1}\\", tPlace.PluginID, tPlace.Platform));  //now PluginID which contains ThePluginInfo.cdeMID
            }

            if (tPlace != null && File.Exists(tMetaFile + "META.CDEM"))
            {
                TheServicesMarketPlace tPl = null;
                using (StreamReader sr = new StreamReader(tMetaFile + "META.CDEM"))
                {
                    String line = sr.ReadToEnd();
                    tPl = TheCommonUtils.DeserializeJSONStringToObject <TheServicesMarketPlace>(line);
                }
                if ((tInfo != null && tInfo.CurrentVersion <= tPl.CurrentVersion) || (tPl != null && tPlace.CurrentVersion <= tPl.CurrentVersion))
                {
                    return($"{tPlace?.ServiceName} has existing Version in Store: PInfo:{tInfo?.CurrentVersion} vs Meta:{tPl?.CurrentVersion} vs Place:{tPlace?.CurrentVersion}");
                }
            }
            if (tPlace == null)
            {
                tPlace = new TheServicesMarketPlace();
                tPlace.Capabilities    = tInfo.Capabilities;
                tPlace.Categories      = tInfo.Categories;
                tPlace.PluginID        = tInfo.cdeMID; //PluginID now contains ThePluginInfo.cdeMID
                tPlace.CurrentVersion  = tInfo.CurrentVersion;
                tPlace.LongDescription = tInfo.LongDescription;
                tPlace.Developer       = tInfo.Developer;
                tPlace.DeveloperUrl    = tInfo.DeveloperUrl;
                tPlace.HomeUrl         = tInfo.HomeUrl;
                tPlace.Platform        = tInfo.Platform;
                tPlace.Price           = tInfo.Price;
                tPlace.ServiceName     = tInfo.ServiceName;
                tPlace.AvailableSince  = DateTime.Now;
                tPlace.RaterCount      = new List <int>()
                {
                    0, 0, 0, 0, 0
                };
                tPlace.Rating             = 0;
                tPlace.DownloadCounter    = 0;
                tPlace.ServiceDescription = string.IsNullOrEmpty(tInfo.ServiceDescription) ? tInfo.ServiceName : tInfo.ServiceDescription;
                if (TheBaseAssets.MyServiceHostInfo != null)
                {
                    if (string.IsNullOrEmpty(tPlace.HomeUrl))
                    {
                        tPlace.HomeUrl = TheBaseAssets.MyServiceHostInfo.GetPrimaryStationURL(false) + "/%PluginID%";
                    }
                    tPlace.IconUrl = tInfo.IconUrl;
                    if (string.IsNullOrEmpty(tPlace.IconUrl) || tPlace.IconUrl == "toplogo-150.png")
                    {
                        tPlace.IconUrl = "<i class=\"cl-font cl-Logo cl-4x\"></i>"; // TheBaseAssets.MyServiceHostInfo.UPnPIcon;
                    }
                    if (tPlace.IconUrl.EndsWith(".png", StringComparison.OrdinalIgnoreCase) || tPlace.IconUrl.EndsWith(".jpg", StringComparison.OrdinalIgnoreCase))
                    {
                        tPlace.IconUrl = $"<img src='{tPlace.IconUrl}' class='Blocked' width='78' height='78'></img>";
                    }
                    else if (tPlace.IconUrl.StartsWith("FA"))
                    {
                        tPlace.IconUrl = "<i class='fa faIcon " + (tPlace.IconUrl.Substring(3, 1) == "S" ? "fa-spin " : "") + "fa-" + tPlace.IconUrl.Substring(2, 1) + "x'>&#x" + tPlace.IconUrl.Substring(4, tPlace.IconUrl.Length - 4) + ";</i>";
                    }
                }
                if (Directory.Exists(tMetaFile + "new"))
                {
                    var res = CreateCDEX(tPlace, tMetaFile, true, out packageFilePath);
                    if (res != null)
                    {
                        return(res);
                    }
                    //Directory.Move(tMetaFile + "new", tMetaFile + "DONE_" + TheCommonUtils.GetTimeStamp());
                }
                else
                {
                    return("Error: Output directory does not exists");
                }
            }
            else
            {
                if (tInfo.CurrentVersion > tPlace.CurrentVersion)
                {
                    tPlace.CurrentVersion = tInfo.CurrentVersion;
                }
                var res = CreateCDEX(tPlace, tMetaFile, bForce, out packageFilePath);
                if (res != null)
                {
                    return(res);
                }
            }
            tPlace.LastUpdate = DateTime.Now;
            using (StreamWriter sr = new StreamWriter(tMetaFile + "META.CDEM"))
                sr.Write(TheCommonUtils.SerializeObjectToJSONString <TheServicesMarketPlace>(tPlace));
            return("");
        }
Exemple #5
0
        private static string CreateCDEX(string storeDirectoryPath, ThePluginInfo tInfo, ILogger logger, bool bCheckForFileOverwrite, out string cdexPath)
        {
            var pluginTempDirectory = Path.Combine(storeDirectoryPath, $"newCDEX_{Guid.NewGuid()}"); // ensure each plug-in/packging operation gets it's own directory if packaging overlaps for different platforms/flavors of the same plug-in
            var error = ThePluginPackager.CreatePluginPackage(tInfo, null, pluginTempDirectory, false, out cdexPath);

            if (string.IsNullOrEmpty(error))
            {
                // Package it into a .CDEP for use with mesh manager
                string cdepFileName = $"{tInfo.ServiceName.Replace('.', '-')}{(tInfo.Platform > 0 ? $" {tInfo.Platform}" : "")} V{tInfo.CurrentVersion:0.0000}.CDEP";
                string cdepFilePath = Path.Combine(storeDirectoryPath, cdepFileName);
                byte[] oldContent   = null;
                if (File.Exists(cdepFilePath))
                {
                    if (bCheckForFileOverwrite)
                    {
                        logger.WriteLine($"WARNING: File conflict: {cdepFilePath} already existed. Replacing.");
                        oldContent = File.ReadAllBytes(cdepFilePath);
                    }
                    File.Delete(cdepFilePath);
                }
                else
                {
                    logger.WriteLine($"Creating file: {cdepFilePath}.");
                }
                System.IO.Compression.ZipFile.CreateFromDirectory(Path.Combine(pluginTempDirectory, "store"), cdepFilePath, System.IO.Compression.CompressionLevel.Optimal, false);
                if (oldContent != null)
                {
                    var newContent = File.ReadAllBytes(cdepFilePath);
                    if (oldContent.SequenceEqual(newContent))
                    {
                        logger.WriteLine($"WARNING: Overwritten file was identical: {cdepFilePath}.");
                    }
                    else
                    {
                        logger.WriteLine($"WARNING: Overwritten file was different: {cdepFilePath}.");
                        //File.WriteAllBytes($"{cdepFilePath}.conflict", oldContent);
                    }
                }
            }
            else
            {
                logger.WriteLine($"ERROR: {error}");
                return(error);
            }

            var finalPluginPath = Path.Combine(storeDirectoryPath, Path.GetFileName(cdexPath));

            {
                byte[] oldContent = null;
                try
                {
                    if (File.Exists(finalPluginPath))
                    {
                        if (bCheckForFileOverwrite)
                        {
                            logger.WriteLine($"WARNING: File conflict: {finalPluginPath} already existed.");
                            oldContent = File.ReadAllBytes(finalPluginPath);
                        }
                        File.Delete(finalPluginPath);
                    }
                    else
                    {
                        logger.WriteLine($"Creating file: {finalPluginPath}.");
                    }
                }
                catch { }
                File.Move(cdexPath, finalPluginPath);

                if (oldContent != null)
                {
                    var newContent = File.ReadAllBytes(finalPluginPath);
                    if (oldContent.SequenceEqual(newContent))
                    {
                        logger.WriteLine($"WARNING: Overwritten file was identical: {finalPluginPath}.");
                    }
                    else
                    {
                        logger.WriteLine($"WARNING: Overwritten file was different: {finalPluginPath}.");
                        //File.WriteAllBytes($"{cdepFilePath}.conflict", oldContent);
                    }
                }
            }
            Directory.Delete(pluginTempDirectory, true);
            cdexPath = finalPluginPath;
            return(error);
        }
Exemple #6
0
        internal static void InitAssets(TheBaseApplication pApp)
        {
            if (IsInitialized)
            {
                return;
            }
            IsInitialized = true;
            if (MyServiceHostInfo == null || !(MySecrets?.IsApplicationIDValid() == true))
            {
                MasterSwitch = false;
                return;
            }
            MyApplication = pApp;

            #region step 1: Moved from StartApplication to here as all the following code is updating TheBaseAssets
            //The following section are "app.config" only settings required before cdeTPI is loaded. These settings cannot be set via the Provisioning Service
            int delay = TheCommonUtils.CInt(MySettings.GetSetting("StartupDelay"));
            if (delay > 0)
            {
                TheCommonUtils.SleepOneEye((uint)(delay * 1000), 100);
            }

            string temp = MySettings.GetSetting("AllowEnvironmentVarsToOverrideConfig");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.AllowEnvironmentVarsToOverrideConfig = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("AllowEnvironmentVars");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.AllowEnvironmentVars = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("DEBUGLEVEL");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.DebugLevel = (eDEBUG_LEVELS)TheCommonUtils.CInt(temp);
            }
            //Clouds have special behavior and the CDE needs to know this upfront
            temp = MySettings.GetSetting("IsCloudService");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.IsCloudService = TheCommonUtils.CBool(temp);
            }
            temp = MySettings.GetSetting("ISOEN");
            if (!string.IsNullOrEmpty(temp))
            {
                MyServiceHostInfo.IsIsolated  = true;
                MyServiceHostInfo.IsoEngine   = temp;
                MyServiceHostInfo.cdeNodeType = cdeNodeType.Active;
            }
            else
            {
                temp = MySettings.GetSetting("UseRandomDeviceID");
                if (!string.IsNullOrEmpty(temp))
                {
                    MyServiceHostInfo.UseRandomDeviceID = TheCommonUtils.CBool(temp);
                }
            }

            //Step 2: Restore from backup if exists
#if CDE_NET45 // Backup/Restore only support on NET45
            // To ensure that restored backups are not overwritten during shutdown, we write them to a temp directory and move them into place on start up
            if (!MyServiceHostInfo.UseRandomDeviceID && !MyServiceHostInfo.IsIsolated)
            {
                string cacheParentPath = TheCommonUtils.GetCurrentAppDomainBaseDirWithTrailingSlash() + "ClientBin\\";
                if (Directory.Exists(cacheParentPath + "__CacheToRestore"))
                {
                    // Keep the old Cache around just in case
                    try
                    {
                        // First make space for the old copy, in case there was one already
                        if (Directory.Exists(cacheParentPath + "__CacheOld"))
                        {
                            Directory.Delete(cacheParentPath + "__CacheOld", true);
                        }
                    }
                    catch
                    {
                        //ignored
                    }
                    try
                    {
                        Directory.Move(cacheParentPath + "Cache", cacheParentPath + "__CacheOld");
                    }
                    catch
                    {
                        //ignored
                    }

                    // Now move the restored cache into place
                    try
                    {
                        Directory.Move(cacheParentPath + "__CacheToRestore", cacheParentPath + "Cache");
                    }
                    catch
                    {
                        TheSystemMessageLog.ToCo("Failure while restoring backup");
                    }
                }
            }
#endif

            MyServiceHostInfo.EnableTaskKPIs = TheCommonUtils.CBool(MySettings.GetSetting("EnableTaskKPIs"));
            if (MyServiceHostInfo.EnableTaskKPIs)
            {
                var taskKpiThread = new Thread(() =>
                {
                    do
                    {
                        var kpis = TheCommonUtils.GetTaskKpis(null);
                        TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: {TheCommonUtils.SerializeObjectToJSONString(kpis)}");
                        Thread.Sleep(1000); // Keeping it simple here, to minimize interference on task scheduler/thread scheduler etc. (Assumption: not used on production systems) // TheCommonUtils.SleepOneEye(1000, 1000);
                    } while (MasterSwitch && !Engines.TheCDEngines.IsHostReady && MyServiceHostInfo.EnableTaskKPIs);
                    TheSystemMessageLog.ToCo($"Tasks {DateTime.Now}: KPIs Handoff to NodeHost");
                });
                taskKpiThread.Start();
            }
            #endregion

            if (MyActivationManager == null)
            {
                MyActivationManager = new TheDefaultActivationManager(MySecrets, MySYSLOG);
            }


            #region step 3: analyse os environment information
            OperatingSystem os           = Environment.OSVersion;
            var             osInfoForLog = $"C-DEngine version: {BuildVersion} OS:{Environment.OSVersion} OS Version:{os.VersionString} OS Version Numbers: {os.Version.Major}.{os.Version.Minor}.{os.Version.Build}.{os.Version.Revision} Platform:{os.Platform} SP:{os.ServicePack} Processor Count: {Environment.ProcessorCount} IsMono:{(Type.GetType("Mono.Runtime") != null)} IsNetCore:{TheCommonUtils.IsNetCore()} Product: {TheCommonUtils.GetAssemblyProduct(typeof(TheBaseAssets))} ";
            TheSystemMessageLog.ToCo(osInfoForLog);
            MyServiceHostInfo.OSInfo = osInfoForLog;
            string dotNetInfoForLog = string.Empty;
#if !CDE_NET35 && !CDE_NET4
            try
            {
                string frameworkDescription = null;
                string osDescription        = null;
                string processArchitecture  = null;
                string osArchitecture       = null;

#if CDE_STANDARD
                frameworkDescription = System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription;
                osDescription        = System.Runtime.InteropServices.RuntimeInformation.OSDescription;
                processArchitecture  = System.Runtime.InteropServices.RuntimeInformation.ProcessArchitecture.ToString();
                osArchitecture       = System.Runtime.InteropServices.RuntimeInformation.OSArchitecture.ToString();
#else
                var rtInfoType = Type.GetType("System.Runtime.InteropServices.RuntimeInformation, System.Runtime.InteropServices.RuntimeInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a");
                if (rtInfoType != null)
                {
                    frameworkDescription = rtInfoType.GetProperty("FrameworkDescription").GetValue(null).ToString();
                    osDescription        = rtInfoType.GetProperty("OSDescription").GetValue(null).ToString();
                    processArchitecture  = rtInfoType.GetProperty("ProcessArchitecture").GetValue(null).ToString();
                    osArchitecture       = rtInfoType.GetProperty("OSArchitecture").GetValue(null).ToString();
                }
#endif
                if (!string.IsNullOrEmpty(frameworkDescription))
                {
                    dotNetInfoForLog = $"NetFrameWork:{frameworkDescription} Processor:{processArchitecture} OS:{osDescription } OS Arch:{osArchitecture}";
                    TheSystemMessageLog.ToCo(dotNetInfoForLog);
                    MyServiceHostInfo.OSInfo += $" {dotNetInfoForLog}";
                }
            }
            catch
            {
            }
#endif
            if (TheCommonUtils.IsMono()) // CODE REVIEW: Need to clean this up - do we mean Mono or Linux or case-insensitive file systems? CM: No- here we need this to find out if we are running in the MONO Runtime
            {
                MyServiceHostInfo.cdePlatform = cdePlatform.MONO_V3;
            }
            else
            {
#if CDE_NET35
                MyServiceHostInfo.cdePlatform = cdePlatform.X32_V3;
#elif CDE_NET4
                MyServiceHostInfo.cdePlatform = Environment.Is64BitProcess ? cdePlatform.NETV4_64 : cdePlatform.NETV4_32;
#elif CDE_STANDARD
                MyServiceHostInfo.cdePlatform = cdePlatform.NETSTD_V20;
#else
                MyServiceHostInfo.cdePlatform = TheCommonUtils.GetAssemblyPlatform(Assembly.GetEntryAssembly(), false, out var empty);// old: Environment.Is64BitProcess ? cdePlatform.X64_V3 : cdePlatform.X32_V4;
#endif
            }
            TheSystemMessageLog.ToCo("BaseDir: " + MyServiceHostInfo.BaseDirectory);
            #endregion

            #region step 4: Prepare essential Subsystems (Syslog, ScopeManager, Diagnostics, Caches, AppInfo)
            MySYSLOG = new TheSystemMessageLog(500); // No more ToCo after this point (will be ignored)
            TheCDEKPIs.Reset();

            MyServiceHostInfo.MiniHostInfo.MySYSLOG = MySYSLOG;
            MyServiceHostInfo.MiniHostInfo.MyKPIs   = new TheKPIs();
            if (MyScopeManager == null)
            {
                MyScopeManager = new TheDefaultScopeManager();
            }
            MyScopeManager.SetMiniHSI(MyServiceHostInfo.MiniHostInfo);
            MyScopeManager.RegisterScopeChanged(localEventScopeChanged);

            TheDiagnostics.InitDiagnostics();
            TheDiagnostics.SetThreadName("MAIN THREAD");
            TheQueuedSenderRegistry.Startup();

            MyBlobCache     = new TheMirrorCache <TheBlobData>(MyServiceHostInfo.TO.StorageCleanCycle);
            MyReceivedParts = new TheMirrorCache <TheReceivedParts>(MyServiceHostInfo.TO.StorageCleanCycle);
            //TODO: I hope there is a better way to do this for Metro!
            MyServiceTypes.Add(typeof(TheBaseAssets));

            MyServiceHostInfo.TO.MakeHeartNormal();

            MyAppInfo = new ThePluginInfo
            {
                cdeMID             = MyServiceHostInfo.cdeMID,
                CurrentVersion     = MyServiceHostInfo.CurrentVersion,
                Developer          = MyServiceHostInfo.VendorName,
                DeveloperUrl       = MyServiceHostInfo.VendorUrl,
                HomeUrl            = MyServiceHostInfo.SiteName,
                IconUrl            = MyServiceHostInfo.UPnPIcon,
                LongDescription    = MyServiceHostInfo.Description,
                Platform           = MyServiceHostInfo.cdePlatform,
                Copyrights         = MyServiceHostInfo.Copyrights,
                Price              = 0,
                ServiceDescription = MyServiceHostInfo.Title,
                ServiceName        = MyServiceHostInfo.ApplicationName,
                Capabilities       = new List <eThingCaps> {
                    eThingCaps.Host
                },
                Categories    = new List <string>(),
                FilesManifest = new List <string>()
            };
            if (MyServiceHostInfo.ManifestFiles != null)
            {
                MyAppInfo.FilesManifest.AddRange(MyServiceHostInfo.ManifestFiles);
            }
            #endregion

            //Now load provisioning and local settings then parse them
#pragma warning disable CS0618 // Type or member is obsolete - its allowed here
            if (!TheCDESettings.ParseSettings(MyCmdArgs, true, false))
#pragma warning restore CS0618 // Type or member is obsolete
            {
                MasterSwitch = false;
                return;
            }

            if (MyCodeSigner == null)
            {
                MyCodeSigner = new TheDefaultCodeSigning(MySecrets, MySYSLOG);
            }
            string tBaseDir = MyServiceHostInfo.BaseDirectory;
            if (MyServiceHostInfo.cdeHostingType == cdeHostType.IIS)
            {
                tBaseDir += "bin\\";
            }
            string uDir = tBaseDir;
            if (!string.IsNullOrEmpty(MyServiceHostInfo.ISMMainExecutable))
            {
                uDir += MyServiceHostInfo.ISMMainExecutable;
                if (MyServiceHostInfo.cdeHostingType != cdeHostType.IIS)
                {
                    var hostPath = uDir + ".exe";
                    if (!File.Exists(hostPath))
                    {
                        // We may be running under .Net Core with a .dll-based host
                        hostPath = uDir + ".dll";
                    }
                    uDir = hostPath;
                }
            }
            else
            {
                uDir += "C-DEngine.dll";
            }
            MyServiceHostInfo.CodeSignThumb = MyCodeSigner.GetAppCert(MyServiceHostInfo.DontVerifyTrust, uDir, MyServiceHostInfo.VerifyTrustPath, MyServiceHostInfo.DontVerifyIntegrity);  //Must be loaded here to set trust level in HSI

            if (MyLoc as TheDefaultLocalizationUtils != null)
            {
                (MyLoc as TheDefaultLocalizationUtils).DoPseudoLoc = TheCommonUtils.CBool(MySettings.GetSetting("DoPseudoLoc"));
            }

            #region step 5: output some system information
            if (MyServiceHostInfo.IsMemoryOptimized)
            {
                MySYSLOG.SetMaxLogEntries(10);
            }
            MySYSLOG.WriteToLog(4151, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", osInfoForLog, eMsgLevel.l4_Message));

            if (!string.IsNullOrEmpty(dotNetInfoForLog))
            {
                MySYSLOG.WriteToLog(4152, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", dotNetInfoForLog, eMsgLevel.l4_Message));
            }
            MySYSLOG.WriteToLog(4153, TSM.L(eDEBUG_LEVELS.ESSENTIALS) ? null : new TSM("TheBaseAssets", "BaseDir: " + MyServiceHostInfo.BaseDirectory, eMsgLevel.l4_Message));
            #endregion

            #region step 6: determine WebSocket8 vs. WebSocketsSharp
            var ws8FlagTemp = MySettings.GetSetting("DisallowWebSocket8");
            if (!string.IsNullOrEmpty(ws8FlagTemp))
            {
                MyServiceHostInfo.IsWebSocket8Active = !TheCommonUtils.CBool(ws8FlagTemp);
                MySYSLOG.WriteToLog(4154, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", $"Setting IsWebSocket8Active to {MyServiceHostInfo.IsWebSocket8Active} due to config", eMsgLevel.l4_Message));
            }
            else
            {
                MyServiceHostInfo.IsWebSocket8Active = true;
            }
            if ((os.Platform != PlatformID.Win32NT && !TheCommonUtils.IsNetCore()) || (os.Platform == PlatformID.Win32NT && (os.Version.Major < 6 || (os.Version.Major == 6 && os.Version.Minor < 2))))
            {
                MyServiceHostInfo.IsWebSocket8Active = false;
                string tWSMsg = "Older Windows or non-Windows OS Detected - No OS Support for WebSockets Found: ";
#if !CDE_USECSWS //OK
                TheBaseAssets.MyServiceHostInfo.DisableWebSockets = true;
                tWSMsg += "WebSockets are turned Off";
#else
                tWSMsg += "Switching to WebSockets-Sharp";
#endif
                MySYSLOG.WriteToLog(4155, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", tWSMsg, eMsgLevel.l4_Message));
            }
            #endregion

            #region step 7: Initialize Localization subsystem (ILocalizationHooks)
            bool bLocInitialized = false;
            try
            {
                var entryAssembly = Assembly.GetEntryAssembly();    //This does not work in IIS!
                if (entryAssembly != null)
                {
                    var CDEPlugins = from t in entryAssembly.GetTypes()
                                     let ifs = t.GetInterfaces()
                                               where ifs != null && ifs.Length > 0 && (ifs.Contains(typeof(ILocalizationHooks)))
                                               select new { Type = t, t.Namespace, t.Name, t.FullName };
                    if (CDEPlugins != null && CDEPlugins.Any())
                    {
                        MyLoc = Activator.CreateInstance(CDEPlugins.First().Type) as ILocalizationHooks;
                    }
                    bLocInitialized = true;
                }
            }
            catch
            {
            }
            if (!bLocInitialized)
            {
                MySYSLOG.WriteToLog(4156, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", "3rd Party ILocalization Hooks not found - using built-in", eMsgLevel.l4_Message));
            }
            #endregion

            #region step 8: Set MyStationUrl
            switch (MyServiceHostInfo.cdeHostingType)
            {
            case cdeHostType.Phone:
            case cdeHostType.Metro:
                MyServiceHostInfo.MyDeviceMoniker = "CDEV://";
                break;

            case cdeHostType.Silverlight:
                MyServiceHostInfo.MyDeviceMoniker = "CDES://";
                break;

            case cdeHostType.Device:
                MyServiceHostInfo.MyDeviceMoniker = "CDEC://";
                break;

            case cdeHostType.Mini:
                MyServiceHostInfo.MyDeviceMoniker = "CDEM://";
                break;

            default:     //Services
                MyServiceHostInfo.MyDeviceMoniker = "CDEB://";
                break;
            }
            if (TheCommonUtils.IsHostADevice())
            {
                MyServiceHostInfo.MyStationURL = MyServiceHostInfo.MyDeviceMoniker + "{" + MyServiceHostInfo.MyDeviceInfo.DeviceID + "}".ToUpper(); //MSU-OK
            }
            else
            {
                if (MyServiceHostInfo.MyAltStationURLs.Count(s => s.StartsWith("CDEB")) == 0)
                {
                    MyServiceHostInfo.MyAltStationURLs.Add("CDEB://{" + MyServiceHostInfo.MyDeviceInfo.DeviceID + "}"); //TODO: Backchannel Possibly save to Config File
                }
            }
            #endregion

            #region step 9: Start Localhost QSender and SessionStateManager
            MySession        = new TheSessionStateManager(MyServiceHostInfo);
            LocalHostQSender = new TheQueuedSender();                                                                                                                                                                                 //NO connected or Error Event necessary
            LocalHostQSender.StartSender(new TheChannelInfo(MyServiceHostInfo.MyDeviceInfo.DeviceID, MyScopeManager.ScopeID, MyServiceHostInfo.MyDeviceInfo.SenderType, MyServiceHostInfo.GetPrimaryStationURL(false)), null, false); //NEW:2.06 Setting Realscope here ///null correct - no subs on LocalhostQS in beginning //RScope-OK
            if ((MyServiceHostInfo.DisableWebSockets || MyServiceHostInfo.MyStationWSPort == 0) && !TheCommonUtils.IsHostADevice())
            {
                MySYSLOG.WriteToLog(4157, TSM.L(eDEBUG_LEVELS.OFF) ? null : new TSM("TheBaseAssets", $"WebSockets Disabled - no WSPort specified {MyServiceHostInfo.MyStationWSPort} or DisableWebSocket={MyServiceHostInfo.DisableWebSockets}", eMsgLevel.l4_Message));
            }
            #endregion

            // Post Device ID settings

            //Step 10: Save all settings to local cdeTPI
            MySettings.UpdateLocalSettings();
        }