Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- If((Get-Module -ListAvailable -Name dbatools) -eq $null) {
- # try to install dbatools module
- try {
- Install-Module dbatools -ErrorAction Stop
- }
- catch {
- throw [System.ArgumentException] "You need to install the dbatools module, which requires administrator privileges."
- }
- }
- Import-Module dbatools
- Add-Type -AssemblyName PresentationCore, PresentationFramework, WindowsBase, System.Windows.Forms, System.Drawing
- $Global:syncHash = [hashtable]::Synchronized(@{})
- ## LOAD INVENTORY TO SYNCHASH ###
- $syncHash.InventoryFileLocation = $PSScriptRoot
- $syncHash.Servers = (Import-CSV -Path "$($syncHash.InventoryFileLocation)\servers.csv" | Sort-Object -Property ServerName)
- $syncHash.ServersChanged = $false
- $syncHash.InventoryLocked = $false
- $syncHash.ParentPID = $PID
- If(Test-Path "$PSScriptRoot\inv.loc") {
- [System.Windows.MessageBox]::Show("Someone is editing the inventory file! All modify operations are disabled.", "Information", "OK", "Information")
- $syncHash.InventoryLocked = $true
- }
- Else {
- New-Item -Path "$PSScriptRoot\inv.loc" | Out-Null
- }
- $newRunspace = [runspacefactory]::CreateRunspace()
- $newRunspace.ApartmentState = "STA"
- $newRunspace.ThreadOptions = "ReuseThread"
- $newRunspace.Open()
- $newRunspace.SessionStateProxy.SetVariable("syncHash", $syncHash)
- $guiCmd = [PowerShell]::Create().AddScript({
- [xml]$mainWindowXAML = @"
- <Window
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="SQL Server Inventory" Height="620" Width="920" MinWidth="920" Background="#FF323242"
- Icon="$($syncHash.InventoryFileLocation)\favicon.ico">
- <Window.Resources>
- <Style TargetType="DataGridCell">
- <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self},Path=Content.Text}" />
- <Setter Property="ToolTipService.InitialShowDelay" Value="500" />
- </Style>
- </Window.Resources>
- <DockPanel x:Name="dckContainer" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Margin="10,10,10,10" LastChildFill="True">
- <UniformGrid Rows="1" Columns="4" HorizontalAlignment="Stretch" DockPanel.Dock="Top">
- <UniformGrid.Resources>
- <Style TargetType="{x:Type Button}">
- <Setter Property="FontWeight" Value="Bold"/>
- <Setter Property="FontSize" Value="16"/>
- <Setter Property="Width" Value="216"/>
- <Setter Property="Height" Value="30"/>
- </Style>
- </UniformGrid.Resources>
- <Button x:Name="btnAddServer" Content="Add SQL Server" Width="216" HorizontalAlignment="Left"/>
- <Button x:Name="btnModifyServer" Content="Modify Selected Server" Width="216" HorizontalAlignment="Center"/>
- <Button x:Name="btnRemoveServer" Content="Remove Selected Server(s)" Width="216" HorizontalAlignment="Center"/>
- <Button x:Name="btnRescanServer" Content="Rescan Selected Server(s)" Width="216" HorizontalAlignment="Right"/>
- </UniformGrid>
- <Separator HorizontalAlignment="Stretch" Margin="0,10,0,10" DockPanel.Dock="Top"/>
- <DataGrid x:Name="dgvInventory" RowHeight="20" IsReadOnly="True" HorizontalAlignment="Stretch" DockPanel.Dock="Top" AutoGenerateColumns="False" Background="#FF49495F" ClipToBounds="True" CanUserResizeRows="False" CanUserSortColumns="True" ScrollViewer.VerticalScrollBarVisibility="Visible">
- <DataGrid.ContextMenu>
- <ContextMenu>
- <MenuItem x:Name="mnuAdd" Header="Add Server" />
- <Separator />
- <MenuItem x:Name="mnuModify" Header="Modify Server" />
- <MenuItem x:Name="mnuRescan" Header="Rescan Server(s)" />
- <MenuItem x:Name="mnuRemove" Header="Remove Server(s)" />
- </ContextMenu>
- </DataGrid.ContextMenu>
- <DataGrid.Columns>
- <DataGridTextColumn Header="Server Name" Binding="{Binding ServerName}" Width="5*" SortDirection="Ascending" />
- <DataGridTextColumn Header="IP Address" Binding="{Binding IPAddress}" Width="3*" />
- <DataGridTextColumn Header="Description" Binding="{Binding Description}" Width="6*" />
- <DataGridTextColumn Header="Version" Binding="{Binding Version}" Width="3*"/>
- <DataGridTextColumn Header="SP" Binding="{Binding SP}" Width="1*" />
- <DataGridTextColumn Header="Edition" Binding="{Binding Edition}" Width="5* "/>
- <DataGridTextColumn Header="Windows OS" Binding="{Binding WindowsOS}" Width="6*" />
- </DataGrid.Columns>
- </DataGrid>
- </DockPanel>
- </Window>
- "@
- $XMLReader = (New-Object System.Xml.XmlNodeReader $mainWindowXAML)
- $syncHash.MainWindow = [Windows.Markup.XamlReader]::Load($XMLReader)
- $syncHash.MainWindowControls = @{}
- $mainWindowXAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | % {
- $syncHash.MainWindowControls.Add($_.Name, $syncHash.MainWindow.FindName($_.Name))
- }
- #region Background runspace to clean up jobs
- $Script:JobCleanup = [hashtable]::Synchronized(@{})
- $Script:Jobs = [System.Collections.ArrayList]::Synchronized((New-Object System.Collections.ArrayList))
- $JobCleanup.Flag = $true
- $newRunspace = [runspacefactory]::CreateRunspace()
- $newRunspace.ApartmentState = "STA"
- $newRunspace.ThreadOptions = "ReuseThread"
- $newRunspace.Open()
- $newRunspace.SessionStateProxy.SetVariable("JobCleanup", $JobCleanup)
- $newRunspace.SessionStateProxy.SetVariable("Jobs", $Jobs)
- $JobCleanup.PowerShell = [PowerShell]::Create().AddScript({
- Do {
- Foreach($Runspace in $Jobs) {
- If($Runspace.Runspace.isCompleted) {
- [void]$Runspace.PowerShell.EndInvoke($Runspace.Runspace)
- $Runspace.PowerShell.Dispose()
- $Runspace.Runspace = $null
- $Runspace.PowerShell = $null
- }
- }
- $temphash = $Jobs.Clone()
- $temphash | ? { $_.Runspace -eq $null } | % { $Jobs.Remove($_) }
- Start-Sleep -Seconds 1
- } While($JobCleanup.Flag)
- })
- $JobCleanup.PowerShell.Runspace = $newRunspace
- $JobCleanup.Thread = $JobCleanup.PowerShell.BeginInvoke()
- #endregion Background runspace to clean up jobs
- # Initial load of inventory into GUI
- $syncHash.MainWindowControls.dgvInventory.ItemsSource = $syncHash.Servers
- # If locked, disable the menu buttons
- $syncHash.MainWindow.Add_Loaded({
- If($syncHash.InventoryLocked) {
- $syncHash.MainWindowControls.Keys | ? { $_.Substring(0,3) -in ("mnu", "btn") } | % { $syncHash.MainWindowControls.$_.IsEnabled = $false }
- }
- })
- # Context menu handlers, just trigger the button events
- $syncHash.MainWindowControls.mnuAdd.Add_Click({
- $syncHash.MainWindowControls.btnAddServer.RaiseEvent((New-Object -TypeName System.Windows.RoutedEventArgs -ArgumentList $([System.Windows.Controls.Button]::ClickEvent)))
- })
- $syncHash.MainWindowControls.mnuModify.Add_Click({
- $syncHash.MainWindowControls.btnModifyServer.RaiseEvent((New-Object -TypeName System.Windows.RoutedEventArgs -ArgumentList $([System.Windows.Controls.Button]::ClickEvent)))
- })
- $syncHash.MainWindowControls.mnuRescan.Add_Click({
- $syncHash.MainWindowControls.btnRescanServer.RaiseEvent((New-Object -TypeName System.Windows.RoutedEventArgs -ArgumentList $([System.Windows.Controls.Button]::ClickEvent)))
- })
- $syncHash.MainWindowControls.mnuRemove.Add_Click({
- $syncHash.MainWindowControls.btnRemoveServer.RaiseEvent((New-Object -TypeName System.Windows.RoutedEventArgs -ArgumentList $([System.Windows.Controls.Button]::ClickEvent)))
- })
- # Handles spawning the Add Server window
- $syncHash.MainWindowControls.btnAddServer.Add_Click({
- $newRunspace =[runspacefactory]::CreateRunspace()
- $newRunspace.ApartmentState = "STA"
- $newRunspace.ThreadOptions = "ReuseThread"
- $newRunspace.Open()
- $newRunspace.SessionStateProxy.SetVariable("SyncHash",$SyncHash)
- $PowerShell = [PowerShell]::Create().AddScript({
- If($syncHash.AddWindow -ne $null) {
- $syncHash.AddWindow.Dispatcher.Invoke(
- [action]{ $syncHash.AddWindow.Activate() },
- "Normal"
- )
- }
- Else {
- [xml]$addWindowXAML = @"
- <Window
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Add SQL Server" Height="220" Width="270" Background="#323242" ResizeMode="NoResize"
- Icon="$($syncHash.InventoryFileLocation)\favicon.ico">
- <Grid Margin="10">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- <RowDefinition Height="5"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100"/>
- <ColumnDefinition Width="*"/>
- </Grid.ColumnDefinitions>
- <Label Grid.Row="0" Grid.Column="0" Content="Server Name:" Foreground="White" FontWeight="Bold" HorizontalContentAlignment="Right"/>
- <Label Grid.Row="1" Grid.Column="0" Content="Instance Name:" Foreground="White" FontWeight="Bold" HorizontalContentAlignment="Right"/>
- <TextBox x:Name="txtServerName" Grid.Row="0" Grid.Column="1" Height="20" HorizontalAlignment="Stretch"/>
- <TextBox x:Name="txtInstanceName" Grid.Row="1" Grid.Column="1" Height="20" HorizontalAlignment="Stretch" Text="MSSQLSERVER" Foreground="Gray"/>
- <TextBox x:Name="txtDescription" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Text="Enter description" Foreground="Gray" TextWrapping="Wrap"/>
- <Button x:Name="btnAddServer" Grid.Row="4" Grid.Column="0" Grid.ColumnSpan="2" Content="Add Server"/>
- </Grid>
- </Window>
- "@
- $XMLReader = (New-Object System.Xml.XmlNodeReader $addWindowXAML)
- $syncHash.AddWindow = [Windows.Markup.XamlReader]::Load($XMLReader)
- $syncHash.AddWindowControls = @{}
- $addWindowXAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | % {
- $syncHash.AddWindowControls.Add($_.Name, $syncHash.AddWindow.FindName($_.Name))
- }
- # Handler to clear this window's controls out on close
- $syncHash.AddWindow.Add_Closed({
- $syncHash.AddWindowControls = $null
- $syncHash.AddWindow = $null
- })
- # Handler to add new server to inventory
- $syncHash.AddWindowControls.btnAddServer.Add_Click({
- $txtServerName = $syncHash.AddWindowControls.txtServerName
- $txtInstanceName = $syncHash.AddWindowControls.txtInstanceName
- $txtDescription = $syncHash.AddWindowControls.txtDescription
- If($syncHash.AddWindowControls.txtServerName.Text -eq "") {
- [System.Windows.MessageBox]::Show("Server name cannot be blank!", "Error", "OK", "Error")
- Return
- }
- ElseIf($syncHash.Servers.ServerName -contains $txtServerName.Text) {
- [System.Windows.MessageBox]::Show("Server already exists in inventory!", "Error", "OK", "Error")
- Return
- }
- $syncHash.AddWindowControls.btnAddServer.IsEnabled = $false
- If($txtInstanceName.Text -eq "MSSQLSERVER") {
- $ServerName = $txtServerName.Text
- }
- Else {
- $ServerName = "$($txtServerName.Text)\$($txtInstanceName.Text)"
- }
- If($txtDescription.Text -eq "Enter description") { $Description = "" } Else { $Description = $txtDescription.Text }
- $ServerData = [PSCustomObject]@{ServerName=$ServerName; IPAddress=""; Description=$Description; Version=""; SP=""; Edition=""; WindowsOS=""}
- $syncHash.Servers += $ServerData
- $syncHash.MainWindowControls.dgvInventory.Dispatcher.Invoke(
- [action]{
- $SortDesc = $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions[0]
- If($SortDesc -eq $null) {
- $SortDesc = New-Object System.ComponentModel.SortDescription("ServerName", "Ascending")
- }
- $syncHash.MainWindowControls.dgvInventory.ItemsSource = $syncHash.Servers
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Clear()
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Add($SortDesc)
- $columnFields = $syncHash.MainWindowControls.dgvInventory.Columns.Binding.Path.Path
- # This is super hacky but it will freeze if I try to pipe to where-object or foreach...
- $colIdx = 0
- while($colIdx -lt $columnFields.Count) {
- if($columnFields[$colIdx] -eq $SortDesc.PropertyName) {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $SortDesc.Direction
- }
- else {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $null
- }
- }
- },
- "Normal"
- )
- $syncHash.ServersChanged = $true
- $syncHash.AddWindow.Close()
- [System.Windows.MessageBox]::Show("Added server $($ServerData.ServerName)", "Success", "OK", "Information")
- })
- # Handlers for default text on instance name
- $syncHash.AddWindowControls.txtInstanceName.Add_GotFocus({
- $txtInstanceName = $syncHash.AddWindowControls.txtInstanceName
- If($txtInstanceName.Text -eq "MSSQLSERVER") {
- $txtInstanceName.Text = ""
- $txtInstanceName.Foreground = "Black"
- }
- })
- $syncHash.AddWindowControls.txtInstanceName.Add_LostFocus({
- $txtInstanceName = $syncHash.AddWindowControls.txtInstanceName
- If($txtInstanceName.Text -eq "") {
- $txtInstanceName.Text = "MSSQLSERVER"
- $txtInstanceName.Foreground = "Gray"
- }
- })
- # Handlers for default text on description
- $syncHash.AddWindowControls.txtDescription.Add_GotFocus({
- $txtDescription = $syncHash.AddWindowControls.txtDescription
- If($txtDescription.Text -eq "Enter description") {
- $txtDescription.Text = ""
- $txtDescription.Foreground = "Black"
- }
- })
- $syncHash.AddWindowControls.txtDescription.Add_LostFocus({
- $txtDescription = $syncHash.AddWindowControls.txtDescription
- If($txtDescription.Text -eq "") {
- $txtDescription.Text = "Enter description"
- $txtDescription.Foreground = "Gray"
- }
- })
- $syncHash.AddWindow.ShowDialog() | Out-Null
- }
- })
- $PowerShell.Runspace = $newRunspace
- [void]$Jobs.Add((
- [pscustomobject]@{
- PowerShell = $PowerShell
- Runspace = $PowerShell.BeginInvoke()
- }
- ))
- })
- $syncHash.MainWindowControls.btnModifyServer.Add_Click({
- $newRunspace =[runspacefactory]::CreateRunspace()
- $newRunspace.ApartmentState = "STA"
- $newRunspace.ThreadOptions = "ReuseThread"
- $newRunspace.Open()
- $newRunspace.SessionStateProxy.SetVariable("SyncHash",$SyncHash)
- $PowerShell = [PowerShell]::Create().AddScript({
- If($syncHash.ModifyWindow -ne $null) {
- $syncHash.ModifyWindow.Dispatcher.Invoke(
- [action]{ $syncHash.ModifyWindow.Close() },
- "Normal"
- )
- $syncHash.ModifyWindow = $null
- $syncHash.ModifyWindowControls = $null
- }
- $script:ServerItem = $null
- $syncHash.MainWindow.Dispatcher.Invoke({ $script:ServerItem = $syncHash.MainWindowControls.dgvInventory.SelectedItem },"Normal")
- If($ServerItem -eq $null) {
- [System.Windows.MessageBox]::Show("You must select a server to modify", "Information", "OK", "Information")
- Return
- }
- $ServerName = $script:ServerItem.ServerName
- $ServerDesc = $script:ServerItem.Description
- If($ServerDesc -eq "") {
- $ServerDesc = "Enter description"
- $DescColor = "Gray"
- }
- Else {
- $DescColor = "Black"
- }
- [xml]$modifyWindowXAML = @"
- <Window
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- Title="Modify SQL Server ($ServerName)" Height="220" Width="270" Background="#323242" ResizeMode="NoResize"
- Icon="$($syncHash.InventoryFileLocation)\favicon.ico">
- <Grid Margin="10">
- <Grid.RowDefinitions>
- <RowDefinition Height="Auto"/>
- <RowDefinition Height="*"/>
- <RowDefinition Height="5"/>
- <RowDefinition Height="Auto"/>
- </Grid.RowDefinitions>
- <Grid.ColumnDefinitions>
- <ColumnDefinition Width="100"/>
- <ColumnDefinition Width="*"/>
- </Grid.ColumnDefinitions>
- <Label Grid.Row="0" Grid.Column="0" Content="Server Name:" Foreground="White" FontWeight="Bold" HorizontalContentAlignment="Right" />
- <TextBox x:Name="txtServerName" Grid.Row="0" Grid.Column="1" Height="20" HorizontalAlignment="Stretch" IsEnabled="False" Text="$ServerName"/>
- <TextBox x:Name="txtDescription" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Foreground="$DescColor" TextWrapping="Wrap" AcceptsReturn="True"/>
- <Button x:Name="btnUpdateServer" Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Content="Update Server $ServerName"/>
- </Grid>
- </Window>
- "@
- $XMLReader = (New-Object System.Xml.XmlNodeReader $modifyWindowXAML)
- $syncHash.ModifyWindow = [Windows.Markup.XamlReader]::Load($XMLReader)
- $syncHash.ModifyWindowControls = @{}
- $modifyWindowXAML.SelectNodes("//*[@*[contains(translate(name(.),'n','N'),'Name')]]") | % {
- $syncHash.ModifyWindowControls.Add($_.Name, $syncHash.ModifyWindow.FindName($_.Name))
- }
- # Handler to load the server description into the textbox
- # Needed to handle the newlines
- $syncHash.ModifyWindow.Add_Loaded({
- $syncHash.ModifyWindowControls.txtDescription.Text = $ServerDesc
- })
- # Handler to clear this window's controls out on close
- $syncHash.ModifyWindow.Add_Closed({
- $syncHash.ModifyWindowControls = $null
- $syncHash.ModifyWindow = $null
- })
- # Handler for default description text
- $syncHash.ModifyWindowControls.txtDescription.Add_GotFocus({
- $txtDescription = $syncHash.ModifyWindowControls.txtDescription
- If($txtDescription.Text -eq "Enter description") {
- $txtDescription.Text = ""
- $txtDescription.Foreground = "Black"
- }
- })
- $syncHash.ModifyWindowControls.txtDescription.Add_LostFocus({
- $txtDescription = $syncHash.ModifyWindowControls.txtDescription
- If($txtDescription.Text -eq "") {
- $txtDescription.Text = "Enter description"
- $txtDescription.Foreground = "Gray"
- }
- })
- # Handler for update button
- $syncHash.ModifyWindowControls.btnUpdateServer.Add_Click({
- $Description = $syncHash.ModifyWindowControls.txtDescription.Text
- $ServerName = $syncHash.ModifyWindowControls.txtServerName.Text
- If($Description -eq "Enter description") { $Description = "" }
- ($syncHash.Servers | ? { $_.ServerName -eq $ServerName }).Description = $Description
- $syncHash.MainWindow.Dispatcher.Invoke([action]{
- $SortDesc = $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions[0]
- If($SortDesc -eq $null) {
- $SortDesc = New-Object System.ComponentModel.SortDescription("ServerName", "Ascending")
- }
- $syncHash.MainWindowControls.dgvInventory.ItemsSource = $syncHash.Servers
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Add($SortDesc)
- $columnFields = $syncHash.MainWindowControls.dgvInventory.Columns.Binding.Path.Path
- # This is super hacky but it will freeze if I try to pipe to where-object or foreach... probably some error somewhere that I can't see
- $colIdx = 0
- while($colIdx -lt $columnFields.Count) {
- if($columnFields[$colIdx] -eq $SortDesc.PropertyName) {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $SortDesc.Direction
- }
- else {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $null
- }
- }
- }, "Normal")
- $syncHash.ServersChanged = $true
- $syncHash.ModifyWindow.Close()
- [System.Windows.MessageBox]::Show("Successfully updated server $ServerName", "Success", "OK", "Information")
- })
- $syncHash.ModifyWindow.ShowDialog() | Out-Null
- })
- $PowerShell.Runspace = $newRunspace
- [void]$Jobs.Add((
- [pscustomobject]@{
- PowerShell = $PowerShell
- Runspace = $PowerShell.BeginInvoke()
- }
- ))
- })
- $syncHash.MainWindowControls.btnRemoveServer.Add_Click({
- $SelectedItems = $syncHash.MainWindowControls.dgvInventory.SelectedItems
- If($SelectedItems.Count -eq 0) {
- [System.Windows.MessageBox]::Show("You must select a server to remove", "Information", "OK", "Information")
- Return
- }
- $ServerNames = $SelectedItems.ServerName
- $ConfirmDelete = [System.Windows.MessageBox]::Show("Are you sure you wish to delete the following servers?`n`n$($ServerNames -join "`n")", "Warning", "YesNo", "Warning")
- If($ConfirmDelete -eq "Yes") {
- $SortDesc = $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions[0]
- If($SortDesc -eq $null) {
- $SortDesc = New-Object System.ComponentModel.SortDescription("ServerName", "Ascending")
- }
- $syncHash.Servers = ($syncHash.Servers | ? { $_.ServerName -notin $ServerNames })
- $syncHash.MainWindowControls.dgvInventory.ItemsSource = $syncHash.Servers
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Clear()
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Add($SortDesc)
- $columnFields = $syncHash.MainWindowControls.dgvInventory.Columns.Binding.Path.Path
- # This is super hacky but it will freeze if I try to pipe to where-object or foreach... probably some error somewhere that I can't see
- $colIdx = 0
- while($colIdx -lt $columnFields.Count) {
- if($columnFields[$colIdx] -eq $SortDesc.PropertyName) {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $SortDesc.Direction
- }
- else {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $null
- }
- }
- $syncHash.ServersChanged = $true
- [System.Windows.MessageBox]::Show("Successfully removed $($ServerNames.Count) servers", "Success", "OK", "Information")
- }
- })
- $syncHash.MainWindowControls.btnRescanServer.Add_Click({
- $SelectedItems = $syncHash.MainWindowControls.dgvInventory.SelectedItems
- If($SelectedItems.Count -eq 0) {
- [System.Windows.MessageBox]::Show("You must select a server to rescan", "Information", "OK", "Information")
- Return
- }
- $ServerNames = ($SelectedItems.ServerName | % { ($_ -split "\\")[0] } | Select -Unique)
- $InstanceNames = $SelectedItems.ServerName
- $ConfirmScan = [System.Windows.MessageBox]::Show("Are you sure you wish to rescan the following servers? This could a few minutes and the UI may appear unresponsive!`n`n$($InstanceNames -join "`n")", "Warning", "YesNo", "Warning")
- If($ConfirmScan -eq "Yes") {
- $syncHash.MainWindow.Title += " - Scanning..."
- $SqlProperties = ($InstanceNames | % { @{InstanceName=$_} } )
- Get-DbaInstanceProperty -SqlInstance $InstanceNames | ? { $_.Name -in @("ComputerName", "Edition", "VersionString", "ProductLevel") } | % {
- $Instance = $_.ComputerName
- If($_.InstanceName -ne "MSSQLSERVER") { $Instance = "$Instance\$($_.InstanceName)" }
- ($SqlProperties | ? { $_.InstanceName -eq $Instance }).Add($_.Name, $_.Value)
- }
- $OperatingSystems = (Get-DbaOperatingSystem -ComputerName $ServerNames | Select ComputerName, OSVersion)
- $IPAddresses = ($ServerNames | % { @{ComputerName=$_; IPAddress=(Resolve-DnsName $_).IPAddress} })
- $InstanceNames | % {
- $ThisInstance = $_
- $ComputerName = ($ThisInstance -split "\\")[0]
- $Server = ($syncHash.Servers | ? { $_.ServerName -eq $ThisInstance })
- $SQLInstanceProperties = ($SqlProperties | ? { $_.InstanceName -eq $ThisInstance })
- $Server.IPAddress = ($IPAddresses | ? { $_.ComputerName -eq $ComputerName }).IPAddress
- $Server.Version = $SQLInstanceProperties.VersionString
- $Server.SP = $SQLInstanceProperties.ProductLevel
- $Server.Edition = $SQLInstanceProperties.Edition
- $Server.WindowsOS = ($OperatingSystems | ? { $_.ComputerName -eq "$ComputerName" -or $_.ComputerName -eq "$ComputerName.domain.local" }).OSVersion.Trim()
- }
- $SortDesc = $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions[0]
- If($SortDesc -eq $null) {
- $SortDesc = New-Object System.ComponentModel.SortDescription("ServerName", "Ascending")
- }
- $syncHash.MainWindowControls.dgvInventory.ItemsSource = $syncHash.Servers
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Clear()
- $syncHash.MainWindowControls.dgvInventory.Items.SortDescriptions.Add($SortDesc)
- $columnFields = $syncHash.MainWindowControls.dgvInventory.Columns.Binding.Path.Path
- # This is super hacky but it will freeze if I try to pipe to where-object or foreach... probably some error somewhere that I can't see
- $colIdx = 0
- while($colIdx -lt $columnFields.Count) {
- if($columnFields[$colIdx] -eq $SortDesc.PropertyName) {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $SortDesc.Direction
- }
- else {
- $syncHash.MainWindowControls.dgvInventory.Columns[$colIdx++].SortDirection = $null
- }
- }
- $syncHash.ServersChanged = $true
- $syncHash.MainWindowControls.dgvInventory.Items.Refresh()
- $syncHash.MainWindow.Title = "SQL Server Inventory"
- [System.Windows.MessageBox]::Show("Successfully rescanned servers", "Success", "OK", "Information")
- }
- })
- # Handler for double-clicking (modifying) inventory item
- $syncHash.MainWindowControls.dgvInventory.Add_MouseDoubleClick({
- If($syncHash.InventoryLocked -eq $false) {
- $syncHash.MainWindowControls.btnModifyServer.RaiseEvent((New-Object -TypeName System.Windows.RoutedEventArgs -ArgumentList $([System.Windows.Controls.Button]::ClickEvent)))
- }
- })
- $syncHash.MainWindow.Add_Closing({
- If($syncHash.ServersChanged) {
- $Confirm = [System.Windows.MessageBox]::Show("Do you want to save before exiting?", "Warning", "YesNoCancel", "Exclamation")
- If($Confirm -eq "Cancel") {
- $_.Cancel = $true
- Return
- }
- ElseIf($Confirm -eq "Yes") {
- If(Test-Path "$($syncHash.InventoryFileLocation)\servers.csv.bak") { Remove-Item -Path "$($syncHash.InventoryFileLocation)\servers.csv.bak" }
- Rename-Item -Path "$($syncHash.InventoryFileLocation)\servers.csv" -NewName "servers.csv.bak"
- $syncHash.Servers | Export-Csv -Path "$($syncHash.InventoryFileLocation)\servers.csv" -NoTypeInformation
- }
- }
- If($syncHash.InventoryLocked -eq $false) {
- Remove-Item "$($syncHash.InventoryFileLocation)\inv.loc"
- }
- $syncHash.Keys | ? { $_.EndsWith("Window") -and $_ -ne "MainWindow" } | % {$Window = $_; $syncHash.$Window.Dispatcher.Invoke({[action]$syncHash.$Window.Close()},"Normal")}
- Stop-Process -Id $syncHash.ParentPID
- })
- $syncHash.MainWindow.ShowDialog() | Out-Null
- $syncHash.Error = $Error
- })
- $guiCmd.Runspace = $newRunspace
- $data = $guiCmd.BeginInvoke()
Advertisement
Add Comment
Please, Sign In to add comment