/// <summary> /// Load the assemblies that contain the classes that we will serve via COM. These will be located in the same folder as our executable. /// </summary> /// <returns></returns> private static bool LoadComObjectAssemblies() { s_ComObjectAssys = new ArrayList(); s_ComObjectTypes = new ArrayList(); // put everything into one folder, the same as the server. string assyPath = Assembly.GetEntryAssembly().Location; assyPath = Path.GetDirectoryName(assyPath); DirectoryInfo d = new DirectoryInfo(assyPath); foreach (FileInfo fi in d.GetFiles("*.dll")) { TL.LogMessage("LoadComObjectAssemblies", $"Found file: {fi.FullName}"); string aPath = fi.FullName; // // First try to load the assembly and get the types for // the class and the class factory. If this doesn't work ???? // try { Assembly so = Assembly.LoadFrom(aPath); //PWGS Get the types in the assembly Type[] types = so.GetTypes(); foreach (Type type in types) { // PWGS Now checks the type rather than the assembly // Check to see if the type has the ServedClassName attribute, only use it if it does. MemberInfo info = type; object[] attrbutes = info.GetCustomAttributes(typeof(ServedClassNameAttribute), false); if (attrbutes.Length > 0) { TL.LogMessage("LoadComObjectAssemblies", $"Type: {type.Name} has ServedClassAttribute"); s_ComObjectTypes.Add(type); //PWGS - much simpler s_ComObjectAssys.Add(so); } } } catch (BadImageFormatException) { TL.LogMessage("LoadComObjectAssemblies", $"Preceding type is not an assembly"); // Probably an attempt to load a Win32 DLL (i.e. not a .net assembly) // Just swallow the exception and continue to the next item. continue; } catch (Exception e) { MessageBox.Show("Failed to load served COM class assembly " + fi.Name + " - " + e.Message, LOCAL_SERVER_NAME, MessageBoxButtons.OK, MessageBoxIcon.Stop); TL.LogMessageCrLf("LoadComObjectAssemblies", $"Exception while getting types: {e.ToString()}"); return(false); } } return(true); }
private static void Client_DownloadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e) { try // Ignore any errors here { if (e.Cancelled) { if (TL != null) { TL.LogMessage("Download Status", string.Format("Download timed out")); } } else if (e.Error != null) { downloadError = e.Error; if (TL != null) { TL.LogMessageCrLf("Download Error", string.Format("Error: {0}", downloadError.Message)); } } else { if (TL != null) { TL.LogMessage("Download Status", string.Format("Download Completed OK,")); } } DownloadComplete = true; } catch { } }
static void Main(string[] args) { AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); try { TL = new TraceLogger("", "SetFireWallRules"); TL.Enabled = true; Version version = Assembly.GetEntryAssembly().GetName().Version; TL.LogMessage("SetFireWallRules", string.Format("Version {0}, Run on {1}", version.ToString(), DateTime.Now.ToString("dddd d MMMM yyyy HH:mm:ss"))); TL.BlankLine(); // Add the event handler for handling non-UI thread exceptions to the event. CommandLine.Parser.Default.ParseArguments <Options>(args) .WithParsed <Options>(opts => ProcessOptions(opts)) .WithNotParsed <Options>((errs) => HandleParseError(errs)); TL.Enabled = false; TL = null; } catch (Exception ex) { TraceLogger TL = new TraceLogger("SetFireWallRulesMainException") { Enabled = true }; TL.LogMessageCrLf("Main", "Unhandled exception: " + ex.ToString()); TL.Enabled = false; TL.Dispose(); TL = null; } }
internal static void LogMessageCrLf(string identifier, string message, params object[] args) { if (started) { Log.LogFinish(" ..."); } log.LogMessageCrLf(identifier, string.Format(message, args)); }
//log messages and send to screen when appropriate public static void LogMessage(string section, string logMessage) { // Make sure none of these failing stops the overall migration process try { Console.WriteLine(logMessage); } catch { } try { TL.LogMessageCrLf(section, logMessage); // The CrLf version is used in order properly to format exception messages } catch { } try { EventLogCode.LogEvent("UninstallAscom", logMessage, EventLogEntryType.Information, GlobalConstants.EventLogErrors.UninstallASCOMInfo, ""); } catch { } }
/// <summary> /// Log a message making sure that the TraceLogger exists. /// This is to work round an issue with the form timers that seem to fire after the form and trace logger have been disposed /// </summary> /// <param name="source"></param> /// <param name="message"></param> private void LogMessage(string source, string message) { try { if (!(TL == null)) { TL.LogMessageCrLf(source, message); } } catch { } // Ignore errors here }
/// <summary> /// Initializes a new instance of the <see cref="Simulator"/> class. /// Must be public for COM registration. /// </summary> public CoverCalibrator() { try { // Initialise the driver trace logger TL = new TraceLogger("", "CoverCalibratorSimulator"); // Read device configuration from the ASCOM Profile store, this also sets the trace logger enabled state ReadProfile(); TL.LogMessage("CoverCalibrator", "Starting initialisation"); // Initialise remaining components utilities = new Util(); calibratorTimer = new System.Timers.Timer(); if (CalibratorStablisationTimeValue > 0.0) { calibratorTimer.Interval = Convert.ToInt32(CalibratorStablisationTimeValue * 1000.0); // Set the timer interval in milliseconds from the stabilisation time in seconds } calibratorTimer.Elapsed += CalibratorTimer_Tick; TL.LogMessage("CoverCalibrator", $"Set calibrator timer to: {calibratorTimer.Interval}ms."); coverTimer = new System.Timers.Timer(); if (CoverOpeningTimeValue > 0.0) { coverTimer.Interval = Convert.ToInt32(CoverOpeningTimeValue * 1000.0); // Set the timer interval in milliseconds from the opening time in seconds } coverTimer.Elapsed += CoverTimer_Tick; TL.LogMessage("CoverCalibrator", $"Set cover timer to: {coverTimer.Interval}ms."); // Initialise internal start-up values IsConnected = false; // Initialise connected to false brightnessValue = 0; // Set calibrator brightness to 0 i.e. off coverState = CoverStateInitialisationValue; // Set the cover state as set by the user calibratorState = CalibratorStateInitialisationValue; // Set the calibration state as set by the user TL.LogMessage("CoverCalibrator", "Completed initialisation"); } catch (Exception ex) { // Create a message to the user string message = $"Exception while creating CoverCalibrator simulator: \r\n{ex.ToString()}"; // Attempt to log the message try { TL.Enabled = true; TL.LogMessageCrLf("Initialisation", message); } catch { } // Ignore any errors while attempting to log the error // Display the error to the user MessageBox.Show(message, "ASCOM CoverCalibrator Simulator Exception", MessageBoxButtons.OK, MessageBoxIcon.Error); // Display the message top the user } }
private void AddAppID(string progID, string exeName, string sAPPID, DCOMAuthenticationLevel authenticationLevel) { RegistryKey rkCLSID = null; RegistryKey rkAPPID = null; RegistryKey rkAPPIDExe = null; try { LogMessage("AddAppID", "ProgID: " + progID + ", ExeName: " + exeName + ", Appid: " + sAPPID); int hr = CLSIDFromProgID(progID, out Guid gCLSID); string sCLSID = "{" + new GuidConverter().ConvertToString(gCLSID) + "}"; LogMessage("AddAppID", " CLSID: " + sCLSID); rkCLSID = Registry.ClassesRoot.OpenSubKey("CLSID\\" + sCLSID, RegistryKeyPermissionCheck.ReadWriteSubTree); LogMessage("AddAppID", string.Format("Registry key rkCLSID is null: {0}", rkCLSID == null)); rkCLSID.SetValue("AppId", sAPPID); rkAPPID = Registry.ClassesRoot.CreateSubKey("APPID\\" + sAPPID, RegistryKeyPermissionCheck.ReadWriteSubTree); rkAPPID.SetValue("", rkCLSID.GetValue("")); // Same description as class rkAPPID.SetValue("AppId", sAPPID); rkAPPID.SetValue("AuthenticationLevel", authenticationLevel, RegistryValueKind.DWord); // RPC_C_AUTHN_LEVEL_NONE if (exeName != "") // If want AppId\Exe.name { rkAPPIDExe = Registry.ClassesRoot.CreateSubKey("AppId\\" + exeName, RegistryKeyPermissionCheck.ReadWriteSubTree); rkAPPIDExe.SetValue("", rkCLSID.GetValue("")); // Same description as class rkAPPIDExe.SetValue("AppId", sAPPID); } LogMessage("AddAppID", "OK - Completed"); } catch (Exception ex) { errorCount += 1; LogMessage("AddAppID", string.Format("Failed to add AppID info for {0}", progID)); TL.LogMessageCrLf("AddAppID", "Exception: " + ex.ToString()); } finally { if (rkCLSID != null) { rkCLSID.Close(); } if (rkAPPID != null) { rkAPPID.Close(); } if (rkAPPIDExe != null) { rkAPPIDExe.Close(); } } }
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Exception exception = (Exception)e.ExceptionObject; TraceLogger TL = new TraceLogger("SetNetworkPemissionsException") { Enabled = true }; TL.LogMessageCrLf("Main", "Unhandled exception: " + exception.ToString()); TL.Enabled = false; TL.Dispose(); Environment.Exit(0); }
static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) { Exception exception = (Exception)e.ExceptionObject; TraceLogger TL = new TraceLogger("RemoteAccessServerException") { Enabled = true }; TL.LogMessageCrLf("Main", "Unhandled exception: " + exception.ToString()); Process.Start(TL.LogFileName); TL.Enabled = false; TL.Dispose(); Environment.Exit(0); }
public void TraceLogger_InstanceTests() { String logType = $"{GetType().Name}"; Console.WriteLine($"Starting Test: {logType}"); TraceLogger tl = new TraceLogger(logType); tl.Enabled = true; TraceLogger.Debug($"\tPath: {tl.FullPath}"); TraceLogger.Debug($"\tEnabled: {tl.Enabled}"); tl.LogMessage(nameof(TraceLogger_InstanceTests), $"\tPath: {tl.FullPath}"); tl.LogMessageCrLf(nameof(TraceLogger_InstanceTests), $"\tEnabled: {tl.Enabled}"); }
/// <summary> /// Initializes a new instance of the <see cref="Focuser"/> class. /// Must be public for COM registration. /// </summary> public Focuser() { try { TL = new TraceLogger("", "FocusSimulator"); TL.Enabled = RegistryCommonCode.GetBool(GlobalConstants.SIMULATOR_TRACE, GlobalConstants.SIMULATOR_TRACE_DEFAULT); TL.LogMessage("New", "Started"); //check to see if the profile is ok if (ValidateProfile()) { TL.LogMessage("New", "Validated OK"); KeepMoving = false; LastOffset = 0; RateOfChange = 1; MouseDownTime = DateTime.MaxValue; //Initialise to "don't accelerate" value RandomGenerator = new Random(); //Temperature fluctuation random generator LoadFocuserKeyValues(); TL.LogMessage("New", "Loaded Key Values"); //Handbox = new FocuserHandboxForm(this); //Handbox.Hide(); //TL.LogMessage("FocusSettingsForm", "Created Handbox"); // start a timer that monitors and moves the focuser _moveTimer = new System.Timers.Timer(); _moveTimer.Elapsed += new System.Timers.ElapsedEventHandler(MoveTimer_Tick); _moveTimer.Interval = 100; _moveTimer.Enabled = true; _lastTemp = Temperature; Target = _position; TL.LogMessage("New", "Started Simulation"); } else { TL.LogMessage("New", "Registering Profile"); RegisterWithProfile(); TL.LogMessage("New", "Registered OK"); } TL.LogMessage("New", "Completed"); } catch (Exception ex) { TL.LogMessageCrLf("New Exception", ex.ToString()); Console.WriteLine($"Focuser: {ex}"); } }
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { TraceLogger TL = new TraceLogger("RemoteAccessServerException") { Enabled = true }; TL.LogMessageCrLf("Main", "Thread exception: " + e.Exception.ToString()); Process.Start(TL.LogFileName); TL.Enabled = false; TL.Dispose(); //MessageBox.Show(e.Exception.Message, "Unhandled Thread Exception, see RemoteAccessServerException log for details."); Environment.Exit(0); }
public static string Encrypt(this string clearText, TraceLogger TL) { try { byte[] clearBytes = Encoding.UTF8.GetBytes(clearText); byte[] entropyBytes = Encoding.UTF8.GetBytes(GenerateEntropy()); byte[] encryptedBytes = ProtectedData.Protect(clearBytes, entropyBytes, dataProtectionScope); string encryptedText = Convert.ToBase64String(encryptedBytes); TL.LogMessage("Encrypt", encryptedText); return(encryptedText); } catch (Exception ex) { TL.LogMessageCrLf("Encrypt", ex.ToString()); return("Unable to encrypt this value"); } }
/// <summary> /// Crates a new instance of the NativeHelpers component /// </summary> /// <exception cref="HelperException">Thrown if the NativeHelpers support library DLL cannot be loaded</exception> public NativeHelpers() { int lastError; TL = new TraceLogger("NativeHelpers"); TL.Enabled = RegistryCommonCode.GetBool(GlobalConstants.TRACE_UTIL, GlobalConstants.TRACE_UTIL_DEFAULT); try { string VideoDllFile = null; System.Text.StringBuilder ReturnedPath = new System.Text.StringBuilder(260); //Find the root location of the common files directory containing the ASCOM support files. if (Is64Bit()) // 64bit application so find the 32bit folder location, usually Program Files (x86)\Common Files { VideoDllFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86) + VIDEOUTILS_DLL_LOCATION + VIDEOUTILS64_DLL_NAME; } else //32bit application so just go with the .NET returned value usually, Program Files\Common Files { VideoDllFile = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + VIDEOUTILS_DLL_LOCATION + VIDEOUTILS32_DLL_NAME; } TL.LogMessage("New", "Loading NativeHelpers library DLL: " + VideoDllFile); VideoDllHandle = LoadLibrary(VideoDllFile); lastError = Marshal.GetLastWin32Error(); if (VideoDllHandle != IntPtr.Zero) // Loaded successfully { TL.LogMessage("New", "Loaded NativeHelpers library OK"); } else // Did not load { TL.LogMessage("New", "Error loading NativeHelpers library: " + lastError.ToString("X8")); throw new HelperException("Error code returned from LoadLibrary when loading NativeHelpers library: " + lastError.ToString("X8")); } TL.LogMessage("NativeHelpers", "Created"); } catch (Exception ex) { TL.LogMessageCrLf("NativeHelpers ctor", ex.ToString()); } }
static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) { Version assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; // Create a trace logger and log the exception TraceLogger TL = new TraceLogger("DynamicClientThreadException") { Enabled = true }; TL.LogMessage("Main", string.Format("ASCOM Dynamic Client Manager - Thread exception. Version: {0}", assemblyVersion.ToString())); TL.LogMessageCrLf("Main", e.Exception.ToString()); // Display the exception in the default .txt editor and exit Process.Start(TL.LogFileName); TL.Enabled = false; TL.Dispose(); Environment.Exit(0); }
public static string Unencrypt(this string encryptedText, TraceLogger TL) { try { if (encryptedText == null) { return(""); // Deal with initial case where text has not yet been encrypted } byte[] encryptedBytes = Convert.FromBase64String(encryptedText); byte[] entropyBytes = Encoding.UTF8.GetBytes(GenerateEntropy()); byte[] clearBytes = ProtectedData.Unprotect(encryptedBytes, entropyBytes, dataProtectionScope); string clearText = Encoding.UTF8.GetString(clearBytes); TL.LogMessage("Unencrypt", encryptedText); return(clearText); } catch (Exception ex) { TL.LogMessageCrLf("Unencrypt", ex.ToString()); return("Unable to decrypt this value"); } }
/// <summary> /// Initialises the form /// </summary> public Form1(TraceLogger TLParameter) { try { InitializeComponent(); TL = TLParameter; // Save the supplied trace logger Version assemblyVersion = Assembly.GetExecutingAssembly().GetName().Version; LblVersionNumber.Text = "Version " + assemblyVersion.ToString(); TL.LogMessage("Initialise", string.Format("Application Version: {0}", assemblyVersion.ToString())); profile = new Profile(); remoteDrivers = new List <DriverRegistration>(); deviceTypeSummary = new Dictionary <string, int>(StringComparer.InvariantCultureIgnoreCase); // Create a dictionary using a case insensitive key comparer ReadConfiguration(); // Get the current configuration // Add event handlers for the number of devices numeric up-down controls NumCamera.ValueChanged += NumValueChanged; NumDome.ValueChanged += NumValueChanged; NumFilterWheel.ValueChanged += NumValueChanged; NumFocuser.ValueChanged += NumValueChanged; NumObservingConditions.ValueChanged += NumValueChanged; NumRotator.ValueChanged += NumValueChanged; NumSafetyMonitor.ValueChanged += NumValueChanged; NumSwitch.ValueChanged += NumValueChanged; NumTelescope.ValueChanged += NumValueChanged; TL.LogMessage("Initialise", string.Format("Initialisation completed")); } catch (Exception ex) { TL.LogMessageCrLf("initialise - Exception", ex.ToString()); MessageBox.Show("Sorry, en error occurred on start up, please report this error message on the ASCOM Talk forum hosted at Groups.Io.\r\n\n" + ex.Message, "ASCOM Dynamic Clients", MessageBoxButtons.OK, MessageBoxIcon.Error); DisableControls(false); // Disable all controls except exit } }
/// <summary> /// Lof an informational message /// </summary> /// <param name="section">Name of the code section that the message is from </param> /// <param name="logMessage">The message to record</param> static public void LogMessage(string section, string logMessage) { Console.WriteLine(logMessage); TL.LogMessageCrLf(section, logMessage); // The CrLf version is used in order properly to format exception messages EventLogCode.LogEvent("InstallTemplates", logMessage, EventLogEntryType.Information, GlobalConstants.EventLogErrors.InstallTemplatesInfo, ""); }
static void Main(string[] args) { // Add the event handler for handling UI thread exceptions to the event. Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); // Set the unhandled exception mode to force all exceptions to go through our handler. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // Add the event handler for handling non-UI thread exceptions to the event. AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); TL = new TraceLogger("", "DynamicClients"); TL.Enabled = true; try { string parameter = ""; // Initialise the supplied parameter to empty string if (args.Length > 0) { parameter = args[0]; // Copy any supplied parameter to the parameter variable } TL.LogMessage("Main", string.Format(@"Supplied parameter: ""{0}""", parameter)); parameter = parameter.TrimStart(' ', '-', '/', '\\'); // Remove any parameter prefixes and leading spaces parameter = parameter.TrimEnd(' '); // Remove any trailing spaces TL.LogMessage("Main", string.Format(@"Trimmed parameter: ""{0}""", parameter)); switch (parameter.ToUpperInvariant()) // Act on the supplied parameter, if any { case "": // Run the application in user interactive mode Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); TL.LogMessage("Main", "Starting application form"); Application.Run(new Form1(TL)); break; case "INSTALLERSETUP": // Called by the installer to create drivers on first time use TL.LogMessage("Main", "Running installer setup"); // Find if there are any driver files already installed, indicating that this is not a first time install string localServerPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86) + Form1.REMOTE_SERVER_PATH; string deviceType = "*"; string searchPattern = string.Format(Form1.REMOTE_CLIENT_DRIVER_NAME_TEMPLATE, deviceType); TL.LogMessage("Main", "About to create base key"); RegistryKey remoteRegistryKey = RegistryKey.OpenBaseKey(SharedConstants.ASCOM_REMOTE_CONFIGURATION_HIVE, RegistryView.Default).CreateSubKey(SharedConstants.ASCOM_REMOTE_CONFIGURATION_KEY, true); bool alreadyRun = bool.Parse((string)remoteRegistryKey.GetValue(ALREADY_RUN, "false")); TL.LogMessage("Main", string.Format("Already run: {0}", alreadyRun)); if (!alreadyRun) // We have not run yet { TL.LogMessage("Main", string.Format("First time setup - migrating profiles and creating dynamic drivers")); // Only attempt first time setup if the local server executable is present string localServerExe = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86) + Form1.REMOTE_SERVER_PATH + Form1.REMOTE_SERVER; // Get the local server path if (File.Exists(localServerExe)) // Local server does exist { // Migrate any ASCOM.WebX.DEVICE profile entries to ASCOM.RemoteX.DEVICE profile entries TL.LogMessage("Main", string.Format("Migrating any ASCOM.WebX.DEVICETYPE profiles to ASCOM.RemoteX.DEVICETYPE")); MigrateProfiles("Camera"); MigrateProfiles("Dome"); MigrateProfiles("FilterWheel"); MigrateProfiles("Focuser"); MigrateProfiles("ObservingConditions"); MigrateProfiles("Rotator"); MigrateProfiles("SafetyMonitor"); MigrateProfiles("Switch"); MigrateProfiles("Telescope"); // Remove any driver or pdb driver files left in the , local server directory DeleteFiles(localServerPath, @"ascom\.remote\d\.\w+\.dll", "ASCOM.RemoteX.DLL"); DeleteFiles(localServerPath, @"ascom\.remote\d\.\w+\.pdb", "ASCOM.RemoteX.PDB"); DeleteFiles(localServerPath, @"ascom\.web\d\.\w+\.dll", "ASCOM.WebX.DLL"); DeleteFiles(localServerPath, @"ascom\.web\d\.\w+\.pdb", "ASCOM.WebX.PDB"); // Create the required drivers TL.LogMessage("Main", string.Format("Creating one remote client driver of each device type")); Form1.CreateDriver("Camera", 1, localServerPath, TL); Form1.CreateDriver("Dome", 1, localServerPath, TL); Form1.CreateDriver("FilterWheel", 1, localServerPath, TL); Form1.CreateDriver("Focuser", 1, localServerPath, TL); Form1.CreateDriver("ObservingConditions", 1, localServerPath, TL); Form1.CreateDriver("Rotator", 1, localServerPath, TL); Form1.CreateDriver("SafetyMonitor", 1, localServerPath, TL); Form1.CreateDriver("Switch", 1, localServerPath, TL); Form1.CreateDriver("Telescope", 1, localServerPath, TL); // Register the drivers TL.LogMessage("Main", "Registering drivers"); Form1.RunLocalServer(localServerExe, "-regserver", TL); // Record that we have run once on this PC TL.LogMessage("Main", string.Format("Setting already run to true")); remoteRegistryKey.SetValue(ALREADY_RUN, "true"); TL.LogMessage("Main", string.Format("Set already run to true")); } else // Local server can not be found so report the issue { string errorMessage = string.Format("Could not find local server {0}, unable to register drivers", localServerExe); TL.LogMessage("Main", errorMessage); MessageBox.Show(errorMessage); } } else // Drivers are already installed so no action required { TL.LogMessage("Main", string.Format("This application has already run successful so this is not a first time installation - no action taken")); } break; default: // Unrecognised parameter so flag this to the user string errMsg = string.Format("Unrecognised parameter: {0}, the only valid value is /InstallerSetup", parameter); MessageBox.Show(errMsg); break; } } catch (Exception ex) { string errMsg = ("DynamicRemoteClients exception: " + ex.ToString()); TL.LogMessageCrLf("Main", errMsg); MessageBox.Show(errMsg); } TL.Enabled = false; TL.Dispose(); TL = null; }
private static void SetLocalServerFireWallOutboundRule(string applicationPath) { try // Make sure that we still try and set the firewall rules even if we bomb out trying to get information on the firewall configuration { TL.LogMessage("QueryFireWall", string.Format("Firewall version: {0}", FirewallManager.Version.ToString())); // Log the firewall version in use foreach (IFirewallProfile profile in FirewallManager.Instance.Profiles) { TL.LogMessage("QueryFireWall", string.Format("Found current firewall profile {0}, enabled: {1}", profile.Type.ToString(), profile.IsActive)); } COMTypeResolver cOMTypeResolver = new COMTypeResolver(); IFirewallProductsCollection thirdPartyFirewalls = FirewallManager.GetRegisteredProducts(cOMTypeResolver); TL.LogMessage("QueryFireWall", string.Format("number of third party firewalls: {0}", thirdPartyFirewalls.Count)); foreach (FirewallProduct firewall in thirdPartyFirewalls) { TL.LogMessage("QueryFireWall", $"Found third party firewall: {firewall.Name} - {firewall.FriendlyName}"); //foreach (IFirewallProfile profile in firewall.) //{ // TL.LogMessage("QueryFireWall", string.Format("Found third party firewall profile {0}, enabled: {1}", profile.Type.ToString(), profile.IsActive)); //} } } catch (Exception ex) { TL.LogMessageCrLf("QueryFireWall", "Exception: " + ex.ToString()); } TL.BlankLine(); try { if ((new WindowsPrincipal(WindowsIdentity.GetCurrent())).IsInRole(WindowsBuiltInRole.Administrator)) // Application is being run with Administrator privilege so go ahead and set the firewall rules { // Check whether the specified file exists if (File.Exists(applicationPath)) // The file does exist so process it { string applicationPathFull = Path.GetFullPath(applicationPath); TL.LogMessage("SetFireWallOutboundRule", string.Format("Supplied path: {0}, full path: {1}", applicationPath, applicationPathFull)); // Now clear up previous instances of this rule IEnumerable <IFirewallRule> query = FirewallManager.Instance.Rules.Where(ruleName => ruleName.Name.ToUpperInvariant().StartsWith(LOCAL_SERVER_OUTBOUND_RULE_NAME.ToUpperInvariant())); List <IFirewallRule> queryCopy = query.ToList(); foreach (IFirewallRule existingRule in queryCopy) { TL.LogMessage("SetFireWallOutboundRule", string.Format("Found rule: {0}", existingRule.Name)); FirewallManager.Instance.Rules.Remove(existingRule); // Delete the rule TL.LogMessage("SetFireWallOutboundRule", string.Format("Deleted rule: {0}", existingRule.Name)); } IFirewallRule rule = FirewallManager.Instance.CreateApplicationRule(FirewallManager.Instance.GetProfile(FirewallProfiles.Domain | FirewallProfiles.Private | FirewallProfiles.Public).Type, LOCAL_SERVER_OUTBOUND_RULE_NAME, FirewallAction.Allow, applicationPathFull); rule.Direction = FirewallDirection.Outbound; // Add the group name to the outbound rule if (rule is FirewallWASRule) //Rules.StandardRule) { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is a standard rule"); ((FirewallWASRule)rule).Grouping = GROUP_NAME; TL.LogMessage("SetHttpSysFireWallRule", $"Group name set to: {GROUP_NAME}"); } else { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is not a standard rule"); } if (rule is FirewallWASRuleWin7) { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is a WIN7 rule"); ((FirewallWASRuleWin7)rule).Grouping = GROUP_NAME; TL.LogMessage("SetHttpSysFireWallRule", $"Group name set to: {GROUP_NAME}"); } else { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is not a WIN7 rule"); } if (rule is FirewallWASRuleWin8) { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is a WIN8 rule"); ((FirewallWASRuleWin8)rule).Grouping = GROUP_NAME; TL.LogMessage("SetHttpSysFireWallRule", $"Group name set to: {GROUP_NAME}"); } else { TL.LogMessage("SetHttpSysFireWallRule", "Firewall rule is not a WIN8 rule"); } TL.LogMessage("SetFireWallOutboundRule", "Successfully created outbound rule"); FirewallManager.Instance.Rules.Add(rule); TL.LogMessage("SetFireWallOutboundRule", string.Format("Successfully added outbound rule for {0}", applicationPathFull)); } else { TL.LogMessage("SetFireWallOutboundRule", string.Format("The specified file does not exist: {0}", applicationPath)); Console.WriteLine("The specified file does not exist: {0}", applicationPath); } } else { TL.LogMessage("SetFireWallOutboundRule", "Not running as Administrator so unable to set firewall rules."); Console.WriteLine("Not running as Administrator so unable to set firewall rules."); } TL.BlankLine(); } catch (Exception ex) { TL.LogMessageCrLf("SetFireWallOutboundRule", "Exception: " + ex.ToString()); Console.WriteLine("SetFireWallOutboundRule threw an exception: " + ex.Message); } }
internal MemberFactory(string progId, TraceLogger ascomDriverTraceLogger) { //_tl = new TraceLogger("", "MemberFactory"); //_tl.Enabled = RegistryCommonCode.GetBool(GlobalConstants.DRIVERACCESS_TRACE, GlobalConstants.DRIVERACCESS_TRACE_DEFAULT); TL = ascomDriverTraceLogger; // Save the supplied TraceLogger object for use in method calls TL.LogMessage("ProgID", progId); _strProgId = progId; GetInterfaces = new List <Type>(); // Get Type Information GetObjType = Type.GetTypeFromProgID(progId); //check to see if it found the type information if (GetObjType == null) { //no type information found throw error throw new ASCOM.Utilities.Exceptions.HelperException("Check Driver: cannot create object type of progID: " + _strProgId); } //setup the property IsComObject = GetObjType.IsCOMObject; TL.LogMessage("IsComObject", GetObjType.IsCOMObject.ToString()); // Create an instance of the object GetLateBoundObject = Activator.CreateInstance(GetObjType); // Get list of interfaces but don't throw an exception if this fails try { var objInterfaces = GetObjType.GetInterfaces(); foreach (Type objInterface in objInterfaces) { GetInterfaces.Add(objInterface); TL.LogMessage("GetInterfaces", "Found interface: " + objInterface.AssemblyQualifiedName); } } catch (Exception ex) { TL.LogMessageCrLf("GetInterfaces", "Exception: " + ex.ToString()); } /*MemberInfo[] members = GetObjType.GetMembers(); * foreach (MemberInfo mi in members) * { * TL.LogMessage("Member", Enum.GetName(typeof(MemberTypes), mi.MemberType) + " " + mi.Name); * if (mi.MemberType == MemberTypes.Method) * { * foreach (ParameterInfo pi in ((MethodInfo)mi).GetParameters()) * { * TL.LogMessage("Parameter", * " " + pi.Name + * " " + pi.ParameterType.Name + * " " + pi.ParameterType.AssemblyQualifiedName); * } * } * }*/ //no instance found throw error if (GetLateBoundObject == null) { TL.LogMessage("Exception", "GetLateBoudObject is null, throwing HelperException"); throw new ASCOM.Utilities.Exceptions.HelperException("Check Driver: cannot create driver instance of progID: " + _strProgId); } }
/// <summary> /// Migrate profile names from previous client version /// </summary> /// <param name="DeviceType"></param> /// <remarks>The first ASCOM Remote release used device ProgIds of the form ASCOM.WebX.DEVICETYPE. This and future versions use ProgIDs of the form ASCOM.RemoteX.DEVICETYPE. This routine renames the /// Profile entries of any original release drivers to match the new form.</remarks> private static void MigrateProfiles(string DeviceType) { const string IP_ADDRESS_NOT_PRESENT = "IP Address NOT present"; try { TL.LogMessage("MigrateProfiles", string.Format("Migrating device type {0}", DeviceType)); for (int i = 1; i <= 2; i++) { string webProgIdKeyName = string.Format(@"SOFTWARE\ASCOM\{0} Drivers\ASCOM.Web{1}.{0}", DeviceType, i); TL.LogMessage("MigrateProfiles", string.Format("Processing registry value: {0}", webProgIdKeyName)); RegistryKey webProgIdKey = Registry.LocalMachine.OpenSubKey(webProgIdKeyName, true); // Open the key for writing if (!(webProgIdKey == null)) // ProgID exists { string ipAddress = (string)webProgIdKey.GetValue("IP Address", IP_ADDRESS_NOT_PRESENT); TL.LogMessage("MigrateProfiles", string.Format("Found IP Address: {0}", ipAddress)); if (!(ipAddress == IP_ADDRESS_NOT_PRESENT))// IP Address value exists so we need to try and rename this profile { // Does a current ASCOM>remoteX profile exist, if so then we can't migrate so leave as is string remoteProgIdkeyName = string.Format(@"SOFTWARE\ASCOM\{0} Drivers\ASCOM.Remote{1}.{0}", DeviceType, i); TL.LogMessage("MigrateProfiles", string.Format("Checking whether registry key {0} exists", remoteProgIdkeyName)); RegistryKey remoteProgIdKey = Registry.LocalMachine.OpenSubKey(remoteProgIdkeyName, true); // Open the key for writing if (remoteProgIdKey == null) // The "Remote" Profile does not exist so we can just rename the "Web" profile { TL.LogMessage("MigrateProfiles", string.Format("The registry key {0} does not exist - creating it", remoteProgIdkeyName)); Registry.LocalMachine.CreateSubKey(remoteProgIdkeyName, true); remoteProgIdKey = Registry.LocalMachine.OpenSubKey(remoteProgIdkeyName, true); // Open the key for writing TL.LogMessage("MigrateProfiles", string.Format("Registry key {0} created OK", remoteProgIdkeyName)); string[] valueNames = webProgIdKey.GetValueNames(); foreach (string valueName in valueNames) { string value; if (valueName == "") // Special handling for the default value - need to change chooser description to ASCOM Remote Client X { value = string.Format("ASCOM Remote Client {0}", i); TL.LogMessage("MigrateProfiles", string.Format("Changing Chooser description to {0} ", value)); } else { value = (string)webProgIdKey.GetValue(valueName); TL.LogMessage("MigrateProfiles", string.Format("Found Web registry value name {0} = {1}", valueName, value)); } TL.LogMessage("MigrateProfiles", string.Format("Setting Remote registry value {0} to {1}", valueName, value)); remoteProgIdKey.SetValue(valueName, value); } TL.LogMessage("MigrateProfiles", string.Format("Driver successfully migrated - deleting Profile {0}", webProgIdKeyName)); Registry.LocalMachine.DeleteSubKey(webProgIdKeyName); TL.LogMessage("MigrateProfiles", string.Format("Successfully deleted Profile {0}", webProgIdKeyName)); } else // The "Remote" profile already exists so we can't migrate the old "Web" profile { TL.LogMessage("MigrateProfiles", string.Format("The {0} key already exists so we cannot migrate the {1} profile - no action taken", remoteProgIdkeyName, webProgIdKeyName)); } } else // No IP address value means that this profile is unconfigured so just delete it. { TL.LogMessage("MigrateProfiles", string.Format("Driver not configured - deleting Profile {0}", webProgIdKeyName)); Registry.LocalMachine.DeleteSubKey(webProgIdKeyName); TL.LogMessage("MigrateProfiles", string.Format("Successfully deleted Profile {0}", webProgIdKeyName)); } } else // ProgID doesn't exist { TL.LogMessage("MigrateProfiles", string.Format("ProgId {0} does not exist - no action taken", webProgIdKeyName)); } } } catch (Exception ex) { TL.LogMessageCrLf("MigrateProfiles", ex.ToString()); } }
private static string DownloadFile(string Function, string DataFile, WebClient Client, TraceLogger TL) { string tempFileName; Stopwatch timeOutTimer; tempFileName = Path.GetTempFileName(); timeOutTimer = new Stopwatch(); TL.LogMessage(Function, string.Format("About to download {0} from {1} as {2}", DataFile, Client.BaseAddress, tempFileName)); Client.DownloadFileAsync(new Uri(DataFile, UriKind.Relative), tempFileName); int printCount = 0; //DateTime timeOut = DateTime.Now.AddSeconds(DownloadTimeout); DownloadComplete = false; downloadError = null; timeOutTimer.Start(); do { if (printCount == 9) { TL.LogMessage(Function, string.Format("Waiting for download to complete...{0} / {1} seconds", timeOutTimer.Elapsed.TotalSeconds.ToString("0"), parameters.DownloadTaskTimeOut)); printCount = 0; } else { printCount += 1; } Thread.Sleep(100); } while (!DownloadComplete & (timeOutTimer.Elapsed.TotalSeconds < parameters.DownloadTaskTimeOut)); if (DownloadComplete) { if (downloadError == null) // No error occurred { TL.LogMessage(Function, "Response headers"); WebHeaderCollection responseHeaders = Client.ResponseHeaders; if (!(responseHeaders is null)) { foreach (string header in responseHeaders.AllKeys) { TL.LogMessage(Function, string.Format("Response header {0} = {1}", header, responseHeaders[header])); } } FileInfo info = new FileInfo(tempFileName); TL.LogMessage(Function, string.Format("Successfully downloaded {0} from {1} as {2}. Size: {3}", DataFile, Client.BaseAddress, tempFileName, info.Length)); } else // An error occurred { // Just throw the error, which will be reported in the calling routine throw downloadError; } } else { TL.LogMessage(Function, string.Format("Download cancelled because of {0} second timeout", DownloadTimeout)); try { Client.CancelAsync(); } catch (Exception ex) { TL.LogMessageCrLf("DownloadFile", "Exception cancelling download: " + ex.ToString()); } throw new TimeoutException(string.Format("Timed out downloading {0} from {1} as {2}", DataFile, Client.BaseAddress, tempFileName)); } TL.BlankLine(); return(tempFileName); }
/// <summary> /// Create a new Alpaca client executable using the supplied parameters /// </summary> /// <param name="DeviceType">The ASCOM device type to create</param> /// <param name="DeviceNumber">The number of this device type to create</param> /// <param name="OutputDirectory">The directory in which to place the compiled assembly</param> /// <remarks> /// This subroutine creates compiler source line definitions (not source code as such) and stores them in memory /// When complete, the compiler is called and the resultant assembly is stored in the specified output directory. /// The code created has no function as such it is just a shell with all of the heavy lifting undertaken by an inherited base class that is supplied pre-compiled /// The resultant assembly for Camera device 1 has this form: /// /// using System; /// using System.Runtime.InteropServices; /// namespace ASCOM.DynamicRemoteClients /// { /// [Guid("70495DF9-C01E-4987-AE49-E12967202C7F")] <====> The GUID is dynamically created on the user's machine so that it is unique for every driver /// [ProgId(DRIVER_PROGID)] /// [ServedClassName(DRIVER_DISPLAY_NAME)] /// [ClassInterface(ClassInterfaceType.None)] /// public class Camera : CameraBaseClass <====> Created from supplied parameters - all executable code is in the base class /// { /// private const string DRIVER_NUMBER = "1"; <====> Created from supplied parameters /// private const string DEVICE_TYPE = "Camera"; <====> Created from supplied parameters /// private const string DRIVER_DISPLAY_NAME = SharedConstants.DRIVER_DISPLAY_NAME + " " + DRIVER_NUMBER; /// private const string DRIVER_PROGID = SharedConstants.DRIVER_PROGID_BASE + DRIVER_NUMBER + "." + DEVICE_TYPE; /// public Camera() : base(DRIVER_NUMBER, DRIVER_DISPLAY_NAME, DRIVER_PROGID) /// { /// } /// } /// } /// </remarks> internal static void CreateAlpacaClient(string DeviceType, int DeviceNumber, string ProgId, string DisplayName, string localServerPath) { TL.LogMessage("CreateAlpacaClient", $"Creating new ProgID: for {DeviceType} device {DeviceNumber} with ProgID: {ProgId} and display name: {DisplayName}"); try { // Generate the container unit CodeCompileUnit program = new CodeCompileUnit(); // Generate the namespace CodeNamespace ns = new CodeNamespace("ASCOM.DynamicRemoteClients"); // Add required imports ns.Imports.Add(new CodeNamespaceImport("System")); ns.Imports.Add(new CodeNamespaceImport("System.Runtime.InteropServices")); // Declare the device class CodeTypeDeclaration deviceClass = new CodeTypeDeclaration() { Name = DeviceType, IsClass = true }; // Add the class base type deviceClass.BaseTypes.Add(new CodeTypeReference { BaseType = DeviceType + BASE_CLASS_POSTFIX }); TL.LogMessage("CreateAlpacaClient", "Created base type"); // Create custom attributes to decorate the class CodeAttributeDeclaration guidAttribute = new CodeAttributeDeclaration("Guid", new CodeAttributeArgument(new CodePrimitiveExpression(Guid.NewGuid().ToString()))); CodeAttributeDeclaration progIdAttribute = new CodeAttributeDeclaration("ProgId", new CodeAttributeArgument(new CodeArgumentReferenceExpression("DRIVER_PROGID"))); CodeAttributeDeclaration servedClassNameAttribute = new CodeAttributeDeclaration("ServedClassName", new CodeAttributeArgument(new CodeArgumentReferenceExpression("DRIVER_DISPLAY_NAME"))); CodeAttributeDeclaration classInterfaceAttribute = new CodeAttributeDeclaration("ClassInterface", new CodeAttributeArgument(new CodeArgumentReferenceExpression("ClassInterfaceType.None"))); CodeAttributeDeclarationCollection customAttributes = new CodeAttributeDeclarationCollection() { guidAttribute, progIdAttribute, servedClassNameAttribute, classInterfaceAttribute }; TL.LogMessage("CreateAlpacaClient", "Created custom attributes"); // Add the custom attributes to the class deviceClass.CustomAttributes = customAttributes; // Create some class level private constants CodeMemberField driverNumberConst = new CodeMemberField(typeof(string), "DRIVER_NUMBER"); driverNumberConst.Attributes = MemberAttributes.Private | MemberAttributes.Const; driverNumberConst.InitExpression = new CodePrimitiveExpression(DeviceNumber.ToString()); CodeMemberField deviceTypeConst = new CodeMemberField(typeof(string), "DEVICE_TYPE"); deviceTypeConst.Attributes = MemberAttributes.Private | MemberAttributes.Const; deviceTypeConst.InitExpression = new CodePrimitiveExpression(DeviceType); CodeMemberField driverDisplayNameConst = new CodeMemberField(typeof(string), "DRIVER_DISPLAY_NAME"); driverDisplayNameConst.Attributes = (MemberAttributes.Private | MemberAttributes.Const); driverDisplayNameConst.InitExpression = new CodePrimitiveExpression(DisplayName); CodeMemberField driverProgIDConst = new CodeMemberField(typeof(string), "DRIVER_PROGID"); driverProgIDConst.Attributes = MemberAttributes.Private | MemberAttributes.Const; driverProgIDConst.InitExpression = new CodePrimitiveExpression(ProgId); // Add the constants to the class deviceClass.Members.AddRange(new CodeMemberField[] { driverNumberConst, deviceTypeConst, driverDisplayNameConst, driverProgIDConst }); TL.LogMessage("CreateAlpacaClient", "Added constants to class"); // Declare the class constructor CodeConstructor constructor = new CodeConstructor(); constructor.Attributes = MemberAttributes.Public | MemberAttributes.Final; // Add a call to the base class with required parameters constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("DRIVER_NUMBER")); constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("DRIVER_DISPLAY_NAME")); constructor.BaseConstructorArgs.Add(new CodeArgumentReferenceExpression("DRIVER_PROGID")); deviceClass.Members.Add(constructor); TL.LogMessage("CreateAlpacaClient", "Added base constructor"); // Add the class to the namespace ns.Types.Add(deviceClass); TL.LogMessage("CreateAlpacaClient", "Added class to name space"); // Add the namespace to the program, which is now complete program.Namespaces.Add(ns); TL.LogMessage("CreateAlpacaClient", "Added name space to program"); // Construct the path to the output DLL String dllName = $"{localServerPath.TrimEnd('\\')}\\{SharedConstants.DRIVER_PROGID_BASE}{DeviceNumber}.{DeviceType}.dll"; TL.LogMessage("CreateAlpacaClient", string.Format("Output file name: {0}", dllName)); // Create relevant compiler options to shape the compilation CompilerParameters cp = new CompilerParameters() { GenerateExecutable = false, // Specify output of a DLL OutputAssembly = dllName, // Specify the assembly file name to generate GenerateInMemory = false, // Save the assembly as a physical file. TreatWarningsAsErrors = false, // Don't treat warnings as errors. IncludeDebugInformation = true // Include debug information }; TL.LogMessage("CreateAlpacaClient", "Created compiler parameters"); // Add required assembly references to make sure the compilation succeeds cp.ReferencedAssemblies.Add(@"ASCOM.Attributes.dll"); // Must be present in the current directory because the compiler doesn't use the GAC cp.ReferencedAssemblies.Add(@"ASCOM.DeviceInterfaces.dll"); // Must be present in the current directory because the compiler doesn't use the GAC cp.ReferencedAssemblies.Add(@"ASCOM.Newtonsoft.Json.dll"); // Must be present in the current directory because the compiler doesn't use the GAC cp.ReferencedAssemblies.Add(@"RestSharp.dll"); // Must be present in the current directory cp.ReferencedAssemblies.Add(@"ASCOM.AlpacaClientDeviceBaseClasses.dll"); // Must be present in the current directory cp.ReferencedAssemblies.Add(SharedConstants.ALPACA_CLIENT_LOCAL_SERVER); // Must be present in the current directory Assembly executingAssembly = Assembly.GetExecutingAssembly(); cp.ReferencedAssemblies.Add(executingAssembly.Location); foreach (AssemblyName assemblyName in executingAssembly.GetReferencedAssemblies()) { cp.ReferencedAssemblies.Add(Assembly.Load(assemblyName).Location); } TL.LogMessage("CreateAlpacaClient", "Added assembly references"); // Create formatting options for the generated code that will be logged into the trace logger CodeGeneratorOptions codeGeneratorOptions = new CodeGeneratorOptions() { BracingStyle = "C", IndentString = " ", VerbatimOrder = true, BlankLinesBetweenMembers = false }; // Get a code provider so that we can compile the program CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); TL.LogMessage("CreateAlpacaClient", "Created CSharp provider"); // Write the generated code to the trace logger using (MemoryStream outputStream = new MemoryStream()) { using (StreamWriter writer = new StreamWriter(outputStream)) { provider.GenerateCodeFromNamespace(ns, writer, codeGeneratorOptions); } MemoryStream actualStream = new MemoryStream(outputStream.ToArray()); using (StreamReader reader = new StreamReader(actualStream)) { do { TL.LogMessage("GeneratedCode", reader.ReadLine()); } while (!reader.EndOfStream); } } provider.Dispose(); // Compile the source contained in the "program" variable CompilerResults cr = provider.CompileAssemblyFromDom(cp, program); TL.LogMessage("CreateAlpacaClient", string.Format("Compiled assembly - {0} errors", cr.Errors.Count)); // Report success or errors if (cr.Errors.Count > 0) { // Display compilation errors. foreach (CompilerError ce in cr.Errors) { TL.LogMessage("CreateAlpacaClient", string.Format("Compiler error: {0}", ce.ToString())); } } else { // Display a successful compilation message. TL.LogMessage("CreateAlpacaClient", "Assembly compiled OK!"); } TL.BlankLine(); } catch (Exception ex) { TL.LogMessageCrLf("CreateAlpacaClient", ex.ToString()); } }
static void Main(string[] args) { string errMsg; // Add unhandled exception handlers Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException); // Add the event handler for handling UI thread exceptions to the event. Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); // Set the unhandled exception mode to force all exceptions to go through our handler. AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); // Add the event handler for handling non-UI thread exceptions to the event. TL = new TraceLogger("", "AlpacaDynamicClientManager"); TL.Enabled = RegistryCommonCode.GetBool(GlobalConstants.TRACE_UTIL, GlobalConstants.TRACE_UTIL_DEFAULT); try { string commandParameter = ""; // Initialise the supplied parameter to empty string TL.LogMessage("Main", $"Number of parameters: {args.Count()}"); foreach (string arg in args) { TL.LogMessage("Main", $"Received parameter: \"{arg}\""); } if (args.Length > 0) { commandParameter = args[0]; // Copy any supplied command parameter to the parameter variable } TL.LogMessage("Main", string.Format(@"Supplied parameter: ""{0}""", commandParameter)); commandParameter = commandParameter.TrimStart(' ', '-', '/', '\\'); // Remove any parameter prefixes and leading spaces commandParameter = commandParameter.TrimEnd(' '); // Remove any trailing spaces TL.LogMessage("Main", string.Format(@"Trimmed parameter: ""{0}""", commandParameter)); switch (commandParameter.ToUpperInvariant()) // Act on the supplied parameter, if any { case "": case "MANAGEDEVICES": // Run the application in user interactive mode Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); TL.LogMessage("Main", "Starting device management form"); Application.Run(new ManageDevicesForm(TL)); break; case "CREATEALPACACLIENT": // Validate supplied parameters before passing to the execution method if (args.Length < 5) { // Validate the number of parameters - must be 5: Command DeviceType COMDeviceNumber ProgID DeviceName errMsg = $"The CreateAlpacaClient command requires 4 parameters: DeviceType COMDeviceNumber ProgID DeviceName e.g. /CreateAlpacaClient Telescope 1 ASCOM.AlpacaDynamic1.Telescope \"Device Chooser description\""; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Validate that the supplied device type is one that is supported for Alpaca if (!supportedDeviceTypes.Contains(args[1], StringComparer.OrdinalIgnoreCase)) { errMsg = $"The supplied ASCOM device type '{args[1]}' is not supported: The command format is \"/CreateAlpacaClient ASCOMDeviceType AlpacaDeviceUniqueID\" e.g. /CreateAlpacaClient Telescope 84DC2495-CBCE-4A9C-A703-E342C0E1F651"; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Validate that the supplied device number is an integer int comDevicenumber; bool comDevicenunberIsInteger = int.TryParse(args[2], out comDevicenumber); if (!comDevicenunberIsInteger) { errMsg = $"The supplied COM device number is not an integer: {args[2]}"; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } string localServerPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86) + SharedConstants.ALPACA_CLIENT_LOCAL_SERVER_PATH; TL.LogMessage("CreateAlpacaClient", $"Alpaca local server folder: {localServerPath}"); // The supplied parameters pass validation so run the create device form to obtain the device description and create the driver CreateAlpacaClient(args[1], comDevicenumber, args[3], args[4], localServerPath); // Call the execution method with correctly cased device type and unique ID parameters string localServerExe = $"{localServerPath}\\{SharedConstants.ALPACA_CLIENT_LOCAL_SERVER}"; TL.LogMessage("CreateAlpacaClient", $"Alpaca local server exe name: {localServerExe}"); RunLocalServer(localServerExe, "-regserver", TL); break; case "CREATENAMEDCLIENT": // Validate supplied parameters before passing to the execution method if (args.Length < 4) { // Validate the number of parameters - must be 4: Command DeviceType COMDeviceNumber ProgID errMsg = $"The CreateAlpacaClient command requires 3 parameters: DeviceType COMDeviceNumber ProgID e.g. /CreateAlpacaClient Telescope 1 ASCOM.AlpacaDynamic1.Telescope"; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Validate that the supplied device type is one that is supported for Alpaca if (!supportedDeviceTypes.Contains(args[1], StringComparer.OrdinalIgnoreCase)) { errMsg = $"The supplied ASCOM device type '{args[1]}' is not supported: The command format is \"/CreateAlpacaClient ASCOMDeviceType AlpacaDeviceUniqueID\" e.g. /CreateAlpacaClient Telescope 84DC2495-CBCE-4A9C-A703-E342C0E1F651"; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } // Validate that the supplied device number is an integer comDevicenunberIsInteger = int.TryParse(args[2], out comDevicenumber); if (!comDevicenunberIsInteger) { errMsg = $"The supplied COM device number is not an integer: {args[2]}"; TL.LogMessageCrLf("CreateAlpacaClient", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Client Manager", MessageBoxButtons.OK, MessageBoxIcon.Error); return; } localServerPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFilesX86) + SharedConstants.ALPACA_CLIENT_LOCAL_SERVER_PATH; TL.LogMessage("CreateAlpacaClient", $"Alpaca local server folder: {localServerPath}"); // The supplied parameters pass validation so run the create device form to obtain the device description and create the driver Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); TL.LogMessage("Main", "Starting device creation form"); Application.Run(new CreateDeviceForm(args[1], comDevicenumber, args[3], localServerPath, TL)); break; default: // Unrecognised parameter so flag this to the user errMsg = $"Unrecognised command: '{commandParameter}', the valid command are:\r\n" + $"/CreateAlpacaClient DeviceType COMDeviceNumber ProgID DeviceName\r\n" + $"CreateNamedClient DeviceType COMDeviceNumber ProgID\r\n" + $"/ManageDevices"; TL.LogMessage("Main", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Clients", MessageBoxButtons.OK, MessageBoxIcon.Error); break; } } catch (Exception ex) { errMsg = ("DynamicRemoteClients exception: " + ex.ToString()); TL.LogMessageCrLf("Main", errMsg); MessageBox.Show(errMsg, "ASCOM Dynamic Clients", MessageBoxButtons.OK, MessageBoxIcon.Error); } TL.Enabled = false; TL.Dispose(); TL = null; }
private static readonly double UNKNOWN_LEAP_SECONDS = double.MinValue; // Value for dates which have not yet been determined static void Main(string[] args) { try { // In December 2020, ascom-standards.org minimum SSL protocol version is TLS1.2 // Normally, this application will use the OS default SSL protocol, but Windows 7 default protocol is earlier that TLS1.2 and connection cannot be established to ascom-standards.org from this OS. // The following command ensures that TLS1.2 will be tried in addition to the OS default protocol. ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.SystemDefault; // Get some basic details for this run string runBy = WindowsIdentity.GetCurrent().Name; // Get the name of the user executing this program bool isSystem = WindowsIdentity.GetCurrent().IsSystem; DateTime now = DateTime.Now; ReturnCode = 0; // Initialise return code to success // Get access to the ASCOM Profile store and retrieve the trace logger configuration RegistryAccess profile = new RegistryAccess(); string traceFileName = ""; string traceBasePath = ""; if (isSystem) // If we are running as user SYSTEM, create our own trace file name so that all scheduled job trace files end up in the same directory { // Get the configured trace file directory and make sure that it exists traceBasePath = profile.GetProfile(GlobalItems.ASTROMETRY_SUBKEY, GlobalItems.DOWNLOAD_TASK_TRACE_PATH_VALUE_NAME, string.Format(GlobalItems.DOWNLOAD_TASK_TRACE_DEFAULT_PATH_FORMAT, Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments)) ).TrimEnd('\\'); Directory.CreateDirectory(traceBasePath); // Now make the full trace file name from the path above and the file name format template traceFileName = string.Format(GlobalItems.DOWNLOAD_TASK_TRACE_FILE_NAME_FORMAT, traceBasePath, now.Year, now.Month, now.Day, now.Hour.ToString("00"), now.Minute.ToString("00"), now.Second.ToString("00")); } // Get the trace state from the Profile string DownloadTaskTraceEnabledString = profile.GetProfile(GlobalItems.ASTROMETRY_SUBKEY, GlobalItems.DOWNLOAD_TASK_TRACE_ENABLED_VALUE_NAME, GlobalItems.DOWNLOAD_TASK_TRACE_ENABLED_DEFAULT.ToString()); if (!Boolean.TryParse(DownloadTaskTraceEnabledString, out bool DownloadTaskTraceEnabledValue)) //' String parsed OK so no further action { //'Returned string doesn't represent a boolean so use the default DownloadTaskTraceEnabledValue = GlobalItems.DOWNLOAD_TASK_TRACE_ENABLED_DEFAULT; } // Create the trace logger with either the supplied fully qualified name if running as SYSTEM or an automatic file name if running as a normal user TL = new TraceLogger(traceFileName, GlobalItems.DOWNLOAD_TASK_TRACE_LOG_FILETYPE); TL.Enabled = DownloadTaskTraceEnabledValue; // Set the trace state TL.IdentifierWidth = GlobalItems.DOWNLOAD_TASK_TRACE_LOGGER_IDENTIFIER_FIELD_WIDTH; invariantCulture = new CultureInfo(""); invariantCulture.Calendar.TwoDigitYearMax = 2117; // Specify that two digit years will be converted to the range 2018-2117 - Likely to outlast ASCOM Platform and me! monthAbbrev = invariantCulture.DateTimeFormat.AbbreviatedMonthNames; // Get the 12 three letter abbreviated month names of the year invariantTextInfo = invariantCulture.TextInfo; TL.LogMessage("EarthRotationUpdate", string.Format("InstalledUICulture: {0}, CurrentUICulture: {1}, CurrentCulture: {2}", CultureInfo.InstalledUICulture.Name, CultureInfo.CurrentUICulture, CultureInfo.CurrentCulture)); parameters = new EarthRotationParameters(TL); // Get configuration from the Profile store string runDate = now.ToString(GlobalItems.DOWNLOAD_TASK_TIME_FORMAT, CultureInfo.CurrentUICulture); // Get today's date and time in a locally readable format hostURIString = parameters.DownloadTaskDataSource; // Initialise the data source URI if (args.Length > 0) { foreach (string arg in args) { TL.LogMessage("EarthRotationUpdate", string.Format("Received parameter: {0}", arg)); } } // If we have been provided with an "Initialise" parameter then stop here after having set up all the default profile values by creating the EarthRotationParameters object if (args.Length == 1) { if (args[0].Trim(' ', '-', '\\', '/').Equals("INITIALISE", StringComparison.OrdinalIgnoreCase)) // Test for the presence of and act on the initialise argument ignoring everything else { TL.LogMessage("EarthRotationUpdate", string.Format("Earth rotation parameter initialisation run on {0} by {1}, IsSystem: {2}", runDate, runBy, isSystem)); LogEvent(string.Format("Earth rotation parameter initialisation run on {0} by {1}, IsSystem: {2}", runDate, runBy, isSystem), EventLogEntryType.Information); TL.LogMessage("EarthRotationUpdate", string.Format("Calling ManageScheduledTask")); parameters.ManageScheduledTask(); TL.LogMessage("EarthRotationUpdate", string.Format("Completed ManageScheduledTask")); Environment.Exit(0); } } // If we have been provided with a "DataSource" override parameter then apply the new URI otherwise read it from the Profile if (args.Length == 2) { if (args[0].Trim(' ', '-', '\\', '/').Equals("DATASOURCE", StringComparison.OrdinalIgnoreCase)) // Test for the presence of and act on the data source argument ignoring everything else { TL.LogMessage("EarthRotationUpdate", string.Format("Data source override parameter provided: {0}", args[1])); string overrideDataSource = args[1].Trim(' ', '"'); bool UriValid = false; // Set the valid flag false, then set to true if the download source starts with a supported URI prefix if (overrideDataSource.StartsWith(GlobalItems.URI_PREFIX_HTTP, StringComparison.OrdinalIgnoreCase)) { UriValid = true; } if (overrideDataSource.StartsWith(GlobalItems.URI_PREFIX_HTTPS, StringComparison.OrdinalIgnoreCase)) { UriValid = true; } if (overrideDataSource.StartsWith(GlobalItems.URI_PREFIX_FTP, StringComparison.OrdinalIgnoreCase)) { UriValid = true; } if (UriValid) { hostURIString = overrideDataSource; TL.LogMessage("EarthRotationUpdate", string.Format("Data source override parameter is valid and will be used: {0}", hostURIString)); } else { TL.LogMessage("EarthRotationUpdate", string.Format("Data source override parameter {0} is not valid and the Profile data source will be used instead: {1}", overrideDataSource, hostURIString)); } } } // Ensure that the host URI string, wherever it has come from, ends with a single backslash otherwise the URI will be incorrect when the file name is formed hostURIString = hostURIString.TrimEnd(' ', '-', '\\', '/') + "/"; LogEvent(string.Format("Run on {0} by {1}, IsSystem: {2}", runDate, runBy, isSystem), EventLogEntryType.Information); TL.LogMessage("EarthRotationUpdate", string.Format("Run on {0} by {1}, IsSystem: {2}", runDate, runBy, isSystem)); TL.BlankLine(); LogEvent(string.Format("Log file: {0}, Trace state: {1}, Log file path: {2}", TL.LogFileName, parameters.DownloadTaskTraceEnabled, TL.LogFilePath), EventLogEntryType.Information); TL.LogMessage("EarthRotationUpdate", string.Format("Log file: {0}, Trace state: {1}, Log file path: {2}", TL.LogFileName, parameters.DownloadTaskTraceEnabled, TL.LogFilePath)); TL.LogMessage("EarthRotationUpdate", string.Format("Earth rotation data last updated: {0}", parameters.EarthRotationDataLastUpdatedString)); TL.LogMessage("EarthRotationUpdate", string.Format("Data source: {0}", hostURIString)); DownloadTimeout = parameters.DownloadTaskTimeOut; WebClient client = new WebClient(); client.DownloadProgressChanged += Client_DownloadProgressChanged; client.DownloadFileCompleted += Client_DownloadFileCompleted; Uri hostURI = new Uri(hostURIString); if (WebRequest.DefaultWebProxy.GetProxy(hostURI) == hostURI) { TL.LogMessage("EarthRotationUpdate", "No proxy server detected, going directly to Internet"); // No proxy is in use so go straight out } else // Proxy is in use so set it and apply credentials { TL.LogMessage("EarthRotationUpdate", "Setting default proxy"); client.Proxy = WebRequest.DefaultWebProxy; TL.LogMessage("EarthRotationUpdate", "Setting default credentials"); client.Proxy.Credentials = CredentialCache.DefaultCredentials; TL.LogMessage("EarthRotationUpdate", "Using proxy server: " + WebRequest.DefaultWebProxy.GetProxy(hostURI).ToString()); } client.Headers.Add("user-agent", GlobalItems.DOWNLOAD_TASK_USER_AGENT); client.Headers.Add("Accept", "text/plain"); client.Encoding = Encoding.ASCII; client.BaseAddress = hostURIString; NetworkCredential credentials = new NetworkCredential("anonymous", "guest"); // Apply some standard credentials for FTP sites client.Credentials = credentials; TL.BlankLine(); // Get the latest delta UT1 values try { string dUT1fileName = DownloadFile("DeltaUT1", GlobalItems.DELTAUT1_FILE, client, TL); // Download the latest delta UT1 values and receive the filename holding the data FileInfo info = new FileInfo(dUT1fileName); // Find out if we have any data if (info.Length > 0) // We actually received some data so process it { // List the data position parameters that will be used to extract the delta UT1 data from the file TL.LogMessage("DeltaUT1", string.Format("Expected file format for the {0} file", GlobalItems.DELTAUT1_FILE)); TL.LogMessage("DeltaUT1", string.Format("Year string start position: {0}, Year string length: {1}", GlobalItems.DELTAUT1_YEAR_START, GlobalItems.DELTAUT1_YEAR_LENGTH)); TL.LogMessage("DeltaUT1", string.Format("Month string start position: {0}, Month string length: {1}", GlobalItems.DELTAUT1_MONTH_START, GlobalItems.DELTAUT1_MONTH_LENGTH)); TL.LogMessage("DeltaUT1", string.Format("Day string start position: {0}, Day string length: {1}", GlobalItems.DELTAUT1_DAY_START, GlobalItems.DELTAUT1_DAY_LENGTH)); TL.LogMessage("DeltaUT1", string.Format("Julian date start position: {0}, Julian date string length: {1}", GlobalItems.DELTAUT1_JULIAN_DATE_START, GlobalItems.DELTAUT1_JULIAN_DATE_LENGTH)); TL.LogMessage("DeltaUT1", string.Format("Delta UT1 start position: {0}, Delta UT1 string length: {1}", GlobalItems.DELTAUT1_START, GlobalItems.DELTAUT1_LENGTH)); TL.BlankLine(); profile.DeleteKey(GlobalItems.AUTOMATIC_UPDATE_DELTAUT1_SUBKEY_NAME); // Clear out old delta UT1 values profile.CreateKey(GlobalItems.AUTOMATIC_UPDATE_DELTAUT1_SUBKEY_NAME); // Process the data file using (var filestream = new FileStream(dUT1fileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { using (var file = new StreamReader(filestream, Encoding.ASCII, true, 4096)) { string lineOfText; DateTime date; while ((lineOfText = file.ReadLine()) != null) // Get lines of text one at a time and parse them { try { // Extract string values for data items string yearString = lineOfText.Substring(GlobalItems.DELTAUT1_YEAR_START, GlobalItems.DELTAUT1_YEAR_LENGTH); string monthString = lineOfText.Substring(GlobalItems.DELTAUT1_MONTH_START, GlobalItems.DELTAUT1_MONTH_LENGTH); string dayString = lineOfText.Substring(GlobalItems.DELTAUT1_DAY_START, GlobalItems.DELTAUT1_DAY_LENGTH); string julianDateString = lineOfText.Substring(GlobalItems.DELTAUT1_JULIAN_DATE_START, GlobalItems.DELTAUT1_JULIAN_DATE_LENGTH); string dUT1String = lineOfText.Substring(GlobalItems.DELTAUT1_START, GlobalItems.DELTAUT1_LENGTH); // Validate that the data items are parse-able bool yearOK = int.TryParse(yearString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int year); bool monthOK = int.TryParse(monthString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int month); bool dayOK = int.TryParse(dayString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int day); bool julianDateOK = double.TryParse(julianDateString, NumberStyles.Float, CultureInfo.InvariantCulture, out double julianDate); bool dut1OK = double.TryParse(dUT1String, NumberStyles.Float, CultureInfo.InvariantCulture, out double dUT1); if (yearOK & monthOK & dayOK & julianDateOK & dut1OK) // We have good values for all data items so save these to the Profile { year = invariantCulture.Calendar.ToFourDigitYear(year); // Convert the two digit year to a four digit year date = new DateTime(year, month, day); // Only save the item if it is from a few days back or is a future prediction if (date.Date >= DateTime.Now.Date.Subtract(new TimeSpan(GlobalItems.DOWNLOAD_TASK_NUMBER_OF_BACK_DAYS_OF_DELTAUT1_DATA_TO_LOAD, 0, 0, 0))) { string deltaUT1ValueName = string.Format(GlobalItems.DELTAUT1_VALUE_NAME_FORMAT, date.Year.ToString(GlobalItems.DELTAUT1_VALUE_NAME_YEAR_FORMAT), date.Month.ToString(GlobalItems.DELTAUT1_VALUE_NAME_MONTH_FORMAT), date.Day.ToString(GlobalItems.DELTAUT1_VALUE_NAME_DAY_FORMAT)); TL.LogMessage("DeltaUT1", string.Format("Setting {0}, JD = {1} - DUT1 = {2} with key: {3}", date.ToLongDateString(), julianDate, dUT1, deltaUT1ValueName)); profile.WriteProfile(GlobalItems.AUTOMATIC_UPDATE_DELTAUT1_SUBKEY_NAME, deltaUT1ValueName, dUT1.ToString("0.000", CultureInfo.InvariantCulture)); } } else { TL.LogMessage("DeltaUT1", string.Format("Unable to parse Delta UT1 values from the line below - Year: {0}, Month: {1}, Day: {2}, Julian Day: {3},Delta UT1: {4}", yearString, monthString, dayString, julianDateString, dUT1String)); TL.LogMessage("DeltaUT1", string.Format("Corrupt line: {0}", lineOfText)); } } catch (Exception ex) { TL.LogMessageCrLf("DeltaUT1", string.Format("Unexpected exception: {0}, parsing line: ", ex.Message, lineOfText)); TL.LogMessageCrLf("DeltaUT1", ex.ToString()); } } } } } else { TL.LogMessage("DeltaUT1", string.Format("Downloaded file size was zero so nothing to process!")); } File.Delete(dUT1fileName); TL.BlankLine(); } catch (WebException ex) // An issue occurred with receiving the leap second file over the network { TL.LogMessageCrLf("DeltaUT1", string.Format("Error: {0} - delta UT1 data not updated", ex.Message)); ReturnCode = 1; } catch (Exception ex) { TL.LogMessageCrLf("DeltaUT1", ex.ToString()); ReturnCode = 2; } // Get the latest leap second values try { string leapSecondsfileName = DownloadFile("LeapSeconds", GlobalItems.LEAP_SECONDS_FILE, client, TL); // Download the latest leap second values and receive the filename holding the data FileInfo info = new FileInfo(leapSecondsfileName); // Find out if we have any data if (info.Length > 0) // We actually received some data so process it { // List the data position parameters that will be used to extract the delta UT1 data from the file TL.LogMessage("LeapSeconds", string.Format("Expected file format for the {0} file", GlobalItems.DELTAUT1_FILE)); TL.LogMessage("LeapSeconds", string.Format("Year string start position: {0}, Year string length: {1}", GlobalItems.LEAP_SECONDS_YEAR_START, GlobalItems.LEAP_SECONDS_YEAR_LENGTH)); TL.LogMessage("LeapSeconds", string.Format("Month string start position: {0}, Month string length: {1}", GlobalItems.LEAP_SECONDS_MONTH_START, GlobalItems.LEAP_SECONDS_MONTH_LENGTH)); TL.LogMessage("LeapSeconds", string.Format("Day string start position: {0}, Day string length: {1}", GlobalItems.LEAP_SECONDS_DAY_START, GlobalItems.LEAP_SECONDS_DAY_LENGTH)); TL.LogMessage("LeapSeconds", string.Format("Julian date start position: {0}, Julian date string length: {1}", GlobalItems.LEAP_SECONDS_JULIAN_DATE_START, GlobalItems.LEAP_SECONDS_JULIAN_DATE_LENGTH)); TL.LogMessage("LeapSeconds", string.Format("Leap seconds start position: {0}, Leap seconds string length: {1}", GlobalItems.LEAP_SECONDS_LEAPSECONDS_START, GlobalItems.LEAP_SECONDS_LEAPSECONDS_LENGTH)); TL.BlankLine(); profile.DeleteKey(GlobalItems.AUTOMATIC_UPDATE_LEAP_SECOND_HISTORY_SUBKEY_NAME);; // Clear out old leap second values profile.CreateKey(GlobalItems.AUTOMATIC_UPDATE_LEAP_SECOND_HISTORY_SUBKEY_NAME); // Process the data file using (var filestream = new FileStream(leapSecondsfileName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { double currentLeapSeconds = UNKNOWN_LEAP_SECONDS; double nextLeapSeconds = 0.0; DateTime leapSecondDate = UNKNOWN_DATE; DateTime nextleapSecondsDate = UNKNOWN_DATE; using (var file = new StreamReader(filestream, Encoding.ASCII, true, 4096)) { string lineOfText; DateTime latestLeapSecondDate = UNKNOWN_DATE; while ((lineOfText = file.ReadLine()) != null) // Get lines of text one at a time and parse them { try { // Read values from the file as strings based on their position within the file string yearString = lineOfText.Substring(GlobalItems.LEAP_SECONDS_YEAR_START, GlobalItems.LEAP_SECONDS_YEAR_LENGTH); string monthString = lineOfText.Substring(GlobalItems.LEAP_SECONDS_MONTH_START, GlobalItems.LEAP_SECONDS_MONTH_LENGTH); string dayString = lineOfText.Substring(GlobalItems.LEAP_SECONDS_DAY_START, GlobalItems.LEAP_SECONDS_DAY_LENGTH); string julianDateString = lineOfText.Substring(GlobalItems.LEAP_SECONDS_JULIAN_DATE_START, GlobalItems.LEAP_SECONDS_JULIAN_DATE_LENGTH); string leapSecondsString = lineOfText.Substring(GlobalItems.LEAP_SECONDS_LEAPSECONDS_START, GlobalItems.LEAP_SECONDS_LEAPSECONDS_LENGTH); // Validate that the data items are parse-able bool yearOK = int.TryParse(yearString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int year); bool dayOK = int.TryParse(dayString, NumberStyles.Integer, CultureInfo.InvariantCulture, out int day); bool julianDateOK = double.TryParse(julianDateString, NumberStyles.Float, CultureInfo.InvariantCulture, out double julianDate); bool leapSecondsOK = double.TryParse(leapSecondsString, NumberStyles.Float, CultureInfo.InvariantCulture, out double leapSeconds); // Get the month number by trimming the month string, converting to lower case then title case then looking up the index in the abbreviated months array int month = Array.IndexOf(monthAbbrev, invariantTextInfo.ToTitleCase(monthString.Trim(' ').ToLower(CultureInfo.InvariantCulture))) + 1; // If IndexOf fails, it returns -1 so the resultant month number will be zero and this is checked below if (yearOK & (month > 0) & dayOK & julianDateOK & leapSecondsOK) // We have good values for all data items so save these to the Profile { double modifiedJulianDate = julianDate - GlobalItems.MODIFIED_JULIAN_DAY_OFFSET; leapSecondDate = new DateTime(year, month, day); // Write all leap second values and Julian dates that they become effective to the leap second history subkey profile.WriteProfile(GlobalItems.AUTOMATIC_UPDATE_LEAP_SECOND_HISTORY_SUBKEY_NAME, julianDate.ToString(CultureInfo.InvariantCulture), leapSeconds.ToString(CultureInfo.InvariantCulture)); if ((leapSecondDate.Date >= latestLeapSecondDate) & (leapSecondDate.Date <= DateTime.UtcNow.Date.Subtract(new TimeSpan(GlobalItems.TEST_HISTORIC_DAYS_OFFSET, 0, 0, 0)))) { currentLeapSeconds = leapSeconds; } if ((leapSecondDate.Date > DateTime.UtcNow.Date.Subtract(new TimeSpan(GlobalItems.TEST_HISTORIC_DAYS_OFFSET, 0, 0, 0))) & (nextleapSecondsDate == UNKNOWN_DATE)) // Record the next leap seconds value in the file { nextLeapSeconds = leapSeconds; nextleapSecondsDate = leapSecondDate; } TL.LogMessage("LeapSeconds", string.Format("Leap second takes effect on: {0}, Modified JD = {1} - Current Leap Seconds = {2}, Latest Leap Seconds: {3}, Next Leap Seconds: {4} on {5}", leapSecondDate.ToLongDateString(), modifiedJulianDate, leapSeconds, currentLeapSeconds, nextLeapSeconds, nextleapSecondsDate.ToLongDateString())); } else { TL.LogMessage("LeapSeconds", string.Format("Unable to parse leap second values from the line below - Year: {0}, Month: {1}, Day: {2}, Julian Day: {3},Leap seconds: {4}", yearString, monthString, dayString, julianDateString, leapSecondsString)); TL.LogMessage("LeapSeconds", string.Format("Corrupt line: {0}", lineOfText)); } } catch (Exception ex) { TL.LogMessageCrLf("LeapSeconds", ex.ToString()); } } } TL.BlankLine(); if (currentLeapSeconds == UNKNOWN_LEAP_SECONDS) // No valid leap seconds were found so indicate that this { profile.WriteProfile(GlobalItems.ASTROMETRY_SUBKEY, GlobalItems.AUTOMATIC_LEAP_SECONDS_VALUENAME, GlobalItems.AUTOMATIC_LEAP_SECONDS_NOT_AVAILABLE_DEFAULT); } else // Persist the current leap second value to the Profile { parameters.AutomaticLeapSecondsString = currentLeapSeconds.ToString(CultureInfo.InvariantCulture); // Also include a value that is in the SOFA library defaults but is not in the USNO files. It pre-dates the start of UTC but I am assuming that IAU is correct on this occasion profile.WriteProfile(GlobalItems.AUTOMATIC_UPDATE_LEAP_SECOND_HISTORY_SUBKEY_NAME, double.Parse("2436934.5", CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture), double.Parse("1.4178180", CultureInfo.InvariantCulture).ToString(CultureInfo.InvariantCulture)); } // Persist the next leap second value and its implementation date if these have been announced if (nextleapSecondsDate == UNKNOWN_DATE) // No announcement has been made { parameters.NextLeapSecondsString = GlobalItems.DOWNLOAD_TASK_NEXT_LEAP_SECONDS_NOT_PUBLISHED_MESSAGE; parameters.NextLeapSecondsDateString = GlobalItems.DOWNLOAD_TASK_NEXT_LEAP_SECONDS_NOT_PUBLISHED_MESSAGE; } else // A future leap second has been announced { parameters.NextLeapSecondsString = nextLeapSeconds.ToString(CultureInfo.InvariantCulture); parameters.NextLeapSecondsDateString = nextleapSecondsDate.ToString(GlobalItems.DOWNLOAD_TASK_TIME_FORMAT, CultureInfo.InvariantCulture); } TL.BlankLine(); TL.LogMessage("LeapSeconds", string.Format("Current Leap Seconds = {0}, Next Leap Seconds: {1} on {2}", currentLeapSeconds, nextLeapSeconds, nextleapSecondsDate.ToLongDateString())); } } else { TL.LogMessage("LeapSeconds", string.Format("Downloaded file size was zero so nothing to process!")); } parameters.EarthRotationDataLastUpdatedString = runDate; // Save a new last run time to the Profile TL.BlankLine(); TL.LogMessage("LeapSeconds", string.Format("Task completed.")); File.Delete(leapSecondsfileName); parameters.Dispose(); parameters = null; } catch (WebException ex) // An issue occurred with receiving the leap second file over the network { TL.LogMessageCrLf("LeapSeconds", string.Format("Error: {0} - leap second data not updated.", ex.Message)); ReturnCode = 3; } catch (Exception ex) { TL.LogMessageCrLf("LeapSeconds", ex.ToString()); ReturnCode = 4; } TL.Enabled = false; TL.Dispose(); TL = null; } catch (Exception ex) { try { TL.LogMessageCrLf("EarthRotationUpdate", ex.ToString()); } catch { } EventLogCode.LogEvent("EarthRotationUpdate", string.Format("EarthRotationUpdate - Unexpected exception: {0}", ex.Message), EventLogEntryType.Error, GlobalConstants.EventLogErrors.EarthRotationUpdate, ex.ToString()); ReturnCode = 5; } Environment.Exit(ReturnCode); }
/// <summary> /// Event handler for Connect button /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnConnect_Click(System.Object sender, System.EventArgs e) { bool usedConnected = true; TL = new TraceLogger("", TRACE_LOGGER_NAME); TL.Enabled = true; dynamic driver = null; try { txtStatus.Clear(); LogMsg("Create", "Creating device"); Type type = Type.GetTypeFromProgID(CurrentDevice); driver = Activator.CreateInstance(type); LogMsg("Connected", "Connecting to device"); if (CurrentDeviceType.ToUpperInvariant() == "FOCUSER") { try { LogMsg("Connected", "Trying Connected"); driver.Connected = true; } catch (Exception ex) { LogMsg("Connected", "Trying Link: " + ex.Message); driver.Link = true; usedConnected = false; } } else { driver.Connected = true; } LogMsg("", ""); try { LogMsg("Name", driver.Name); } catch (Exception ex) { LogMsg("Name", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Description", driver.Description); } catch (Exception ex) { LogMsg("Description", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("DriverInfo", driver.DriverInfo); } catch (Exception ex) { LogMsg("DriverInfo", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("DriverVersion", driver.DriverVersion); } catch (Exception ex) { LogMsg("DriverVersion", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("InterfaceVersion", driver.InterfaceVersion.ToString()); } catch (Exception ex) { LogMsg("InterfaceVersion", "Property not available - " + ex.Message); ex.ToString(); } // Device specific commands switch (CurrentDeviceType.ToUpperInvariant()) { case "TELESCOPE": try { LogMsg("RA, Dec", Util.HoursToHMS(driver.RightAscension, ":", ":", "", 3) + " " + Util.DegreesToDMS(driver.Declination, ":", ":", "", 3)); } catch (Exception ex) { LogMsg("RA, Dec", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Latitude, Longitude", Util.DegreesToDMS(driver.SiteLatitude, ":", ":", "", 3) + " " + Util.DegreesToDMS(driver.SiteLongitude, ":", ":", "", 3)); } catch (Exception ex) { LogMsg("Latitude, Longitude", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Tracking", driver.Tracking.ToString()); } catch (Exception ex) { LogMsg("Tracking", "Property not available - " + ex.Message); ex.ToString(); } break; case "FOCUSER": try { LogMsg("IsMoving", driver.IsMoving.ToString()); } catch (Exception ex) { LogMsg("IsMoving", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Position", driver.Position.ToString()); } catch (Exception ex) { LogMsg("Position", "Property not available - " + ex.Message); ex.ToString(); } break; case "FILTERWHEEL": try { LogMsg("Position", driver.Position.ToString()); } catch (Exception ex) { LogMsg("Position", "Property not available - " + ex.Message); ex.ToString(); } try { string[] names = driver.Names; foreach (string name in names) { LogMsg("Filter name", name); } } catch (Exception ex) { LogMsg("Names", "Property not available - " + ex.Message); ex.ToString(); } break; case "ROTATOR": try { LogMsg("IsMoving", driver.IsMoving.ToString()); } catch (Exception ex) { LogMsg("IsMoving", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Position", driver.Position.ToString()); } catch (Exception ex) { LogMsg("Position", "Property not available - " + ex.Message); ex.ToString(); } break; case "DOME": try { LogMsg("Azimuth, Altitude", Util.DegreesToDMS(driver.Azimuth, ":", ":", "", 3) + " " + Util.DegreesToDMS(driver.Altitude, ":", ":", "", 3)); } catch (Exception ex) { LogMsg("Azimuth, Altitude", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("AtHome", driver.AtHome.ToString()); } catch (Exception ex) { LogMsg("AtHome", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("AtPark", driver.AtPark.ToString()); } catch (Exception ex) { LogMsg("AtPark", "Property not available - " + ex.Message); ex.ToString(); } break; case "CAMERA": try { LogMsg("CameraXSize", driver.CameraXSize.ToString()); } catch (Exception ex) { LogMsg("CameraXSize", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("CameraYSize", driver.CameraYSize.ToString()); } catch (Exception ex) { LogMsg("CameraYSize", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("BinX", driver.BinX.ToString()); } catch (Exception ex) { LogMsg("BinX", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("BinY", driver.BinY.ToString()); } catch (Exception ex) { LogMsg("BinY", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("MaxBinX", driver.MaxBinX.ToString()); } catch (Exception ex) { LogMsg("MaxBinX", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("MaxBinY", driver.MaxBinY.ToString()); } catch (Exception ex) { LogMsg("MaxBinY", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("HasShutter", driver.HasShutter.ToString()); } catch (Exception ex) { LogMsg("HasShutter", "Property not available - " + ex.Message); ex.ToString(); } break; case "VIDEO": try { LogMsg("Width", driver.Width.ToString()); } catch (Exception ex) { LogMsg("Width", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("Height", driver.Height.ToString()); } catch (Exception ex) { LogMsg("Height", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("ExposureMax", driver.ExposureMax.ToString()); } catch (Exception ex) { LogMsg("ExposureMax", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("ExposureMin", driver.ExposureMin.ToString()); } catch (Exception ex) { LogMsg("ExposureMin", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("FrameRate", driver.FrameRate.ToString()); } catch (Exception ex) { LogMsg("FrameRate", "Property not available - " + ex.Message); ex.ToString(); } try { LogMsg("CanConfigureDevice", driver.CanConfigureDeviceProperties.ToString()); } catch (Exception ex) { LogMsg("CanConfigureDevice", "Property not available - " + ex.Message); ex.ToString(); } break; case "SWITCH": try { LogMsg("MaxSwitch", driver.MaxSwitch.ToString()); } catch (Exception ex) { LogMsg("MaxSwitch", "Property not available - " + ex.Message); ex.ToString(); } break; case "SAFETYMONITOR": try { LogMsg("IsSafe", driver.IsSafe.ToString()); } catch (Exception ex) { LogMsg("IsSafe", "Property not available - " + ex.Message); ex.ToString(); } break; default: break; } LogMsg("", ""); LogMsg("Connected", "Disconnecting from device"); if (usedConnected) { driver.Connected = false; } else { driver.Link = false; } } catch (Exception ex) { LogMsg("Error", ex.ToString()); } finally { try { LogMsg("Dispose", "Disposing of device"); driver.Dispose(); LogMsg("Dispose", "Completed disposal"); } catch (System.NotImplementedException) { LogMsg("Dispose", "Dispose is not implemented inthis driver"); } catch (Exception ex1) { TL.LogMessageCrLf("Dispose error", ex1.ToString()); } try { LogMsg("ReleaseComObject", "Releasing COM instance"); int count = Marshal.ReleaseComObject(driver); LogMsg("ReleaseComObject", "Completed release. Count: " + count); } catch (Exception ex2) { TL.LogMessageCrLf("ReleaseComObject error", ex2.ToString()); } } try { LogMsg("GC Collect", "Starting garbage collection"); driver = null; GC.Collect(); LogMsg("GC Collect", "Completed garbage collection"); } catch (Exception ex) { TL.LogMessageCrLf("GC Collect", ex.ToString()); } TL.Enabled = false; TL.Dispose(); }
/// <summary> /// Trawls through the Platform source code base picking out all GUIDs explicitly defined. These are then written out as the /// GUIDList class in the RemoveASCOM program so that it can remove these from the user's PC. This dynamic approach is used so that this /// application is maintenance free as new GUIDs are added in future. /// /// This program is run by the build process before RemoveASCOM is compiled so that GUIDList is up to date. /// </summary> /// <param name="args">Accepts one parameter, the full path to the base of the Exported Platform source code.</param> /// <remarks> If the command line parameter is omitted the program will default to values appropriate to the development environment as oposed to the build environment.</remarks> static void Main(string[] args) { // Settings for use in the development environment, these are overriden by a command line argument in the build environment string developmentSearchPath = @"..\..\..\.."; string outputPath = @"\Remove ASCOM\Remove ASCOM\"; string devlopmentPath = developmentSearchPath + outputPath; string outputClassFileName = @"DynamicLists.vb"; string outputTextFileName = @"GUIDList.txt"; string platformInstallerTextFileName = @"\Releases\ASCOM 6\Platform\Installer Project\Ascom Platform 6.mia.txt"; string developerInstallerTextFileName = @"\Releases\ASCOM 6\Developer\Installer Project\ASCOM Platform 6 Developer.mia.txt"; // Construct the development environment values string sourceSearchPath = developmentSearchPath; string outputClassFullFileName = devlopmentPath + outputClassFileName; string outputTextFullFileName = devlopmentPath + outputTextFileName; string platformInstallerTextFileFullName = developmentSearchPath + platformInstallerTextFileName; string developerInstallerTextFileFullName = developmentSearchPath + developerInstallerTextFileName; // Storage for the GUIDs found and a suppression list of GUIDs that should be left undisturbed SortedList <string, string> guidList = new SortedList <string, string>(); List <string> guidSuppressionList = new List <string>(); // Storage for the lists of files installed by the Platform SortedSet <string> platformFileList = new SortedSet <string>(); SortedSet <string> developerFileList = new SortedSet <string>(); using (TraceLogger TL = new TraceLogger("", "MakeDynamicLists")) { TL.Enabled = true; // // Create the list of GUIDs created by the Platform // try { // Override the source and output paths if a command line search path is provided if (args.Length > 0) { sourceSearchPath = args[0]; outputClassFullFileName = args[0] + outputPath + outputClassFileName; outputTextFullFileName = args[0] + outputPath + outputTextFileName; platformInstallerTextFileFullName = args[0] + platformInstallerTextFileName; developerInstallerTextFileFullName = args[0] + developerInstallerTextFileName; } TL.LogMessage("Main", "Search path: " + Path.GetFullPath(sourceSearchPath)); TL.LogMessage("Main", "Output class file: " + Path.GetFullPath(outputClassFullFileName)); TL.LogMessage("Main", "Output text file: " + Path.GetFullPath(outputTextFullFileName)); // Add required items to the suppression list so that they are not deleted by RemoveASCOM when it runs guidSuppressionList.Add("00000001-0000-0000-C000-000000000046"); guidSuppressionList.Add("00000002-0000-0000-C000-000000000046"); // Set up a regular expression for a GUID format e.g.: Guid("0EF59E5C-2715-4E91-8A5E-38FE388B4F00") // Regular expression groups within the matched GUID: <-G1-><--------------G2------------------> // Group 2 picks out the GUID value inside the double quote characters. This is used as m.Groups[2] below Regex regexGuid = new Regex(@"(Guid\(\"")([0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12})""", RegexOptions.IgnoreCase); // Get a list of all the files with a .cs CSharp extension List <string> files = new List <string>(Directory.GetFiles(sourceSearchPath, "*.cs*", SearchOption.AllDirectories)); TL.LogMessage("Main", "Number of C# files found: " + files.Count); // Add the list of files with a .vb extension files.AddRange(new List <string>(Directory.GetFiles(sourceSearchPath, "*.vb*", SearchOption.AllDirectories))); TL.LogMessage("Main", "Total files found: " + files.Count); // Process the list of files opening each file in turn and searching every line with the GUID regular expression // Save every match except for those on the suppression list foreach (string file in files) { if (!file.Contains(Path.GetFileName(outputClassFullFileName))) // Process all files except our output file! { List <string> lines = new List <string>(File.ReadAllLines(file)); // Get all lines into a list foreach (string line in lines) // Iterate over the list of lines { Match m = regexGuid.Match(line); // Use the regular expression to search for a match if (m.Success) // We have found a GUID { try { // Check whether this a GUID to suppress if (!guidSuppressionList.Contains(m.Groups[2].ToString())) // Not suppressed { guidList.Add(m.Groups[2].ToString(), Path.GetFullPath(file)); // Add the GUID to the found GUIDs list TL.LogMessage("Main", "Match: " + m.Groups[2] + " in: " + file); } else // This GUID should be left alone so don't add it to the list { TL.LogMessage("Main", "Suppressing: " + m.Groups[2] + " in: " + file); } } catch (ArgumentException) // The GUID has already been added so ignore it as a duplicate { TL.LogMessage("Main", "Duplicate: " + m.Groups[2] + " in: " + file); } } } } } } catch (Exception ex) { TL.LogMessageCrLf("Main", "Exception creating GUID list: " + ex.ToString()); } TL.BlankLine(); // Create lists of "Install Files" lines in the Platform and Developer installer scripts platformFileList = FindInstalledFiles(platformInstallerTextFileFullName, TL); // Lines from the Platform installer developerFileList = FindInstalledFiles(developerInstallerTextFileFullName, TL); // Lines from the Developer installer. TL.BlankLine(); // // Create the class file that will be used by the RemoveASCOM program // try { // Create the streamwriter to make the updated GUIDList class file and the readable txt file StreamWriter outputTextFile = new StreamWriter(outputTextFullFileName); StreamWriter outputClassFile = new StreamWriter(outputClassFullFileName); // Add the first lines of the GUID text list outputTextFile.WriteLine(@"This is a list of the GUIDs that will be removed by RemoveASCOM"); outputTextFile.WriteLine(" "); // Add the first lines of the DynamicLists class outputClassFile.WriteLine(@"' ***** WARNING ***** WARNING ***** WARNING *****"); outputClassFile.WriteLine(" "); outputClassFile.WriteLine(@"' This class is dynamically generated by the MakeDynamicLists Program."); outputClassFile.WriteLine(@"' Do not alter this class, alter the MakeDynamicLists program instead and your changes will appear when the next build is made."); outputClassFile.WriteLine(" "); outputClassFile.WriteLine("Imports System.Collections.Generic"); outputClassFile.WriteLine("Imports System.IO"); outputClassFile.WriteLine(" "); outputClassFile.WriteLine("Class DynamicLists"); outputClassFile.WriteLine(""); // Add the first lines of the GUIDs member outputClassFile.WriteLine(" Shared Function GUIDs(TL as TraceLogger) As SortedList(Of String, String)"); outputClassFile.WriteLine(" Dim guidList As SortedList(Of String, String)"); outputClassFile.WriteLine(" guidList = New SortedList(Of String, String)"); // Add the GUIDs in the list foreach (KeyValuePair <string, string> guid in guidList) { TL.LogMessage("Main", "Adding to class: " + guid.Key + " in: " + guid.Value); outputClassFile.WriteLine(" Try : guidList.Add(\"" + guid.Key + "\", \"" + guid.Value + "\") :TL.LogMessage(\"GUIDs\",\"Added GUID: \" + \"" + guid.Key + "\") : Catch ex As ArgumentException : TL.LogMessage(\"GUIDs\",\"Duplicate GUID: \" + \"" + guid.Key + "\"):End Try"); outputTextFile.WriteLine(guid.Key + " defined in: " + guid.Value); } // Add the closing lines of the GUIDs member outputClassFile.WriteLine(" Return guidList"); outputClassFile.WriteLine(" End Function"); outputClassFile.WriteLine(""); // Add the first lines of the PlatformFiles member outputClassFile.WriteLine(" Shared Function PlatformFiles(TL as TraceLogger) As SortedSet(Of String)"); outputClassFile.WriteLine(" Dim fileList As SortedSet(Of String)"); outputClassFile.WriteLine(" fileList = New SortedSet(Of String)"); // Add the files in the list foreach (string file in platformFileList) { TL.LogMessage("Main", "Adding to class: " + file); outputClassFile.WriteLine(" Try : fileList.Add(\"" + file + "\") :TL.LogMessage(\"PlatformFiles\",\"Added file: " + file + "\") : Catch ex As Exception : TL.LogMessage(\"PlatformFiles\",\"Exception: \" + ex.ToString()):End Try"); } // Add the closing lines of the PlatformFiles member outputClassFile.WriteLine(" Return fileList"); outputClassFile.WriteLine(" End Function"); outputClassFile.WriteLine(""); // Add the first lines of the DeveloperFiles member outputClassFile.WriteLine(" Shared Function DeveloperFiles(TL as TraceLogger) As SortedSet(Of String)"); outputClassFile.WriteLine(" Dim fileList As SortedSet(Of String)"); outputClassFile.WriteLine(" fileList = New SortedSet(Of String)"); // Add the files in the list foreach (string file in developerFileList) { TL.LogMessage("Main", "Adding to class: " + file); outputClassFile.WriteLine(" Try : fileList.Add(\"" + file + "\") :TL.LogMessage(\"DeveloperFiles\",\"Added file: " + file + "\") : Catch ex As Exception : TL.LogMessage(\"PlatformFiles\",\"Exception: \" + ex.ToString()):End Try"); } // Add the closing lines of the DeveloperFiles member outputClassFile.WriteLine(" Return fileList"); outputClassFile.WriteLine(" End Function"); outputClassFile.WriteLine(""); // Add the closing lines of the DynamicLists class outputClassFile.WriteLine("End Class"); // Close the files outputTextFile.Flush(); outputTextFile.Close(); outputClassFile.Flush(); outputClassFile.Close(); } catch (Exception ex) { TL.LogMessageCrLf("Main", "Exception writing class file: " + ex.ToString()); } } }
static SortedSet <string> FindInstalledFiles(string installerTextFileFullName, TraceLogger TL) { SortedSet <String> fileList; // Variable to hold the returned list of Install File lines try { fileList = new SortedSet <string>(); // Create a SortedSet to hold the lines returned // Set up a regular expression to pick out the file name and install path from an Installaware Install Files line // Comment: Install Files ..\..\..\..\ASCOM.Utilities\ASCOM.Utilities\bin\Release\ASCOM.Utilities.dll to $COMMONFILES$\ASCOM\Platform\v6 // Groups within the matched line: <Comment> <---------------------------------FileName--------------------------------> <---------InstallPath---------> Regex regexInstallFile = new Regex(@"\s*(?<Comment>[\w\W]*)\sInstall Files\s*(?<FileName>[\w\W]*) to (?<InstallPath>[\w\W]*)", RegexOptions.IgnoreCase); // Set up a regular expression to pick out the compiler variable from the InstallPath part of an Installaware Install Files line // $COMMONFILES$\ASCOM\Platform\v6 // Group within the matched line: <--CompVar--> Regex regexInstallerVariables = new Regex(@"\$(?<CompVar>[\w]*)\$.*", RegexOptions.IgnoreCase); // Create the list of installer lines to be processed TL.LogMessage("FindInstalledFiles", "Reading installer file: " + installerTextFileFullName); List <string> lines = new List <string>(File.ReadAllLines(installerTextFileFullName)); // Get all Platform installer lines into a list // Iterate over the list of lines identifying "Install File" lines and recording them for use by the RemoveASCOM program foreach (string line in lines) { Match m = regexInstallFile.Match(line); // Use the regular expression to search for a match if (m.Success) // We have found an installed file { if (!m.Groups["Comment"].ToString().ToUpperInvariant().Contains("COMMENT:")) // Process non comment lines { TL.LogMessage("FindInstalledFiles", "Found installed file: " + m.Groups["FileName"].ToString() + " " + m.Groups["InstallPath"].ToString()); // Now check whether it has a variable Match mVar = regexInstallerVariables.Match(m.Groups["InstallPath"].ToString()); if (mVar.Success) // Yes, we have a compiler variable { switch (mVar.Groups["CompVar"].ToString().ToUpperInvariant()) // Check that the variable is recognised { case "TARGETDIR": // These are the recognised variables for files that should be cleaned up by RemoveASCOM case "COMMONFILES": case "COMMONFILES64": TL.LogMessage("Main", "Found: " + mVar.Groups["CompVar"].ToString() + ", including this file"); string targetFullFileName = m.Groups["InstallPath"].ToString() + @"\" + Path.GetFileName(m.Groups["FileName"].ToString()); fileList.Add(targetFullFileName); break; case "WINSYSDIR": // These are the variables used where files should be left in place by RemoveASCOM case "WINDIR": TL.LogMessage("Main", "Found WINDIR or WINSYSDIR, ignoring this file"); break; default: // Throw an error if a new variable is encountered so that it can be added to one of the preceeding groups. TL.LogMessage("FindInstalledFiles", "ERROR - Found UNKNOWN COMPILER VARIABLE: " + mVar.Groups["CompVar"].ToString() + " in line: " + line); MessageBox.Show("ERROR - Found UNKNOWN COMPILER VARIABLE: " + mVar.Groups["CompVar"].ToString() + " in line: " + line, "MakeDynamicLists Build Environment Program", MessageBoxButtons.OK, MessageBoxIcon.Exclamation); Environment.Exit(1); break; } } } else { TL.LogMessage("FindInstalledFiles", "Ignoring comment line: " + line); } } else // This is not an "Install Files" line so ignore it { } } return(fileList); } catch (Exception ex) { TL.LogMessageCrLf("FindInstalledFiles", "Exception reading installer text file: " + ex.ToString()); return(new SortedSet <string>()); } }