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);
1012 Msg =
"newer version";
1014 Msg =
"same version";
1016 Msg =
"Skipping file. Destination folder contains " + Msg +
": " + From;
1025 Session.Log(
"Copying " + From +
" to " + To);
1026 File.Copy(From, To,
true);
1029 if (!
string.IsNullOrEmpty(To2))
1031 bool Copy2 = From != To2;
1033 if (Copy2 && OnlyIfNewer && File.Exists(To2))
1035 DateTime ToTP = File.GetLastWriteTimeUtc(To2);
1036 DateTime FromTP = File.GetLastWriteTimeUtc(From);
1043 Msg =
"newer version";
1045 Msg =
"same version";
1047 Msg =
"Skipping file. Destination folder contains " + Msg +
": " + From;
1056 Session.Log(
"Copying " + From +
" to " + To2);
1057 File.Copy(From, To2,
true);
1064 private enum CopyOptions
1070 private static void CopyContent(Session Session,
string SourceFolder,
string AppFolder,
string DataFolder, XmlElement Parent)
1072 foreach (XmlNode N
in Parent.ChildNodes)
1074 if (N is XmlElement E)
1076 switch (E.LocalName)
1079 KeyValuePair<string, string> FileNames;
1083 FileNames = GetFileName(E, SourceFolder);
1085 catch (FileNotFoundException)
1091 string FileName = FileNames.Key;
1092 string SourceFileName = FileNames.Value;
1093 CopyOptions CopyOptions =
XML.
Attribute(E,
"copy", CopyOptions.IfNewer);
1095 Session.Log(
"Content file: " + FileName);
1097 if (!
string.IsNullOrEmpty(DataFolder) && !Directory.Exists(DataFolder))
1099 Session.Log(
"Creating folder " + DataFolder +
".");
1100 Directory.CreateDirectory(DataFolder);
1103 if (!
string.IsNullOrEmpty(AppFolder) && !Directory.Exists(AppFolder))
1105 Session.Log(
"Creating folder " + AppFolder +
".");
1106 Directory.CreateDirectory(AppFolder);
1111 CopyFileIfNewer(Session, SourceFileName,
1112 Path.Combine(DataFolder, FileName),
1113 Path.Combine(AppFolder, FileName),
1114 CopyOptions == CopyOptions.IfNewer);
1116 catch (FileNotFoundException)
1125 string SourceFolder2 = Path.Combine(SourceFolder, Name);
1126 string AppFolder2 = Path.Combine(AppFolder, Name);
1127 string DataFolder2 = Path.Combine(DataFolder, Name);
1129 Session.Log(
"Folder: " + Name,
1130 new KeyValuePair<string, object>(
"Source", SourceFolder2),
1131 new KeyValuePair<string, object>(
"App", AppFolder2),
1132 new KeyValuePair<string, object>(
"Data", DataFolder2));
1134 CopyContent(Session, SourceFolder2, AppFolder2, DataFolder2, E);
1140 FileNames = GetFileName(E, SourceFolder);
1142 catch (FileNotFoundException)
1148 FileName = FileNames.Key;
1149 SourceFileName = FileNames.Value;
1151 Session.Log(
"External program file: " + FileName);
1153 if (!
string.IsNullOrEmpty(AppFolder) && !Directory.Exists(AppFolder))
1155 Session.Log(
"Creating folder " + AppFolder +
".");
1156 Directory.CreateDirectory(AppFolder);
1161 CopyFileIfNewer(Session, SourceFileName, Path.Combine(AppFolder, FileName),
null,
false);
1163 catch (FileNotFoundException)
1170 Environment.SpecialFolder SpecialFolder =
XML.
Attribute(E,
"folder", Environment.SpecialFolder.ProgramFiles);
1173 SourceFolder2 = Path.Combine(SourceFolder, Name);
1174 AppFolder2 = GetFolderPath(SpecialFolder, Name);
1175 DataFolder2 = Path.Combine(DataFolder, Name);
1177 Session.Log(
"Folder: " + Name,
1178 new KeyValuePair<string, object>(
"Source", SourceFolder2),
1179 new KeyValuePair<string, object>(
"App", AppFolder2),
1180 new KeyValuePair<string, object>(
"Data", DataFolder2));
1182 CopyContent(Session, SourceFolder2, AppFolder2, DataFolder2, E);
1189 private static string GetFolderPath(SpecialFolder SpecialFolder,
string Name)
1191 string s = Environment.GetFolderPath(SpecialFolder);
1192 string Result = Path.Combine(s, Name);
1194 if (Directory.Exists(Result))
1197 if (s.EndsWith(
"(x86)"))
1199 s = s.Substring(0, s.Length - 5).TrimEnd();
1200 string Result2 = Path.Combine(s, Name);
1202 if (Directory.Exists(Result2))
1209 private static void Uninstall(Session Session,
string ManifestFile,
string ServerApplication,
string ProgramDataFolder,
bool Remove)
1215 if (
string.IsNullOrEmpty(ManifestFile))
1216 throw new Exception(
"Missing manifest file.");
1218 if (
string.IsNullOrEmpty(ServerApplication))
1219 throw new Exception(
"Missing server application.");
1221 if (
string.IsNullOrEmpty(ProgramDataFolder))
1223 ProgramDataFolder = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData),
"IoT Gateway");
1227 Session.Log(
"Using default program data folder: " + ProgramDataFolder);
1230 if (!File.Exists(ServerApplication))
1231 throw new Exception(
"Server application not found: " + ServerApplication);
1233 Session.Log(
"Getting assembly name of server.");
1234 AssemblyName ServerName = GetAssemblyName(ServerApplication);
1235 Session.Log(
"Server assembly name: " + ServerName.ToString());
1237 string DepsJsonFileName;
1239 int i = ServerApplication.LastIndexOf(
'.');
1241 DepsJsonFileName = ServerApplication;
1243 DepsJsonFileName = ServerApplication.Substring(0, i);
1245 DepsJsonFileName +=
".deps.json";
1247 Session.Log(
"deps.json file name: " + DepsJsonFileName);
1249 if (!File.Exists(DepsJsonFileName))
1250 throw new Exception(
"Invalid server executable. No corresponding deps.json file found.");
1252 Session.Log(
"Opening " + DepsJsonFileName);
1254 string s = File.ReadAllText(DepsJsonFileName);
1256 Session.Log(
"Parsing " + DepsJsonFileName);
1258 if (!(
JSON.
Parse(s) is Dictionary<string, object> Deps))
1259 throw new Exception(
"Invalid deps.json file. Unable to install.");
1261 Session.Log(
"Loading manifest file.");
1263 XmlDocument Manifest =
new XmlDocument();
1264 Manifest.Load(ManifestFile);
1266 XmlElement Module = Manifest[
"Module"];
1267 string AppFolder = Path.GetDirectoryName(ServerApplication);
1269 Session.Log(
"App folder: " + AppFolder);
1271 foreach (XmlNode N
in Module.ChildNodes)
1273 if (N is XmlElement E && E.LocalName ==
"Assembly")
1275 KeyValuePair<string, string> FileNames = GetFileName(E, AppFolder);
1276 string FileName = FileNames.Key;
1277 string AppFileName = FileNames.Value;
1279 Assembly A = Assembly.LoadFrom(AppFileName);
1280 AssemblyName AN = A.GetName();
1281 string Key = AN.Name +
"/" + AN.Version.ToString();
1283 if (!(Deps is
null) && Deps.TryGetValue(
"targets", out
object Obj) && Obj is Dictionary<string, object> Targets)
1285 Targets.Remove(Key);
1287 foreach (KeyValuePair<string, object> P
in Targets)
1289 if (P.Value is Dictionary<string, object> Target)
1291 foreach (KeyValuePair<string, object> P2
in Target)
1293 if (P2.Key.StartsWith(ServerName.Name +
"/") &&
1294 P2.Value is Dictionary<string, object> App &&
1295 App.TryGetValue(
"dependencies", out
object Obj2) &&
1296 Obj2 is Dictionary<string, object> Dependencies)
1298 Dependencies.Remove(AN.Name);
1306 if (!(Deps is
null) && Deps.TryGetValue(
"libraries", out
object Obj3) && Obj3 is Dictionary<string, object> Libraries)
1308 foreach (KeyValuePair<string, object> P
in Libraries)
1310 if (P.Key.StartsWith(AN.Name +
"/"))
1312 Libraries.Remove(P.Key);
1320 RemoveFile(Session, AppFileName);
1321 if (FileName.EndsWith(
".dll", StringComparison.CurrentCultureIgnoreCase))
1323 string PdbFileName = FileName.Substring(0, FileName.Length - 4) +
".pdb";
1324 RemoveFile(Session, PdbFileName);
1330 Session.Log(
"Encoding JSON");
1336 typeof(
JSON).Assembly);
1341 Session.Log(
"Writing " + DepsJsonFileName);
1342 File.WriteAllText(DepsJsonFileName, s, Encoding.UTF8);
1344 if (Path.GetDirectoryName(ManifestFile) == AppFolder)
1345 RemoveFile(Session, ManifestFile);
1348 private static bool RemoveFile(Session Session,
string FileName)
1350 if (!File.Exists(FileName))
1353 Session.Log(
"Deleting " + FileName);
1356 File.Delete(FileName);
1358 catch (Exception ex)
1360 Session.Log(
"Unable to delete file. Error reported: " + ex.Message);
1366 private static KeyValuePair<string, string> GetFileName(XmlElement E,
string ReferenceFolder)
1369 string AbsFileName = Path.Combine(ReferenceFolder, FileName);
1370 if (File.Exists(AbsFileName))
1371 return new KeyValuePair<string, string>(FileName, AbsFileName);
1374 if (
string.IsNullOrEmpty(AltFolder))
1375 throw new FileNotFoundException(
"File not found: " + AbsFileName);
1377 AbsFileName = Path.Combine(AltFolder, FileName);
1378 if (File.Exists(AbsFileName))
1379 return new KeyValuePair<string, string>(FileName, AbsFileName);
1381 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 .