Public/SCJBServerTeamTools.ps1
function SCJBServerTeamTools { <# .LINK https://www.powershellgallery.com/packages/SCJBServerTeamTools .EXAMPLE SCJBServerTeamTools Open to the home window .EXAMPLE SCJBServerTeamTools -QuickLaunch ADLookups Open to the ADLookups window .EXAMPLE SCJBServerTeamTools -QuickLaunch RSOP Open to the RSOP window .EXAMPLE STT -QuickLaunch SCCMDeployments Open using the alias to the SCCM deployments window #> # MAIN TODO # - function for creating windows (leave out variable creation) or a foreach of each .xml in the assets folder. # - help window # - users - member of sccm collection (probably doesn't matter, we have like 10 user collections) # - IntuneDeviceDetails needs to exit cleaner back to the home window when there is an error, such as failing to login to graph. # - _UpdateSCCMDevices use API instead # - SCCM Collection members # - display a heartbeat like PDQ for computers to know they are online and can be queried # - datagrid header padding between columns # - hide first run output of LoganShell folder creation # - get smarter about looping through an object to create the pscustomobject dynamically for the datagrid [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Blackholes are fun.')] param ( [Parameter(Mandatory = $false)] [ValidateSet('ADLookups', 'RSOP', 'SCCMDeployments', 'Query')] [string] $QuickLaunch, [switch]$ShowSettings ) # WPF framework Add-Type -AssemblyName PresentationFramework # Windows Form framework (message boxes) Add-Type -AssemblyName System.Windows.Forms # Add-Type -AssemblyName System.Drawing #region Pre-run checks if ((Get-WindowsCapability -Online -Name Rsat.ActiveDirectory.DS-LDS.Tools).State -eq 'NotPresent') { Write-Warning 'RSAT AD Tools must be installed prior to use.' break } try { $Script:PDC = Get-ADDomainController -Filter * | Where-Object OperationMasterRoles -Contains 'PDCEmulator' } catch { Write-Warning 'Unable to contact a domain controller.' break } #endregion #region First Run Write-Verbose 'Checking for first run' if (!(Test-Path -Path $env:APPDATA\LoganShell\settings.json)) { # Settings file doesn't exist Write-Verbose 'First Run, creating directory and saving settings.' if (!(Test-Path -Path $env:APPDATA\LoganShell\)) { $Blackhole = New-Item -Path $env:APPDATA -Name 'LoganShell' -ItemType Directory } Write-Verbose 'Prompting for initial input' $userinput = Read-Host -Prompt 'Do you want to enable SCCM functionality? (Y/N)' switch ($userinput) { 'Y' { $EnableSCCM = $true $SCCMServerInput = Read-Host -Prompt 'What is the hostname for the SCCM server?' } 'N' { $EnableSCCM = $false } default { Write-Host 'Invalid option. Run again.' break } } $userinput = Read-Host -Prompt 'Do you want to enable Exchange on-premise functionality? (Y/N)' switch ($userinput) { 'Y' { $EnableExchange = $true } 'N' { $EnableExchange = $false } default { Write-Host 'Invalid option. Run again.' break } } Write-Verbose 'Setting temporary storage location' $ObjectFolder = 'C:\temp\Loganshell\' if (!(Test-Path $ObjectFolder)) { Write-Verbose 'Creating path.' New-Item -Path $ObjectFolder -ItemType Directory -Force -ErrorAction Stop } Write-Verbose 'Set PDCEmulator DC as default' $DefaultDC = $PDC.Name try { # Save default settings $InitialSplat = @{ Path = "$env:APPDATA\LoganShell\" SCCM = $EnableSCCM SCCMServer = $SCCMServerInput Exchange = $EnableExchange DefaultDC = $DefaultDC ObjectFolder = $ObjectFolder } _InitialSettings @InitialSplat -ErrorAction Stop } catch { throw $_ } Write-Verbose 'Done setting up for first run.' } #endregion Write-Verbose 'Loading Settings' try { $Script:STTSettings = _LoadSettings -File $env:APPDATA\LoganShell\Settings.json -ErrorAction Stop } catch { throw $_ } if ($ShowSettings) { Write-Output $STTSettings break } if ($STTSettings.DCSettings.DomainController) { $Script:GetObjectSplat = @{ Server = $STTSettings.DCSettings.DomainController } } else { $Script:GetObjectSplat = @{ } } if ($STTSettings.Theme) { switch ($STTSettings.Theme) { 'Light' { $ThemeFile = "$ModuleRoot\Assets\LightTheme.xaml" } 'Dark' { $ThemeFile = "$ModuleRoot\Assets\DarkTheme.xaml" } 'Violet' { $ThemeFile = "$ModuleRoot\Assets\VioletTheme.xaml" } Default { $ThemeFile = "$ModuleRoot\Assets\LightTheme.xaml" } } } else { # Old settings file $ThemeFile = "$ModuleRoot\Assets\LightTheme.xaml" } #region RSOP $xamlFile = "$ModuleRoot\Assets\RSOP.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $RSOP = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "RSOP_$($_.Name)" -Value $RSOP.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion #region ADLookups $xamlFile = "$ModuleRoot\Assets\ADLookups.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $ADLookups = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "ADLookups_$($_.Name)" -Value $ADLookups.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion #region SCCMDeployments $xamlFile = "$ModuleRoot\Assets\SCCMDeployments.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $SCCMDeployments = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "SCCMDeployments_$($_.Name)" -Value $SCCMDeployments.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion #region GenericDataGrid $xamlFile = "$ModuleRoot\Assets\GenericDataGrid.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $GenericDataGrid = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "GenericDataGrid_$($_.Name)" -Value $GenericDataGrid.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion #region Options $xamlFile = "$ModuleRoot\Assets\Options.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $Options = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "Options_$($_.Name)" -Value $Options.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion #region HomeWindow $xamlFile = "$ModuleRoot\Assets\HomeWindow.xaml" #create window $inputXML = Get-Content $xamlFile -Raw $inputXML = $inputXML -replace 'mc:Ignorable="d"', '' -replace 'x:N', 'N' -replace '^<Win.*', '<Window' [XML]$XAML = $inputXML $xaml.window.'Window.Resources'.ResourceDictionary.'ResourceDictionary.MergedDictionaries'.ResourceDictionary.Source = $ThemeFile #Read XAML $reader = (New-Object System.Xml.XmlNodeReader $xaml) try { $HomeWindow = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "HomeWindow_$($_.Name)" -Value $HomeWindow.FindName($_.Name) -ErrorAction Stop } catch { throw } } #endregion _RSOPWindowUIEvents _ADLookupsUIEvents _SCCMDeploymentsUIEvents _GenericDataGridUIEvents _OptionsUIEvents _HomeWindowUIEvents switch ($QuickLaunch) { 'ADLookups' { Write-Output 'Loading ADLookups....' $null = $ADLookups.ShowDialog() } 'RSOP' { Write-Output 'Loading RSOP....' $null = $RSOP.ShowDialog() } 'SCCMDeployments' { Write-Output 'Loading SCCM Deployments....' $null = $SCCMDeployments.ShowDialog() } 'Query' { Write-Output 'Loading Computer Query....' $null = $GenericDataGrid.ShowDialog() } Default { Write-Output 'Loading ServerTeamTools....' $null = $HomeWindow.ShowDialog() } } } |