} //end capture_data private void install_sibling() { string s_name_noext = "iedusm"; // install the OTHER program not this one (for update) string s_path = IEdu.get_software_destination_file_path(s_name_noext, false); bool install_as_service_enable = true; if (s_path == null) { //TODO: copy iedusm from somewhere s_path = IEdu.get_software_destination_file_path(s_name_noext, false); } if (s_path != null) { //see <https://stackoverflow.com/questions/2072288/installing-windows-service-programmatically>: //ManagedInstallerClass.InstallHelper(new string[] { s_path }); //starting it as per codemonkey from <https://stackoverflow.com/questions/1036713/automatically-start-a-windows-service-on-install>: //results in access denied (same if done manually, unless "Log on as" is changed from LocalService to Local System //serviceInstaller //using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName)) //using (ServiceController sc = new ServiceController("iedusm")) //{ // sc.Start(); //} //TODO: finish this (install IeduSM) } }
private static void detach_software(string[] names) { if (names != null) { if (names.Length > 0) { for (int i = 0; i < names.Length; i++) { string s_name = names[i]; string s_path = IEdu.get_software_destination_file_path(s_name, false); if (s_path != null) { if (!File.Exists(s_path)) { throw new ApplicationException("get_software_destination_file_path(" + s_name + ",false) returned a bad path (this should never happen when 2nd param is false--it should return null if service was not found in that case)"); } detach_service(s_path); } else { Console.Error.WriteLine("WARNING: " + s_name + " was already uninstalled."); } } } else { Console.Error.WriteLine("ERROR: detach_software got empty name array."); } } else { Console.Error.WriteLine("ERROR: detach_software got null name array."); } }
private void uninstall_sibling() { string s_name_noext = "iedusm"; //uninstall the OTHER program not this one (for update) string s_path = IEdu.get_software_destination_file_path(s_name_noext, false); if (s_path != null) { ManagedInstallerClass.InstallHelper(new string[] { "/u", s_path }); } else { Console.Error.WriteLine("iedup WARNING: " + s_path + " was already uninstalled."); } }
//private async Task ss_timer_Elapsed//would normally be a Task but ok not since is event --see https://stackoverflow.com/questions/39260486/is-it-okay-to-attach-async-event-handler-to-system-timers-timer //private async void ss_timer_ElapsedAsync(object sender, ElapsedEventArgs e) { // ss_timer.Stop(); // await Task.Run(() => capture_data()); // if (timers_enable&&(ss_timer!=null)) ss_timer.Start(); //} private void ss_timer_ElapsedSync(object sender, ElapsedEventArgs e) { ss_timer.Stop(); ss_timer.Enabled = false; if (settings.ContainsKey("delete_self_enable") && IEdu.is_true(settings["delete_self_enable"])) { //Process.Start("cmd.exe", "timeout 8 > Nul & Del " + // System.Reflection.Assembly.GetExecutingAssembly().Location); delete_self(5); //less than 8 since caller (such as iedusm) checks if still exists after 5 this.Stop(); } else { capture_data(); if (timers_enable && (ss_timer != null)) { ss_timer.Enabled = true; ss_timer.Start(); } } first_run_out_enable = false; }
//private async void capture_data() { private void capture_data() { string loggedOnUserName = null; Dictionary <string, string> body = new Dictionary <string, string>(); body["section"] = "track"; body["mode"] = "create"; body.Add("MachineName", Environment.MachineName); //string IP = Request.UserHostName; string HostName = IEdu.GetHostName(); // DetermineHostName(IP); body.Add("HostName", HostName); StreamWriter outs = null; if (debug_enable || first_run_out_enable) { outs = new StreamWriter(text_path); } if (outs != null && err != null) { outs.WriteLine(err); err = null; } try { //list logged on users as per Sameet from <https://stackoverflow.com/questions/1244000/find-out-the-current-users-username-when-multiple-users-are-logged-on> ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT UserName FROM Win32_ComputerSystem"); int session_count = 0; ManagementObjectCollection queryObjs = searcher.Get(); foreach (ManagementObject queryObj in queryObjs) { string prefix = "session_i_" + session_count.ToString() + "_"; //NOTE: iterating queryObj as a Dictionary results in "ManagementObjectSearcher does not contain a public definition for GetEnumerator" foreach (PropertyData pd in queryObj.Properties) { body.Add(prefix + pd.Name, pd.Value.ToString()); } loggedOnUserName = queryObj["UserName"].ToString(); loggedOnUserName = loggedOnUserName.Substring(loggedOnUserName.LastIndexOf('\\') + 1); body["UserName"] = loggedOnUserName; //TODO: only add if known to be current active local session user } if (!body.ContainsKey("UserName")) { //add all if active local session user was not found above: int user_count = 0; foreach (ManagementObject queryObj in queryObjs) { loggedOnUserName = queryObj["UserName"].ToString(); loggedOnUserName = loggedOnUserName.Substring(loggedOnUserName.LastIndexOf('\\') + 1); body.Add("UserNames_i_" + user_count, loggedOnUserName); } } } catch (Exception ex) { if (outs != null) { outs.WriteLine("Could not finish getting users: " + ex.ToString()); } } WlanClient client = new WlanClient(); // Wlan = new WlanClient(); try { int collected_count = 0; foreach (WlanClient.WlanInterface wlanIface in client.Interfaces) { string local_mac = ""; //System.Net.NetworkInformation.PhysicalAddress PhysicalAddress pa = wlanIface.NetworkInterface.GetPhysicalAddress(); local_mac = wlanIface.NetworkInterface.GetPhysicalAddress().ToString(); //wlanIface.InterfaceGuid.ToString(); if (!body.ContainsKey("MAC")) { body.Add("MAC", local_mac); } Wlan.WlanBssEntryN[] wlanBssEntries = wlanIface.GetNetworkBssList(); foreach (Wlan.WlanBssEntryN network in wlanBssEntries) { string prefix = "remotewifi_i_" + collected_count.ToString() + "_"; int rss = network.BaseEntry.rssi; //TODO: check network.IEs too // MessageBox.Show(rss.ToString()); byte[] remote_mac_bytes = network.BaseEntry.dot11Bssid; string remote_mac_s = ""; for (int i = 0; i < remote_mac_bytes.Length; i++) { remote_mac_s += remote_mac_bytes[i].ToString("x2").PadLeft(2, '0').ToUpper(); } body.Add(prefix + "MAC", remote_mac_s); body.Add(prefix + "SSID", System.Text.ASCIIEncoding.ASCII.GetString(network.BaseEntry.dot11Ssid.SSID).ToString().Trim(badchars)); body.Add(prefix + "signal_percent", network.BaseEntry.linkQuality.ToString()); body.Add(prefix + "type", network.BaseEntry.dot11BssType.ToString()); body.Add(prefix + "RSSID", rss.ToString()); collected_count++; } //end for remote nodes if (collected_count > 0) { break; //no need to check other Wireless adapters } } //end for wireless adapters if (outs != null) { foreach (KeyValuePair <string, string> entry in body) { outs.WriteLine(entry.Key + ": " + entry.Value); } } } catch (Exception ex) { if (outs != null) { outs.WriteLine(ex.Message); } } try{ if (outs != null) { outs.WriteLine("settings:"); } foreach (KeyValuePair <string, string> entry in settings) { if (outs != null) { outs.WriteLine(" " + entry.Key + ": " + entry.Value); } body["settings_k_" + entry.Key] = entry.Value; } if (debug_enable) { Thread.Sleep(500); // wait for file } } catch (Exception ex) { if (outs != null) { outs.WriteLine("error: could not finish appending settings to telemetry"); outs.WriteLine("exception: >"); outs.WriteLine(IEdu.foldable_yaml_value(" ", ex.ToString())); } } try { if (outs != null) { outs.WriteLine("settings_path: " + settings_path); } if (settings.ContainsKey("ping_url") && settings["ping_url"].Length > 0) { string form_method = null; //ok to be null--http_form will default to POST if (settings.ContainsKey("form_method")) { form_method = settings["form_method"]; } string response = IEdu.http_send_as_form(settings["ping_url"], form_method, body); if (outs != null) { outs.WriteLine("posted_to: " + settings["ping_url"]); outs.WriteLine("# empty response is ok below"); if (response != null) { outs.WriteLine("response: '" + response + "'"); } else { outs.WriteLine("response: ~"); } } if (response != null) { string[] responses = null; if (response.Contains("\n")) { responses = response.Split(new char[] { '\n' }); } else { responses = new string[] { response } }; string this_section = null; for (int r_i = 0; r_i < responses.Length; r_i++) { string this_response_trim = responses[r_i].Trim(); if (!this_response_trim.StartsWith("#") && this_response_trim.Length > 0) { if (this_response_trim.EndsWith(":") && !responses[r_i].StartsWith(" ")) { this_section = this_response_trim.Substring(0, this_response_trim.Length - 1); if (outs != null) { outs.WriteLine("notice: response contains object named " + this_section); } } else { if (!responses[r_i].StartsWith(" ")) { this_section = null; } int name_start_i = 0; int name_ender_i = this_response_trim.IndexOf(":", name_start_i); if (name_ender_i > -1) { string this_name = this_response_trim.Substring(name_start_i, name_ender_i - name_start_i); int val_start_i = name_ender_i + 1; string this_val = this_response_trim.Substring(val_start_i).Trim(); if (this_section == "null") { if (this_name == "success") { if (outs != null) { outs.WriteLine(responses[r_i]); } } else if (this_name == "error") { if (outs != null) { outs.WriteLine(responses[r_i]); } } else if (this_name == "notice") { if (outs != null) { outs.WriteLine(responses[r_i]); } } else { if (outs != null) { outs.WriteLine("warning: got unknown data \"" + responses[r_i] + "\" in unknown section named " + ((this_section != null)?("\"" + this_section + "\""):"null")); } } } else if (this_section == "settings") { settings[this_name] = this_val; if (outs != null) { outs.WriteLine("changed setting " + this_name + " to '" + this_val + "'"); } save_settings(); } else { if (outs != null) { outs.WriteLine("warning: found data \"" + responses[r_i] + "\" in unknown section named " + ((this_section != null)?("\"" + this_section + "\""):"null")); } } } else if (outs != null) { outs.WriteLine("error: bad syntax in a response line--missing ':' in '" + this_response_trim + "'"); } } } } } } else if (outs != null) { outs.WriteLine("error: missing ping_url in capture_data"); } } catch (Exception ex) { if (outs != null) { outs.WriteLine("error: Could not finish posting: " + ex.ToString()); } } if (outs != null) { try { outs.Close(); } catch {}; //don't care outs = null; } } //end capture_data
private static void update_software(string[] names) { if (names != null) { if (names.Length > 0) { Console.Error.WriteLine("update_software will check for already-installed versions in (list may have dups since forces check for x86 in environment variables):"); string[] destination_dir_paths = IEdu.get_software_destination_possible_folder_paths(names[0]); for (int j = 0; j < destination_dir_paths.Length; j++) { Console.Error.WriteLine(" - " + destination_dir_paths[j].Replace(char.ToString(Path.DirectorySeparatorChar) + names[0], "")); } Console.Error.WriteLine(); for (int i = 0; i < names.Length; i++) { bool copyfiles_enable = false; string s_name = names[i]; try { string source_file_path = IEdu.get_software_source_file_path(s_name); if (source_file_path == null) { string msg = "A source for " + s_name + " could not be found in:"; string[] sources = IEdu.get_software_source_expected_paths(s_name); for (int l = 0; l < sources.Length; l++) { msg += "\n - " + sources[l]; } throw new ApplicationException(msg); } string destination_file_path = IEdu.get_software_destination_file_path(s_name, false); //TODO: also update bool update_enable = true; //TODO: only enable if version changed if (destination_file_path == null) { Console.Error.WriteLine("update_software did not find the program " + s_name + ", so installing..."); string destination_folder_path = IEdu.get_software_destination_folder_path(s_name, true); if (source_file_path != null && File.Exists(source_file_path)) { //setup (copy files to destination) //guaranteed to not to return null when 2nd param is true if (!Directory.Exists(destination_folder_path)) { Directory.CreateDirectory(destination_folder_path); } copyfiles_enable = true; } else { Console.Error.WriteLine("ERROR: The missing service was not copied to " + destination_folder_path + " because the installer service could not find the install source in any of the following locations:"); string[] possible_sources = IEdu.get_software_source_expected_paths(s_name); for (int k = 0; k < possible_sources.Length; k++) { Console.Error.WriteLine(" - " + possible_sources[k]); } Console.Error.WriteLine(); } } else { if (update_enable) { IEduSM.detach_service(IEdu.get_software_destination_file_path(s_name, false)); copyfiles_enable = true; } } if (copyfiles_enable) { //we are already assured by get_service_path that the following doesn't exist since fell through to github: string new_s_path = IEdu.get_software_destination_file_path(s_name, true); Console.Error.WriteLine("Copying '" + s_name + "' from GitHub build folder to '" + new_s_path + "'"); try { if (File.Exists(new_s_path)) { File.Delete(new_s_path); } } catch (Exception exn) { Console.Error.WriteLine("Could not finish deleting old version of " + s_name + ": " + exn.ToString()); } if (!File.Exists(new_s_path)) { File.Copy(source_file_path, new_s_path); if (!File.Exists(new_s_path)) { Console.Error.WriteLine("Could not copy '" + source_file_path + "' to destination directory '" + IEdu.get_software_destination_folder_path(s_name, true) + "'. You must run this as Administrator."); } else { destination_file_path = IEdu.get_software_destination_file_path(s_name, false); } } else { Console.Error.WriteLine("Could not install " + s_name + " since old version couldn't be deleted (maybe you didn't have permission to delete the file, or didn't have permission to detach (\"uninstall\") a service [or stop services which would have to be done first if running])!"); } } if (destination_file_path != null) { if (copyfiles_enable) { //already copied files, but now need to install service SINCE they were (updated/added). //NOTE: get_service_path assures that s_path exists in this case // (if it was in GitHub folder, install to ProgramFiles was already tried, // and s_path changed to Program Files*\<s_name>\<s_name>.exe). // see <https://docs.microsoft.com/en-us/dotnet/framework/windows-services/walkthrough-creating-a-windows-service-application-in-the-component-designer#code-snippet-1> // via <https://stackoverflow.com/questions/2072288/installing-windows-service-programmatically>: //detach_software(new string[] {s_name}); //detach_service(s_path); //already done if existed0 ManagedInstallerClass.InstallHelper(new string[] { destination_file_path }); //Starting it as per codemonkey from <https://stackoverflow.com/questions/1036713/automatically-start-a-windows-service-on-install>: // results in access denied (same if done manually, unless "Log on as" is changed from LocalService to Local System //serviceInstaller //ServiceProcessInstaller serviceProcessInstaller1 = new ServiceProcessInstaller(); //serviceProcessInstaller1.Account = System.ServiceProcess.ServiceAccount.LocalSystem; //serviceProcessInstaller1.Installers //using (ServiceController sc = new ServiceController(s_name)) { // sc.ServiceType = ServiceType.InteractiveProcess;//TODO: is this correct? // sc.Start(); //} // and doesn't have a way to set account, so set in IEduInstaller.cs which inherits from Installer and don't call it manually /* * // --below won't work either since Commit is called by install utilities which know the state of the service (but don't need overload since can start it manually) * Installer installer; * * * installer = new Installer(); * ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller(); * serviceProcessInstaller.Account = ServiceAccount.LocalSystem; // Or whatever account you want * ServiceInstaller si = new ServiceInstaller(); * si.DelayedAutoStart = true; * si.DisplayName = s_name; * si.Description = s_name; * si.DisplayName = s_name; * //si.HelpText * //si.Installers * //si.Parent //do set since not child * si.ServiceName = s_name; * //si.ServicesDependedOn //do not set since not parent either * //si.Site // I dont' know what this does * si.StartType = ServiceStartMode.Automatic; * * //var serviceInstaller = new ServiceInstaller * //{ * // DisplayName = "Insert the display name here", * // StartType = ServiceStartMode.Automatic, // Or whatever startup type you want * // Description = "Insert a description for your service here", * // ServiceName = "Insert the service name here" * //}; * installer.Installers.Add(serviceProcessInstaller); // why was this _serviceProcessInstaller fre0n? * installer.Installers.Add(si); * installer.Commit(); */ Console.WriteLine("Trying to start service manually..."); ServiceController sc = new ServiceController(s_name); // using (ServiceController sc = new ServiceController(serviceInstaller.ServiceName)) //sc.ServiceType = ServiceType.InteractiveProcess; // TODO: why is this readonly and should it be changed somehow? sc.Start(); //or use IEduPServiceInstaller (see its cs file) based on fre0n's answer from <https://stackoverflow.com/questions/2253051/credentials-when-installing-windows-service/2253140#2253140>: } else { Console.Error.WriteLine("Update for " + s_name + " was not enabled/needed."); } } else { Console.Error.WriteLine("ERROR: Path to " + s_name + " could not be detected."); } } catch (Exception exn) { string var_msg = (names[i] != null)?("'" + names[i] + "'"):"null"; Console.Error.WriteLine("Could not finish update_software named " + var_msg + ":" + exn.ToString()); } } //end for i<names.Length } else { Console.Error.WriteLine("ERROR: update_software got empty names array"); } } else { Console.Error.WriteLine("ERROR: update_software got null names array"); } }
private static void uninstall_services(string[] names, bool delete_enable) { if (names != null) { if (names.Length > 0) { for (int i = 0; i < names.Length; i++) { try { string s_path = IEdu.get_software_destination_file_path(names[i], false); if (s_path != null) { detach_service(s_path); string parent_path = IEdu.get_software_destination_folder_path(names[i], false); //guaranteed to be non-null since s_path was non-null if (!File.Exists(s_path)) { throw new ApplicationException("file does not exist (this should never happen when 2nd param of get_software_destination_file_path is false)"); } if (delete_enable) { string service_uninstall_log_path = Path.Combine(parent_path, "iedup.InstallLog"); Console.WriteLine("Waiting for service uninstall to finish..."); if (File.Exists(service_uninstall_log_path)) { //TODO: maybe analyze that log //File.Delete(service_uninstall_log_path); } Thread.Sleep(5000); //wait for iedup.InstallLog to be written //TODO: see <https://stackoverflow.com/questions/10579679/c-sharp-winform-delete-folders-and-files-on-uninstall-permission-error> find out why access is denied in `File.Delete(s_path)` when s_path DOES exist and is detached (NOT "installed as service" anymore) -- service_uninstall_log_path can be deleted but s_path cannot. try { File.SetAttributes(s_path, FileAttributes.Normal); File.Delete(s_path); //true for recursive Directory.Delete(parent_path, true); //true for recursive } catch { Console.Error.WriteLine("File.Delete access to \"" + s_path + "\" was denied, trying system's delete command..."); Process.Start("cmd.exe", "timeout 5 > Nul & Del \"" + s_path + "\""); Thread.Sleep(8); if (File.Exists(s_path)) { Console.WriteLine("Still failed to delete, trying -delete-self option..."); Process.Start(s_path, "-delete_self"); //NOTE: doesn't run even if running is admin due to "magical" annoying Microsoft permission level for services Thread.Sleep(8); if (File.Exists(s_path)) { Console.WriteLine("WARNING: failed to delete '" + s_path + "'"); string this_progdata_path = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), names[i]); string this_settings_path = Path.Combine(this_progdata_path, "settings.yml"); ArrayList lines = new ArrayList(); bool is_found = false; //changing settings assumes target service is not running or will check date of settings file modification try { if (File.Exists(this_settings_path)) { StreamReader ins = new StreamReader(this_settings_path); string line; while ((line = ins.ReadLine()) != null) { if (line.StartsWith("delete_self_enable:")) { lines.Add("delete_self_enable: true"); is_found = true; } else { lines.Add(line); } } ins.Close(); StreamWriter outs = new StreamWriter(this_settings_path); foreach (string this_line in lines) { outs.WriteLine(this_line); } if (!is_found) { outs.WriteLine("delete_self_enable: true"); } outs.Close(); } } catch (Exception exn) { Console.Error.WriteLine(exn.ToString()); } } } } } } else { Console.Error.WriteLine("WARNING in uninstall_services: " + names[i] + " was already removed."); } } catch (Exception exn) { string var_msg = (names[i] != null)?("'" + names[i] + "'"):"null"; Console.Error.WriteLine("Could not finish uninstalling service named " + var_msg + " in uninstall_services(...," + (delete_enable?"true":"false") + "):" + exn.ToString()); } } } else { Console.Error.WriteLine("ERROR: uninstall_services got empty paths array."); } } else { Console.Error.WriteLine("ERROR: uninstall_services got null paths array."); } }