/// <summary> /// Handles all setup tasks as the form is loaded. /// </summary> /// <param name="sender">Contains the object of the control or object that generated the event.</param> /// <param name="e">Contains all the event data.</param> private void MetroWindow_Loaded(object sender, RoutedEventArgs e) { // Parse Application Launch Switches string[] CmdArgs = Environment.GetCommandLineArgs(); OptionSet Options = new OptionSet() { { "d|dev|development", v => Development = true }, { "s=|settings=", (string v) => AppSettingsJson = v } }; List <string> extra; try { extra = Options.Parse(CmdArgs); } catch (OptionException Ex) { MessageBox.Show("Error parsing the arguments: " + Ex.Message); } string SettingsFile = File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), AppSettingsJson)); try { Settings = JsonConvert.DeserializeObject <AppSettings>(SettingsFile); } catch (JsonException ex) { MessageBox.Show(ex.Message, "Error parsing JSON", MessageBoxButton.OK, MessageBoxImage.Error); Environment.Exit(22); } // Setup WebService WebService = new ConfigMgrWebService(Settings.WebServiceURI); // Universal Code (Both PE and Windows) if (Development) { MessageBox.Show("Development environment selected, will not work in production."); } else { Type EnvironmentType = Type.GetTypeFromProgID("Microsoft.SMS.TSEnvironment"); dynamic TSEnvironment = Activator.CreateInstance(EnvironmentType); if (TSEnvironment.Value["_SMSTSMachineName"] != null) { TextBoxComputerName.Text = TSEnvironment.Value["_SMSTSMachineName"]; } } // Use logo file BitmapImage OverlayImage = new BitmapImage(); OverlayImage.BeginInit(); OverlayImage.UriSource = new Uri(Path.Combine(AppDomain.CurrentDomain.BaseDirectory.ToString(), Settings.LogoSource)); OverlayImage.EndInit(); OverlayLogo.Width = Settings.LogoWidth; OverlayLogo.Height = Settings.LogoHeight; OverlayLogo.Source = OverlayImage; // Setup all the tabs foreach (Tab tab in Settings.Tabs) { // Handle ComputerName Tab Settings if (tab.TabName == "TabComputerName") { if (!tab.Enabled) { TabControlMainWindow.Items.Remove(TabComputerName); } else { if (!tab.RuleGreaterLessThanEnabled) { GridComputerNameRules.Children.Remove(LabelRuleGreaterThan); GridComputerNameRules.Children.Remove(LabelRuleGreaterThanStatus); GridComputerNameRules.Children.Remove(LabelRuleLessThan); GridComputerNameRules.Children.Remove(LabelRuleLessThanStatus); ButtonComputerNameNext.IsEnabled = true; } else { LabelRuleGreaterThan.Content = "REQ - Length >= " + tab.RuleGreaterThan + ":"; LabelRuleLessThan.Content = "REQ - Length <= " + tab.RuleLessThan + ":"; ComputerNameGreaterThan = tab.RuleGreaterThan; ComputerNameLessThan = tab.RuleLessThan; } if (!tab.RuleStartsWithEnabled) { GridComputerNameRules.Children.Remove(LabelRuleStartsWith); GridComputerNameRules.Children.Remove(LabelRuleStartsWithStatus); } else { LabelRuleStartsWith.Content = "REQ - Starts With " + tab.RuleStartsWith + ":"; ComputerNameStartsWith = tab.RuleStartsWith; } if (!tab.RuleEndsWithEnabled) { GridComputerNameRules.Children.Remove(LabelRuleEndsWith); GridComputerNameRules.Children.Remove(LabelRuleEndsWithStatus); } else { LabelRuleEndsWith.Content = "REQ - Ends With " + tab.RuleEndsWith + ":"; ComputerNameEndsWith = tab.RuleEndsWith; } } } if (tab.TabName == "TabComputerBind") { if (!tab.Enabled) { TabControlMainWindow.Items.Remove(TabComputerBind); } else { foreach (BindLocations BindLocation in tab.BindLocations) { TreeViewItem RootOU = new TreeViewItem { Header = BindLocation.RootName, IsExpanded = false, Focusable = false }; TreeViewComputerBind.Items.Add(RootOU); try { ADOrganizationalUnit[] organizationalUnits = WebService.GetADOrganizationalUnits(Settings.WebServiceKey, BindLocation.OU); foreach (ADOrganizationalUnit ou in organizationalUnits) { TreeViewItem subTreeItem = new TreeViewItem { Header = ou.Name, IsExpanded = false, Tag = ou.DistinguishedName }; RootOU.Items.Add(subTreeItem); if (ou.HasChildren) { subTreeItem.Focusable = false; AddChildADNodes(ou, subTreeItem); } } } catch { MessageBox.Show("Error on AD entry: " + BindLocation.OU); } } } } // Handle Pre Flight Checks Tab Settings if (tab.TabName == "TabPreFlight") { if (!tab.Enabled) { TabControlMainWindow.Items.Remove(TabPreFlight); } else { foreach (PreFlightCheck preFlightCheck in tab.PreFlightChecks) { bool CheckPass; PreFlightCheckers preFlightCheckers = new PreFlightCheckers(); RowDefinition newRow = new RowDefinition { Height = GridLength.Auto }; GridPreFlightChecks.RowDefinitions.Add(newRow); Label newLabelDescription = new Label { Content = preFlightCheck.CheckDescription }; GridPreFlightChecks.Children.Add(newLabelDescription); Grid.SetRow(newLabelDescription, GridPreFlightChecks.RowDefinitions.Count - 1); Grid.SetColumn(newLabelDescription, 0); switch (preFlightCheck.CheckType) { case "offlineFilesDetected": if (preFlightCheck.CheckPassState == preFlightCheckers.OfflineFilesDetected()) { CheckPass = true; } else { CheckPass = false; } break; case "physicalDiskCount": if (preFlightCheckers.PhysicalDiskCount(preFlightCheck.DiskCheckLimit)) { CheckPass = true; } else { CheckPass = false; } break; case "ethernetConnected": if (preFlightCheckers.EthernetNetworkConnectionDetected()) { CheckPass = true; } else { CheckPass = false; } break; case "networkConnectivityCheck": if (preFlightCheckers.TestNetworkConnectivity(preFlightCheck.NetworkAddress)) { CheckPass = true; } else { CheckPass = false; } break; case "64bitOS": if (Environment.Is64BitOperatingSystem) { CheckPass = true; } else { CheckPass = false; } break; default: CheckPass = false; break; } if (preFlightCheck.Required && !CheckPass) { PreFlightPass = false; } Label newLabelStatus = new Label(); if (CheckPass) { newLabelStatus.Content = "Pass"; newLabelStatus.Foreground = (Brush)Application.Current.Resources["ValidItemBrush"]; } else { newLabelStatus.Content = "Fail"; newLabelStatus.Foreground = (Brush)Application.Current.Resources["InvalidItemBrush"]; } GridPreFlightChecks.Children.Add(newLabelStatus); Grid.SetRow(newLabelStatus, GridPreFlightChecks.RowDefinitions.Count - 1); Grid.SetColumn(newLabelStatus, 1); } } } if (tab.TabName == "TabUserProfiles") { if (!tab.Enabled) { TabControlMainWindow.Items.Remove(TabUserProfiles); } else { SelectQuery Win32UserProfile = new SelectQuery("SELECT * FROM Win32_UserProfile WHERE Loaded != True"); ManagementObjectSearcher Searcher = new ManagementObjectSearcher(Win32UserProfile); SecurityIdentifier CurrentUser = null; try { CurrentUser = WindowsIdentity.GetCurrent().User; } catch { MessageBox.Show("Error getting current user."); } foreach (ManagementObject Profile in Searcher.Get()) { try { string UserProfileName = new SecurityIdentifier(Profile["SID"].ToString()).Translate(typeof(NTAccount)).ToString(); string UserProfileSid = Profile["SID"].ToString(); if (CurrentUser.Value != UserProfileSid.ToUpper()) { if (tab.DomainUsersOnly) { if (UserProfileName.StartsWith(tab.UserDomainPrefix)) { ListBoxUserProfiles.Items.Add(UserProfileName); } } else { ListBoxUserProfiles.Items.Add(UserProfileName); } } } catch (IdentityNotMappedException) { string userProfileName = Profile["LocalPath"].ToString(); string userProfileSid = Profile["SID"].ToString(); ListBoxUserProfiles.Items.Add(userProfileName); } } } } if (tab.TabName == "TabApplications") { if (!tab.Enabled) { TabControlMainWindow.Items.Remove(TabApplications); } else { foreach (SoftwareSection SoftwareSection in Settings.SoftwareSections) { TreeViewItem SectionHeader = new TreeViewItem { Header = SoftwareSection.SoftwareSectionName, IsExpanded = true }; foreach (SoftwareSubCategory SoftwareCategory in SoftwareSection.SubCategories) { TreeViewItem CategoryHeader = new TreeViewItem { Header = SoftwareCategory.CategoryName, IsExpanded = true }; CMApplication[] CategoryApps = WebService.GetCMApplicationByCategory(Settings.WebServiceKey, SoftwareCategory.CategorySCCM); foreach (CMApplication Application in CategoryApps) { TreeViewItem App = new TreeViewItem { Header = new CheckBox { Content = Application.ApplicationName } }; CategoryHeader.Items.Add(App); } SectionHeader.Items.Add(CategoryHeader); } TreeViewApplications.Items.Add(SectionHeader); } } } if (tab.TabType == "CustomTab") { if (tab.Enabled) { FrontEndTab tabItem = new FrontEndTab(tab, Development); tabItem.NextButton.Click += NextButtonHandler; tabItem.ProcessTabLayout(tab.TabLayout); TabControlMainWindow.Items.Insert(TabControlMainWindow.Items.IndexOf(TabFinish), tabItem); CustomTabs.Add(tabItem); } } } }
/// <summary> /// Wraps the GetNetLocalGroupMembers call with a timeout, and then processes the results into objects /// </summary> /// <param name="computer"></param> /// <param name="rid">The relative ID of the group we want to query</param> /// <returns></returns> private static async Task <List <GenericMember> > GetNetLocalGroupMembers(Computer computer, LocalGroupRids rid) { var sids = new IntPtr[0]; var groupMemberList = new List <GenericMember>(); var task = Task.Run(() => CallLocalGroupApi(computer, rid, out sids)); //Run the API call along with a 10 second timeout if (await Task.WhenAny(task, Task.Delay(10000)) != task) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Timeout", Task = $"GetNetLocalGroup-{rid}" }); return(groupMemberList); } //Check the result of the task var taskResult = task.Result; if (!taskResult) { return(groupMemberList); } if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Success", Task = $"GetNetLocalGroup-{rid}" }); } //Take our pointers to sids and convert them into string sids for matching var convertedSids = new List <string>(); for (var i = 0; i < sids.Length; i++) { try { var sid = new SecurityIdentifier(sids[i]).Value; convertedSids.Add(sid); } catch { //SID Resolution failed for some reason, so ignore it } finally { //Set the IntPtr to zero, so we can GC those sids[i] = IntPtr.Zero; } } //Null out sids, so garbage collection takes care of it sids = null; //Extract the domain SID from the computer's sid, to avoid creating more SecurityIdentifier objects var domainSid = computer.ObjectIdentifier.Substring(0, computer.ObjectIdentifier.LastIndexOf('-')); // The first account in our list should always be the default RID 500 for the machine, but we'll take some extra precautions var machineSid = convertedSids.DefaultIfEmpty("DUMMYSTRING").FirstOrDefault(x => x.EndsWith("-500") && !x.StartsWith(domainSid)) ?? "DUMMYSTRING"; //If we found a machine sid, strip the ending bit off if (machineSid.StartsWith("S-1-5-21")) { machineSid = machineSid.Substring(0, machineSid.LastIndexOf('-')); } foreach (var sid in convertedSids) { //Filter out local accounts if (sid.StartsWith(machineSid)) { continue; } var(finalSid, type) = await ResolutionHelpers.ResolveSidAndGetType(sid, computer.Domain); //Filter out null sids, usually from deconflictions if (finalSid == null) { continue; } groupMemberList.Add(new GenericMember { MemberType = type, MemberId = finalSid }); } return(groupMemberList); }
/// <summary> /// Wraps the GetNetLocalGroupMembers call with a timeout, and then processes the results into objects /// </summary> /// <param name="computer"></param> /// <param name="rid">The relative ID of the group we want to query</param> /// <returns></returns> private static async Task <List <GenericMember> > GetNetLocalGroupMembers(Computer computer, LocalGroupRids rid) { var sids = new IntPtr[0]; var groupMemberList = new List <GenericMember>(); var task = Task.Run(() => CallLocalGroupApi(computer, rid, out sids)); if (await Task.WhenAny(task, Task.Delay(10000)) != task) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Timeout", Task = $"GetNetLocalGroup-{rid}" }); return(groupMemberList); } var taskResult = task.Result; if (!taskResult) { return(groupMemberList); } if (Options.Instance.DumpComputerStatus) { OutputTasks.AddComputerStatus(new ComputerStatus { ComputerName = computer.DisplayName, Status = "Success", Task = $"GetNetLocaGroup-{rid}" }); } //Take our pointers to sids and convert them into string sids for matching var convertedSids = new List <string>(); for (var i = 0; i < sids.Length; i++) { try { var sid = new SecurityIdentifier(sids[i]).Value; convertedSids.Add(sid); } catch { // ignored } finally { //Set the IntPtr to zero, so we can GC those sids[i] = IntPtr.Zero; } } //Null out sids, so garbage collection takes care of it sids = null; //Extract the domain SID from the computer's sid, to avoid creating more SecurityIdentifier objects var domainSid = computer.ObjectIdentifier.Substring(0, computer.ObjectIdentifier.LastIndexOf('-')); string machineSid; // The first account in our list should always be the default RID 500 for the machine, but we'll take some extra precautions try { machineSid = convertedSids.First(x => x.EndsWith("-500") && !x.StartsWith(domainSid)); } catch { machineSid = "DUMMYSTRING"; } foreach (var sid in convertedSids) { if (sid.StartsWith(machineSid)) { continue; } LdapTypeEnum type; var finalSid = sid; if (CommonPrincipal.GetCommonSid(finalSid, out var common)) { finalSid = Helpers.ConvertCommonSid(sid, null); type = common.Type; } else { type = await Helpers.LookupSidType(sid); } groupMemberList.Add(new GenericMember { MemberType = type, MemberId = finalSid }); } return(groupMemberList); }