private static void ProcessOptions(Options opts) { TL.LogMessage("ProcessOptions", string.Format("Local server path: {0}", opts.LocalServerPath)); TL.LogMessage("ProcessOptions", string.Format("Remote server path: {0}", opts.RemoteServerPath)); TL.LogMessage("ProcessOptions", string.Format("API URI: {0}", opts.SetApiUriAcl)); TL.LogMessage("ProcessOptions", string.Format("Manafgement URI: {0}", opts.SetManagementUriAcl)); TL.BlankLine(); // Set firewall rules depending on which command line parameter was supplied if (opts.LocalServerPath != NOT_PRESENT_FLAG) { SetFireWallRules(opts.LocalServerPath, LOCAL_SERVER_RULE_NAME_BASE); } if (opts.RemoteServerPath != NOT_PRESENT_FLAG) { SetFireWallRules(opts.RemoteServerPath, REMOTE_SERVER_RULE_NAME_BASE); } // Set http.sys ACLs as needed if (opts.SetApiUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetApiUriAcl); } if (opts.SetManagementUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetManagementUriAcl); } }
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; } }
private static void ProcessOptions(Options opts) { TL.LogMessage("ProcessOptions", $"Local server path: {opts.LocalServerPath}"); TL.LogMessage("ProcessOptions", $"API URI: {opts.SetApiUriAcl}"); TL.LogMessage("ProcessOptions", $"Remote server management URI: {opts.SetRemoteServerManagementUriAcl}"); TL.LogMessage("ProcessOptions", $"Alpaca device management URI: {opts.SetAlpacaManagementUriAcl}"); TL.LogMessage("ProcessOptions", $"Alpaca device HTML setup URI: {opts.SetAlpacaSetupUriAcl}"); TL.LogMessage("ProcessOptions", $"HTTP.SYS port: {opts.HttpDotSysPort}"); TL.LogMessage("ProcessOptions", $"HTTP.SYS supplied user name: {opts.UserName}"); // Get the supplied user name but substitute the current user name if none was supplied string userName = $"\"{opts.UserName}\""; if (userName == NOT_PRESENT_FLAG) { userName = $"{Environment.UserDomainName}\\{Environment.UserName}"; } TL.LogMessage("ProcessOptions", $"HTTP.SYS user name that will be used: {userName}"); TL.BlankLine(); // Set firewall rules as needed if (opts.LocalServerPath != NOT_PRESENT_FLAG) { SetLocalServerFireWallOutboundRule(opts.LocalServerPath); } if (opts.HttpDotSysPort != NOT_PRESENT_FLAG) { SetHttpSysFireWallInboundRule(opts.HttpDotSysPort); } // Set http.sys ACLs as needed if (opts.SetApiUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetApiUriAcl, userName); } if (opts.SetRemoteServerManagementUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetRemoteServerManagementUriAcl, userName); } if (opts.SetAlpacaManagementUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetAlpacaManagementUriAcl, userName); } if (opts.SetAlpacaSetupUriAcl != NOT_PRESENT_FLAG) { SetAcl(opts.SetAlpacaSetupUriAcl, userName); } }
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); }
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> /// 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()); } } }
/// <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()); } }
/// <summary> /// Calls a method on an object dynamically. /// /// parameterTypes must match the parameters and in the same order. /// </summary> /// <param name="memberCode">1-GetProperty, 2-SetProperty, 3-Method</param> /// <param name="memberName">The member name to call as a string</param> /// <param name="parameterTypes">Array of paramerter types in order</param> /// <param name="parms">Array of parameters in order</param> /// <exception cref="PropertyNotImplementedException"></exception> /// <exception cref="MethodNotImplementedException"></exception> /// <returns>object</returns> internal object CallMember(int memberCode, string memberName, Type[] parameterTypes, params object[] parms) { TL.BlankLine(); switch (memberCode) { case 1: // Property Read PropertyInfo propertyGetInfo = GetObjType.GetProperty(memberName); if (propertyGetInfo != null) // We have a .NET object { TL.LogMessage(memberName + " Get", "GET " + memberName + " - .NET"); try { //run the .net object object result = propertyGetInfo.GetValue(GetLateBoundObject, null); TL.LogMessage(memberName + " Get", " " + result.ToString()); return(result); } catch (TargetInvocationException e) { GetTargetInvocationExceptionHandler(memberName, e); } catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } //check the type to see if it's a COM object if (IsComObject) // We have a COM object { TL.LogMessage(memberName + " Get", "GET " + memberName + " - COM"); try { //run the COM object property object result = GetObjType.InvokeMember(memberName, BindingFlags.Default | BindingFlags.GetProperty, null, GetLateBoundObject, new object[] { }, CultureInfo.InvariantCulture); TL.LogMessage(memberName + " Get", " " + result.ToString()); return(result); } catch (COMException e) { TL.LogMessageCrLf("COMException", e.ToString()); if (e.ErrorCode == int.Parse("80020006", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName + " Get", " Throwing PropertyNotImplementedException: " + _strProgId + " " + memberName); throw new PropertyNotImplementedException(_strProgId + " " + memberName, false, e); } TL.LogMessageCrLf(memberName + " Get", "Re-throwing exception"); throw; } catch (TargetInvocationException e) { TL.LogMessageCrLf("TargetInvocationException", e.ToString()); if (e.InnerException is COMException) { string message = e.InnerException.Message; int errorcode = ((COMException)e.InnerException).ErrorCode; // Telescope simulator in V1 mode throws not implemented exceptions rather than some kind of missing member exception, so test for this! if (errorcode == int.Parse("80040400", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName + " Get", " Translating COM not implemented exception to PropertyNotImplementedException: " + _strProgId + " " + memberName); throw new PropertyNotImplementedException(_strProgId + " " + memberName, false, e); } else // Throw a new COM exception that looks like the original exception, containing the original inner COM exception for reference { TL.LogMessageCrLf(memberName + " Get", "COM Exception so throwing inner exception: '" + message + "' '0x" + String.Format("{0:x8}", errorcode) + "'"); throw new DriverAccessCOMException(message, errorcode, e); } } GetTargetInvocationExceptionHandler(memberName, e); } catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } //evertyhing failed so throw an exception TL.LogMessage(memberName + " Get", " The object is neither a .NET object nor a COM object!"); throw new PropertyNotImplementedException(_strProgId + " " + memberName, false); case 2: // Property Write PropertyInfo propertySetInfo = GetObjType.GetProperty(memberName); if (propertySetInfo != null) // We have a .NET object { TL.LogMessage(memberName + " Set", "SET " + memberName + " - .NET"); try { TL.LogMessage(memberName + " Set", " " + parms[0].ToString()); propertySetInfo.SetValue(GetLateBoundObject, parms[0], null); return(null); } catch (TargetInvocationException e) { SetTargetInvocationExceptionHandler(memberName, e); } catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } //check the type to see if it's a COM object if (IsComObject) { TL.LogMessage(memberName + " Set", "SET " + memberName + " - COM"); try { TL.LogMessage(memberName + " Set", " " + parms[0].ToString()); //run the COM object property GetObjType.InvokeMember(memberName, BindingFlags.Default | BindingFlags.SetProperty, null, GetLateBoundObject, parms, CultureInfo.InvariantCulture); return(null); } catch (COMException e) { TL.LogMessageCrLf("COMException", e.ToString()); if (e.ErrorCode == int.Parse("80020006", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName + " Set", " Throwing PropertyNotImplementedException: " + _strProgId + " " + memberName); throw new PropertyNotImplementedException(_strProgId + " " + memberName, true, e); } TL.LogMessageCrLf(memberName + " Set", " Re-throwing exception"); throw; } catch (TargetInvocationException e) { TL.LogMessageCrLf("TargetInvocationException", e.ToString()); if (e.InnerException is COMException) { string message = e.InnerException.Message; int errorcode = ((COMException)e.InnerException).ErrorCode; // Telescope simulator in V1 mode throws not implemented exceptions rather than some kind of missing member exception, so test for this! if (errorcode == int.Parse("80040400", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName + " Set", " Translating COM not implemented exception to PropertyNotImplementedException: " + _strProgId + " " + memberName); throw new PropertyNotImplementedException(_strProgId + " " + memberName, true, e); } else // Throw a new COM exception that looks like the original exception, containing the original inner COM exception for reference { TL.LogMessageCrLf(memberName + " Set", "COM Exception so throwing inner exception: '" + message + "' '0x" + String.Format("{0:x8}", errorcode) + "'"); throw new DriverAccessCOMException(message, errorcode, e); } } SetTargetInvocationExceptionHandler(memberName, e); } catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } //evertyhing failed so throw an exception TL.LogMessage("PropertySet", " The object is neither a .NET object nor a COM object!"); throw new PropertyNotImplementedException(_strProgId + " " + memberName, true); case 3: // Method TL.LogMessage(memberName, "Start"); /*foreach (Type t in parameterTypes) * { * TL.LogMessage(memberName, " Parameter: " + t.FullName); * }*/ var methodInfo = GetObjType.GetMethod(memberName); //, parameterTypes); //Peter: Had to take parameterTypes out to get CanMoveAxis to work with .NET drivers if (methodInfo != null) { //TL.LogMessage(memberName, " Got MethodInfo"); //ParameterInfo[] pars = methodInfo.GetParameters(); /*foreach (ParameterInfo p in pars) * { * TL.LogMessage(memberName, " Parameter: " + p.ParameterType); * } */ try { foreach (object parm in parms) { TL.LogMessage(memberName, " Parameter: " + parm.ToString()); } TL.LogMessage(memberName, " Calling " + memberName); object result = methodInfo.Invoke(GetLateBoundObject, parms); if (result == null) { TL.LogMessage(memberName, " Successfully called method, no return value"); } else { TL.LogMessage(memberName, " " + result.ToString()); } return(result); } catch (TargetInvocationException e) { MethodTargetInvocationExceptionHandler(memberName, e); } // Unexpected exception so throw it all to the client catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } //check the type to see if it's a COM object if (IsComObject) { try { //run the COM object method foreach (object parm in parms) { TL.LogMessage(memberName, " Parameter: " + parm.ToString()); } TL.LogMessage(memberName, " Calling " + memberName + " - it is a COM object"); object result = GetObjType.InvokeMember(memberName, BindingFlags.Default | BindingFlags.InvokeMethod, null, GetLateBoundObject, parms, CultureInfo.InvariantCulture); if (result == null) { TL.LogMessage(memberName, " Successfully called method, no return value"); } else { TL.LogMessage(memberName, " " + result.ToString()); } return(result); } catch (COMException e) { TL.LogMessageCrLf("COMException", e.ToString()); if (e.ErrorCode == int.Parse("80020006", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName, " Throwing MethodNotImplementedException: " + _strProgId + " " + memberName); throw new MethodNotImplementedException(_strProgId + " " + memberName); } TL.LogMessageCrLf(memberName, "Re-throwing exception"); throw; } catch (TargetInvocationException e) { TL.LogMessageCrLf("TargetInvocationException", e.ToString()); if (e.InnerException is COMException) { string message = e.InnerException.Message; int errorcode = ((COMException)e.InnerException).ErrorCode; // Telescope simulator in V1 mode throws not implemented exceptions rather than some kind of missing member exception, so test for this! if (errorcode == int.Parse("80040400", NumberStyles.HexNumber, CultureInfo.InvariantCulture)) { TL.LogMessageCrLf(memberName, " Translating COM not implemented exception to MethodNotImplementedException: " + _strProgId + " " + memberName); throw new MethodNotImplementedException(_strProgId + " " + memberName, e); } else // Throw a new COM exception that looks like the original exception, containing the original inner COM exception for reference { TL.LogMessageCrLf(memberName, " COM Exception so throwing inner exception: '" + message + "' '0x" + String.Format("{0:x8}", errorcode) + "'"); throw new DriverAccessCOMException(message, errorcode, e); } } MethodTargetInvocationExceptionHandler(memberName, e); } catch (Exception e) { TL.LogMessageCrLf("Exception", e.ToString()); throw; } } TL.LogMessage(memberName, " is neither a .NET object nor a COM object!"); throw new MethodNotImplementedException(_strProgId + " " + memberName); default: return(null); } }
/// <summary> /// Reads the current device configuration from the Profile and saves this for use elsewhere /// </summary> private void ReadConfiguration() { ArrayList deviceTypes = profile.RegisteredDeviceTypes; Regex regex = new Regex(REGEX_FORMAT_STRING, RegexOptions.Compiled | RegexOptions.IgnoreCase); deviceTypeSummary.Clear(); remoteDrivers.Clear(); // List all the up-down controls present foreach (Control ctrl in this.Controls) { if (ctrl.GetType() == typeof(NumericUpDown)) { TL.LogMessage("ReadConfiguration", string.Format("Found NumericUpDown control {0}", ctrl.Name)); ctrl.BackColor = SystemColors.Window; } } // Extract a list of the remote client drivers from the list of devices in the Profile foreach (string deviceType in deviceTypes) { ArrayList devices = profile.RegisteredDevices(deviceType); foreach (KeyValuePair device in devices) { Match match = regex.Match(device.Key); if (match.Success) { DriverRegistration foundDriver = new DriverRegistration(); foundDriver.ProgId = match.Groups["0"].Value; foundDriver.Number = int.Parse(match.Groups[DEVICE_NUMBER].Value, CultureInfo.InvariantCulture); foundDriver.DeviceType = match.Groups[DEVICE_TYPE].Value; remoteDrivers.Add(foundDriver); TL.LogMessage("ReadConfiguration", string.Format("{0} - {1} - {2}", foundDriver.ProgId, foundDriver.Number, foundDriver.DeviceType)); } } TL.BlankLine(); } // List the remote client drivers and create summary counts of client drivers of each device type foreach (string deviceType in deviceTypes) { List <DriverRegistration> result = (from s in remoteDrivers where s.DeviceType.Equals(deviceType, StringComparison.InvariantCultureIgnoreCase) select s).ToList(); foreach (DriverRegistration driver in result) { TL.LogMessage("ReadConfiguration", string.Format("{0} driver: {1} - {2} - {3}", deviceType, driver.ProgId, driver.Number, driver.DeviceType)); } deviceTypeSummary.Add(deviceType, result.Count); } // List the summary information foreach (string deviceType in deviceTypes) { TL.LogMessage("ReadConfiguration", string.Format("There are {0} {1} remote drivers", deviceTypeSummary[deviceType], deviceType)); } // Set the numeric up-down controls to the current number of drivers of each type NumCamera.Value = deviceTypeSummary["Camera"]; NumDome.Value = deviceTypeSummary["Dome"]; NumFilterWheel.Value = deviceTypeSummary["FilterWheel"]; NumFocuser.Value = deviceTypeSummary["Focuser"]; NumObservingConditions.Value = deviceTypeSummary["ObservingConditions"]; NumRotator.Value = deviceTypeSummary["Rotator"]; NumSafetyMonitor.Value = deviceTypeSummary["SafetyMonitor"]; NumSwitch.Value = deviceTypeSummary["Switch"]; NumTelescope.Value = deviceTypeSummary["Telescope"]; }
static int Main(string[] args) { if (args[0].ToUpperInvariant() == "/SETPROFILEACL") // Set and check the Profile registry ACL { try { TL = new TraceLogger("", "SetProfileACL"); // Create a trace logger so we can log what happens TL.Enabled = true; // Create the Profile key if required and set its access rights LogMessage("SetRegistryACL", "Creating RegistryAccess object"); using (regAccess = new RegistryAccess(TL)) { LogMessage("SetRegistryACL", "Setting Profile registry ACL"); regAccess.SetRegistryACL(); } TL.BlankLine(); // Check whether the Profile key has the required access rights using (RegistryKey hklm32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32)) { if (!UserhasFullProfileAccessRights(hklm32, REGISTRY_ROOT_KEY_NAME)) { returnCode = 99; } } } catch (Exception ex) { LogError("SetProfileACL", ex.ToString()); returnCode = 1; } } else // Remove previous platforms, if present { try { TL = new TraceLogger("", "UninstallASCOM"); // Create a trace logger so we can log what happens TL.Enabled = true; LogMessage("Uninstall", "Creating RegistryAccess object"); regAccess = new RegistryAccess(TL); //Create a RegistryAccess object that will use the UninstallASCOM trace logger to ensure all messages appear in one log file // This has been removed because it destroys the ability to remove 5.5 after use and does NOT restore all the // Platform 5 files resulting in an unexpected automatic repair. Its left here just in case, Please DO NOT RE-ENABLE THIS FEATURE unless have a way round the resulting issues // CreateRestorePoint(); LogMessage("Uninstall", "Removing previous versions of ASCOM...."); //Initial setup bool is64BitProcess = (IntPtr.Size == 8); bool is64BitOperatingSystem = is64BitProcess || InternalCheckIsWow64(); LogMessage("Uninstall", "OS is 64bit: " + is64BitOperatingSystem.ToString() + ", Process is 64bit: " + is64BitProcess.ToString()); string platform4164KeyValue = null; string platform564aKeyValue = null; string platform564bKeyValue = null; string platform564KeyValue = null; string platform5564KeyValue = null; bool found = false; if (is64BitOperatingSystem) // Is a 64bit OS { platform4164KeyValue = Read(UNINSTALL_STRING, PLATFORM_4164); // Read the 4.1 uninstall string platform5564KeyValue = Read(UNINSTALL_STRING, PLATFORM_5564); // Read the 5.5 uninstall string platform564aKeyValue = Read(UNINSTALL_STRING, PLATFORM_564a); // Read the 5.0A uninstall string platform564bKeyValue = Read(UNINSTALL_STRING, PLATFORM_564b); // Read the 5.0B uninstall string if (platform564bKeyValue != null) // We have a 5.0B value so go with this { platform564KeyValue = platform564bKeyValue; LogMessage("Uninstall", "Found 64bit Platform 5.0B"); } else if (platform564aKeyValue != null) // No 5.0B value so go with 5.0A if it is present { platform564KeyValue = platform564aKeyValue; LogMessage("Uninstall", "Found 64bit Platform 5.0A"); //Now have to fix a missing registry key that fouls up the uninstaller - this was fixed in 5B but prevents 5A from uninstalling on 64bit systems RegistryKey RKey = Registry.ClassesRoot.CreateSubKey(@"AppID\{DF2EB077-4D59-4231-9CB4-C61AD4ECB874}"); RKey.SetValue("", "Fixed registry key value"); RKey.Close(); RKey = null; LogMessage("Uninstall", @"Successfully set AppID\{DF2EB077-4D59-4231-9CB4-C61AD4ECB874}"); } StringBuilder Path = new StringBuilder(260); int rc = SHGetSpecialFolderPath(IntPtr.Zero, Path, CSIDL_PROGRAM_FILES_COMMONX86, 0); ascomDirectory = Path.ToString() + @"\ASCOM"; LogMessage("Uninstall", "64bit Common Files Path: " + ascomDirectory); } else //32 bit OS { ascomDirectory = Environment.GetFolderPath(Environment.SpecialFolder.CommonProgramFiles) + @"\ASCOM"; LogMessage("Uninstall", "32bit Common Files Path: " + ascomDirectory); } string platform4132KeyValue = Read(UNINSTALL_STRING, PLATFORM_4132); string platform5532KeyValue = Read(UNINSTALL_STRING, PLATFORM_5532); string platform532aKeyValue = Read(UNINSTALL_STRING, PLATFORM_532a); string platform532bKeyValue = Read(UNINSTALL_STRING, PLATFORM_532b); string platform532KeyValue = null; if (platform532bKeyValue != null) // We have a 5.0B value so go with this { platform532KeyValue = platform532bKeyValue; LogMessage("Uninstall", "Found 32bit Platform 5,0B"); } else if (platform532aKeyValue != null) // No 5.0B value so go with 5.0A if it is present { platform532KeyValue = platform532aKeyValue; LogMessage("Uninstall", "Found 32bit Platform 5,0A"); } // Backup the profile based on the latest platform installed if ((platform5564KeyValue != null) | (platform5532KeyValue != null)) { regAccess.BackupProfile("5.5"); } else if ((platform564KeyValue != null) | (platform532KeyValue != null)) { regAccess.BackupProfile("5"); } else { regAccess.BackupProfile(""); } //remove 5.5 if (platform5564KeyValue != null) { LogMessage("Uninstall", "64 Removing ASCOM 5.5... " + platform5564KeyValue); found = true; RunProcess(platform5564KeyValue, " /VERYSILENT /NORESTART /LOG"); RemoveAssembly("policy.1.0.ASCOM.DriverAccess"); // Remove left over policy file } else { if (platform5532KeyValue != null) { LogMessage("Uninstall", "32 Removing ASCOM 5.5... " + platform5532KeyValue); found = true; RunProcess(platform5532KeyValue, " /VERYSILENT /NORESTART /LOG"); RemoveAssembly("policy.1.0.ASCOM.DriverAccess"); // Remove left over policy file } } //remove 5.0 if (platform564KeyValue != null) { FixHelper("Helper.dll", 5, 0);// Original helpers should be in place at this point, check and fix if not to prevent Platform 5 uninstaller from failing FixHelper("Helper2.dll", 4, 0); LogMessage("Uninstall", "64 Removing ASCOM 5... " + platform564KeyValue); found = true; RunProcess("MsiExec.exe", SplitKey(platform564KeyValue)); } else { if (platform532KeyValue != null) { FixHelper("Helper.dll", 5, 0); FixHelper("Helper2.dll", 4, 0); LogMessage("Uninstall", "32 Removing ASCOM 5... " + platform532KeyValue); found = true; RunProcess("MsiExec.exe", SplitKey(platform532KeyValue)); } } //Remove 4.1 //remove 5.0 if (platform4164KeyValue != null) { LogMessage("Uninstall", "64 Removing ASCOM 4.1... " + platform4164KeyValue); found = true; string[] vals = platform4164KeyValue.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries); LogMessage("Uninstall", @"Found uninstall values: """ + vals[0] + @""", """ + vals[1] + @""""); RunProcess(vals[0], @"/S /Z " + vals[1]); CleanUp4(); } else { if (platform4132KeyValue != null) { LogMessage("Uninstall", "32 Removing ASCOM 4.1... " + platform4132KeyValue); found = true; string[] vals = platform4132KeyValue.Split(new string[] { " " }, System.StringSplitOptions.RemoveEmptyEntries); LogMessage("Uninstall", @"Found uninstall values: """ + vals[0] + @""", """ + vals[1] + @""""); RunProcess(vals[0], @"/S /Z " + vals[1]); CleanUp4(); } } if (found == true) { CleanUp55(); CleanUp5(); } else { LogMessage("Uninstall", "No previous platforms found"); } LogMessage("Uninstall", "Setting Profile registry ACL"); regAccess.SetRegistryACL(); // Restore the relevant profile based on the latest platform installed if ((platform5564KeyValue != null) | (platform5532KeyValue != null)) { LogMessage("Uninstall", "Restoring Platform 5.5 Profile"); regAccess.RestoreProfile("5.5"); } else if ((platform564KeyValue != null) | (platform532KeyValue != null)) { LogMessage("Uninstall", "Restoring Platform 5 Profile"); regAccess.RestoreProfile("5"); } LogMessage("Uninstall", "Disposing of registry access object"); regAccess.Dispose(); regAccess = null; LogMessage("Uninstall", "Completed uninstall process"); } catch (Exception ex) { LogError("Uninstall", ex.ToString()); returnCode = 1; } } TL.Enabled = false; // Clean up trace logger TL.Dispose(); return(returnCode); }
static private bool UserhasFullProfileAccessRights(RegistryKey key, string subKey) { RegistryKey sKey; bool foundFullAccess = false; string builtInUsers; try { builtInUsers = GetBuiltInUsers().ToUpperInvariant(); TL.LogMessage("RegistryRights", (subKey == "") ? key.Name.ToString() : key.Name.ToString() + @"\" + subKey); if (subKey == "") { sKey = key; } else { sKey = key.OpenSubKey(subKey); } RegistrySecurity sec = sKey.GetAccessControl(); // System.Security.AccessControl.AccessControlSections.All) foreach (RegistryAccessRule RegRule in sec.GetAccessRules(true, true, typeof(NTAccount))) // Iterate over the rule set and list them { try { TL.LogMessage("RegistryRights", RegRule.AccessControlType.ToString() + " " + RegRule.IdentityReference.ToString() + " " + RegRule.RegistryRights.ToString() + " / " + (RegRule.IsInherited ? "Inherited" : "NotInherited") + " / " + RegRule.InheritanceFlags.ToString() + " / " + RegRule.PropagationFlags.ToString()); } catch (Exception ex1) { TL.LogMessageCrLf("RegistryRights", "Issue formatting registry rights: " + ex1.ToString()); } if ((RegRule.IdentityReference.ToString().ToUpperInvariant() == builtInUsers) & (RegRule.RegistryRights == global::System.Security.AccessControl.RegistryRights.FullControl)) { foundFullAccess = true; } } if (foundFullAccess) { TL.BlankLine(); TL.LogMessage("RegistryRights", "OK - SubKey " + subKey + @" does have full registry access rights for BUILTIN\Users"); } else { LogError("RegistryRights", "Subkey " + subKey + @" does not have full access rights for BUILTIN\Users!"); } } catch (NullReferenceException) { TL.LogMessageCrLf("RegistryRights", "The subkey: " + key.Name + @"\" + subKey + " does not exist."); } catch (Exception ex) { TL.LogMessageCrLf("RegistryRights", "Issue reading registry rights: " + ex.ToString()); } TL.BlankLine(); return(foundFullAccess); }