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 .EXAMPLE STT -ShowSettings Outputs the tools settings file in a PS object. #> # 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 # - datagrid header padding between columns # - hide first run output of LoganShell folder creation # - move 'constants' to this function. # - ComputerStats CPU round to 0 or 2 decimal places # - figure out how to resort datagrids # - user tab - actions with a verify messagebox # - computer tab - install updates # - computer tab - schedule reboot # - verify that the settingssaved variable works correctly # - add user or computer to a group with out-gridview # - computerstats - make filter stuff work on datagrid # - use the $Session variable for stuff # - options - default domain and add that to _SaveSettings # - adlookups - updating caches shows please wait while loading # - find tab - users search show name # - rsop - show text box to right for the text based gpresult that collapes # - adlookups - computer tab slow when computer is offline. [CmdletBinding()] [System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSUseDeclaredVarsMoreThanAssignments', '', Justification = 'Blackholes are fun.')] param ( [Parameter(Mandatory = $false)] [ValidateSet('ADLookups', 'RSOP', 'SCCMDeployments', 'ComputerStats', 'Passphrase', 'WUG')] [string] $QuickLaunch, [Parameter(Mandatory = $false, HelpMessage = 'This will just output the contents of the settings file.')] [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 and constants # Testing for the AD module manifest since workstations and servers use different methods to check the installation of RSAT tools and this seems faster. # TODO was still not working on SVM165 even with RSAT installed. # if (Test-Path 'C:\WINDOWS\System32\WindowsPowerShell\v1.0\Modules\ActiveDirectory\ActiveDirectory.psd1') { # Write-Warning 'RSAT AD Tools must be installed prior to use.' # break # } try { $Script:PDC = (Get-ADDomain).PDCEmulator } catch { Write-Warning 'Unable to contact a domain controller.' break } $Script:Module = Get-Module SCJBServerTeamTools $Script:ModuleName = 'SCJBServerTeamTools' #endregion #region First Run Write-Verbose 'Checking for first run' # TODO move this to it's own function with _InitialSettings 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 } try { # Save default settings $InitialSplat = @{ Path = "$env:APPDATA\LoganShell\" SCCM = $EnableSCCM SCCMServer = $SCCMServerInput Exchange = $EnableExchange DefaultDC = $PDC ObjectFolder = $ObjectFolder } _InitialSettings @InitialSplat -ErrorAction Stop } catch { throw $_ } Write-Verbose 'Done setting up for first run.' } #endregion #region Loading Settings Write-Verbose 'Loading Settings' try { _LoadSettings -File $env:APPDATA\LoganShell\Settings.json -ErrorAction Stop } catch { throw $_ } if ($ShowSettings) { Write-Output $STTSettings break } 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" } #endregion #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 ComputerStats $xamlFile = "$ModuleRoot\Assets\ComputerStats.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 { $Global:ComputerStats = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "ComputerStats_$($_.Name)" -Value $ComputerStats.FindName($_.Name) -Scope Global -ErrorAction Stop } catch { throw } } #endregion #region Passphrases $xamlFile = "$ModuleRoot\Assets\Passphrases.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 { $Passphrases = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "Passphrases_$($_.Name)" -Value $Passphrases.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 WUG $xamlFile = "$ModuleRoot\Assets\WhatsUpGold.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 { $WhatsUpGold = [Windows.Markup.XamlReader]::Load( $reader ) } catch { Write-Warning $_.Exception throw } $xaml.SelectNodes('//*[@Name]') | ForEach-Object { try { Set-Variable -Name "WhatsUpGold_$($_.Name)" -Value $WhatsUpGold.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 _ComputerStatsUIEvents _OptionsUIEvents _HomeWindowUIEvents _PassphrasesUIEvents _WhatsUpGoldUIEvents #region Update Check Write-Verbose 'Update Check' $UpdateCheck = _CheckForUpdate if ($UpdateCheck.Outdated) { $HomeWindow_UpdateStatusBarItem.Content = 'Update Found!' $MessageSplat = @{ MessageText = "An update was found.`nCurrent version: $($UpdateCheck.Current)`nNew version: $($UpdateCheck.Newest)`nDo you want to update now?`n`nRelease Notes: $($UpdateCheck.ReleaseNotes)" MessageIcon = 'Asterisk' ButtonType = 'YesNo' MessageTitle = 'Update Found' } $Answer = _ShowMessageBox @MessageSplat switch ($Answer) { Yes { Update-Module $ModuleName Write-Host 'Module Updated. Open a new powershell session to load the new version.' break } No { } Default { } } } #endregion # Get-Variable Options_* | Select-Object Name Write-Verbose 'Starting to launch window' 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() } 'ComputerStats' { Write-Output 'Loading Computer Stats....' $null = $ComputerStats.ShowDialog() } 'Passphrase' { Write-Output 'Loading Passphrases....' $null = $Passphrases.ShowDialog() } 'WUG' { Write-Output 'Loading WUG Monitors....' $null = $WhatsUpGold.ShowDialog() } Default { Write-Output 'Loading ServerTeamTools....' $null = $HomeWindow.ShowDialog() } } } |