2using System.Collections.Generic;
3using System.Diagnostics;
5using System.Reflection;
6using System.ServiceProcess;
10using Microsoft.Deployment.WindowsInstaller;
14using static System.Environment;
21 public static ActionResult CreateEventSource(Session Session)
23 Session.Log(
"Checking event sources.");
27 if (!EventLog.Exists(
"IoTGateway") || !EventLog.SourceExists(
"IoTGateway"))
29 Session.Log(
"Creating event source.");
30 EventLog.CreateEventSource(
new EventSourceCreationData(
"IoTGateway",
"IoTGateway"));
31 Session.Log(
"Event source created.");
34 return ActionResult.Success;
38 Session.Log(
"Unable to create event source. Error reported: " + ex.Message);
39 return ActionResult.Failure;
44 public static ActionResult DeleteEventSource(Session Session)
46 Session.Log(
"Checking event sources.");
48 if (EventLog.Exists(
"IoTGateway"))
52 Session.Log(
"Deleting event log.");
53 EventLog.Delete(
"IoTGateway");
54 Session.Log(
"Event log deleted.");
58 Session.Log(
"Unable to delete event log. Error reported: " + ex.Message);
62 if (EventLog.SourceExists(
"IoTGateway"))
66 Session.Log(
"Deleting event source.");
67 EventLog.DeleteEventSource(
"IoTGateway");
68 Session.Log(
"Event source deleted.");
72 Session.Log(
"Unable to delete event source. Error reported: " + ex.Message);
77 return ActionResult.Success;
80 private static void Log(Session Session,
string Msg)
86 public static string AppDataFolder
90 string Result = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);
92 if (!Result.EndsWith(
new string(Path.DirectorySeparatorChar, 1)))
93 Result += Path.DirectorySeparatorChar;
95 Result +=
"IoT Gateway" + Path.DirectorySeparatorChar;
96 if (!Directory.Exists(Result))
97 Directory.CreateDirectory(Result);
120 public static ActionResult InstallAndStartService(Session Session)
122 Session.Log(
"Installing service.");
125 string DisplayName = Session[
"SERVICEDISPLAYNAME"];
126 string Description = Session[
"SERVICEDESCRIPTION"];
127 string InstallDir = Session[
"INSTALLDIR"];
129 if (!InstallDir.EndsWith(
new string(Path.DirectorySeparatorChar, 1)))
130 InstallDir += Path.DirectorySeparatorChar;
132 Session.Log(
"Service Display Name: " + DisplayName);
133 Session.Log(
"Service Description: " + Description);
134 Session.Log(
"Working folder: " + InstallDir);
136 StringBuilder sb =
new StringBuilder();
138 sb.Append(
"-install -displayname \"");
139 sb.Append(DisplayName);
140 sb.Append(
"\" -description \"");
141 sb.Append(Description);
142 sb.Append(
"\" -start AutoStart -immediate");
144 ProcessStartInfo ProcessInformation =
new ProcessStartInfo()
146 FileName = InstallDir +
"Waher.IotGateway.Svc.exe",
147 Arguments = sb.ToString(),
148 UseShellExecute =
false,
149 RedirectStandardError =
true,
150 RedirectStandardOutput =
true,
151 WorkingDirectory = InstallDir,
152 CreateNoWindow =
true,
153 WindowStyle = ProcessWindowStyle.Hidden
156 using (Process P =
new Process())
160 P.ErrorDataReceived += (Sender, e) =>
163 Session.Log(
"ERROR: " + e.Data);
166 P.Exited += (Sender, e) =>
168 Session.Log(
"Process exited.");
171 P.OutputDataReceived += (Sender, e) =>
176 P.StartInfo = ProcessInformation;
179 if (!P.WaitForExit(60000) || Error)
180 throw new Exception(
"Timeout. Service did not install properly.");
183 if (!P.StandardError.EndOfStream)
184 Session.Log(P.StandardError.ReadToEnd());
186 if (!P.StandardOutput.EndOfStream)
187 Session.Log(P.StandardOutput.ReadToEnd());
190 throw new Exception(
"Installation failed. Exit code: " + P.ExitCode.ToString());
194 Session.Log(
"Service installed and started.");
196 return WaitAllModulesStarted(Session);
200 Session.Log(
"Unable to install service. Error reported: " + ex.Message);
201 return ActionResult.Failure;
206 public static ActionResult UninstallService(Session Session)
208 Session.Log(
"Uninstalling service.");
211 string InstallDir = Session[
"INSTALLDIR"];
213 if (!InstallDir.EndsWith(
new string(Path.DirectorySeparatorChar, 1)))
214 InstallDir += Path.DirectorySeparatorChar;
216 Session.Log(
"Working folder: " + InstallDir);
218 ProcessStartInfo ProcessInformation =
new ProcessStartInfo()
220 FileName = InstallDir +
"Waher.IotGateway.Svc.exe",
221 Arguments =
"-uninstall",
222 UseShellExecute =
false,
223 RedirectStandardError =
true,
224 RedirectStandardOutput =
true,
225 WorkingDirectory = InstallDir,
226 CreateNoWindow =
true,
227 WindowStyle = ProcessWindowStyle.Hidden
230 using (Process P =
new Process())
234 P.ErrorDataReceived += (Sender, e) =>
237 Session.Log(
"ERROR: " + e.Data);
240 P.Exited += (Sender, e) =>
242 Session.Log(
"Process exited.");
245 P.OutputDataReceived += (Sender, e) =>
250 P.StartInfo = ProcessInformation;
253 if (!P.WaitForExit(60000) || Error)
254 Session.Log(
"Timeout. Service did not uninstall properly.");
257 if (!P.StandardError.EndOfStream)
258 Session.Log(P.StandardError.ReadToEnd());
260 if (!P.StandardOutput.EndOfStream)
261 Session.Log(P.StandardOutput.ReadToEnd());
264 Session.Log(
"Uninstallation failed. Exit code: " + P.ExitCode.ToString());
267 Session.Log(
"Service uninstalled.");
268 return ActionResult.Success;
275 Session.Log(
"Unable to uninstall service. Error reported: " + ex.Message);
278 return UninstallService2(Session);
281 public static ActionResult UninstallService2(Session Session)
283 Session.Log(
"Uninstalling service (method 2).");
286 string InstallDir = Session[
"INSTALLDIR"];
288 if (!InstallDir.EndsWith(
new string(Path.DirectorySeparatorChar, 1)))
289 InstallDir += Path.DirectorySeparatorChar;
291 Session.Log(
"Working folder: " + InstallDir);
293 ProcessStartInfo ProcessInformation =
new ProcessStartInfo()
296 Arguments =
"delete \"IoT Gateway Service\"",
297 UseShellExecute =
false,
298 RedirectStandardError =
true,
299 RedirectStandardOutput =
true,
300 WorkingDirectory = InstallDir,
301 CreateNoWindow =
true,
302 WindowStyle = ProcessWindowStyle.Hidden
305 using (Process P =
new Process())
309 P.ErrorDataReceived += (Sender, e) =>
312 Session.Log(
"ERROR: " + e.Data);
315 P.Exited += (Sender, e) =>
317 Session.Log(
"Process exited.");
320 P.OutputDataReceived += (Sender, e) =>
325 P.StartInfo = ProcessInformation;
328 if (!P.WaitForExit(60000) || Error)
329 Session.Log(
"Timeout. Service did not uninstall properly.");
332 if (!P.StandardError.EndOfStream)
333 Session.Log(P.StandardError.ReadToEnd());
335 if (!P.StandardOutput.EndOfStream)
336 Session.Log(P.StandardOutput.ReadToEnd());
339 Session.Log(
"Uninstallation failed. Exit code: " + P.ExitCode.ToString());
341 Session.Log(
"Service uninstalled.");
347 Session.Log(
"Unable to uninstall service. Error reported: " + ex.Message);
351 return ActionResult.Success;
355 public static ActionResult StartService(Session Session)
357 Session.Log(
"Starting service.");
360 string InstallDir = Session[
"INSTALLDIR"];
362 ProcessStartInfo ProcessInformation =
new ProcessStartInfo()
365 Arguments =
"start \"IoT Gateway Service\"",
366 UseShellExecute =
false,
367 RedirectStandardError =
true,
368 RedirectStandardOutput =
true,
369 WorkingDirectory = InstallDir,
370 CreateNoWindow =
true,
371 WindowStyle = ProcessWindowStyle.Hidden
374 using (Process P =
new Process())
378 P.ErrorDataReceived += (Sender, e) =>
381 Session.Log(
"ERROR: " + e.Data);
384 P.Exited += (Sender, e) =>
386 Session.Log(
"Process exited.");
389 P.OutputDataReceived += (Sender, e) =>
394 P.StartInfo = ProcessInformation;
397 if (!P.WaitForExit(60000) || Error)
398 throw new Exception(
"Timeout. Service did not start properly.");
401 if (!P.StandardError.EndOfStream)
402 Session.Log(P.StandardError.ReadToEnd());
404 if (!P.StandardOutput.EndOfStream)
405 Session.Log(P.StandardOutput.ReadToEnd());
408 throw new Exception(
"Service start failed. Exit code: " + P.ExitCode.ToString());
412 Session.Log(
"Service started.");
414 return WaitAllModulesStarted(Session);
418 Session.Log(
"Unable to start service. Error reported: " + ex.Message);
420 return ActionResult.Success;
425 public static ActionResult StopService(Session Session)
427 Session.Log(
"Stopping service.");
430 string InstallDir = Session[
"INSTALLDIR"];
432 ProcessStartInfo ProcessInformation =
new ProcessStartInfo()
435 Arguments =
"stop \"IoT Gateway Service\"",
436 UseShellExecute =
false,
437 RedirectStandardError =
true,
438 RedirectStandardOutput =
true,
439 WorkingDirectory = InstallDir,
440 CreateNoWindow =
true,
441 WindowStyle = ProcessWindowStyle.Hidden
444 using (Process P =
new Process())
448 P.ErrorDataReceived += (Sender, e) =>
451 Session.Log(
"ERROR: " + e.Data);
454 P.Exited += (Sender, e) =>
456 Session.Log(
"Process exited.");
459 P.OutputDataReceived += (Sender, e) =>
464 P.StartInfo = ProcessInformation;
467 if (!P.WaitForExit(60000) || Error)
468 Session.Log(
"Timeout. Service did not stop properly.");
471 if (!P.StandardError.EndOfStream)
472 Session.Log(P.StandardError.ReadToEnd());
474 if (!P.StandardOutput.EndOfStream)
475 Session.Log(P.StandardOutput.ReadToEnd());
478 Session.Log(
"Stopping service failed. Exit code: " + P.ExitCode.ToString());
481 DateTime Started = DateTime.Now;
484 Session.Log(
"Service stop request successful. Checking process has stopped");
488 using (Mutex RunningServer =
new Mutex(
false,
"Waher.IoTGateway.Running"))
490 Stopped = RunningServer.WaitOne(1000);
493 RunningServer.ReleaseMutex();
496 while (!Stopped && (DateTime.Now - Started).TotalSeconds < 30);
499 Session.Log(
"Service stopped.");
501 throw new Exception(
"Service stop procedure seems to take time. Cancelling wait.");
508 Session.Log(
"Unable to stop service. Error reported: " + ex.Message);
511 return ActionResult.Success;
625 public static ActionResult OpenLocalhost(Session Session)
627 Session.Log(
"Starting browser.");
632 string StartPage = Session[
"STARTPAGE"];
633 if (StartPage ==
"unset")
634 StartPage =
string.Empty;
636 string Port =
string.Empty;
637 string Protocol =
"http";
641 string s = File.ReadAllText(AppDataFolder +
"Ports.txt");
642 string[] Rows = s.Split(
new char[] {
'\r',
'\n' }, StringSplitOptions.RemoveEmptyEntries);
643 SortedDictionary<int, bool> Ports =
new SortedDictionary<int, bool>();
645 foreach (
string Row
in Rows)
647 if (
int.TryParse(Row, out
int i))
651 if (!Ports.ContainsKey(80))
653 if (Ports.ContainsKey(8080))
655 else if (Ports.ContainsKey(8081))
657 else if (Ports.ContainsKey(8082))
659 else if (Ports.ContainsKey(443))
661 else if (Ports.ContainsKey(8088))
670 Session.Log(
"Unable to get opened ports. Error reported: " + ex.Message);
673 StartPage = Protocol +
"://localhost" + Port +
"/" + StartPage;
674 Session.Log(
"Start Page: " + StartPage);
676 Process.Start(StartPage);
677 Session.Log(
"Browser started.");
681 Session.Log(
"Unable to start browser. Error reported: " + ex.Message);
684 return ActionResult.Success;
687 public static ActionResult WaitAllModulesStarted(Session Session)
689 Session.Log(
"Waiting for all modules to start.");
692 DateTime Start = DateTime.Now;
695 Session.Log(
"Waiting for service to start.");
701 using (Mutex RunningServer =
new Mutex(
false,
"Waher.IoTGateway.Running"))
703 Running = !RunningServer.WaitOne(1000);
706 RunningServer.ReleaseMutex();
712 while (!Running && (DateTime.Now - Start).TotalSeconds < 30);
716 Session.Log(
"Could not detect a start of service. Cancelling wait and continuing.");
717 return ActionResult.Success;
720 Session.Log(
"Waiting for service startup procedure to complete.");
722 using (Mutex StartingServer =
new Mutex(
false,
"Waher.IoTGateway.Starting"))
724 if (StartingServer.WaitOne(120000))
726 StartingServer.ReleaseMutex();
727 Session.Log(
"All modules started.");
730 Session.Log(
"Modules takes too long to start. Cancelling wait and continuing.");
735 Session.Log(
"Unable to wait for all modules to start. The following error was reported: " + ex.Message);
738 return ActionResult.Success;
742 public static ActionResult BeforeUninstallEvent(Session Session)
744 Session.Log(
"Sending BeforeUninstall event.");
747 using (ServiceController ServiceController =
new ServiceController(
"IoT Gateway Service"))
749 ServiceController.ExecuteCommand(128);
754 Session.Log(
"Unable to send event. The following error was reported: " + ex.Message);
757 return ActionResult.Success;
761 public static ActionResult InstallManifest(Session Session)
763 string ManifestFile = Path.Combine(Session[
"INSTALLDIR"], Session[
"ManifestFile"]);
764 string ServerApplication = Path.Combine(Session[
"INSTALLDIR"],
"Waher.IoTGateway.Svc.dll");
765 string ProgramDataFolder = Session[
"APPDATADIR"];
767 Session.Log(
"Installing module: " + ManifestFile);
768 Session.Log(
"Server application: " + ServerApplication);
769 Session.Log(
"Program data folder: " + ProgramDataFolder);
773 Install(Session, ManifestFile, ServerApplication, ProgramDataFolder);
774 return ActionResult.Success;
778 Session.Log(ex.Message);
779 return ActionResult.Failure;
784 public static ActionResult StopServiceAndUninstallManifest(Session Session)
786 ActionResult Result = StopService(Session);
787 if (Result != ActionResult.Success)
790 return UninstallManifest(Session);
794 public static ActionResult UninstallManifest(Session Session)
796 string ManifestFile = Path.Combine(Session[
"INSTALLDIR"], Session[
"ManifestFile"]);
797 string ServerApplication = Path.Combine(Session[
"INSTALLDIR"],
"Waher.IoTGateway.Svc.dll");
798 string ProgramDataFolder = Session[
"APPDATADIR"];
800 Session.Log(
"Uninstalling module: " + ManifestFile);
801 Session.Log(
"Server application: " + ServerApplication);
802 Session.Log(
"Program data folder: " + ProgramDataFolder);
806 Uninstall(Session, ManifestFile, ServerApplication, ProgramDataFolder,
true);
810 Session.Log(ex.Message);
813 return ActionResult.Success;
816 #region From Waher.Utility.Install
818 private static AssemblyName GetAssemblyName(
string ServerApplication)
820 if (ServerApplication.EndsWith(
".exe", StringComparison.CurrentCultureIgnoreCase))
821 ServerApplication = ServerApplication.Substring(0, ServerApplication.Length - 4) +
".dll";
823 return AssemblyName.GetAssemblyName(ServerApplication);
826 private static void Install(Session Session,
string ManifestFile,
string ServerApplication,
string ProgramDataFolder)
834 if (
string.IsNullOrEmpty(ManifestFile))
835 throw new Exception(
"Missing manifest file.");
837 if (
string.IsNullOrEmpty(ProgramDataFolder))
839 ProgramDataFolder = Path.Combine(Environment.GetFolderPath(SpecialFolder.CommonApplicationData),
"IoT Gateway");
843 Session.Log(
"Using default program data folder: " + ProgramDataFolder);
846 if (
string.IsNullOrEmpty(ServerApplication))
847 throw new Exception(
"Missing server application.");
849 if (!File.Exists(ServerApplication))
850 throw new Exception(
"Server application not found: " + ServerApplication);
852 Session.Log(
"Getting assembly name of server.");
853 AssemblyName ServerName = GetAssemblyName(ServerApplication);
854 Session.Log(
"Server assembly name: " + ServerName.ToString());
856 string DepsJsonFileName;
858 int i = ServerApplication.LastIndexOf(
'.');
860 DepsJsonFileName = ServerApplication;
862 DepsJsonFileName = ServerApplication.Substring(0, i);
864 DepsJsonFileName +=
".deps.json";
866 Session.Log(
"deps.json file name: " + DepsJsonFileName);
868 if (!File.Exists(DepsJsonFileName))
869 throw new Exception(
"Invalid server executable. No corresponding deps.json file found.");
871 Session.Log(
"Opening " + DepsJsonFileName);
873 string s = File.ReadAllText(DepsJsonFileName);
875 Session.Log(
"Parsing " + DepsJsonFileName);
877 if (!(
JSON.
Parse(s) is Dictionary<string, object> Deps))
878 throw new Exception(
"Invalid deps.json file. Unable to install.");
880 Session.Log(
"Loading manifest file.");
882 XmlDocument Manifest =
new XmlDocument()
884 PreserveWhitespace =
true
886 Manifest.Load(ManifestFile);
888 XmlElement Module = Manifest[
"Module"];
889 string SourceFolder = Path.GetDirectoryName(ManifestFile);
890 string AppFolder = Path.GetDirectoryName(ServerApplication);
891 string DestManifestFileName = Path.Combine(AppFolder, Path.GetFileName(ManifestFile));
893 CopyFileIfNewer(Session, ManifestFile, DestManifestFileName,
null,
false);
895 Session.Log(
"Source folder: " + SourceFolder);
896 Session.Log(
"App folder: " + AppFolder);
898 foreach (XmlNode N
in Module.ChildNodes)
900 if (N is XmlElement E && E.LocalName ==
"Assembly")
902 KeyValuePair<string, string> FileNames = GetFileName(E, SourceFolder);
903 string FileName = FileNames.Key;
904 string SourceFileName = FileNames.Value;
906 if (CopyFileIfNewer(Session, SourceFileName, Path.Combine(AppFolder, FileName),
null,
true))
908 if (FileName.EndsWith(
".dll", StringComparison.CurrentCultureIgnoreCase))
910 string PdbFileName = FileName.Substring(0, FileName.Length - 4) +
".pdb";
911 if (File.Exists(PdbFileName))
912 CopyFileIfNewer(Session, Path.Combine(SourceFolder, PdbFileName), Path.Combine(AppFolder, PdbFileName),
null,
true);
916 Assembly A = Assembly.LoadFrom(SourceFileName);
917 AssemblyName AN = A.GetName();
919 if (!(Deps is
null) && Deps.TryGetValue(
"targets", out
object Obj) && Obj is Dictionary<string, object> Targets)
921 foreach (KeyValuePair<string, object> P
in Targets)
923 if (P.Value is Dictionary<string, object> Target)
925 foreach (KeyValuePair<string, object> P2
in Target)
927 if (P2.Key.StartsWith(ServerName.Name +
"/") &&
928 P2.Value is Dictionary<string, object> App &&
929 App.TryGetValue(
"dependencies", out
object Obj2) &&
930 Obj2 is Dictionary<string, object> Dependencies)
932 Dependencies[AN.Name] = AN.Version.ToString();
937 Dictionary<string, object> Dependencies2 =
new Dictionary<string, object>();
939 foreach (AssemblyName Dependency
in A.GetReferencedAssemblies())
940 Dependencies2[Dependency.Name] = Dependency.Version.ToString();
942 Dictionary<string, object> Runtime =
new Dictionary<string, object>()
944 { Path.GetFileName(SourceFileName),
new Dictionary<string,object>() }
947 Target[AN.Name +
"/" + AN.Version.ToString()] =
new Dictionary<string, object>()
949 {
"dependencies", Dependencies2 },
950 {
"runtime", Runtime }
956 if (!(Deps is
null) && Deps.TryGetValue(
"libraries", out
object Obj3) && Obj3 is Dictionary<string, object> Libraries)
958 foreach (KeyValuePair<string, object> P
in Libraries)
960 if (P.Key.StartsWith(AN.Name +
"/"))
962 Libraries.Remove(P.Key);
967 Libraries[AN.Name +
"/" + AN.Version.ToString()] =
new Dictionary<string, object>()
969 {
"type",
"project" },
970 {
"serviceable",
false },
971 {
"sha512", string.Empty }
978 CopyContent(Session, SourceFolder, AppFolder, ProgramDataFolder, Module);
980 Session.Log(
"Encoding JSON");
986 typeof(
JSON).Assembly);
991 Session.Log(
"Writing " + DepsJsonFileName);
992 File.WriteAllText(DepsJsonFileName, s, Encoding.UTF8);
995 private static bool CopyFileIfNewer(Session Session,
string From,
string To,
string To2,
bool OnlyIfNewer)
997 if (!File.Exists(From))
998 throw new FileNotFoundException(
"File not found: " + From);
1000 bool Copy1 = From != To;
1002 if (Copy1 && OnlyIfNewer && File.Exists(To))
1004 DateTime ToTP = File.GetLastWriteTimeUtc(To);
1005 DateTime FromTP = File.GetLastWriteTimeUtc(From);
1009 Session.Log(
"Skipping file. Destination folder contains newer version: " + From);
1016 Session.Log(
"Copying " + From +
" to " + To);
1017 File.Copy(From, To,
true);
1020 if (!
string.IsNullOrEmpty(To2))
1022 bool Copy2 = From != To2;
1024 if (Copy2 && OnlyIfNewer && File.Exists(To2))
1026 DateTime ToTP = File.GetLastWriteTimeUtc(To2);
1027 DateTime FromTP = File.GetLastWriteTimeUtc(From);
1031 Session.Log(
"Skipping file. Destination folder contains newer version: " + From);
1038 Session.Log(
"Copying " + From +
" to " + To2);
1039 File.Copy(From, To2,
true);
1046 private enum CopyOptions
1052 private static void CopyContent(Session Session,
string SourceFolder,
string AppFolder,
string DataFolder, XmlElement Parent)
1054 foreach (XmlNode N
in Parent.ChildNodes)
1056 if (N is XmlElement E)
1058 switch (E.LocalName)
1061 KeyValuePair<string, string> FileNames;
1065 FileNames = GetFileName(E, SourceFolder);
1067 catch (FileNotFoundException)
1073 string FileName = FileNames.Key;
1074 string SourceFileName = FileNames.Value;
1075 CopyOptions CopyOptions =
XML.
Attribute(E,
"copy", CopyOptions.IfNewer);
1077 Session.Log(
"Content file: " + FileName);
1079 if (!
string.IsNullOrEmpty(DataFolder) && !Directory.Exists(DataFolder))
1081 Session.Log(
"Creating folder " + DataFolder +
".");
1082 Directory.CreateDirectory(DataFolder);
1085 if (!
string.IsNullOrEmpty(AppFolder) && !Directory.Exists(AppFolder))
1087 Session.Log(
"Creating folder " + AppFolder +
".");
1088 Directory.CreateDirectory(AppFolder);
1093 CopyFileIfNewer(Session, SourceFileName,
1094 Path.Combine(DataFolder, FileName),
1095 Path.Combine(AppFolder, FileName),
1096 CopyOptions == CopyOptions.IfNewer);
1098 catch (FileNotFoundException)
1107 string SourceFolder2 = Path.Combine(SourceFolder, Name);
1108 string AppFolder2 = Path.Combine(AppFolder, Name);
1109 string DataFolder2 = Path.Combine(DataFolder, Name);
1111 Session.Log(
"Folder: " + Name,
1112 new KeyValuePair<string, object>(
"Source", SourceFolder2),
1113 new KeyValuePair<string, object>(
"App", AppFolder2),
1114 new KeyValuePair<string, object>(
"Data", DataFolder2));
1116 CopyContent(Session, SourceFolder2, AppFolder2, DataFolder2, E);
1122 FileNames = GetFileName(E, SourceFolder);
1124 catch (FileNotFoundException)
1130 FileName = FileNames.Key;
1131 SourceFileName = FileNames.Value;
1133 Session.Log(
"External program file: " + FileName);
1135 if (!
string.IsNullOrEmpty(AppFolder) && !Directory.Exists(AppFolder))
1137 Session.Log(
"Creating folder " + AppFolder +
".");
1138 Directory.CreateDirectory(AppFolder);
1143 CopyFileIfNewer(Session, SourceFileName, Path.Combine(AppFolder, FileName),
null,
false);
1145 catch (FileNotFoundException)
1152 Environment.SpecialFolder SpecialFolder =
XML.
Attribute(E,
"folder", Environment.SpecialFolder.ProgramFiles);
1155 SourceFolder2 = Path.Combine(SourceFolder, Name);
1156 AppFolder2 = GetFolderPath(SpecialFolder, Name);
1157 DataFolder2 = Path.Combine(DataFolder, Name);
1159 Session.Log(
"Folder: " + Name,
1160 new KeyValuePair<string, object>(
"Source", SourceFolder2),
1161 new KeyValuePair<string, object>(
"App", AppFolder2),
1162 new KeyValuePair<string, object>(
"Data", DataFolder2));
1164 CopyContent(Session, SourceFolder2, AppFolder2, DataFolder2, E);
1171 private static string GetFolderPath(SpecialFolder SpecialFolder,
string Name)
1173 string s = Environment.GetFolderPath(SpecialFolder);
1174 string Result = Path.Combine(s, Name);
1176 if (Directory.Exists(Result))
1179 if (s.EndsWith(
"(x86)"))
1181 s = s.Substring(0, s.Length - 5).TrimEnd();
1182 string Result2 = Path.Combine(s, Name);
1184 if (Directory.Exists(Result2))
1191 private static void Uninstall(Session Session,
string ManifestFile,
string ServerApplication,
string ProgramDataFolder,
bool Remove)
1197 if (
string.IsNullOrEmpty(ManifestFile))
1198 throw new Exception(
"Missing manifest file.");
1200 if (
string.IsNullOrEmpty(ServerApplication))
1201 throw new Exception(
"Missing server application.");
1203 if (
string.IsNullOrEmpty(ProgramDataFolder))
1205 ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"IoT Gateway");
1209 Session.Log(
"Using default program data folder: " + ProgramDataFolder);
1212 if (!File.Exists(ServerApplication))
1213 throw new Exception(
"Server application not found: " + ServerApplication);
1215 Session.Log(
"Getting assembly name of server.");
1216 AssemblyName ServerName = GetAssemblyName(ServerApplication);
1217 Session.Log(
"Server assembly name: " + ServerName.ToString());
1219 string DepsJsonFileName;
1221 int i = ServerApplication.LastIndexOf(
'.');
1223 DepsJsonFileName = ServerApplication;
1225 DepsJsonFileName = ServerApplication.Substring(0, i);
1227 DepsJsonFileName +=
".deps.json";
1229 Session.Log(
"deps.json file name: " + DepsJsonFileName);
1231 if (!File.Exists(DepsJsonFileName))
1232 throw new Exception(
"Invalid server executable. No corresponding deps.json file found.");
1234 Session.Log(
"Opening " + DepsJsonFileName);
1236 string s = File.ReadAllText(DepsJsonFileName);
1238 Session.Log(
"Parsing " + DepsJsonFileName);
1240 if (!(
JSON.
Parse(s) is Dictionary<string, object> Deps))
1241 throw new Exception(
"Invalid deps.json file. Unable to install.");
1243 Session.Log(
"Loading manifest file.");
1245 XmlDocument Manifest =
new XmlDocument();
1246 Manifest.Load(ManifestFile);
1248 XmlElement Module = Manifest[
"Module"];
1249 string AppFolder = Path.GetDirectoryName(ServerApplication);
1251 Session.Log(
"App folder: " + AppFolder);
1253 foreach (XmlNode N
in Module.ChildNodes)
1255 if (N is XmlElement E && E.LocalName ==
"Assembly")
1257 KeyValuePair<string, string> FileNames = GetFileName(E, AppFolder);
1258 string FileName = FileNames.Key;
1259 string AppFileName = FileNames.Value;
1261 Assembly A = Assembly.LoadFrom(AppFileName);
1262 AssemblyName AN = A.GetName();
1263 string Key = AN.Name +
"/" + AN.Version.ToString();
1265 if (!(Deps is
null) && Deps.TryGetValue(
"targets", out
object Obj) && Obj is Dictionary<string, object> Targets)
1267 Targets.Remove(Key);
1269 foreach (KeyValuePair<string, object> P
in Targets)
1271 if (P.Value is Dictionary<string, object> Target)
1273 foreach (KeyValuePair<string, object> P2
in Target)
1275 if (P2.Key.StartsWith(ServerName.Name +
"/") &&
1276 P2.Value is Dictionary<string, object> App &&
1277 App.TryGetValue(
"dependencies", out
object Obj2) &&
1278 Obj2 is Dictionary<string, object> Dependencies)
1280 Dependencies.Remove(AN.Name);
1288 if (!(Deps is
null) && Deps.TryGetValue(
"libraries", out
object Obj3) && Obj3 is Dictionary<string, object> Libraries)
1290 foreach (KeyValuePair<string, object> P
in Libraries)
1292 if (P.Key.StartsWith(AN.Name +
"/"))
1294 Libraries.Remove(P.Key);
1302 RemoveFile(Session, AppFileName);
1303 if (FileName.EndsWith(
".dll", StringComparison.CurrentCultureIgnoreCase))
1305 string PdbFileName = FileName.Substring(0, FileName.Length - 4) +
".pdb";
1306 RemoveFile(Session, PdbFileName);
1312 Session.Log(
"Encoding JSON");
1318 typeof(
JSON).Assembly);
1323 Session.Log(
"Writing " + DepsJsonFileName);
1324 File.WriteAllText(DepsJsonFileName, s, Encoding.UTF8);
1326 if (Path.GetDirectoryName(ManifestFile) == AppFolder)
1327 RemoveFile(Session, ManifestFile);
1330 private static bool RemoveFile(Session Session,
string FileName)
1332 if (!File.Exists(FileName))
1335 Session.Log(
"Deleting " + FileName);
1338 File.Delete(FileName);
1340 catch (Exception ex)
1342 Session.Log(
"Unable to delete file. Error reported: " + ex.Message);
1348 private static KeyValuePair<string, string> GetFileName(XmlElement E,
string ReferenceFolder)
1351 string AbsFileName = Path.Combine(ReferenceFolder, FileName);
1352 if (File.Exists(AbsFileName))
1353 return new KeyValuePair<string, string>(FileName, AbsFileName);
1356 if (
string.IsNullOrEmpty(AltFolder))
1357 throw new FileNotFoundException(
"File not found: " + AbsFileName);
1359 AbsFileName = Path.Combine(AltFolder, FileName);
1360 if (File.Exists(AbsFileName))
1361 return new KeyValuePair<string, string>(FileName, AbsFileName);
1363 throw new FileNotFoundException(
"File not found: " + AbsFileName);
Helps with common JSON-related tasks.
static object Parse(string Json)
Parses a JSON string.
static string Encode(string s)
Encodes a string for inclusion in JSON.
Helps with common XML-related tasks.
static string Attribute(XmlElement E, string Name)
Gets the value of an XML attribute.
Static class that dynamically manages types and interfaces available in the runtime environment.
static bool IsInitialized
If the inventory has been initialized.
static void Initialize(params Assembly[] Assemblies)
Initializes the inventory engine, registering types and interfaces available in Assemblies .