From 9978040255f841b16097c6713d21d0e28a828cb5 Mon Sep 17 00:00:00 2001 From: Chrissy LeMaire Date: Thu, 22 Nov 2018 04:33:47 +0100 Subject: [PATCH] 0.9.520 --- allcommands.ps1 | 5053 +++++++++++++++++---------------------- bin/dbatools-index.json | 1295 +++++----- 2 files changed, 2861 insertions(+), 3487 deletions(-) diff --git a/allcommands.ps1 b/allcommands.ps1 index 2439ee367a..070e956020 100644 --- a/allcommands.ps1 +++ b/allcommands.ps1 @@ -110,23 +110,27 @@ function Add-DbaAgDatabase { foreach ($replica in $replicas) { $replicadb = Get-DbaAgDatabase -SqlInstance $replica -SqlCredential $SqlCredential -Database $db.Name -AvailabilityGroup $ag.Name - $timeout = 1 - do { - try { - Write-Message -Level Verbose -Message "Trying to add $($replicadb.Name) to $replica" - $timeout++ - $replicadb.JoinAvailablityGroup() - $replicadb.Refresh() - Start-Sleep -Seconds 1 - } catch { - Stop-Function -Message "Error joining database to availability group" -ErrorRecord $_ -Continue + if ($replicadb) { + if ($Pscmdlet.ShouldProcess($ag.Parent.Name, "Joining availability group $db to $($db.Parent.Name)")) { + $timeout = 1 + do { + try { + Write-Message -Level Verbose -Message "Trying to add $($replicadb.Name) to $replica" + $timeout++ + $replicadb.JoinAvailablityGroup() + $replicadb.Refresh() + Start-Sleep -Seconds 1 + } catch { + Stop-Function -Message "Error joining database to availability group" -ErrorRecord $_ -Continue + } + } while (-not $replicadb.IsJoined -and $timeout -lt 10) + + if ($replicadb.IsJoined) { + $replicadb + } else { + Stop-Function -Continue -Message "Could not join $($replicadb.Name) to $replica" + } } - } while (-not $replicadb.IsJoined -and $timeout -lt 10) - - if ($replicadb.IsJoined) { - $replicadb - } else { - Stop-Function -Continue -Message "Could not join $($replicadb.Name) to $replica" } } } @@ -742,7 +746,7 @@ function Add-DbaComputerCertificate { .PARAMETER Credential Allows you to login to $ComputerName using alternative credentials. - .PARAMETER Password + .PARAMETER SecurePassword The password for the certificate, if it is password protected. .PARAMETER Certificate @@ -792,7 +796,8 @@ function Add-DbaComputerCertificate { [Alias("ServerInstance", "SqlServer", "SqlInstance")] [DbaInstance[]]$ComputerName = $env:COMPUTERNAME, [PSCredential]$Credential, - [SecureString]$Password, + [Alias("Password")] + [SecureString]$SecurePassword, [parameter(ValueFromPipeline)] [System.Security.Cryptography.X509Certificates.X509Certificate2[]]$Certificate, [string]$Path, @@ -814,7 +819,7 @@ function Add-DbaComputerCertificate { # This may be too much, but oh well $bytes = [System.IO.File]::ReadAllBytes($Path) $Certificate = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $Certificate.Import($bytes, $Password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet) + $Certificate.Import($bytes, $SecurePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet) } catch { Stop-Function -Message "Can't import certificate." -ErrorRecord $_ return @@ -827,7 +832,7 @@ function Add-DbaComputerCertificate { param ( $CertificateData, - [SecureString]$Password, + [SecureString]$SecurePassword, $Store, @@ -835,7 +840,7 @@ function Add-DbaComputerCertificate { ) $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2 - $cert.Import($CertificateData, $Password, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet) + $cert.Import($CertificateData, $SecurePassword, [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::DefaultKeySet) Write-Message -Level Verbose -Message "Importing cert to $Folder\$Store" $tempStore = New-Object System.Security.Cryptography.X509Certificates.X509Store($Folder, $Store) $tempStore.Open('ReadWrite') @@ -858,7 +863,7 @@ function Add-DbaComputerCertificate { foreach ($cert in $Certificate) { try { - $certData = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::PFX, $Password) + $certData = $cert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::PFX, $SecurePassword) } catch { Stop-Function -Message "Can't export certificate" -ErrorRecord $_ -Continue } @@ -867,7 +872,7 @@ function Add-DbaComputerCertificate { if ($PSCmdlet.ShouldProcess("local", "Connecting to $computer to import cert")) { try { - Invoke-Command2 -ComputerName $computer -Credential $Credential -ArgumentList $certdata, $Password, $Store, $Folder -ScriptBlock $scriptblock -ErrorAction Stop | + Invoke-Command2 -ComputerName $computer -Credential $Credential -ArgumentList $certdata, $SecurePassword, $Store, $Folder -ScriptBlock $scriptblock -ErrorAction Stop | Select-DefaultView -Property FriendlyName, DnsNameList, Thumbprint, NotBefore, NotAfter, Subject, Issuer } catch { Stop-Function -Message "Failure" -ErrorRecord $_ -Target $computer -Continue @@ -1973,7 +1978,7 @@ function Backup-DbaDbMasterKey { .PARAMETER Credential Pass a credential object for the password - .PARAMETER Password + .PARAMETER SecurePassword The password to encrypt the exported key. This must be a SecureString. .PARAMETER InputObject @@ -2024,7 +2029,8 @@ function Backup-DbaDbMasterKey { [PSCredential]$Credential, [string[]]$Database, [string[]]$ExcludeDatabase, - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [string]$Path, [parameter(ValueFromPipeline)] [Microsoft.SqlServer.Management.Smo.Database[]]$InputObject, @@ -2032,7 +2038,7 @@ function Backup-DbaDbMasterKey { ) begin { if ($Credential) { - $Password = $Credential.Password + $SecurePassword = $Credential.Password } } process { @@ -2068,11 +2074,11 @@ function Backup-DbaDbMasterKey { } # If you pass a password param, then you will not be prompted for each database, but it wouldn't be a good idea to build in insecurity - if (-not $Password -and -not $Credential) { - $password = Read-Host -AsSecureString -Prompt "You must enter Service Key password for $instance" - $password2 = Read-Host -AsSecureString -Prompt "Type the password again" + if (-not $SecurePassword -and -not $Credential) { + $SecurePassword = Read-Host -AsSecureString -Prompt "You must enter Service Key password for $instance" + $SecurePassword2 = Read-Host -AsSecureString -Prompt "Type the password again" - if (([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password))) -ne ([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password2)))) { + if (([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword))) -ne ([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword2)))) { Stop-Function -Message "Passwords do not match" -Continue } } @@ -2085,7 +2091,7 @@ function Backup-DbaDbMasterKey { if ($Pscmdlet.ShouldProcess($instance, "Backing up master key to $filename")) { try { - $masterkey.Export($filename, [System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password))) + $masterkey.Export($filename, [System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword))) $status = "Success" } catch { $status = "Failure" @@ -2501,7 +2507,7 @@ function Connect-DbaInstance { .PARAMETER SqlInstance The target SQL Server instance or instances. This can be a collection and receive pipeline input to allow the function to be executed against multiple SQL Server instances. - .PARAMETER Credential + .PARAMETER SqlCredential Credential object used to connect to the SQL Server Instance as a different user. This can be a Windows or SQL Server account. Windows users are determined by the existence of a backslash, so if you are intending to use an alternative Windows connection instead of a SQL login, ensure it contains a backslash. .PARAMETER Database @@ -2549,9 +2555,6 @@ function Connect-DbaInstance { If you specify a failover partner and the primary server is not configured for database mirroring, the connection to the primary server (specified with the Server keyword) will succeed if the primary server is available. - .PARAMETER IsActiveDirectoryUniversalAuth - If this switch is enabled, the connection will be configured to use Azure Active Directory authentication. - .PARAMETER LockTimeout Sets the time in seconds required for the connection to time out when the current transaction is locked. @@ -2602,6 +2605,13 @@ function Connect-DbaInstance { .PARAMETER SqlConnectionOnly Instead of returning a rich SMO server object, this command will only return a SqlConnection object when setting this switch. + .PARAMETER DisableException + By default in most of our commands, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + + This command, however, gifts you with "sea of red" exceptions, by default, because it is useful for advanced scripting. + + Using this switch turns our "nice by default" feature on which makes errors into pretty warnings. + .NOTES Tags: Connect, Connection Author: Chrissy LeMaire (@cl), netnerds.net @@ -2620,13 +2630,13 @@ function Connect-DbaInstance { .EXAMPLE PS C:\> $wincred = Get-Credential ad\sqladmin - PS C:\> Connect-DbaInstance -SqlInstance sql2014 -Credential $wincred + PS C:\> Connect-DbaInstance -SqlInstance sql2014 -SqlCredential $wincred Creates an SMO Server object that connects using alternative Windows credentials .EXAMPLE PS C:\> $sqlcred = Get-Credential sqladmin - PS C:\> $server = Connect-DbaInstance -SqlInstance sql2014 -Credential $sqlcred + PS C:\> $server = Connect-DbaInstance -SqlInstance sql2014 -SqlCredential $sqlcred Login to sql2014 as SQL login sqladmin. @@ -2656,8 +2666,8 @@ function Connect-DbaInstance { [Parameter(Mandatory, ValueFromPipeline)] [Alias("ServerInstance", "SqlServer")] [DbaInstanceParameter[]]$SqlInstance, - [Alias("SqlCredential")] - [PSCredential]$Credential, + [Alias("Credential")] + [PSCredential]$SqlCredential, [object[]]$Database, [string]$AccessToken, [ValidateSet('ReadOnly', 'ReadWrite')] @@ -2667,7 +2677,6 @@ function Connect-DbaInstance { [int]$ConnectTimeout = ([Sqlcollaborative.Dbatools.Connection.ConnectionHost]::SqlConnectionTimeout), [switch]$EncryptConnection, [string]$FailoverPartner, - [switch]$IsActiveDirectoryUniversalAuth, [int]$LockTimeout, [int]$MaxPoolSize, [int]$MinPoolSize, @@ -2684,9 +2693,16 @@ function Connect-DbaInstance { [switch]$TrustServerCertificate, [string]$WorkstationId, [string]$AppendConnectionString, - [switch]$SqlConnectionOnly + [switch]$SqlConnectionOnly, + [switch]$DisableException ) begin { + if ($DisableException) { + $EnableException = $false + } else { + $EnableException = $true + } + Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Connect-DbaServer Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Get-DbaInstance @@ -2709,8 +2725,6 @@ function Connect-DbaInstance { $Fields2000_Login = 'CreateDate' , 'DateLastModified' , 'DefaultDatabase' , 'DenyWindowsLogin' , 'IsSystemObject' , 'Language' , 'LanguageAlias' , 'LoginType' , 'Name' , 'Sid' , 'WindowsLoginAccessType' $Fields200x_Login = $Fields2000_Login + @('AsymmetricKey', 'Certificate', 'Credential', 'ID', 'IsDisabled', 'IsLocked', 'IsPasswordExpired', 'MustChangePassword', 'PasswordExpirationEnabled', 'PasswordPolicyEnforced') $Fields201x_Login = $Fields200x_Login + @('PasswordHashAlgorithm') - - } process { foreach ($instance in $SqlInstance) { @@ -2756,7 +2770,6 @@ function Connect-DbaInstance { if (Test-Bound -ParameterName 'ConnectTimeout') { $server.ConnectionContext.ConnectTimeout = $ConnectTimeout } if (Test-Bound -ParameterName 'Database') { $server.ConnectionContext.DatabaseName = $Database } if (Test-Bound -ParameterName 'EncryptConnection') { $server.ConnectionContext.EncryptConnection = $true } - if (Test-Bound -ParameterName 'IsActiveDirectoryUniversalAuth') { $server.ConnectionContext.IsActiveDirectoryUniversalAuth = $true } if (Test-Bound -ParameterName 'LockTimeout') { $server.ConnectionContext.LockTimeout = $LockTimeout } if (Test-Bound -ParameterName 'MaxPoolSize') { $server.ConnectionContext.MaxPoolSize = $MaxPoolSize } if (Test-Bound -ParameterName 'MinPoolSize') { $server.ConnectionContext.MinPoolSize = $MinPoolSize } @@ -2780,21 +2793,32 @@ function Connect-DbaInstance { } try { - if ($null -ne $Credential.UserName) { - $username = ($Credential.UserName).TrimStart("\") - - if ($username -like "*\*") { - $username = $username.Split("\")[1] - $authtype = "Windows Authentication with Credential" + if ($null -ne $SqlCredential.UserName) { + $username = ($SqlCredential.UserName).TrimStart("\") + + # support both ad\username and username@ad + if ($username -like "*\*" -or $username -like "*@*") { + if ($username -like "*\*") { + $domain, $login = $username.Split("\") + $authtype = "Windows Authentication with Credential" + if ($domain) { + $formatteduser = "$login@$domain" + } else { + $formatteduser = $username.Split("\")[1] + } + } else { + $formatteduser = $SqlCredential.UserName + } + $server.ConnectionContext.LoginSecure = $true $server.ConnectionContext.ConnectAsUser = $true - $server.ConnectionContext.ConnectAsUserName = $username - $server.ConnectionContext.ConnectAsUserPassword = ($Credential).GetNetworkCredential().Password + $server.ConnectionContext.ConnectAsUserName = $formatteduser + $server.ConnectionContext.ConnectAsUserPassword = ($SqlCredential).GetNetworkCredential().Password } else { $authtype = "SQL Authentication" $server.ConnectionContext.LoginSecure = $false $server.ConnectionContext.set_Login($username) - $server.ConnectionContext.set_SecurePassword($Credential.Password) + $server.ConnectionContext.set_SecurePassword($SqlCredential.Password) } } @@ -2819,9 +2843,9 @@ function Connect-DbaInstance { $message = ($message -Split '-->')[0] $message = ($message -Split 'at System.Data.SqlClient')[0] $message = ($message -Split 'at System.Data.ProviderBase')[0] - throw "Can't connect to $instance`: $message " + + Stop-Function -Message "Can't connect to $instance" -ErrorRecord $_ -Continue } - } if ($loadedSmoVersion -ge 11) { @@ -3913,11 +3937,292 @@ function Copy-DbaAgentAlert { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlAlert } } +function Copy-DbaAgentJob { + <# + .SYNOPSIS + Copy-DbaAgentJob migrates jobs from one SQL Server to another. + + .DESCRIPTION + By default, all jobs are copied. The -Job parameter is auto-populated for command-line completion and can be used to copy only specific jobs. + + If the job already exists on the destination, it will be skipped unless -Force is used. + + .PARAMETER Source + Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. + + .PARAMETER SourceSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER Destination + Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. + + .PARAMETER DestinationSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER Job + The job(s) to process. This list is auto-populated from the server. If unspecified, all jobs will be processed. + + .PARAMETER ExcludeJob + The job(s) to exclude. This list is auto-populated from the server. + + .PARAMETER DisableOnSource + If this switch is enabled, the job will be disabled on the source server. + + .PARAMETER DisableOnDestination + If this switch is enabled, the newly migrated job will be disabled on the destination server. + + .PARAMETER WhatIf + If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. + + .PARAMETER Confirm + If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. + + .PARAMETER Force + If this switch is enabled, the Job will be dropped and recreated on Destination. + + .PARAMETER EnableException + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. + + .NOTES + Tags: Migration, Agent, Job + Author: Chrissy LeMaire (@cl), netnerds.net + + Website: https://dbatools.io + Copyright: (c) 2018 by dbatools, licensed under MIT + License: MIT https://opensource.org/licenses/MIT + + .LINK + https://dbatools.io/Copy-DbaAgentJob + + .EXAMPLE + PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster + + Copies all jobs from sqlserver2014a to sqlcluster, using Windows credentials. If jobs with the same name exist on sqlcluster, they will be skipped. + + .EXAMPLE + PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster -Job PSJob -SourceSqlCredential $cred -Force + + Copies a single job, the PSJob job from sqlserver2014a to sqlcluster, using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If a job with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used. + + .EXAMPLE + PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force + + Shows what would happen if the command were executed using force. + + #> + [cmdletbinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] + param ( + [parameter(Mandatory)] + [DbaInstanceParameter]$Source, + [PSCredential]$SourceSqlCredential, + [parameter(Mandatory)] + [DbaInstanceParameter[]]$Destination, + [PSCredential]$DestinationSqlCredential, + [object[]]$Job, + [object[]]$ExcludeJob, + [switch]$DisableOnSource, + [switch]$DisableOnDestination, + [switch]$Force, + [Alias('Silent')] + [switch]$EnableException + ) + begin { + try { + $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source + return + } + + $serverJobs = $sourceServer.JobServer.Jobs + } + process { + if (Test-FunctionInterrupt) { return } + foreach ($destinstance in $Destination) { + try { + $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue + } + $destJobs = $destServer.JobServer.Jobs + + foreach ($serverJob in $serverJobs) { + $jobName = $serverJob.name + $jobId = $serverJob.JobId + + $copyJobStatus = [pscustomobject]@{ + SourceServer = $sourceServer.Name + DestinationServer = $destServer.Name + Name = $jobName + Type = "Agent Job" + Status = $null + Notes = $null + DateTime = [DbaDateTime](Get-Date) + } + + if ($Job -and $jobName -notin $Job -or $jobName -in $ExcludeJob) { + Write-Message -Level Verbose -Message "Job [$jobName] filtered. Skipping." + continue + } + Write-Message -Message "Working on job: $jobName" -Level Verbose + $sql = " + SELECT sp.[name] AS MaintenancePlanName + FROM msdb.dbo.sysmaintplan_plans AS sp + INNER JOIN msdb.dbo.sysmaintplan_subplans AS sps + ON sps.plan_id = sp.id + WHERE job_id = '$($jobId)'" + Write-Message -Message $sql -Level Debug + + $MaintenancePlanName = $sourceServer.Query($sql).MaintenancePlanName + + if ($MaintenancePlanName) { + if ($Pscmdlet.ShouldProcess($destinstance, "Job [$jobName] is associated with Maintenance Plan: $MaintenancePlanNam")) { + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job is associated with maintenance plan" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Job [$jobName] is associated with Maintenance Plan: $MaintenancePlanName" + } + continue + } + + $dbNames = ($serverJob.JobSteps | where-object {$_.SubSystem -ne 'ActiveScripting'}).DatabaseName | Where-Object { $_.Length -gt 0 } + $missingDb = $dbNames | Where-Object { $destServer.Databases.Name -notcontains $_ } + + if ($missingDb.Count -gt 0 -and $dbNames.Count -gt 0) { + if ($Pscmdlet.ShouldProcess($destinstance, "Database(s) $missingDb doesn't exist on destination. Skipping job [$jobName].")) { + $missingDb = ($missingDb | Sort-Object | Get-Unique) -join ", " + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job is dependent on database: $missingDb" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Database(s) $missingDb doesn't exist on destination. Skipping job [$jobName]." + } + continue + } + + $missingLogin = $serverJob.OwnerLoginName | Where-Object { $destServer.Logins.Name -notcontains $_ } + + if ($missingLogin.Count -gt 0) { + if ($force -eq $false) { + if ($Pscmdlet.ShouldProcess($destinstance, "Login(s) $missingLogin doesn't exist on destination. Use -Force to set owner to [sa]. Skipping job [$jobName].")) { + $missingLogin = ($missingLogin | Sort-Object | Get-Unique) -join ", " + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job is dependent on login $missingLogin" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Login(s) $missingLogin doesn't exist on destination. Use -Force to set owner to [sa]. Skipping job [$jobName]." + } + continue + } + } + + $proxyNames = ($serverJob.JobSteps | Where-Object ProxyName).ProxyName + $missingProxy = $proxyNames | Where-Object { $destServer.JobServer.ProxyAccounts.Name -notcontains $_ } + + if ($missingProxy -and $proxyNames) { + if ($Pscmdlet.ShouldProcess($destinstance, "Proxy Account(s) $missingProxy doesn't exist on destination. Skipping job [$jobName].")) { + $missingProxy = ($missingProxy | Sort-Object | Get-Unique) -join ", " + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job is dependent on proxy $missingProxy" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Proxy Account(s) $missingProxy doesn't exist on destination. Skipping job [$jobName]." + } + continue + } + + $operators = $serverJob.OperatorToEmail, $serverJob.OperatorToNetSend, $serverJob.OperatorToPage | Where-Object { $_.Length -gt 0 } + $missingOperators = $operators | Where-Object { $destServer.JobServer.Operators.Name -notcontains $_ } + + if ($missingOperators.Count -gt 0 -and $operators.Count -gt 0) { + if ($Pscmdlet.ShouldProcess($destinstance, "Operator(s) $($missingOperator) doesn't exist on destination. Skipping job [$jobName]")) { + $missingOperator = ($operators | Sort-Object | Get-Unique) -join ", " + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job is dependent on operator $missingOperator" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Operator(s) $($missingOperator) doesn't exist on destination. Skipping job [$jobName]" + } + continue + } + + if ($destJobs.name -contains $serverJob.name) { + if ($force -eq $false) { + if ($Pscmdlet.ShouldProcess($destinstance, "Job $jobName exists at destination. Use -Force to drop and migrate.")) { + $copyJobStatus.Status = "Skipped" + $copyJobStatus.Notes = "Job already exists on destination" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Job $jobName exists at destination. Use -Force to drop and migrate." + } + continue + } else { + if ($Pscmdlet.ShouldProcess($destinstance, "Dropping job $jobName and recreating")) { + try { + Write-Message -Message "Dropping Job $jobName" -Level Verbose + $destServer.JobServer.Jobs[$jobName].Drop() + } catch { + $copyJobStatus.Status = "Failed" + $copyJobStatus.Notes = (Get-ErrorMessage -Record $_).Message + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Stop-Function -Message "Issue dropping job" -Target $jobName -ErrorRecord $_ -Continue + } + } + } + } + + if ($Pscmdlet.ShouldProcess($destinstance, "Creating Job $jobName")) { + try { + Write-Message -Message "Copying Job $jobName" -Level Verbose + $sql = $serverJob.Script() | Out-String + + if ($missingLogin.Count -gt 0 -and $force) { + $saLogin = Get-SqlSaLogin -SqlInstance $destServer + $sql = $sql -replace [Regex]::Escape("@owner_login_name=N'$missingLogin'"), [Regex]::Escape("@owner_login_name=N'$saLogin'") + } + + Write-Message -Message $sql -Level Debug + $destServer.Query($sql) + + $destServer.JobServer.Jobs.Refresh() + $destServer.JobServer.Jobs[$serverJob.name].IsEnabled = $sourceServer.JobServer.Jobs[$serverJob.name].IsEnabled + $destServer.JobServer.Jobs[$serverJob.name].Alter() + } catch { + $copyJobStatus.Status = "Failed" + $copyJobStatus.Notes = (Get-ErrorMessage -Record $_) + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Stop-Function -Message "Issue copying job" -Target $jobName -ErrorRecord $_ -Continue + } + } + + if ($DisableOnDestination) { + if ($Pscmdlet.ShouldProcess($destinstance, "Disabling $jobName")) { + Write-Message -Message "Disabling $jobName on $destinstance" -Level Verbose + $destServer.JobServer.Jobs[$serverJob.name].IsEnabled = $False + $destServer.JobServer.Jobs[$serverJob.name].Alter() + } + } + + if ($DisableOnSource) { + if ($Pscmdlet.ShouldProcess($source, "Disabling $jobName")) { + Write-Message -Message "Disabling $jobName on $source" -Level Verbose + $serverJob.IsEnabled = $false + $serverJob.Alter() + } + } + if ($Pscmdlet.ShouldProcess($destinstance, "Reporting status of migration for $jobname")) { + $copyJobStatus.Status = "Successful" + $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + } + } + } + } + end { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlJob + } +} #ValidationTags#Messaging# -function Copy-DbaAgentCategory { +function Copy-DbaAgentJobCategory { <# .SYNOPSIS - Copy-DbaAgentCategory migrates SQL Agent categories from one SQL Server to another. This is similar to sp_add_category. + Copy-DbaAgentJobCategory migrates SQL Agent categories from one SQL Server to another. This is similar to sp_add_category. https://msdn.microsoft.com/en-us/library/ms181597.aspx @@ -3979,20 +4284,20 @@ function Copy-DbaAgentCategory { Requires: sysadmin access on SQL Servers .LINK - https://dbatools.io/Copy-DbaAgentCategory + https://dbatools.io/Copy-DbaAgentJobCategory .EXAMPLE - PS C:\> Copy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster + PS C:\> Copy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster Copies all operator categories from sqlserver2014a to sqlcluster using Windows authentication. If operator categories with the same name exist on sqlcluster, they will be skipped. .EXAMPLE - PS C:\> Copy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster -OperatorCategory PSOperator -SourceSqlCredential $cred -Force + PS C:\> Copy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster -OperatorCategory PSOperator -SourceSqlCredential $cred -Force Copies a single operator category, the PSOperator operator category from sqlserver2014a to sqlcluster using SQL credentials to authenticate to sqlserver2014a and Windows credentials for sqlcluster. If an operator category with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used. .EXAMPLE - PS C:\> Copy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force + PS C:\> Copy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force Shows what would happen if the command were executed using force. @@ -4015,8 +4320,9 @@ function Copy-DbaAgentCategory { [Alias('Silent')] [switch]$EnableException ) - + begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaAgentCategory function Copy-JobCategory { <# .SYNOPSIS @@ -4314,287 +4620,6 @@ function Copy-DbaAgentCategory { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlAgentCategory } } -function Copy-DbaAgentJob { - <# - .SYNOPSIS - Copy-DbaAgentJob migrates jobs from one SQL Server to another. - - .DESCRIPTION - By default, all jobs are copied. The -Job parameter is auto-populated for command-line completion and can be used to copy only specific jobs. - - If the job already exists on the destination, it will be skipped unless -Force is used. - - .PARAMETER Source - Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. - - .PARAMETER SourceSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER Destination - Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. - - .PARAMETER DestinationSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER Job - The job(s) to process. This list is auto-populated from the server. If unspecified, all jobs will be processed. - - .PARAMETER ExcludeJob - The job(s) to exclude. This list is auto-populated from the server. - - .PARAMETER DisableOnSource - If this switch is enabled, the job will be disabled on the source server. - - .PARAMETER DisableOnDestination - If this switch is enabled, the newly migrated job will be disabled on the destination server. - - .PARAMETER WhatIf - If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. - - .PARAMETER Confirm - If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. - - .PARAMETER Force - If this switch is enabled, the Job will be dropped and recreated on Destination. - - .PARAMETER EnableException - By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. - This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. - Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. - - .NOTES - Tags: Migration, Agent, Job - Author: Chrissy LeMaire (@cl), netnerds.net - - Website: https://dbatools.io - Copyright: (c) 2018 by dbatools, licensed under MIT - License: MIT https://opensource.org/licenses/MIT - - .LINK - https://dbatools.io/Copy-DbaAgentJob - - .EXAMPLE - PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster - - Copies all jobs from sqlserver2014a to sqlcluster, using Windows credentials. If jobs with the same name exist on sqlcluster, they will be skipped. - - .EXAMPLE - PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster -Job PSJob -SourceSqlCredential $cred -Force - - Copies a single job, the PSJob job from sqlserver2014a to sqlcluster, using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If a job with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used. - - .EXAMPLE - PS C:\> Copy-DbaAgentJob -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force - - Shows what would happen if the command were executed using force. - - #> - [cmdletbinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] - param ( - [parameter(Mandatory)] - [DbaInstanceParameter]$Source, - [PSCredential]$SourceSqlCredential, - [parameter(Mandatory)] - [DbaInstanceParameter[]]$Destination, - [PSCredential]$DestinationSqlCredential, - [object[]]$Job, - [object[]]$ExcludeJob, - [switch]$DisableOnSource, - [switch]$DisableOnDestination, - [switch]$Force, - [Alias('Silent')] - [switch]$EnableException - ) - begin { - try { - $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source - return - } - - $serverJobs = $sourceServer.JobServer.Jobs - } - process { - if (Test-FunctionInterrupt) { return } - foreach ($destinstance in $Destination) { - try { - $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue - } - $destJobs = $destServer.JobServer.Jobs - - foreach ($serverJob in $serverJobs) { - $jobName = $serverJob.name - $jobId = $serverJob.JobId - - $copyJobStatus = [pscustomobject]@{ - SourceServer = $sourceServer.Name - DestinationServer = $destServer.Name - Name = $jobName - Type = "Agent Job" - Status = $null - Notes = $null - DateTime = [DbaDateTime](Get-Date) - } - - if ($Job -and $jobName -notin $Job -or $jobName -in $ExcludeJob) { - Write-Message -Level Verbose -Message "Job [$jobName] filtered. Skipping." - continue - } - Write-Message -Message "Working on job: $jobName" -Level Verbose - $sql = " - SELECT sp.[name] AS MaintenancePlanName - FROM msdb.dbo.sysmaintplan_plans AS sp - INNER JOIN msdb.dbo.sysmaintplan_subplans AS sps - ON sps.plan_id = sp.id - WHERE job_id = '$($jobId)'" - Write-Message -Message $sql -Level Debug - - $MaintenancePlanName = $sourceServer.Query($sql).MaintenancePlanName - - if ($MaintenancePlanName) { - if ($Pscmdlet.ShouldProcess($destinstance, "Job [$jobName] is associated with Maintenance Plan: $MaintenancePlanNam")) { - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job is associated with maintenance plan" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Job [$jobName] is associated with Maintenance Plan: $MaintenancePlanName" - } - continue - } - - $dbNames = ($serverJob.JobSteps | where-object {$_.SubSystem -ne 'ActiveScripting'}).DatabaseName | Where-Object { $_.Length -gt 0 } - $missingDb = $dbNames | Where-Object { $destServer.Databases.Name -notcontains $_ } - - if ($missingDb.Count -gt 0 -and $dbNames.Count -gt 0) { - if ($Pscmdlet.ShouldProcess($destinstance, "Database(s) $missingDb doesn't exist on destination. Skipping job [$jobName].")) { - $missingDb = ($missingDb | Sort-Object | Get-Unique) -join ", " - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job is dependent on database: $missingDb" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Database(s) $missingDb doesn't exist on destination. Skipping job [$jobName]." - } - continue - } - - $missingLogin = $serverJob.OwnerLoginName | Where-Object { $destServer.Logins.Name -notcontains $_ } - - if ($missingLogin.Count -gt 0) { - if ($force -eq $false) { - if ($Pscmdlet.ShouldProcess($destinstance, "Login(s) $missingLogin doesn't exist on destination. Use -Force to set owner to [sa]. Skipping job [$jobName].")) { - $missingLogin = ($missingLogin | Sort-Object | Get-Unique) -join ", " - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job is dependent on login $missingLogin" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Login(s) $missingLogin doesn't exist on destination. Use -Force to set owner to [sa]. Skipping job [$jobName]." - } - continue - } - } - - $proxyNames = $serverJob.JobSteps.ProxyName | Where-Object { $_.Length -gt 0 } - $missingProxy = $proxyNames | Where-Object { $destServer.JobServer.ProxyAccounts.Name -notcontains $_ } - - if ($missingProxy.Count -gt 0 -and $proxyNames.Count -gt 0) { - if ($Pscmdlet.ShouldProcess($destinstance, "Proxy Account(s) $($proxyNames[0]) doesn't exist on destination. Skipping job [$jobName].")) { - $missingProxy = ($missingProxy | Sort-Object | Get-Unique) -join ", " - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job is dependent on proxy $($proxyNames[0])" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Proxy Account(s) $($proxyNames[0]) doesn't exist on destination. Skipping job [$jobName]." - } - continue - } - - $operators = $serverJob.OperatorToEmail, $serverJob.OperatorToNetSend, $serverJob.OperatorToPage | Where-Object { $_.Length -gt 0 } - $missingOperators = $operators | Where-Object { $destServer.JobServer.Operators.Name -notcontains $_ } - - if ($missingOperators.Count -gt 0 -and $operators.Count -gt 0) { - if ($Pscmdlet.ShouldProcess($destinstance, "Operator(s) $($missingOperator) doesn't exist on destination. Skipping job [$jobName]")) { - $missingOperator = ($operators | Sort-Object | Get-Unique) -join ", " - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job is dependent on operator $missingOperator" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Operator(s) $($missingOperator) doesn't exist on destination. Skipping job [$jobName]" - } - continue - } - - if ($destJobs.name -contains $serverJob.name) { - if ($force -eq $false) { - if ($Pscmdlet.ShouldProcess($destinstance, "Job $jobName exists at destination. Use -Force to drop and migrate.")) { - $copyJobStatus.Status = "Skipped" - $copyJobStatus.Notes = "Job already exists on destination" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Job $jobName exists at destination. Use -Force to drop and migrate." - } - continue - } else { - if ($Pscmdlet.ShouldProcess($destinstance, "Dropping job $jobName and recreating")) { - try { - Write-Message -Message "Dropping Job $jobName" -Level Verbose - $destServer.JobServer.Jobs[$jobName].Drop() - } catch { - $copyJobStatus.Status = "Failed" - $copyJobStatus.Notes = (Get-ErrorMessage -Record $_).Message - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Stop-Function -Message "Issue dropping job" -Target $jobName -ErrorRecord $_ -Continue - } - } - } - } - - if ($Pscmdlet.ShouldProcess($destinstance, "Creating Job $jobName")) { - try { - Write-Message -Message "Copying Job $jobName" -Level Verbose - $sql = $serverJob.Script() | Out-String - - if ($missingLogin.Count -gt 0 -and $force) { - $saLogin = Get-SqlSaLogin -SqlInstance $destServer - $sql = $sql -replace [Regex]::Escape("@owner_login_name=N'$missingLogin'"), [Regex]::Escape("@owner_login_name=N'$saLogin'") - } - - Write-Message -Message $sql -Level Debug - $destServer.Query($sql) - - $destServer.JobServer.Jobs.Refresh() - $destServer.JobServer.Jobs[$serverJob.name].IsEnabled = $sourceServer.JobServer.Jobs[$serverJob.name].IsEnabled - $destServer.JobServer.Jobs[$serverJob.name].Alter() - } catch { - $copyJobStatus.Status = "Failed" - $copyJobStatus.Notes = (Get-ErrorMessage -Record $_) - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Stop-Function -Message "Issue copying job" -Target $jobName -ErrorRecord $_ -Continue - } - } - - if ($DisableOnDestination) { - if ($Pscmdlet.ShouldProcess($destinstance, "Disabling $jobName")) { - Write-Message -Message "Disabling $jobName on $destinstance" -Level Verbose - $destServer.JobServer.Jobs[$serverJob.name].IsEnabled = $False - $destServer.JobServer.Jobs[$serverJob.name].Alter() - } - } - - if ($DisableOnSource) { - if ($Pscmdlet.ShouldProcess($source, "Disabling $jobName")) { - Write-Message -Message "Disabling $jobName on $source" -Level Verbose - $serverJob.IsEnabled = $false - $serverJob.Alter() - } - } - if ($Pscmdlet.ShouldProcess($destinstance, "Reporting status of migration for $jobname")) { - $copyJobStatus.Status = "Successful" - $copyJobStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - } - } - } - } - end { - Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlJob - } -} function Copy-DbaAgentOperator { <# .SYNOPSIS @@ -4771,10 +4796,10 @@ function Copy-DbaAgentOperator { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlOperator } } -function Copy-DbaAgentProxyAccount { +function Copy-DbaAgentProxy { <# .SYNOPSIS - Copy-DbaAgentProxyAccount migrates proxy accounts from one SQL Server to another. + Copy-DbaAgentProxy migrates proxy accounts from one SQL Server to another. .DESCRIPTION By default, all proxy accounts are copied. The -ProxyAccounts parameter is auto-populated for command-line completion and can be used to copy only specific proxy accounts. @@ -4824,20 +4849,20 @@ function Copy-DbaAgentProxyAccount { Requires: sysadmin access on SQL Servers .LINK - https://dbatools.io/Copy-DbaAgentProxyAccount + https://dbatools.io/Copy-DbaAgentProxy .EXAMPLE - PS C:\> Copy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster + PS C:\> Copy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster Copies all proxy accounts from sqlserver2014a to sqlcluster using Windows credentials. If proxy accounts with the same name exist on sqlcluster, they will be skipped. .EXAMPLE - PS C:\> Copy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster -ProxyAccount PSProxy -SourceSqlCredential $cred -Force + PS C:\> Copy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster -ProxyAccount PSProxy -SourceSqlCredential $cred -Force Copies only the PSProxy proxy account from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If a proxy account with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used. .EXAMPLE - PS C:\> Copy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force + PS C:\> Copy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force Shows what would happen if the command were executed using force. @@ -4857,6 +4882,7 @@ function Copy-DbaAgentProxyAccount { [switch]$EnableException ) begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaAgentProxyAccount try { $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 } catch { @@ -4894,23 +4920,32 @@ function Copy-DbaAgentProxyAccount { Notes = $null DateTime = [Sqlcollaborative.Dbatools.Utility.DbaDateTime](Get-Date) } - - # Proxy accounts rely on Credential accounts + $credentialName = $account.CredentialName - $copyAgentProxyAccountStatus.Name = $credentialName + $copyAgentProxyAccountStatus.Name = $proxyName $copyAgentProxyAccountStatus.Type = "Credential" - + + # Proxy accounts rely on Credential accounts + if (-not $CredentialName) { + $copyAgentProxyAccountStatus.Status = "Skipped" + $copyAgentProxyAccountStatus.Notes = "Skipping migration of $proxyName due to misconfigured (empty) credential name" + $copyAgentProxyAccountStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Skipping migration of $proxyName due to misconfigured (empty) credential name" + continue + } + try { $credentialtest = $destServer.Credentials[$CredentialName] } catch { #here to avoid an empty catch $null = 1 } - + if ($null -eq $credentialtest) { $copyAgentProxyAccountStatus.Status = "Skipped" + $copyAgentProxyAccountStatus.Notes = "Associated credential account, $CredentialName, does not exist on $destinstance" $copyAgentProxyAccountStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Associated credential account, $CredentialName, does not exist on $destinstance. Skipping migration of $proxyName." + Write-Message -Level Verbose -Message "Associated credential account, $CredentialName, does not exist on $destinstance" continue } @@ -4921,8 +4956,7 @@ function Copy-DbaAgentProxyAccount { if ($force -eq $false) { $copyAgentProxyAccountStatus.Status = "Skipped" $copyAgentProxyAccountStatus - Write-Message -Level Verbose -Message "Server proxy account $proxyName exists at destination. Use -Force to drop and migrate." - continue + Stop-Function -Message "Server proxy account $proxyName exists at destination. Use -Force to drop and migrate." -Continue } else { if ($Pscmdlet.ShouldProcess($destinstance, "Dropping server proxy account $proxyName and recreating")) { try { @@ -4974,6 +5008,171 @@ function Copy-DbaAgentProxyAccount { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlProxyAccount } } +function Copy-DbaAgentSchedule { + <# + .SYNOPSIS + Copy-DbaAgentSchedule migrates shared job schedules from one SQL Server to another. + + .DESCRIPTION + All shared job schedules are copied. + + If the associated credential for the account does not exist on the destination, it will be skipped. If the shared job schedule already exists on the destination, it will be skipped unless -Force is used. + + .PARAMETER Source + Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. + + .PARAMETER SourceSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER Destination + Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. + + .PARAMETER DestinationSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER WhatIf + If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. + + .PARAMETER Confirm + If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. + + .PARAMETER Force + If this switch is enabled, the Operator will be dropped and recreated on Destination. + + .PARAMETER EnableException + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. + + .NOTES + Tags: Migration, Agent + Author: Chrissy LeMaire (@cl), netnerds.net + + Website: https://dbatools.io + Copyright: (c) 2018 by dbatools, licensed under MIT + License: MIT https://opensource.org/licenses/MIT + + Requires: sysadmin access on SQL Servers + + .LINK + https://dbatools.io/Copy-DbaAgentSchedule + + .EXAMPLE + PS C:\> Copy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster + + Copies all shared job schedules from sqlserver2014a to sqlcluster using Windows credentials. If shared job schedules with the same name exist on sqlcluster, they will be skipped. + + .EXAMPLE + PS C:\> Copy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force + + Shows what would happen if the command were executed using force. + + #> + [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] + param ( + [parameter(Mandatory)] + [DbaInstanceParameter]$Source, + [PSCredential] + $SourceSqlCredential, + [parameter(Mandatory)] + [DbaInstanceParameter[]]$Destination, + [PSCredential] + $DestinationSqlCredential, + [switch]$Force, + [Alias('Silent')] + [switch]$EnableException + ) + begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaAgentSharedSchedule + try { + $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source + return + } + $serverSchedules = $sourceServer.JobServer.SharedSchedules + } + process { + if (Test-FunctionInterrupt) { return } + foreach ($destinstance in $Destination) { + try { + $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential -MinimumVersion 9 + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue + } + + $destSchedules = $destServer.JobServer.SharedSchedules + foreach ($schedule in $serverSchedules) { + $scheduleName = $schedule.Name + $copySharedScheduleStatus = [pscustomobject]@{ + SourceServer = $sourceServer.Name + DestinationServer = $destServer.Name + Type = "Agent Schedule" + Name = $scheduleName + Status = $null + Notes = $null + DateTime = [Sqlcollaborative.Dbatools.Utility.DbaDateTime](Get-Date) + } + + if ($schedules.Length -gt 0 -and $schedules -notcontains $scheduleName) { + continue + } + + if ($destSchedules.Name -contains $scheduleName) { + if ($force -eq $false) { + if ($Pscmdlet.ShouldProcess($destinstance, "Shared job schedule $scheduleName exists at destination. Use -Force to drop and migrate.")) { + $copySharedScheduleStatus.Status = "Skipped" + $copySharedScheduleStatus.Notes = "Already exists" + $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Shared job schedule $scheduleName exists at destination. Use -Force to drop and migrate." + continue + } + } else { + if ($Pscmdlet.ShouldProcess($destinstance, "Schedule [$scheduleName] has associated jobs. Skipping.")) { + if ($destServer.JobServer.Jobs.JobSchedules.Name -contains $scheduleName) { + $copySharedScheduleStatus.Status = "Skipped" + $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Write-Message -Level Verbose -Message "Schedule [$scheduleName] has associated jobs. Skipping." + } + continue + } else { + if ($Pscmdlet.ShouldProcess($destinstance, "Dropping schedule $scheduleName and recreating")) { + try { + Write-Message -Level Verbose -Message "Dropping schedule $scheduleName" + $destServer.JobServer.SharedSchedules[$scheduleName].Drop() + } catch { + $copySharedScheduleStatus.Status = "Failed" + $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Stop-Function -Message "Issue dropping schedule" -Target $scheduleName -ErrorRecord $_ -Continue + } + } + } + } + } + + if ($Pscmdlet.ShouldProcess($destinstance, "Creating schedule $scheduleName")) { + try { + Write-Message -Level Verbose -Message "Copying schedule $scheduleName" + $sql = $schedule.Script() | Out-String + + Write-Message -Level Debug -Message $sql + $destServer.Query($sql) + + $copySharedScheduleStatus.Status = "Successful" + $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + } catch { + $copySharedScheduleStatus.Status = "Failed" + $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + Stop-Function -Message "Issue creating schedule" -Target $scheduleName -ErrorRecord $_ -Continue + } + } + } + } + } + end { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlSharedSchedule + } +} function Copy-DbaAgentServer { <# .SYNOPSIS @@ -5080,7 +5279,7 @@ function Copy-DbaAgentServer { } Invoke-SmoCheck -SqlInstance $destServer # All of these support whatif inside of them - Copy-DbaAgentCategory -Source $sourceServer -Destination $destServer -Force:$force + Copy-DbaAgentJobCategory -Source $sourceServer -Destination $destServer -Force:$force $destServer.JobServer.JobCategories.Refresh() $destServer.JobServer.OperatorCategories.Refresh() @@ -5092,7 +5291,7 @@ function Copy-DbaAgentServer { Copy-DbaAgentAlert -Source $sourceServer -Destination $destServer -Force:$force -IncludeDefaults $destServer.JobServer.Alerts.Refresh() - Copy-DbaAgentProxyAccount -Source $sourceServer -Destination $destServer -Force:$force + Copy-DbaAgentProxy -Source $sourceServer -Destination $destServer -Force:$force $destServer.JobServer.ProxyAccounts.Refresh() Copy-DbaAgentSchedule -Source $sourceServer -Destination $destServer -Force:$force @@ -5148,170 +5347,6 @@ function Copy-DbaAgentServer { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-DbaSqlServerAgent } } -function Copy-DbaAgentSchedule { - <# - .SYNOPSIS - Copy-DbaAgentSchedule migrates shared job schedules from one SQL Server to another. - - .DESCRIPTION - All shared job schedules are copied. - - If the associated credential for the account does not exist on the destination, it will be skipped. If the shared job schedule already exists on the destination, it will be skipped unless -Force is used. - - .PARAMETER Source - Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. - - .PARAMETER SourceSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER Destination - Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. - - .PARAMETER DestinationSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER WhatIf - If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. - - .PARAMETER Confirm - If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. - - .PARAMETER Force - If this switch is enabled, the Operator will be dropped and recreated on Destination. - - .PARAMETER EnableException - By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. - This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. - Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. - - .NOTES - Tags: Migration, Agent - Author: Chrissy LeMaire (@cl), netnerds.net - - Website: https://dbatools.io - Copyright: (c) 2018 by dbatools, licensed under MIT - License: MIT https://opensource.org/licenses/MIT - - Requires: sysadmin access on SQL Servers - - .LINK - https://dbatools.io/Copy-DbaAgentSchedule - - .EXAMPLE - PS C:\> Copy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster - - Copies all shared job schedules from sqlserver2014a to sqlcluster using Windows credentials. If shared job schedules with the same name exist on sqlcluster, they will be skipped. - - .EXAMPLE - PS C:\> Copy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force - - Shows what would happen if the command were executed using force. - - #> - [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] - param ( - [parameter(Mandatory)] - [DbaInstanceParameter]$Source, - [PSCredential] - $SourceSqlCredential, - [parameter(Mandatory)] - [DbaInstanceParameter[]]$Destination, - [PSCredential] - $DestinationSqlCredential, - [switch]$Force, - [Alias('Silent')] - [switch]$EnableException - ) - begin { - try { - $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 9 - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source - return - } - $serverSchedules = $sourceServer.JobServer.SharedSchedules - } - process { - if (Test-FunctionInterrupt) { return } - foreach ($destinstance in $Destination) { - try { - $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential -MinimumVersion 9 - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue - } - - $destSchedules = $destServer.JobServer.SharedSchedules - foreach ($schedule in $serverSchedules) { - $scheduleName = $schedule.Name - $copySharedScheduleStatus = [pscustomobject]@{ - SourceServer = $sourceServer.Name - DestinationServer = $destServer.Name - Type = "Agent Schedule" - Name = $scheduleName - Status = $null - Notes = $null - DateTime = [Sqlcollaborative.Dbatools.Utility.DbaDateTime](Get-Date) - } - - if ($schedules.Length -gt 0 -and $schedules -notcontains $scheduleName) { - continue - } - - if ($destSchedules.Name -contains $scheduleName) { - if ($force -eq $false) { - if ($Pscmdlet.ShouldProcess($destinstance, "Shared job schedule $scheduleName exists at destination. Use -Force to drop and migrate.")) { - $copySharedScheduleStatus.Status = "Skipped" - $copySharedScheduleStatus.Notes = "Already exists" - $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Shared job schedule $scheduleName exists at destination. Use -Force to drop and migrate." - continue - } - } else { - if ($Pscmdlet.ShouldProcess($destinstance, "Schedule [$scheduleName] has associated jobs. Skipping.")) { - if ($destServer.JobServer.Jobs.JobSchedules.Name -contains $scheduleName) { - $copySharedScheduleStatus.Status = "Skipped" - $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Write-Message -Level Verbose -Message "Schedule [$scheduleName] has associated jobs. Skipping." - } - continue - } else { - if ($Pscmdlet.ShouldProcess($destinstance, "Dropping schedule $scheduleName and recreating")) { - try { - Write-Message -Level Verbose -Message "Dropping schedule $scheduleName" - $destServer.JobServer.SharedSchedules[$scheduleName].Drop() - } catch { - $copySharedScheduleStatus.Status = "Failed" - $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Stop-Function -Message "Issue dropping schedule" -Target $scheduleName -ErrorRecord $_ -Continue - } - } - } - } - } - - if ($Pscmdlet.ShouldProcess($destinstance, "Creating schedule $scheduleName")) { - try { - Write-Message -Level Verbose -Message "Copying schedule $scheduleName" - $sql = $schedule.Script() | Out-String - - Write-Message -Level Debug -Message $sql - $destServer.Query($sql) - - $copySharedScheduleStatus.Status = "Successful" - $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - } catch { - $copySharedScheduleStatus.Status = "Failed" - $copySharedScheduleStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - Stop-Function -Message "Issue creating schedule" -Target $scheduleName -ErrorRecord $_ -Continue - } - } - } - } - } - end { - Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlSharedSchedule - } -} function Copy-DbaBackupDevice { <# .SYNOPSIS @@ -5531,13 +5566,13 @@ function Copy-DbaBackupDevice { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlBackupDevice } } -function Copy-DbaCentralManagementServer { +function Copy-DbaCmsRegServer { <# .SYNOPSIS Migrates SQL Server Central Management groups and server instances from one SQL Server to another. .DESCRIPTION - Copy-DbaCentralManagementServer copies all groups, subgroups, and server instances from one SQL Server to another. + Copy-DbaCmsRegServer copies all groups, subgroups, and server instances from one SQL Server to another. .PARAMETER Source Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. @@ -5551,10 +5586,10 @@ function Copy-DbaCentralManagementServer { .PARAMETER DestinationSqlCredential Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - .PARAMETER CMSGroup + .PARAMETER Group This is an auto-populated array that contains your Central Management Server top-level groups on Source. You can specify one, many or none. - If CMSGroup is not specified, all groups in your Central Management Server will be copied. + If Group is not specified, all groups in your Central Management Server will be copied. .PARAMETER SwitchServerName If this switch is enabled, all instance names will be changed from Source to Destination. @@ -5586,20 +5621,20 @@ function Copy-DbaCentralManagementServer { Requires: sysadmin access on SQL Servers .LINK - https://dbatools.io/Copy-DbaCentralManagementServer + https://dbatools.io/Copy-DbaCmsRegServer .EXAMPLE - PS C:\> Copy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster + PS C:\> Copy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster All groups, subgroups, and server instances are copied from sqlserver2014a CMS to sqlcluster CMS. .EXAMPLE - PS C:\> Copy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster -CMSGroup Group1,Group3 + PS C:\> Copy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster -Group Group1,Group3 Top-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster. .EXAMPLE - PS C:\> Copy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster -CMSGroup Group1,Group3 -SwitchServerName -SourceSqlCredential $SourceSqlCredential -DestinationSqlCredential $DestinationSqlCredential + PS C:\> Copy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster -Group Group1,Group3 -SwitchServerName -SourceSqlCredential $SourceSqlCredential -DestinationSqlCredential $DestinationSqlCredential Top-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster. When adding sql instances to sqlcluster, if the server name of the migrating instance is "sqlcluster", it will be switched to "sqlserver". @@ -5614,13 +5649,14 @@ function Copy-DbaCentralManagementServer { [parameter(Mandatory)] [DbaInstanceParameter[]]$Destination, [PSCredential]$DestinationSqlCredential, - [object[]]$CMSGroup, + [Alias('CMSGroup')] + [string[]]$Group, [switch]$SwitchServerName, [switch]$Force, - [Alias('Silent')] [switch]$EnableException ) begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaCentralManagementServer function Invoke-ParseServerGroup { [cmdletbinding()] param ( @@ -5835,9 +5871,9 @@ function Copy-DbaCentralManagementServer { $toCmStore = Get-DbaCmsRegServerStore -SqlInstance $destServer $stores = $fromCmStore.DatabaseEngineServerGroup - if ($CMSGroup) { + if ($Group) { $stores = @(); - foreach ($groupName in $CMSGroup) { + foreach ($groupName in $Group) { $stores += $fromCmStore.DatabaseEngineServerGroup.ServerGroups[$groupName] } } @@ -8588,6 +8624,177 @@ function Copy-DbaDbMail { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-DbaDatabaseMail } } +function Copy-DbaDbQueryStoreOption { + <# + .SYNOPSIS + Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases. + + .DESCRIPTION + Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases. + + .PARAMETER Source + Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2016 or higher. + + .PARAMETER SourceSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER SourceDatabase + Specifies the database to copy the Query Store configuration from. + + .PARAMETER Destination + Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2016 or higher. + + .PARAMETER DestinationSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER DestinationDatabase + Specifies a list of databases that will receive a copy of the Query Store configuration of the SourceDatabase. + + .PARAMETER Exclude + Specifies a list of databases which will NOT receive a copy of the Query Store configuration. + + .PARAMETER AllDatabases + If this switch is enabled, the Query Store configuration will be copied to all databases on the destination instance. + + .PARAMETER WhatIf + If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. + + .PARAMETER Confirm + If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. + + .PARAMETER EnableException + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. + + .NOTES + Tags: QueryStore + Author: Enrico van de Laar (@evdlaar) + + Website: https://dbatools.io + Copyright: (c) 2018 by dbatools, licensed under MIT + License: MIT https://opensource.org/licenses/MIT + + .LINK + https://dbatools.io/Copy-QueryStoreConfig + + .EXAMPLE + PS C:\> Copy-DbaDbQueryStoreOption -Source ServerA\SQL -SourceDatabase AdventureWorks -Destination ServerB\SQL -AllDatabases + + Copy the Query Store configuration of the AdventureWorks database in the ServerA\SQL instance and apply it on all user databases in the ServerB\SQL Instance. + + .EXAMPLE + PS C:\> Copy-DbaDbQueryStoreOption -Source ServerA\SQL -SourceDatabase AdventureWorks -Destination ServerB\SQL -DestinationDatabase WorldWideTraders + + Copy the Query Store configuration of the AdventureWorks database in the ServerA\SQL instance and apply it to the WorldWideTraders database in the ServerB\SQL Instance. + + #> + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [parameter(Mandatory, ValueFromPipeline)] + [DbaInstanceParameter]$Source, + [PSCredential]$SourceSqlCredential, + [parameter(Mandatory, ValueFromPipeline)] + [object]$SourceDatabase, + [parameter(Mandatory, ValueFromPipeline)] + [DbaInstanceParameter[]]$Destination, + [PSCredential]$DestinationSqlCredential, + [object[]]$DestinationDatabase, + [object[]]$Exclude, + [switch]$AllDatabases, + [Alias('Silent')] + [switch]$EnableException + ) + + begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaQueryStoreConfig + try { + $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential + } catch { + Stop-Function -Message "Can't connect to $Source." -ErrorRecord $_ -Target $Source + return + } + } + + process { + if (Test-FunctionInterrupt) { return } + foreach ($destinstance in $Destination) { + # Grab the Query Store configuration from the SourceDatabase through the Get-DbaQueryStoreConfig function + $SourceQSConfig = Get-DbaDbQueryStoreOption -SqlInstance $sourceServer -Database $SourceDatabase + + if (!$DestinationDatabase -and !$Exclude -and !$AllDatabases) { + Stop-Function -Message "You must specify databases to execute against using either -DestinationDatabase, -Exclude or -AllDatabases." -Continue + } + + foreach ($destinationServer in $destinstance) { + + try { + $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue + } + + # We have to exclude all the system databases since they cannot have the Query Store feature enabled + $dbs = Get-DbaDatabase -SqlInstance $destServer -ExcludeSystem + + if ($DestinationDatabase.count -gt 0) { + $dbs = $dbs | Where-Object { $DestinationDatabase -contains $_.Name } + } + + if ($Exclude.count -gt 0) { + $dbs = $dbs | Where-Object { $exclude -notcontains $_.Name } + } + + if ($dbs.count -eq 0) { + Stop-Function -Message "No matching databases found. Check the spelling and try again." -Continue + } + + foreach ($db in $dbs) { + # skipping the database if the source and destination are the same instance + if (($sourceServer.Name -eq $destinationServer) -and ($SourceDatabase -eq $db.Name)) { + continue + } + Write-Message -Message "Processing destination database: $db on $destinationServer." -Level Verbose + $copyQueryStoreStatus = [pscustomobject]@{ + SourceServer = $sourceServer.name + SourceDatabase = $SourceDatabase + DestinationServer = $destinationServer + Name = $db.name + Type = "QueryStore Configuration" + Status = $null + DateTime = [Sqlcollaborative.Dbatools.Utility.DbaDateTime](Get-Date) + } + + if ($db.IsAccessible -eq $false) { + $copyQueryStoreStatus.Status = "Skipped" + Stop-Function -Message "The database $db on server $destinationServer is not accessible. Skipping database." -Continue + } + + Write-Message -Message "Executing Set-DbaQueryStoreConfig." -Level Verbose + # Set the Query Store configuration through the Set-DbaQueryStoreConfig function + if ($PSCmdlet.ShouldProcess("$db", "Copying QueryStoreConfig")) { + try { + $null = Set-DbaDbQueryStoreOption -SqlInstance $destinationServer -SqlCredential $DestinationSqlCredential ` + -Database $db.name ` + -State $SourceQSConfig.ActualState ` + -FlushInterval $SourceQSConfig.FlushInterval ` + -CollectionInterval $SourceQSConfig.CollectionInterval ` + -MaxSize $SourceQSConfig.MaxSize ` + -CaptureMode $SourceQSConfig.CaptureMode ` + -CleanupMode $SourceQSConfig.CleanupMode ` + -StaleQueryThreshold $SourceQSConfig.StaleQueryThreshold + $copyQueryStoreStatus.Status = "Successful" + } catch { + $copyQueryStoreStatus.Status = "Failed" + Stop-Function -Message "Issue setting Query Store on $db." -Target $db -ErrorRecord $_ -Continue + } + $copyQueryStoreStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + } + } + } + } + } +} #ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle# function Copy-DbaDbTableData { <# @@ -9168,200 +9375,6 @@ function Copy-DbaEndpoint { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlEndpoint } } -function Copy-DbaExtendedEvent { - <# - .SYNOPSIS - Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health. - - .DESCRIPTION - Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health. - - By default, all non-system Extended Events are migrated. - - .PARAMETER Source - Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. - - .PARAMETER SourceSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER Destination - Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. - - .PARAMETER DestinationSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER XeSession - The Extended Event Session(s) to process. This list is auto-populated from the server. If unspecified, all Extended Event Sessions will be processed. - - .PARAMETER ExcludeXeSession - The Extended Event Session(s) to exclude. This list is auto-populated from the server. - - .PARAMETER WhatIf - If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. - - .PARAMETER Confirm - If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. - - .PARAMETER EnableException - By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. - This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. - Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. - - .PARAMETER Force - If this switch is enabled, existing Extended Events sessions on Destination with matching names from Source will be dropped. - - .NOTES - Tags: Migration, ExtendedEvent, XEvent - Author: Chrissy LeMaire (@cl), netnerds.net - - Website: https://dbatools.io - Copyright: (c) 2018 by dbatools, licensed under MIT - License: MIT https://opensource.org/licenses/MIT - - Requires: sysadmin access on SQL Servers - - .LINK - https://dbatools.io/Copy-DbaExtendedEvent - - .EXAMPLE - PS C:\> Copy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster - - Copies all Extended Event sessions from sqlserver2014a to sqlcluster using Windows credentials. - - .EXAMPLE - PS C:\> Copy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred - - Copies all Extended Event sessions from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. - - .EXAMPLE - PS C:\> Copy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -WhatIf - - Shows what would happen if the command were executed. - - .EXAMPLE - PS C:\> Copy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -XeSession CheckQueries, MonitorUserDefinedException - - Copies only the Extended Events named CheckQueries and MonitorUserDefinedException from sqlserver2014a to sqlcluster. - - #> - [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] - param ( - [parameter(Mandatory)] - [DbaInstanceParameter]$Source, - [parameter(Mandatory)] - [DbaInstanceParameter[]]$Destination, - [PSCredential] - $SourceSqlCredential, - [PSCredential] - $DestinationSqlCredential, - [object[]]$XeSession, - [object[]]$ExcludeXeSession, - [switch]$Force, - [Alias('Silent')] - [switch]$EnableException - ) - begin { - try { - $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 11 - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source - return - } - $sourceSqlConn = $sourceServer.ConnectionContext.SqlConnectionObject - $sourceSqlStoreConnection = New-Object Microsoft.SqlServer.Management.Sdk.Sfc.SqlStoreConnection $sourceSqlConn - $sourceStore = New-Object Microsoft.SqlServer.Management.XEvent.XEStore $sourceSqlStoreConnection - $storeSessions = $sourceStore.Sessions | Where-Object { $_.Name -notin 'AlwaysOn_health', 'system_health' } - if ($XeSession) { - $storeSessions = $storeSessions | Where-Object Name -In $XeSession - } - if ($ExcludeXeSession) { - $storeSessions = $storeSessions | Where-Object Name -NotIn $ExcludeXeSession - } - } - process { - if (Test-FunctionInterrupt) { return } - foreach ($destinstance in $Destination) { - try { - $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential -MinimumVersion 11 - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue - } - - $destSqlConn = $destServer.ConnectionContext.SqlConnectionObject - $destSqlStoreConnection = New-Object Microsoft.SqlServer.Management.Sdk.Sfc.SqlStoreConnection $destSqlConn - $destStore = New-Object Microsoft.SqlServer.Management.XEvent.XEStore $destSqlStoreConnection - - Write-Message -Level Verbose -Message "Migrating sessions." - foreach ($session in $storeSessions) { - $sessionName = $session.Name - - $copyXeSessionStatus = [pscustomobject]@{ - SourceServer = $sourceServer.Name - DestinationServer = $destServer.Name - Name = $sessionName - Type = "Extended Event" - Status = $null - Notes = $null - DateTime = [DbaDateTime](Get-Date) - } - - if ($null -ne $destStore.Sessions[$sessionName]) { - if ($force -eq $false) { - if ($Pscmdlet.ShouldProcess($destinstance, "Extended Event Session '$sessionName' was skipped because it already exists on $destinstance.")) { - $copyXeSessionStatus.Status = "Skipped" - $copyXeSessionStatus.Notes = "Already exists" - $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - - Write-Message -Level Verbose -Message "Extended Event Session '$sessionName' was skipped because it already exists on $destinstance." - Write-Message -Level Verbose -Message "Use -Force to drop and recreate." - } - continue - } else { - if ($Pscmdlet.ShouldProcess($destinstance, "Attempting to drop $sessionName")) { - Write-Message -Level Verbose -Message "Extended Event Session '$sessionName' exists on $destinstance." - Write-Message -Level Verbose -Message "Force specified. Dropping $sessionName." - - try { - $destStore.Sessions[$sessionName].Drop() - } catch { - $copyXeSessionStatus.Status = "Failed" - $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - - Stop-Function -Message "Unable to drop session. Moving on." -Target $sessionName -ErrorRecord $_ -Continue - } - } - } - } - - if ($Pscmdlet.ShouldProcess($destinstance, "Migrating session $sessionName")) { - try { - $sql = $session.ScriptCreate().GetScript() | Out-String - - Write-Message -Level Debug -Message $sql - Write-Message -Level Verbose -Message "Migrating session $sessionName." - $null = $destServer.Query($sql) - - if ($session.IsRunning -eq $true) { - $destStore.Sessions.Refresh() - $destStore.Sessions[$sessionName].Start() - } - - $copyXeSessionStatus.Status = "Successful" - $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - } catch { - $copyXeSessionStatus.Status = "Failed" - $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - - Stop-Function -Message "Unable to create session." -Target $sessionName -ErrorRecord $_ - } - } - } - } - } - end { - Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlExtendedEvent - } -} function Copy-DbaLinkedServer { <# .SYNOPSIS @@ -10473,176 +10486,6 @@ function Copy-DbaPolicyManagement { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-DbaSqlPolicyManagement } } -function Copy-DbaQueryStoreConfig { - <# - .SYNOPSIS - Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases. - - .DESCRIPTION - Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases. - - .PARAMETER Source - Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2016 or higher. - - .PARAMETER SourceSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER SourceDatabase - Specifies the database to copy the Query Store configuration from. - - .PARAMETER Destination - Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2016 or higher. - - .PARAMETER DestinationSqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) - - .PARAMETER DestinationDatabase - Specifies a list of databases that will receive a copy of the Query Store configuration of the SourceDatabase. - - .PARAMETER Exclude - Specifies a list of databases which will NOT receive a copy of the Query Store configuration. - - .PARAMETER AllDatabases - If this switch is enabled, the Query Store configuration will be copied to all databases on the destination instance. - - .PARAMETER WhatIf - If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. - - .PARAMETER Confirm - If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. - - .PARAMETER EnableException - By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. - This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. - Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. - - .NOTES - Tags: QueryStore - Author: Enrico van de Laar (@evdlaar) - - Website: https://dbatools.io - Copyright: (c) 2018 by dbatools, licensed under MIT - License: MIT https://opensource.org/licenses/MIT - - .LINK - https://dbatools.io/Copy-QueryStoreConfig - - .EXAMPLE - PS C:\> Copy-DbaQueryStoreConfig -Source ServerA\SQL -SourceDatabase AdventureWorks -Destination ServerB\SQL -AllDatabases - - Copy the Query Store configuration of the AdventureWorks database in the ServerA\SQL instance and apply it on all user databases in the ServerB\SQL Instance. - - .EXAMPLE - PS C:\> Copy-DbaQueryStoreConfig -Source ServerA\SQL -SourceDatabase AdventureWorks -Destination ServerB\SQL -DestinationDatabase WorldWideTraders - - Copy the Query Store configuration of the AdventureWorks database in the ServerA\SQL instance and apply it to the WorldWideTraders database in the ServerB\SQL Instance. - - #> - [CmdletBinding(SupportsShouldProcess = $true)] - param ( - [parameter(Mandatory, ValueFromPipeline)] - [DbaInstanceParameter]$Source, - [PSCredential]$SourceSqlCredential, - [parameter(Mandatory, ValueFromPipeline)] - [object]$SourceDatabase, - [parameter(Mandatory, ValueFromPipeline)] - [DbaInstanceParameter[]]$Destination, - [PSCredential]$DestinationSqlCredential, - [object[]]$DestinationDatabase, - [object[]]$Exclude, - [switch]$AllDatabases, - [Alias('Silent')] - [switch]$EnableException - ) - - begin { - try { - $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential - } catch { - Stop-Function -Message "Can't connect to $Source." -ErrorRecord $_ -Target $Source - return - } - } - - process { - if (Test-FunctionInterrupt) { return } - foreach ($destinstance in $Destination) { - # Grab the Query Store configuration from the SourceDatabase through the Get-DbaQueryStoreConfig function - $SourceQSConfig = Get-DbaDbQueryStoreOption -SqlInstance $sourceServer -Database $SourceDatabase - - if (!$DestinationDatabase -and !$Exclude -and !$AllDatabases) { - Stop-Function -Message "You must specify databases to execute against using either -DestinationDatabase, -Exclude or -AllDatabases." -Continue - } - - foreach ($destinationServer in $destinstance) { - - try { - $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential - } catch { - Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue - } - - # We have to exclude all the system databases since they cannot have the Query Store feature enabled - $dbs = Get-DbaDatabase -SqlInstance $destServer -ExcludeAllSystemDb - - if ($DestinationDatabase.count -gt 0) { - $dbs = $dbs | Where-Object { $DestinationDatabase -contains $_.Name } - } - - if ($Exclude.count -gt 0) { - $dbs = $dbs | Where-Object { $exclude -notcontains $_.Name } - } - - if ($dbs.count -eq 0) { - Stop-Function -Message "No matching databases found. Check the spelling and try again." -Continue - } - - foreach ($db in $dbs) { - # skipping the database if the source and destination are the same instance - if (($sourceServer.Name -eq $destinationServer) -and ($SourceDatabase -eq $db.Name)) { - continue - } - Write-Message -Message "Processing destination database: $db on $destinationServer." -Level Verbose - $copyQueryStoreStatus = [pscustomobject]@{ - SourceServer = $sourceServer.name - SourceDatabase = $SourceDatabase - DestinationServer = $destinationServer - Name = $db.name - Type = "QueryStore Configuration" - Status = $null - DateTime = [Sqlcollaborative.Dbatools.Utility.DbaDateTime](Get-Date) - } - - if ($db.IsAccessible -eq $false) { - $copyQueryStoreStatus.Status = "Skipped" - Stop-Function -Message "The database $db on server $destinationServer is not accessible. Skipping database." -Continue - } - - Write-Message -Message "Executing Set-DbaQueryStoreConfig." -Level Verbose - # Set the Query Store configuration through the Set-DbaQueryStoreConfig function - if ($PSCmdlet.ShouldProcess("$db", "Copying QueryStoreConfig")) { - try { - $null = Set-DbaDbQueryStoreOption -SqlInstance $destinationServer -SqlCredential $DestinationSqlCredential ` - -Database $db.name ` - -State $SourceQSConfig.ActualState ` - -FlushInterval $SourceQSConfig.FlushInterval ` - -CollectionInterval $SourceQSConfig.CollectionInterval ` - -MaxSize $SourceQSConfig.MaxSize ` - -CaptureMode $SourceQSConfig.CaptureMode ` - -CleanupMode $SourceQSConfig.CleanupMode ` - -StaleQueryThreshold $SourceQSConfig.StaleQueryThreshold - $copyQueryStoreStatus.Status = "Successful" - } catch { - $copyQueryStoreStatus.Status = "Failed" - Stop-Function -Message "Issue setting Query Store on $db." -Target $db -ErrorRecord $_ -Continue - } - $copyQueryStoreStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject - } - } - } - } - } -} function Copy-DbaResourceGovernor { <# .SYNOPSIS @@ -11997,7 +11840,7 @@ function Copy-DbaSsisCatalog { function New-SSISDBCatalog { [CmdletBinding(SupportsShouldProcess)] param ( - [System.Security.SecureString]$Password + [System.Security.SecureString]$SecurePassword ) if ($Pscmdlet.ShouldProcess("Creating New SSISDB Catalog")) { if (!$Password) { @@ -12121,7 +11964,7 @@ function Copy-DbaSsisCatalog { } } } else { - New-SSISDBCatalog -Password $CreateCatalogPassword + New-SSISDBCatalog -SecurePassword $CreateCatalogPassword } $destinationSSIS.Refresh() @@ -12696,6 +12539,201 @@ function Copy-DbaSysDbUserObject { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlSysDbUserObjects } } +function Copy-DbaXESession { + <# + .SYNOPSIS + Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health. + + .DESCRIPTION + Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health. + + By default, all non-system Extended Events are migrated. + + .PARAMETER Source + Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher. + + .PARAMETER SourceSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER Destination + Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher. + + .PARAMETER DestinationSqlCredential + Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + + .PARAMETER XeSession + The Extended Event Session(s) to process. This list is auto-populated from the server. If unspecified, all Extended Event Sessions will be processed. + + .PARAMETER ExcludeXeSession + The Extended Event Session(s) to exclude. This list is auto-populated from the server. + + .PARAMETER WhatIf + If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. + + .PARAMETER Confirm + If this switch is enabled, you will be prompted for confirmation before executing any operations that change state. + + .PARAMETER EnableException + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. + + .PARAMETER Force + If this switch is enabled, existing Extended Events sessions on Destination with matching names from Source will be dropped. + + .NOTES + Tags: Migration, ExtendedEvent, XEvent + Author: Chrissy LeMaire (@cl), netnerds.net + + Website: https://dbatools.io + Copyright: (c) 2018 by dbatools, licensed under MIT + License: MIT https://opensource.org/licenses/MIT + + Requires: sysadmin access on SQL Servers + + .LINK + https://dbatools.io/Copy-DbaXESession + + .EXAMPLE + PS C:\> Copy-DbaXESession -Source sqlserver2014a -Destination sqlcluster + + Copies all Extended Event sessions from sqlserver2014a to sqlcluster using Windows credentials. + + .EXAMPLE + PS C:\> Copy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred + + Copies all Extended Event sessions from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. + + .EXAMPLE + PS C:\> Copy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -WhatIf + + Shows what would happen if the command were executed. + + .EXAMPLE + PS C:\> Copy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -XeSession CheckQueries, MonitorUserDefinedException + + Copies only the Extended Events named CheckQueries and MonitorUserDefinedException from sqlserver2014a to sqlcluster. + + #> + [CmdletBinding(DefaultParameterSetName = "Default", SupportsShouldProcess = $true)] + param ( + [parameter(Mandatory)] + [DbaInstanceParameter]$Source, + [parameter(Mandatory)] + [DbaInstanceParameter[]]$Destination, + [PSCredential] + $SourceSqlCredential, + [PSCredential] + $DestinationSqlCredential, + [object[]]$XeSession, + [object[]]$ExcludeXeSession, + [switch]$Force, + [Alias('Silent')] + [switch]$EnableException + ) + begin { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Copy-DbaExtendedEvent + try { + $sourceServer = Connect-SqlInstance -SqlInstance $Source -SqlCredential $SourceSqlCredential -MinimumVersion 11 + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $Source + return + } + $sourceSqlConn = $sourceServer.ConnectionContext.SqlConnectionObject + $sourceSqlStoreConnection = New-Object Microsoft.SqlServer.Management.Sdk.Sfc.SqlStoreConnection $sourceSqlConn + $sourceStore = New-Object Microsoft.SqlServer.Management.XEvent.XEStore $sourceSqlStoreConnection + $storeSessions = $sourceStore.Sessions | Where-Object { $_.Name -notin 'AlwaysOn_health', 'system_health' } + if ($XeSession) { + $storeSessions = $storeSessions | Where-Object Name -In $XeSession + } + if ($ExcludeXeSession) { + $storeSessions = $storeSessions | Where-Object Name -NotIn $ExcludeXeSession + } + } + process { + if (Test-FunctionInterrupt) { return } + foreach ($destinstance in $Destination) { + try { + $destServer = Connect-SqlInstance -SqlInstance $destinstance -SqlCredential $DestinationSqlCredential -MinimumVersion 11 + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $destinstance -Continue + } + + $destSqlConn = $destServer.ConnectionContext.SqlConnectionObject + $destSqlStoreConnection = New-Object Microsoft.SqlServer.Management.Sdk.Sfc.SqlStoreConnection $destSqlConn + $destStore = New-Object Microsoft.SqlServer.Management.XEvent.XEStore $destSqlStoreConnection + + Write-Message -Level Verbose -Message "Migrating sessions." + foreach ($session in $storeSessions) { + $sessionName = $session.Name + + $copyXeSessionStatus = [pscustomobject]@{ + SourceServer = $sourceServer.Name + DestinationServer = $destServer.Name + Name = $sessionName + Type = "Extended Event" + Status = $null + Notes = $null + DateTime = [DbaDateTime](Get-Date) + } + + if ($null -ne $destStore.Sessions[$sessionName]) { + if ($force -eq $false) { + if ($Pscmdlet.ShouldProcess($destinstance, "Extended Event Session '$sessionName' was skipped because it already exists on $destinstance.")) { + $copyXeSessionStatus.Status = "Skipped" + $copyXeSessionStatus.Notes = "Already exists" + $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + + Write-Message -Level Verbose -Message "Extended Event Session '$sessionName' was skipped because it already exists on $destinstance." + Write-Message -Level Verbose -Message "Use -Force to drop and recreate." + } + continue + } else { + if ($Pscmdlet.ShouldProcess($destinstance, "Attempting to drop $sessionName")) { + Write-Message -Level Verbose -Message "Extended Event Session '$sessionName' exists on $destinstance." + Write-Message -Level Verbose -Message "Force specified. Dropping $sessionName." + + try { + $destStore.Sessions[$sessionName].Drop() + } catch { + $copyXeSessionStatus.Status = "Failed" + $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + + Stop-Function -Message "Unable to drop session. Moving on." -Target $sessionName -ErrorRecord $_ -Continue + } + } + } + } + + if ($Pscmdlet.ShouldProcess($destinstance, "Migrating session $sessionName")) { + try { + $sql = $session.ScriptCreate().GetScript() | Out-String + + Write-Message -Level Debug -Message $sql + Write-Message -Level Verbose -Message "Migrating session $sessionName." + $null = $destServer.Query($sql) + + if ($session.IsRunning -eq $true) { + $destStore.Sessions.Refresh() + $destStore.Sessions[$sessionName].Start() + } + + $copyXeSessionStatus.Status = "Successful" + $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + } catch { + $copyXeSessionStatus.Status = "Failed" + $copyXeSessionStatus | Select-DefaultView -Property DateTime, SourceServer, DestinationServer, Name, Type, Status, Notes -TypeName MigrationObject + + Stop-Function -Message "Unable to create session." -Target $sessionName -ErrorRecord $_ + } + } + } + } + } + end { + Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Copy-SqlExtendedEvent + } +} #ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle# function Copy-DbaXESessionTemplate { <# @@ -15153,7 +15191,7 @@ function Export-DbaDacPackage { } $cleaninstance = $instance.ToString().Replace('\', '-') - $dbs = Get-DbaDatabase -SqlInstance $server -OnlyAccessible -ExcludeAllSystemDb -Database $Database -ExcludeDatabase $ExcludeDatabase + $dbs = Get-DbaDatabase -SqlInstance $server -OnlyAccessible -ExcludeSystem -Database $Database -ExcludeDatabase $ExcludeDatabase if (-not $dbs) { Stop-Function -Message "Databases not found on $instance" -Target $instance -Continue } @@ -18802,7 +18840,7 @@ function Find-DbaDatabase { InstanceName = $server.ServiceName SqlInstance = $server.Name Name = $db.Name - SizeMB = $db.Size + Size = [dbasize]($db.Size * 1024 * 1024) Owner = $db.Owner CreateDate = $db.CreateDate ServiceBrokerGuid = $db.ServiceBrokerGuid @@ -18810,8 +18848,7 @@ function Find-DbaDatabase { StoredProcedures = ($db.StoredProcedures | Where-Object { $_.IsSystemObject -eq $false }).Count Views = ($db.Views | Where-Object { $_.IsSystemObject -eq $false }).Count ExtendedProperties = $extendedproperties - Database = $db - } | Select-DefaultView -ExcludeProperty Database, ExtendedProperties, ServiceBrokerGuid, StoredProcedures, Tables, Views + } } } } @@ -18956,7 +18993,7 @@ function Find-DbaDbGrowthEvent { $eventClassFilter = $eventClass -join "," - $sql = " + $sqlTemplate = " BEGIN TRY IF (SELECT CONVERT(INT,[value_in_use]) FROM sys.configurations WHERE [name] = 'default trace enabled' ) = 1 BEGIN @@ -19061,11 +19098,11 @@ function Find-DbaDbGrowthEvent { $dbs = $dbs | Where-Object Name -NotIn $ExcludeDatabase } - #Create dblist name in 'bd1', 'db2' format + #Create dblist name in 'db1', 'db2' format $dbsList = "'$($($dbs | ForEach-Object {$_.Name}) -join "','")'" Write-Message -Level Verbose -Message "Executing query against $dbsList on $instance" - $sql = $sql -replace '_DatabaseList_', $dbsList + $sql = $sqlTemplate -replace '_DatabaseList_', $dbsList Write-Message -Level Debug -Message "Executing SQL Statement:`n $sql" $defaults = 'ComputerName', 'InstanceName', 'SqlInstance', 'EventClass', 'DatabaseName', 'Filename', 'Duration', 'StartTime', 'EndTime', 'ChangeInSize', 'ApplicationName', 'HostName' @@ -25915,8 +25952,8 @@ function Get-DbaBackupInformation { $historyObject.Duration = ([DateTime]$group.Group[0].BackupFinishDate - [DateTime]$group.Group[0].BackupStartDate) $historyObject.Path = [string[]]$Group.Group.BackupPath $historyObject.FileList = ($group.Group.FileList | Select-Object Type, LogicalName, PhysicalName) - $historyObject.TotalSize = ($Group.Group.BackupSize | Measure-Object -Sum).Sum - $HistoryObject.CompressedBackupSize = ($Group.Group.CompressedBackupSize | Measure-Object -Sum).Sum + $historyObject.TotalSize = ($Group.Group.BackupSize.Byte | Measure-Object -Sum).Sum + $HistoryObject.CompressedBackupSize = ($Group.Group.CompressedBackupSize.Byte | Measure-Object -Sum).Sum $historyObject.Type = $description $historyObject.BackupSetId = $group.group[0].BackupSetGUID $historyObject.DeviceType = 'Disk' @@ -28235,15 +28272,15 @@ function Get-DbaDatabase { .PARAMETER ExcludeDatabase Specifies one or more database(s) to exclude from processing. - .PARAMETER ExcludeAllUserDb + .PARAMETER ExcludeUser If this switch is enabled, only databases which are not User databases will be processed. - This parameter cannot be used with -ExcludeAllSystemDb. + This parameter cannot be used with -ExcludeSystem. - .PARAMETER ExcludeAllSystemDb + .PARAMETER ExcludeSystem If this switch is enabled, only databases which are not System databases will be processed. - This parameter cannot be used with -ExcludeAllUserDb. + This parameter cannot be used with -ExcludeUser. .PARAMETER Status Specifies one or more database statuses to filter on. Only databases in the status(es) listed will be returned. Valid options for this parameter are 'Emergency', 'Normal', 'Offline', 'Recovering', 'Restoring', 'Standby', and 'Suspect'. @@ -28306,12 +28343,12 @@ function Get-DbaDatabase { Returns all databases on the local default SQL Server instance. .EXAMPLE - PS C:\> Get-DbaDatabase -SqlInstance localhost -ExcludeAllUserDb + PS C:\> Get-DbaDatabase -SqlInstance localhost -ExcludeUser Returns only the system databases on the local default SQL Server instance. .EXAMPLE - PS C:\> Get-DbaDatabase -SqlInstance localhost -ExcludeAllSystemDb + PS C:\> Get-DbaDatabase -SqlInstance localhost -ExcludeSystem Returns only the user databases on the local default SQL Server instance. @@ -28367,10 +28404,10 @@ function Get-DbaDatabase { [Alias("Databases")] [object[]]$Database, [object[]]$ExcludeDatabase, - [Alias("SystemDbOnly", "NoUserDb")] - [switch]$ExcludeAllUserDb, - [Alias("UserDbOnly", "NoSystemDb")] - [switch]$ExcludeAllSystemDb, + [Alias("SystemDbOnly", "NoUserDb", "ExcludeAllUserDb")] + [switch]$ExcludeUser, + [Alias("UserDbOnly", "NoSystemDb", "ExcludeAllSystemDb")] + [switch]$ExcludeSystem, [string[]]$Owner, [switch]$Encrypted, [ValidateSet('EmergencyMode', 'Normal', 'Offline', 'Recovering', 'Restoring', 'Standby', 'Suspect')] @@ -28391,8 +28428,8 @@ function Get-DbaDatabase { begin { - if ($ExcludeAllUserDb -and $ExcludeAllSystemDb) { - Stop-Function -Message "You cannot specify both ExcludeAllUserDb and ExcludeAllSystemDb." -Continue -EnableException $EnableException + if ($ExcludeUser -and $ExcludeSystem) { + Stop-Function -Message "You cannot specify both ExcludeUser and ExcludeSystem." -Continue -EnableException $EnableException } } @@ -28448,9 +28485,9 @@ function Get-DbaDatabase { $dblastused = Invoke-QueryDBlastUsed } - if ($ExcludeAllUserDb) { + if ($ExcludeUser) { $DBType = @($true) - } elseif ($ExcludeAllSystemDb) { + } elseif ($ExcludeSystem) { $DBType = @($false) } else { $DBType = @($false, $true) @@ -29385,7 +29422,7 @@ function Get-DbaDbExtentDiff { foreach ($instance in $SqlInstance) { try { - $server = Connect-DbaInstance -SqlInstance $instance -SqlCredential $SqlCredential -NonPooled + $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $SqlCredential -NonPooled } catch { Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } @@ -32559,9 +32596,14 @@ function Get-DbaDbSpace { Returns all user database files and free space information for the localhost and localhost\namedinstance SQL Server instances. Processes data via the pipeline. .EXAMPLE - PS C:\> Get-DbaDbSpace -SqlInstance localhost -Database db1, db2 + PS C:\> Get-DbaDbSpace -SqlInstance localhost -Database db1, db2 | Where-Object { $_.SpaceUntilMaxSize.Megabyte -lt 1 } + + Returns database files and free space information for the db1 and db2 on localhost where there is only 1MB left until the space is maxed out + + .EXAMPLE + PS C:\> Get-DbaDbSpace -SqlInstance localhost -Database db1, db2 | Where-Object { $_.SpaceUntilMaxSize.Gigabyte -lt 1 } - Returns database files and free space information for the db1 and db2 on localhost. + Returns database files and free space information for the db1 and db2 on localhost where there is only 1GB left until the space is maxed out #> [CmdletBinding()] @@ -32570,10 +32612,9 @@ function Get-DbaDbSpace { [DbaInstanceParameter[]]$SqlInstance, [System.Management.Automation.PSCredential]$SqlCredential, [Alias("Databases")] - [object[]]$Database, - [object[]]$ExcludeDatabase, + [string[]]$Database, + [string[]]$ExcludeDatabase, [switch]$IncludeSystemDBs, - [Alias('Silent')] [switch]$EnableException ) @@ -32699,23 +32740,23 @@ function Get-DbaDbSpace { } [pscustomobject]@{ - ComputerName = $server.ComputerName - InstanceName = $server.ServiceName - SqlInstance = $server.DomainInstanceName - Database = $row.DBName - FileName = $row.FileName - FileGroup = $row.FileGroup - PhysicalName = $row.PhysicalName - FileType = $row.FileType - UsedSpaceMB = $UsedMB - FreeSpaceMB = $FreeMB - FileSizeMB = $row.FileSizeMB - PercentUsed = $PercentUsed - AutoGrowth = $row.GrowthMB - AutoGrowType = $row.GrowthType - SpaceUntilMaxSizeMB = $SpaceUntilMax - AutoGrowthPossibleMB = $row.PossibleAutoGrowthMB - UnusableSpaceMB = $UnusableSpace + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + Database = $row.DBName + FileName = $row.FileName + FileGroup = $row.FileGroup + PhysicalName = $row.PhysicalName + FileType = $row.FileType + UsedSpace = [dbasize]($UsedMB * 1024 * 1024) + FreeSpace = [dbasize]($FreeMB * 1024 * 1024) + FileSize = [dbasize]($row.FileSizeMB * 1024 * 1024) + PercentUsed = $PercentUsed + AutoGrowth = [dbasize]($row.GrowthMB * 1024 * 1024) + AutoGrowType = $row.GrowthType + SpaceUntilMaxSize = [dbasize]($SpaceUntilMax * 1024 * 1024) + AutoGrowthPossible = [dbasize]($row.PossibleAutoGrowthMB * 1024 * 1024) + UnusableSpace = [dbasize]($UnusableSpace * 1024 * 1024) } } } catch { @@ -38974,9 +39015,6 @@ function Get-DbaMemoryUsage { .PARAMETER Credential Credential object used to connect to the SQL Server as a different user - .PARAMETER Simple - Shows a simplified set of counters. Excludes only totals for Plancounters and BufManpagecounters - .PARAMETER EnableException By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. @@ -38996,20 +39034,19 @@ function Get-DbaMemoryUsage { https://dbatools.io/Get-DbaMemoryUsage .EXAMPLE - PS C:\> Get-DbaMemoryUsage -ComputerName ServerA + PS C:\> Get-DbaMemoryUsage -ComputerName sql2017 - Returns a custom object displaying Server, counter instance, counter, number of pages, memory in KB, memory in MB + Returns a custom object displaying Server, counter instance, counter, number of pages, memory .EXAMPLE - PS C:\> Get-DbaMemoryUsage -ComputerName ServerA\sql987 -Simple + PS C:\> Get-DbaMemoryUsage -ComputerName sql2017\sqlexpress -SqlCredential sqladmin | Where-Object { $_.Memory.Megabyte -gt 100 } - Returns a custom object with Server, counter instance, counter, number of pages, memory in KB, memory in MB + Logs into the sql2017\sqlexpress as sqladmin using SQL Authentication then returns results only where memory exceeds 100 MB .EXAMPLE - PS C:\> Get-DbaMemoryUsage -ComputerName ServerA\sql987 | Out-Gridview - - Returns a gridview displaying Server, counter instance, counter, number of pages, memory in KB, memory in MB + PS C:\> $servers | Get-DbaMemoryUsage | Out-Gridview + Gets results from an array of $servers then diplays them in a gridview. #> [CmdletBinding()] param ( @@ -39017,8 +39054,6 @@ function Get-DbaMemoryUsage { [Alias("Host", "cn", "Server")] [DbaInstanceParameter[]]$ComputerName = $env:COMPUTERNAME, [PSCredential]$Credential, - [switch]$Simple, - [Alias('Silent')] [switch]$EnableException ) @@ -39058,8 +39093,7 @@ function Get-DbaMemoryUsage { CounterInstance = (($_.Path.split("\")[-2]).replace("mssql`$", "")).split(':')[1] Counter = $_.Path.split("\")[-1] Pages = $null - MemKB = $_.cookedvalue - MemMB = $_.cookedvalue / 1024 + Memory = $_.cookedvalue / 1024 } } } catch { @@ -39081,8 +39115,7 @@ function Get-DbaMemoryUsage { CounterInstance = (($_.Path.split("\")[-2]).replace("mssql`$", "")).split(':')[1] Counter = $_.Path.split("\")[-1] Pages = $_.cookedvalue - MemKB = $_.cookedvalue * 8192 / 1024 - MemMB = $_.cookedvalue * 8192 / 1048576 + Memory = $_.cookedvalue * 8192 / 1048576 } } } catch { @@ -39104,8 +39137,7 @@ function Get-DbaMemoryUsage { CounterInstance = (($_.Path.split("\")[-2]).replace("mssql`$", "")).split(':')[1] Counter = $_.Path.split("\")[-1] Pages = $_.cookedvalue - MemKB = $_.cookedvalue * 8192 / 1024.0 - MemMB = $_.cookedvalue * 8192 / 1048576.0 + Memory = $_.cookedvalue * 8192 / 1048576.0 } } } catch { @@ -39127,8 +39159,7 @@ function Get-DbaMemoryUsage { CounterInstance = (($_.Path.split("\")[-2]).replace("mssql`$", "")).split(':')[1] Counter = $_.Path.split("\")[-1] Pages = $null - MemKB = $_.cookedvalue - MemMB = $_.cookedvalue / 1024 + Memory = $_.cookedvalue / 1024 } } } catch { @@ -39150,8 +39181,7 @@ function Get-DbaMemoryUsage { CounterInstance = (($_.Path.split("\")[-2]).replace("mssql`$", "")).split(':')[1] Counter = $_.Path.split("\")[-1] Pages = $null - MemKB = $_.cookedvalue / 1024 - MemMB = $_.cookedvalue / 1024 / 1024 + Memory = $_.cookedvalue / 1024 / 1024 } } } catch { @@ -39167,7 +39197,16 @@ function Get-DbaMemoryUsage { if ($reply.FullComputerName) { $Computer = $reply.FullComputerName try { - Invoke-Command2 -ComputerName $Computer -Credential $Credential -ScriptBlock $scriptblock -argumentlist $Memcounters, $Plancounters, $BufManpagecounters, $SSAScounters, $SSIScounters + foreach ($result in (Invoke-Command2 -ComputerName $Computer -Credential $Credential -ScriptBlock $scriptblock -argumentlist $Memcounters, $Plancounters, $BufManpagecounters, $SSAScounters, $SSIScounters)) { + [PSCustomObject]@{ + ComputerName = $result.ComputerName + SqlInstance = $result.SqlInstance + CounterInstance = $result.CounterInstance + Counter = $result.Counter + Pages = $result.Pages + Memory = [dbasize]($result.Memory * 1024 * 1024) + } + } } catch { Stop-Function -Message "Failure" -ErrorRecord $_ -Target $computer -Continue } @@ -40097,7 +40136,7 @@ function Get-DbaOrphanUser { } } Write-Message -Level Verbose -Message "Validating users on database '$db'." - $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($_.Sid.Length -gt 16 -and $_.LoginType -eq [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin) -eq $false } + $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and (($_.Sid.Length -gt 16 -and $_.LoginType -in @([Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin, [Microsoft.SqlServer.Management.Smo.LoginType]::Certificate)) -eq $false) } if ($UsersToWork.Count -gt 0) { Write-Message -Level Verbose -Message "Orphan users found" @@ -41934,7 +41973,7 @@ function Get-DbaPlanCache { process { foreach ($instance in $SqlInstance) { try { - $server = Connect-DbaInstance -SqlInstance $instance -SqlCredential $sqlcredential + $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $sqlcredential } catch { Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } @@ -42414,27 +42453,27 @@ function Get-DbaProcess { } } } +#ValidationTags#CodeStyle,Messaging,FlowControl,Pipeline# function Get-DbaProductKey { <# .SYNOPSIS - Gets SQL Server Product Keys from local or destination SQL Servers. Works with SQL Server 2005-2016 + Gets SQL Server Product Keys from local or destination SQL Servers. Works with SQL Server 2005-2017 .DESCRIPTION - Using a string of servers, a text file, or Central Management Server to provide a list of servers, this script will go to each server and get the product key for all installed instances. Clustered instances are supported as well. Requires regular user access to the SQL instances, SMO installed locally, Remote Registry enabled and accessible by the account running the script. + This command find the product key for all installed instances. Clustered instances are supported as well. Uses key decoder by Jakob Bindslet (http://goo.gl/1jiwcB) - .PARAMETER SqlInstance + .PARAMETER ComputerName The target SQL Server instance or instances. - .PARAMETER SqlCredential - Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) + .PARAMETER Credential + Login to the target Windows instance using alternative credentials. Windows Authentication supported. Accepts credential objects (Get-Credential) - .PARAMETER SqlCms - Deprecated, pipe in from Get-DbaCmsRegServer + .PARAMETER SqlCredential + This command logs into the SQL instance to gather additional information. - .PARAMETER ServersFromFile - Deprecated, pipe in from Get-Content + Use this parameter to connect to the discovered SQL instances using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) .PARAMETER EnableException By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. @@ -42453,7 +42492,7 @@ function Get-DbaProductKey { https://dbatools.io/Get-DbaProductKey .EXAMPLE - PS C:\> Get-DbaProductKey -SqlInstance winxp, sqlservera, sqlserver2014a, win2k8 + PS C:\> Get-DbaProductKey -ComputerName winxp, sqlservera, sqlserver2014a, win2k8 Gets SQL Server versions, editions and product keys for all instances within each server or workstation. @@ -42461,88 +42500,139 @@ function Get-DbaProductKey { [CmdletBinding()] param ( [parameter(ValueFromPipeline, Mandatory)] - [Alias("ServerInstance", "SqlServer", "SqlInstances")] - [DbaInstanceParameter[]]$SqlInstance, + [Alias("SqlInstance")] + [DbaInstanceParameter[]]$ComputerName, [PSCredential]$SqlCredential, - [string]$SqlCms, - [string]$ServersFromFile, + [PSCredential]$Credential, [switch]$EnableException ) begin { - Function Unlock-SqlInstanceKey { - [CmdletBinding()] - param ( - [Parameter(Mandatory)] - [byte[]]$data, - [int]$version - ) - try { - if ($version -ge 11) { $binArray = ($data)[0 .. 66] } - else { $binArray = ($data)[52 .. 66] } - $charsArray = "B", "C", "D", "F", "G", "H", "J", "K", "M", "P", "Q", "R", "T", "V", "W", "X", "Y", "2", "3", "4", "6", "7", "8", "9" - for ($i = 24; $i -ge 0; $i--) { - $k = 0 - for ($j = 14; $j -ge 0; $j--) { - $k = $k * 256 -bxor $binArray[$j] - $binArray[$j] = [math]::truncate($k / 24) - $k = $k % 24 + $scriptblock = { + $versionMajor = $args[0] + $instanceReg = $args[1] + $edition = $args[2] + + Function Unlock-SqlInstanceKey { + [CmdletBinding()] + param ( + [Parameter(Mandatory)] + [byte[]]$data, + [int]$version + ) + try { + if ($version -ge 11) { + $binArray = ($data)[0 .. 66] + } else { + $binArray = ($data)[52 .. 66] } - $productKey = $charsArray[$k] + $productKey - if (($i % 5 -eq 0) -and ($i -ne 0)) { - $productKey = "-" + $productKey + $charsArray = "B", "C", "D", "F", "G", "H", "J", "K", "M", "P", "Q", "R", "T", "V", "W", "X", "Y", "2", "3", "4", "6", "7", "8", "9" + for ($i = 24; $i -ge 0; $i--) { + $k = 0 + for ($j = 14; $j -ge 0; $j--) { + $k = $k * 256 -bxor $binArray[$j] + $binArray[$j] = [math]::truncate($k / 24) + $k = $k % 24 + } + $productKey = $charsArray[$k] + $productKey + if (($i % 5 -eq 0) -and ($i -ne 0)) { + $productKey = "-" + $productKey + } } + } catch { + $productkey = "Cannot decode product key." } - } catch { - $productkey = "Cannot decode product key." + return $productKey } - return $productKey - } - } + $localmachine = [Microsoft.Win32.RegistryHive]::LocalMachine + $defaultview = [Microsoft.Win32.RegistryView]::Default + $reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey($localmachine, $defaultview) - process { - if ($SqlCms) { - Stop-Function -Message "Please pipe in servers using Get-DbaCmsRegServer instead" - return - } + switch ($versionMajor) { + 9 { + $sqlversion = "SQL Server 2005 $servicePack" + $findkeys = $reg.OpenSubKey("$($instanceReg.Path)\ProductID", $false) + foreach ($findkey in $findkeys.GetValueNames()) { + if ($findkey -like "DigitalProductID*") { + $key = @("$($instanceReg.Path)\ProductID\$findkey") + } + } + } + 10 { + $sqlversion = "SQL Server 2008 $servicePack" + if ($server.VersionMinor -eq 50) { + $sqlversion = "SQL Server 2008 R2 $servicePack" + } + $key = @("$($instanceReg.Path)\Setup\DigitalProductID") + } + 11 { + $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") + $sqlversion = "SQL Server 2012 $servicePack" + } + 12 { + $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") + $sqlversion = "SQL Server 2014 $servicePack" + } + 13 { + $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") + $sqlversion = "SQL Server 2016 $servicePack" + } + 14 { + $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") + $sqlversion = "SQL Server 2017 $servicePack" + } + default { + Stop-Function -Message "SQL version not currently supported." -Continue + } + } + if ($edition -notlike "*Express*") { + $sqlkey = '' + foreach ($k in $key) { + $subkey = Split-Path $k + $binaryvalue = Split-Path $k -Leaf + try { + $binarykey = $($reg.OpenSubKey($subkey)).GetValue($binaryvalue) + break + } catch { + $binarykey = $null + } + } - If ($ServersFromFile) { - Stop-Function -Message "Please pipe in servers using Get-Content instead" - return + if ($null -eq $binarykey) { + $sqlkey = "Could not read Product Key from registry on $env:COMPUTERNAME" + } else { + try { + $sqlkey = Unlock-SqlInstanceKey $binarykey $versionMajor + } catch { + $sqlkey = "Unable to unlock key" + } + } + } else { + $sqlkey = "SQL Server Express Edition" + } + + [pscustomobject]@{ + Version = $sqlversion + Key = $sqlkey + } + $reg.Close() } + } - foreach ($instance in $SqlInstance) { - $computerName = $instance.ComputerName + process { + foreach ($computer in $ComputerName) { try { - $regRoots = Get-DbaRegistryRoot -ComputerName $computerName -EnableException + $registryroot = Get-DbaRegistryRoot -ComputerName $computer.ComputerName -EnableException } catch { - Stop-Function -Message "Can't access registry for $computerName. Is the Remote Registry service started?" -Continue - } - if ($instance.IsLocalhost) { - $localmachine = [Microsoft.Win32.RegistryHive]::LocalMachine - $defaultview = [Microsoft.Win32.RegistryView]::Default - $reg = [Microsoft.Win32.RegistryKey]::OpenBaseKey($localmachine, $defaultview) - } else { - # Get IP for remote registry access. It's the most reliable. - try { $ipaddr = ([System.Net.Dns]::GetHostAddresses($computerName)).IPAddressToString } - catch { - Stop-Function -Message "Can't resolve $computerName. Skipping." -Continue - } - - try { - $reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey("LocalMachine", $ipaddr) - } catch { - Stop-Function -Message "Can't access registry for $computerName. Is the Remote Registry service started?" -Continue - } + Stop-Function -Message "Can't access registry for $($computer.ComputerName). Is the Remote Registry service started?" -Continue } - if (-not($regRoots)) { - Stop-Function -Message "No instances found on $computerName. Skipping." -Continue + if (-not $registryroot) { + Stop-Function -Message "No instances found on $($computer.ComputerName)" -Continue } # Get Product Keys for all instances on the server. - foreach ($instanceReg in $regRoots) { - + foreach ($instanceReg in $registryroot) { try { $server = Connect-SqlInstance -SqlInstance $instanceReg.SqlInstance -SqlCredential $SqlCredential -MinimumVersion 10 } catch { @@ -42550,87 +42640,29 @@ function Get-DbaProductKey { } $servicePack = $server.ProductLevel + $versionMajor = $server.VersionMajor Write-Message -Level Debug -Message "$instance $instanceName version is $($server.VersionMajor)" - switch ($server.VersionMajor) { - 9 { - $sqlversion = "SQL Server 2005 $servicePack" - $findkeys = $reg.OpenSubKey("$($instanceReg.Path)\ProductID", $false) - foreach ($findkey in $findkeys.GetValueNames()) { - if ($findkey -like "DigitalProductID*") { - $key = @("$($instanceReg.Path)\ProductID\$findkey") - } - } - } - 10 { - $sqlversion = "SQL Server 2008 $servicePack" - if ($server.VersionMinor -eq 50) { - $sqlversion = "SQL Server 2008 R2 $servicePack" - } - $key = @("$($instanceReg.Path)\Setup\DigitalProductID") - } - 11 { - $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") - $sqlversion = "SQL Server 2012 $servicePack" - } - 12 { - $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") - $sqlversion = "SQL Server 2014 $servicePack" - } - 13 { - $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") - $sqlversion = "SQL Server 2016 $servicePack" - } - 14 { - $key = @("$($instanceReg.Path)\Setup\DigitalProductID", "$($instanceReg.Path)\ClientSetup\DigitalProductID") - $sqlversion = "SQL Server 2017 $servicePack" - } - default { - Stop-Function -Message "SQL version not currently supported." -Continue - } - } - if ($server.Edition -notlike "*Express*") { - $sqlkey = '' - foreach ($k in $key) { - $subkey = Split-Path $k - $binaryvalue = Split-Path $k -Leaf - try { - $binarykey = $($reg.OpenSubKey($subkey)).GetValue($binaryvalue) - break - } catch { - $binarykey = $null - } - } - - if ($null -eq $binarykey) { - $sqlkey = "Could not read Product Key from registry on $computername" - } else { - try { - $sqlkey = Unlock-SqlInstanceKey $binarykey $server.VersionMajor - } catch { - $sqlkey = "Unable to unlock key" - } - } - } else { - $sqlkey = "SQL Server Express Edition" + try { + $results = Invoke-Command2 -ComputerName $computer.ComputerName -Credential $Credential -ScriptBlock $scriptblock -ArgumentList $server.VersionMajor, $instanceReg, $server.Edition + } catch { + Stop-Function -Message "Failure" -ErrorRecord $_ } [pscustomobject]@{ - "SQL Instance" = $server.DomainInstanceName - "SQL Version" = $sqlversion - "SQL Edition" = $server.Edition - "Product Key" = $sqlkey + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + Version = $results.Version + Edition = $server.Edition + Key = $results.Key } } - $reg.Close() } } end { Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Get-SqlServerKey Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Get-DbaSqlProductKey - - Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Parameter CMSStore - Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Parameter ServersFromFile } } #ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle# @@ -42663,7 +42695,7 @@ function Get-DbaQueryExecutionTime { .PARAMETER MinExecMs Allows you to limit the scope to queries with a specified average execution time. Default value is 500 (ms). - .PARAMETER ExcludeSystemDatabases + .PARAMETER ExcludeSystem Allows you to suppress output on system databases .PARAMETER EnableException @@ -42716,7 +42748,8 @@ function Get-DbaQueryExecutionTime { [parameter(Position = 3, Mandatory = $false)] [int]$MinExecMs = 500, [parameter(Position = 4, Mandatory = $false)] - [switch]$ExcludeSystemDatabases, + [Alias("ExcludeSystemDatabases")] + [switch]$ExcludeSystem, [Alias('Silent')] [switch]$EnableException ) @@ -42826,7 +42859,7 @@ function Get-DbaQueryExecutionTime { $dbs = $dbs | Where-Object Name -In $Database } - if ($ExcludeSystemDatabases) { + if ($ExcludeSystem) { $dbs = $dbs | Where-Object { $_.IsSystemObject -eq $false } } @@ -50768,29 +50801,25 @@ function Import-DbaCmsRegServer { Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Import-DbaRegisteredServer } } -function Import-DbaCsvToSql { +function Import-DbaCsv { <# .SYNOPSIS - Efficiently imports very large (and small) CSV files into SQL Server using only the .NET Framework and PowerShell. + Efficiently imports very large (and small) CSV files into SQL Server. .DESCRIPTION - Import-DbaCsvToSql takes advantage of .NET's super fast SqlBulkCopy class to import CSV files into SQL Server at up to 90,000 rows a second. - - The entire import is contained within a transaction, so if a failure occurs or the script is aborted, no changes will persist. - - If the table specified does not exist, it will be automatically created using best guessed data types. In addition, the destination table can be truncated prior to import. + Import-DbaCsv takes advantage of .NET's super fast SqlBulkCopy class to import CSV files into SQL Server. - The Query parameter will be used to import only the data returned from a SQL Query executed against the CSV file(s). This function supports a number of bulk copy options. Please see parameter list for details. + The entire import is performed within a transaction, so if a failure occurs or the script is aborted, no changes will persist. - .PARAMETER CSV - Specifies path to the CSV file(s) to be imported. Multiple files may be imported if they are formatted similarly. + If the table specified does not exist and -AutoCreateTable, it will be automatically created using slow and efficient but accomodating data types. - If no file is specified, a dialog box will appear to select your file(s). + .PARAMETER Path + Specifies path to the CSV file(s) to be imported. Multiple files may be imported at once. - .PARAMETER FirstRowColumns - If this switch is enabled, the first row in the file will be used as column names for the data being imported. + .PARAMETER NoHeaderRow + By default, the first row is used to determine column names for the data being imported. - If the first row does not contain column names and -Query is specified, use field names "column1, column2, column3" and so on. + Use this switch if the first row contains data and not column names. .PARAMETER Delimiter Specifies the delimiter used in the imported file(s). If no delimiter is specified, comma is assumed. @@ -50798,7 +50827,7 @@ function Import-DbaCsvToSql { Valid delimiters are '`t`, '|', ';',' ' and ',' (tab, pipe, semicolon, space, and comma). .PARAMETER SingleColumn - Specifies that the file contains a single column of data + Specifies that the file contains a single column of data. Otherwise, the delimiter check bombs. .PARAMETER SqlInstance The SQL Server Instance to import data into. @@ -50819,43 +50848,18 @@ function Import-DbaCsvToSql { .PARAMETER Table Specifies the SQL table or view where CSV will be imported into. - If a table name is not specified, the table name will be automatically determined from the filename, and a prompt will appear to confirm the table name. + If a table name is not specified, the table name will be automatically determined from the filename. - If a table does not currently exist, it will created. SQL datatypes are determined from the first row of the CSV that contains data (skips first row if -FirstRowColumns is specified). Datatypes used are: bigint, numeric, datetime and varchar(MAX). + If the table specified does not exist and -AutoCreateTable, it will be automatically created using slow and efficient but accomodating data types. If the automatically generated table datatypes do not work for you, please create the table prior to import. + .PARAMETER AutoCreateTable + If this switch is enabled, the table will be created if it does not already exist. The table will be created with sub-optimal data types such as nvarchar(max) + .PARAMETER Truncate If this switch is enabled, the destination table will be truncated prior to import. - .PARAMETER Safe - If this switch is enabled, OleDb is used to import the records. By default, Import-DbaCsvToSql uses StreamReader for imports. StreamReader is super fast, but may not properly parse some files. - - When using OleDb the import will be slower but more predictable when it comes to parsing CSV files. A schema.ini is automatically generated for best results. If schema.ini currently exists in the directory, it will be moved to a temporary location, then moved back. - - OleDB also enables the script to use the -Query parameter, which enables you to import specific subsets of data within a CSV file. OleDB imports at up to 21,000 rows/sec. - - .PARAMETER Turbo - If this switch is enabled, a Table Lock will be created for the import to make the import run as fast as possible. Depending upon the number of columns and datatypes, this may be over 90,000 records per second. - - This switch cannot be used in conjunction with -Query. - - Remember the Turbo button? This one actually works. Turbo is mega fast, but may not handle some datatypes as well as other methods. - - If your CSV file is rather vanilla and doesn't have a ton of NULLs, Turbo may work well for you. - - .PARAMETER First - Specifies the number of rows to import. If this parameter is omitted, the entire file is imported. Row counts start at the top of the file, but skip the first row if -FirstRowColumns is specified. - - Use -Query if you need advanced First (TOP) functionality. - - .PARAMETER Query - Specifies a query to execute against the CSV data to select/modify the data being imported. - - To make command line queries easy, this module will convert the word "csv" to the actual CSV formatted table name. If the FirstRowColumns switch is not used, the query should use column1, column2, column3, etc. - - Cannot be used in conjunction with -Turbo or -First. When -Query is specified, the slower import method, OleDb, will be used. - .PARAMETER NotifyAfter Specifies the import row count interval for reporting progress. A notification will be shown after each group of this many rows has been imported. @@ -50888,8 +50892,22 @@ function Import-DbaCsvToSql { Per Microsoft "Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable." + .PARAMETER NoProgress + The progress bar is pretty but can slow down imports. Use this parameter to quietly import. + + .PARAMETER WhatIf + Shows what would happen if the command were to run. No actions are actually performed. + + .PARAMETER Confirm + Prompts you for confirmation before executing any changing operations within the command. + + .PARAMETER EnableException + By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message. + This avoids overwhelming you with "sea of red" exceptions, but is inconvenient because it basically disables advanced scripting. + Using this switch turns this "nice by default" feature off and enables you to catch exceptions with your own try/catch. + .NOTES - Tags: Migration + Tags: Migration, Import Author: Chrissy LeMaire (@cl), netnerds.net Website: https://dbatools.io @@ -50897,297 +50915,73 @@ function Import-DbaCsvToSql { License: MIT https://opensource.org/licenses/MIT .LINK - https://blog.netnerds.net/2015/09/Import-DbaCsvtosql-super-fast-csv-to-sql-server-import-powershell-module/ - - .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv C:\temp\housing.csv -SqlInstance sql001 -Database markets - - Imports the entire comma-delimited housing.csv to the SQL "markets" database on a SQL Server named sql001. - - Since a table name was not specified, the table name is automatically determined from filename as "housing" and a prompt will appear to confirm table name. - - The first row is not skipped, as it does not contain column names. + https://dbatools.io/Import-DbaCsv .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv .\housing.csv -SqlInstance sql001 -Database markets -Table housing -First 100000 -Safe -Delimiter "`t" -FirstRowColumns + PS C:\> Import-DbaCsv -Path C:\temp\housing.csv -SqlInstance sql001 -Database markets - Imports the first 100,000 rows of the tab delimited housing.csv file to the "housing" table in the "markets" database on a SQL Server named sql001. Since -Safe was specified, the OleDB method will be used for the bulk import. The first row is skipped, as it contains column names. + Imports the entire comma-delimited housing.csv to the SQL "markets" database on a SQL Server named sql001, using the first row as column names. - .EXAMPLE - PS C:\> Import-DbaCsvToSql -csv C:\temp\huge.txt -SqlInstance sqlcluster -Database locations -Table latitudes -Delimiter "|" -Turbo - - Imports all records from the pipe delimited huge.txt file using the fastest method possible into the latitudes table within the locations database. Obtains a table lock for the duration of the bulk copy operation. This specific command has been used - to import over 10.5 million rows in 2 minutes. + Since a table name was not specified, the table name is automatically determined from filename as "housing". .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv C:\temp\housing.csv, .\housing2.csv -SqlInstance sql001 -Database markets -Table housing -Delimiter "`t" -query "select top 100000 column1, column3 from csv" -Truncate + PS C:\> Import-DbaCsv -Path .\housing.csv -SqlInstance sql001 -Database markets -Table housing -Delimiter "`t" -NoHeaderRow - Truncates the "housing" table, then imports columns 1 and 3 of the first 100000 rows of the tab-delimited housing.csv in the C:\temp directory, and housing2.csv in the current directory. Since the query is executed against both files, a total of 200,000 rows will be imported. + Imports the entire comma-delimited housing.csv, including the first row which is not used for colum names, to the SQL markets database, into the housing table, on a SQL Server named sql001. .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv C:\temp\housing.csv -SqlInstance sql001 -Database markets -Table housing -query "select address, zip from csv where state = 'Louisiana'" -FirstRowColumns -Truncate -FireTriggers - - Uses the first line to determine CSV column names. Truncates the "housing" table on the SQL Server, then imports the address and zip columns from all records in the housing.csv where the state equals Louisiana. + PS C:\> Import-DbaCsv -Path C:\temp\huge.txt -SqlInstance sqlcluster -Database locations -Table latitudes -Delimiter "|" - Triggers are fired for all rows. Note that this does slightly slow down the import. + Imports the entire pipe-delimited huge.txt to the locations database, into the latitudes table on a SQL Server named sqlcluster. .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv c:\temp\SingleColumn.csv -SqlInstance sql001 -Database markets -Table TempTable -SingleColumn + PS C:\> Import-DbaCsv -Path c:\temp\SingleColumn.csv -SqlInstance sql001 -Database markets -Table TempTable -SingleColumn - Upload the single column Csv SingleColumn.csv to Temptable which has just one column + Imports the single column CSV into TempTable .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv "\\FileServer\To Import\housing.csv" -SqlInstance sql001 -Database markets + PS C:\> Get-ChildItem -Path \\FileServer\csvs | Import-DbaCsv -SqlInstance sql001, sql002 -Database tempdb -AutoCreateTable - Imports the entire comma-delimited housing.csv located in the share named "To Import" on FileServer to the SQL "markets" database on a SQL Server named sql001. + Imports every CSV in the \\FileServer\csvs path into both sql001 and sql002's tempdb database. Each CSV will be imported into an automatically determined table name. .EXAMPLE - PS C:\> Import-DbaCsvToSql -Csv '\\FileServer\R$\To Import\housing.csv' -SqlInstance sql001 -Database markets + PS C:\> Get-ChildItem -Path \\FileServer\csvs | Import-DbaCsv -SqlInstance sql001, sql002 -Database tempdb -AutoCreateTable -WhatIf - Imports the entire comma-delimited housing.csv located in the directory R:\To Import on FileServer using the administrative share to the SQL "markets" database on a SQL Server named sql001. + Shows what would happen if the command were to be executed - #> - [CmdletBinding(DefaultParameterSetName = "Default")] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseSingularNouns", "", Justification = "Internal functions are ignored")] - [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "", Justification = "For Parameters SQLCredential and SQLCredentialPath")] + #> + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Low')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseDeclaredVarsMoreThanAssignments", "line", Justification = "Variable line is used, False Positive on line 330")] param ( - [string[]]$Csv, + [parameter(ValueFromPipeline)] + [ValidateNotNullOrEmpty()] + [Alias("Csv", "FullPath")] + [object[]]$Path, [Parameter(Mandatory)] - [Alias("ServerInstance", "SqlServer")] - [DbaInstanceParameter]$SqlInstance, - [object]$SqlCredential, + [DbaInstanceParameter[]]$SqlInstance, + [pscredential]$SqlCredential, + [Parameter(Mandatory)] + [string]$Database, [string]$Table, [string]$Schema = "dbo", [switch]$Truncate, - [ValidateSet("`t", "|", ";", " ", ",")] [string]$Delimiter = ",", [switch]$SingleColumn, - [switch]$FirstRowColumns, - [parameter(ParameterSetName = "reader")] - [switch]$Turbo, - [parameter(ParameterSetName = "ole")] - [switch]$Safe, - [int]$First = 0, - [parameter(ParameterSetName = "ole")] - [string]$Query = "select * from csv", [int]$BatchSize = 50000, - [int]$NotifyAfter, + [int]$NotifyAfter = 50000, [switch]$TableLock, [switch]$CheckConstraints, [switch]$FireTriggers, [switch]$KeepIdentity, [switch]$KeepNulls, - #[Parameter(DontShow)] - [switch]$shellswitch, - #[Parameter(DontShow)] - [string]$SqlCredentialPath + [switch]$AutoCreateTable, + [switch]$NoProgress, + [switch]$NoHeaderRow, + [switch]$EnableException ) - - DynamicParam { - - if ($SqlInstance.length -gt 0) { - # Auto populate database list from specified sqlserver - $paramconn = New-Object System.Data.SqlClient.SqlConnection - - if ($SqlCredentialPath.length -gt 0) { - $SqlCredential = Import-CliXml $SqlCredentialPath - } - - if ($SqlCredential.count -eq 0 -or $null -eq $SqlCredential) { - $paramconn.ConnectionString = "Data Source=$SqlInstance;Integrated Security=True;" - } else { - $paramconn.ConnectionString = "Data Source=$SqlInstance;User Id=$($SqlCredential.UserName); Password=$($SqlCredential.GetNetworkCredential().Password);" - } - - try { - $paramconn.Open() - $sql = "select name from master.dbo.sysdatabases" - $paramcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $paramconn, $null) - $paramdt = New-Object System.Data.DataTable - $paramdt.Load($paramcmd.ExecuteReader()) - $databaselist = $paramdt.rows.name - $null = $paramcmd.Dispose() - $null = $paramconn.Close() - $null = $paramconn.Dispose() - } catch { - # But if the routine fails, at least let them specify a database manually - $databaselist = "" - } - - # Reusable parameter setup - $newparams = New-Object System.Management.Automation.RuntimeDefinedParameterDictionary - $attributes = New-Object System.Management.Automation.ParameterAttribute - $attributes.Mandatory = $false - - # Database list parameter setup - $dbattributes = New-Object -Type System.Collections.ObjectModel.Collection[System.Attribute] - $dbattributes.Add($attributes) - # If a list of databases were returned, populate the parameter set - if ($databaselist.length -gt 0) { - $dbvalidationset = New-Object System.Management.Automation.ValidateSetAttribute -ArgumentList $databaselist - $dbattributes.Add($dbvalidationset) - } - - $Database = New-Object -Type System.Management.Automation.RuntimeDefinedParameter("Database", [String], $dbattributes) - $newparams.Add("Database", $Database) - return $newparams - } - } - begin { - function Get-Columns { - <# - .SYNOPSIS - TextFieldParser will be used instead of an OleDbConnection. - This is because the OleDbConnection driver may not exist on x64. - - .EXAMPLE - $columns = Get-Columns -Csv .\myfile.csv -Delimiter "," -FirstRowColumns $true - - .OUTPUTS - Array of column names - #> - - param ( - [Parameter(Mandatory)] - [string[]]$Csv, - [Parameter(Mandatory)] - [string]$Delimiter, - [Parameter(Mandatory)] - [bool]$FirstRowColumns - ) - - $columnparser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser($csv[0]) - $columnparser.TextFieldType = "Delimited" - $columnparser.SetDelimiters($Delimiter) - $rawcolumns = $columnparser.ReadFields() - - if ($FirstRowColumns -eq $true) { - $columns = ($rawcolumns | ForEach-Object { $_ -Replace '"' } | Select-Object -Property @{ Name = "name"; Expression = { "[$_]" } }).name - } else { - $columns = @() - foreach ($number in 1..$rawcolumns.count) { - $columns += "[column$number]" - } - } - - $columnparser.Close() - $columnparser.Dispose() - return $columns - } - - function Get-ColumnText { - <# - .SYNOPSIS - Returns an array of data, which can later be parsed for potential datatypes. - - .EXAMPLE - $columns = Get-Columns -Csv .\myfile.csv -Delimiter "," - - .OUTPUTS - Array of column data - #> - param ( - [Parameter(Mandatory)] - [string[]]$Csv, - [Parameter(Mandatory)] - [string]$Delimiter - ) - $columnparser = New-Object Microsoft.VisualBasic.FileIO.TextFieldParser($csv[0]) - $columnparser.TextFieldType = "Delimited" - $columnparser.SetDelimiters($Delimiter) - $line = $columnparser.ReadLine() - # Skip a line, in case first line are column names - $line = $columnparser.ReadLine() - $datatext = $columnparser.ReadFields() - $columnparser.Close() - $columnparser.Dispose() - return $datatext - } - - function Write-Schemaini { - <# - .SYNOPSIS - Unfortunately, passing delimiter within the OleDBConnection connection string is unreliable, so we'll use schema.ini instead. The default delimiter in Windows changes depending on country, so we'll do this for every delimiter, even commas. - - Get OLE datatypes based on best guess of column data within the -Columns parameter. - - Sometimes SQL will accept a datetime that OLE won't, so Text will be used for datetime. - - .EXAMPLE - $columns = Get-Columns -Csv C:\temp\myfile.csv -Delimiter "," - $movedschemainis = Write-Schemaini -Csv C:\temp\myfile.csv -Columns $columns -ColumnText $columntext -Delimiter "," -FirstRowColumns $true - - .OUTPUTS - Creates new schema files, that look something like this: - - [housingdata.csv] - Format=Delimited(,) - ColNameHeader=True - Col1="House ID" Long - Col2="Description" Memo - Col3="Price" Double - - Returns an array of existing schema files that have been moved, if any. - #> - param ( - [Parameter(Mandatory)] - [string[]]$Csv, - [Parameter(Mandatory)] - [string[]]$Columns, - [string[]]$ColumnText, - [Parameter(Mandatory)] - [string]$Delimiter, - [Parameter(Mandatory)] - [bool]$FirstRowColumns - ) - - $movedschemainis = @{ } - foreach ($file in $csv) { - $directory = Split-Path $file - $schemaexists = Test-Path "$directory\schema.ini" - if ($schemaexists -eq $true) { - $newschemaname = "$env:TEMP\$(Split-Path $file -leaf)-schema.ini" - $movedschemainis.Add($newschemaname, "$directory\schema.ini") - Move-Item "$directory\schema.ini" $newschemaname -Force - } - - $filename = Split-Path $file -leaf; $directory = Split-Path $file - Add-Content -Path "$directory\schema.ini" -Value "[$filename]" - Add-Content -Path "$directory\schema.ini" -Value "Format=Delimited($InternalDelimiter)" - Add-Content -Path "$directory\schema.ini" -Value "ColNameHeader=$FirstRowColumns" - - $index = 0 - $olecolumns = ($columns | ForEach-Object { $_ -Replace "\[|\]", '"' }) - - foreach ($datatype in $columntext) { - $olecolumnname = $olecolumns[$index] - $index++ - - try { - [System.Guid]::Parse($datatype) | Out-Null; $isguid = $true - } catch { - $isguid = $false - } - - if ($isguid -eq $true) { - $oledatatype = "Text" - } elseif ([int64]::TryParse($datatype, [ref]0) -eq $true) { - $oledatatype = "Long" - } elseif ([double]::TryParse($datatype, [ref]0) -eq $true) { - $oledatatype = "Double" - } elseif ([datetime]::TryParse($datatype, [ref]0) -eq $true) { - $oledatatype = "Text" - } else { - $oledatatype = "Memo" - } - - Add-Content -Path "$directory\schema.ini" -Value "Col$($index)`=$olecolumnname $oledatatype" - } - } - return $movedschemainis - } + $FirstRowHeader = $NoHeaderRow -eq $false + $scriptelapsed = [System.Diagnostics.Stopwatch]::StartNew() function New-SqlTable { <# @@ -51198,7 +50992,7 @@ function Import-DbaCsvToSql { Columns parameter determine column names. .EXAMPLE - New-SqlTable -Csv $Csv -Delimiter $InternalDelimiter -Columns $columns -ColumnText $columntext -SqlConn $sqlconn -Transaction $transaction + New-SqlTable -Path $Path -Delimiter $Delimiter -Columns $columns -ColumnText $columntext -SqlConn $sqlconn -Transaction $transaction .OUTPUTS Creates new table @@ -51206,58 +51000,46 @@ function Import-DbaCsvToSql { [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] param ( [Parameter(Mandatory)] - [string[]]$Csv, + [string]$Path, [Parameter(Mandatory)] [string]$Delimiter, - [string[]]$Columns, - [string[]]$ColumnText, + [Parameter(Mandatory)] + [bool]$FirstRowHeader, [System.Data.SqlClient.SqlConnection]$sqlconn, [System.Data.SqlClient.SqlTransaction]$transaction ) + $reader = New-Object LumenWorks.Framework.IO.Csv.CsvReader((New-Object System.IO.StreamReader($Path)), $FirstRowHeader, $Delimiter, 1) + $columns = $reader.GetFieldHeaders() + $reader.Close() + $reader.Dispose() + # Get SQL datatypes by best guess on first data row $sqldatatypes = @(); $index = 0 - foreach ($column in $columntext) { - $sqlcolumnname = $Columns[$index] - $index++ - - # bigint, float, and datetime are more accurate, but it didn't work - # as often as it should have, so we'll just go for a smaller datatype - if ([int64]::TryParse($column, [ref]0) -eq $true) { - $sqldatatype = "varchar(255)" - } elseif ([double]::TryParse($column, [ref]0) -eq $true) { - $sqldatatype = "varchar(255)" - } elseif ([datetime]::TryParse($column, [ref]0) -eq $true) { - $sqldatatype = "varchar(255)" - } else { - $sqldatatype = "varchar(MAX)" - } - - $sqldatatypes += "$sqlcolumnname $sqldatatype" + foreach ($column in $Columns) { + $sqldatatypes += "[$column] varchar(MAX)" } $sql = "BEGIN CREATE TABLE [$schema].[$table] ($($sqldatatypes -join ' NULL,')) END" $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + try { $null = $sqlcmd.ExecuteNonQuery() } catch { $errormessage = $_.Exception.Message.ToString() - throw "Failed to execute $sql. `nDid you specify the proper delimiter? `n$errormessage" + Stop-Function -Continue -Message "Failed to execute $sql. `nDid you specify the proper delimiter? `n$errormessage" } - Write-Output "[*] Successfully created table $schema.$table with the following column definitions:`n $($sqldatatypes -join "`n ")" - # Write-Warning "All columns are created using a best guess, and use their maximum datatype." - Write-Warning "This is inefficient but allows the script to import without issues." - Write-Warning "Consider creating the table first using best practices if the data will be used in production." + Write-Message -Level Verbose -Message "Successfully created table $schema.$table with the following column definitions:`n $($sqldatatypes -join "`n ")" + # Write-Message -Level Warning -Message "All columns are created using a best guess, and use their maximum datatype." + Write-Message -Level Verbose -Message "This is inefficient but allows the script to import without issues." + Write-Message -Level Verbose -Message "Consider creating the table first using best practices if the data will be used in production." } - - if ($shellswitch -eq $false) { Write-Output "[*] Started at $(Get-Date)" } + Write-Message -Level Verbose -Message "Started at $(Get-Date)" # Load the basics [void][Reflection.Assembly]::LoadWithPartialName("System.Data") - [void][Reflection.Assembly]::LoadWithPartialName("Microsoft.VisualBasic") - [void][Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms") # Getting the total rows copied is a challenge. Use SqlBulkCopyExtension. # http://stackoverflow.com/questions/1188384/sqlbulkcopy-row-count-when-complete @@ -51279,765 +51061,291 @@ function Import-DbaCsvToSql { } } ' - Add-Type -ReferencedAssemblies 'System.Data.dll' -TypeDefinition $source -ErrorAction SilentlyContinue + try { + # SilentContinue isn't enough + Add-Type -ReferencedAssemblies 'System.Data.dll' -TypeDefinition $source -ErrorAction Stop + Add-Type -Path "$script:PSModuleRoot\bin\csv\LumenWorks.Framework.IO.dll" -ErrorAction Stop + } catch { + $null = 1 + } } - process { - # turbo mode requires a table lock, or it's just regular fast - if ($turbo -eq $true) { - $tablelock = $true - } - - # Hack to get around the delimter parameter ValidateSet - if ($SingleColumn -eq $true) { - $InternalDelimiter = '' - } else { - $InternalDelimiter = $Delimiter - } - - # The query parameter requires OleDB which is invoked by the "safe" variable - # Actually, a select could be performed on the datatable used in StreamReader, too. - # Maybe that will be done later. - if ($query -ne "select * from csv") { - $safe = $true - } - - if ($first -gt 0 -and $query -ne "select * from csv") { - throw "Cannot use both -Query and -First. If a query is necessary, use TOP $first within your SQL statement." - } - - # In order to support -First in both Streamreader, and OleDb imports, the query must be modified slightly. - if ($first -gt 0) { - $query = "select top $first * from csv" - } + foreach ($filename in $Path) { - # If shell switch occured, and encrypted SQL credentials were written to disk, create $SqlCredential - if ($SqlCredentialPath.length -gt 0) { - $SqlCredential = Import-CliXml $SqlCredentialPath - } - - # Get Database string from RuntimeDefinedParameter if required - if ($database -isnot [string]) { - $database = $PSBoundParameters.Database - } - if ($database.length -eq 0) { - throw "You must specify a database." - } - - # Check to ensure a Windows account wasn't used as a SQL Credential - if ($SqlCredential.count -gt 0 -and $SqlCredential.UserName -like "*\*") { - throw "Only SQL Logins can be used as a SqlCredential." - } - - # If no CSV was specified, prompt the user to select one. - if ($csv.length -eq 0) { - $fd = New-Object System.Windows.Forms.OpenFileDialog - $fd.InitialDirectory = [environment]::GetFolderPath("MyDocuments") - $fd.Filter = "CSV Files (*.csv;*.tsv;*.txt)|*.csv;*.tsv;*.txt" - $fd.Title = "Select one or more CSV files" - $fd.MultiSelect = $true - $null = $fd.showdialog() - $csv = $fd.filenames - if ($csv.length -eq 0) { - throw "No CSV file selected." - } - } else { - foreach ($file in $csv) { - $exists = Test-Path $file - if ($exists -eq $false) { - throw "$file does not exist" - } + if ($filename.FullName) { + $filename = $filename.FullName } - } - - # Resolve the full path of each CSV - $resolvedcsv = @() - foreach ($file in $csv) { - $resolvedcsv += (Resolve-Path $file).ProviderPath - } - $csv = $resolvedcsv - # UniqueIdentifier kills OLE DB / SqlBulkCopy imports. Check to see if destination table contains this datatype. - if ($safe -eq $true) { - $sqlcheckconn = New-Object System.Data.SqlClient.SqlConnection - if ($SqlCredential.count -eq 0 -or $null -eq $SqlCredential) { - $sqlcheckconn.ConnectionString = "Data Source=$SqlInstance;Integrated Security=True;Connection Timeout=3; Initial Catalog=master" - } else { - $username = ($SqlCredential.UserName).TrimStart("\") - $sqlcheckconn.ConnectionString = "Data Source=$SqlInstance;User Id=$username; Password=$($SqlCredential.GetNetworkCredential().Password);Connection Timeout=3; Initial Catalog=master" + if (-not (Test-Path -Path $filename)) { + Stop-Function -Continue -Message "$filename cannot be found" } + $file = (Resolve-Path -Path $filename).ProviderPath + + # Does the second line contain the specified delimiter? try { - $sqlcheckconn.Open() + $firstline = Get-Content -Path $file -TotalCount 2 -ErrorAction Stop } catch { - throw $_.Exception - } - - # Ensure database exists - $sql = "select count(*) from master.dbo.sysdatabases where name = '$database'" - $sqlcheckcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlcheckconn) - $dbexists = $sqlcheckcmd.ExecuteScalar() - if ($dbexists -eq $false) { - throw "Database does not exist on $SqlInstance" + Stop-Function -Continue -Message "Failure reading $file" -ErrorRecord $_ } - - # Change database after the fact, because if db doesn't exist, the login would fail. - $sqlcheckconn.ChangeDatabase($database) - - $sql = "SELECT t.name as datatype FROM sys.columns c - JOIN sys.types t ON t.system_type_id = c.system_type_id - WHERE c.object_id = object_id('$schema.$table') and t.name != 'sysname'" - $sqlcheckcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlcheckconn) - $sqlcolumns = New-Object System.Data.DataTable - $sqlcolumns.load($sqlcheckcmd.ExecuteReader("CloseConnection")) - $sqlcheckconn.Dispose() - if ($sqlcolumns.datatype -contains "UniqueIdentifier") { - throw "UniqueIdentifier not supported by OleDB/SqlBulkCopy. Query and Safe cannot be supported." - } - } - - if ($safe -eq $true) { - # Check for drivers. First, ACE (Access) if file is smaller than 2GB, then JET - # ACE doesn't handle files larger than 2gb. What gives? - foreach ($file in $csv) { - $filesize = (Get-ChildItem $file).Length / 1GB - if ($filesize -gt 1.99) { - $jetonly = $true + if (-not $SingleColumn) { + if ($firstline -notmatch $Delimiter) { + Stop-Function -Message "Delimiter ($Delimiter) not found in first few rows of $file. If this is a single column import, please specify -SingleColumn" + return } } - if ($jetonly -ne $true) { - $provider = (New-Object System.Data.OleDb.OleDbEnumerator).GetElements() | Where-Object { $_.SOURCES_NAME -like "Microsoft.ACE.OLEDB.*" } + # Automatically generate Table name if not specified, then prompt user to confirm + if (-not (Test-Bound -ParameterName Table)) { + $table = [IO.Path]::GetFileNameWithoutExtension($file) + Write-Message -Level Verbose -Message "Table name not specified, using $table" } - if ($null -eq $provider) { - $provider = (New-Object System.Data.OleDb.OleDbEnumerator).GetElements() | Where-Object { $_.SOURCES_NAME -like "Microsoft.Jet.OLEDB.*" } - } - - # If a suitable provider cannot be found (If x64 and Access hasn't been installed) - # switch to x86, because it natively supports JET - if ($null -ne $provider) { - if ($provider -is [system.array]) { - $provider = $provider[$provider.GetUpperBound(0)].SOURCES_NAME - } else { - $provider = $provider.SOURCES_NAME + foreach ($instance in $SqlInstance) { + $elapsed = [System.Diagnostics.Stopwatch]::StartNew() + # Open Connection to SQL Server + try { + $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $sqlcredential -StatementTimeout 0 -MinimumVersion 9 + $sqlconn = $server.ConnectionContext.SqlConnectionObject + $sqlconn.Open() + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } - } - - # If a provider doesn't exist, it is necessary to switch to x86 which natively supports JET. - if ($null -eq $provider) { - # While Install-Module takes care of installing modules to x86 and x64, Import-Module doesn't. - # Because of this, the Module must be exported, written to file, and imported in the x86 shell. - $definition = (Get-Command Import-DbaCsvToSql).Definition - $function = "Function Import-DbaCsvToSql { $definition }" - Set-Content "$env:TEMP\Import-DbaCsvToSql.psm1" $function - # Encode the SQL string, since some characters may mess up after being passed a second time. - $bytes = [System.Text.Encoding]::UTF8.GetBytes($query) - $query = [System.Convert]::ToBase64String($bytes) - - # Put switches back into proper format - $switches = @() - $options = "TableLock", "CheckConstraints", "FireTriggers", "KeepIdentity", "KeepNulls", "Default", "Truncate", "FirstRowColumns", "Safe" - foreach ($option in $options) { - $optionValue = Get-Variable $option -ValueOnly -ErrorAction SilentlyContinue - if ($optionValue -eq $true) { - $switches += "-$option" - } + if ($PSCmdlet.ShouldProcess($instance, "Starting transaction in $Database")) { + # Everything will be contained within 1 transaction, even creating a new table if required + # and truncating the table, if specified. + $transaction = $sqlconn.BeginTransaction() } - # Perform the actual switch, which removes any registered Import-DbaCsvToSql modules - # Then imports, and finally re-executes the command. - $csvParam = ($csv | ForEach-Object { "'$($_ -replace "'", "''")'" }) -join "," - $switches = $switches -join " " - if ($SqlCredential.count -gt 0) { - $SqlCredentialPath = "$env:TEMP\sqlcredential.xml" - Export-CliXml -InputObject $SqlCredential $SqlCredentialPath + # Ensure database exists + $sql = "select count(*) from master.dbo.sysdatabases where name = '$Database'" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + if (($sqlcmd.ExecuteScalar()) -eq 0) { + Stop-Function -Continue -Message "Database does not exist on $instance" } - $command = "Import-DbaCsvToSql -Csv $csvParam -SqlInstance '$SqlInstance'-Database '$database' -Table '$table' -Delimiter '$InternalDelimiter' -First $First -Query '$query' -Batchsize $BatchSize -NotifyAfter $NotifyAfter $switches -shellswitch" + Write-Message -Level Verbose -Message "Database exists" + $sqlconn.ChangeDatabase($Database) - if ($SqlCredentialPath.length -gt 0) { - $command += " -SqlCredentialPath $SqlCredentialPath" - } - Write-Verbose "Switching to x86 shell, then switching back." - &"$env:windir\syswow64\windowspowershell\v1.0\powershell.exe" "$command" - return - } - } + # Ensure Schema exists + $sql = "select count(*) from $Database.sys.schemas where name='$schema'" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - # Do the first few lines contain the specified delimiter? - foreach ($file in $csv) { - try { $firstfewlines = Get-Content $file -First 3 -ErrorAction Stop } - catch { throw "$file is in use." } - if ($SingleColumn -ne $true ) { - foreach ($line in $firstfewlines) { - if (($line -match $InternalDelimiter) -eq $false) { - throw "Delimiter $InternalDelimiter not found in first row of $file." + # If Schema doesn't exist create it + # Defaulting to dbo. + if (($sqlcmd.ExecuteScalar()) -eq 0) { + if (-not $AutoCreateTable) { + Stop-Function -Continue -Message "Schema $Schema does not exist and AutoCreateTable was not specified" } - } - } - } - - # If more than one csv specified, check to ensure number of columns match - if ($csv -is [system.array]) { - if ($SingleColumn -ne $true) { - $numberofcolumns = ((Get-Content $csv[0] -First 1 -ErrorAction Stop) -Split $InternalDelimiter).Count - - foreach ($file in $csv) { - $firstline = Get-Content $file -First 1 -ErrorAction Stop - $newnumcolumns = ($firstline -Split $InternalDelimiter).Count - if ($newnumcolumns -ne $numberofcolumns) { - throw "Multiple csv file mismatch. Do both use the same delimiter and have the same number of columns?" + $sql = "CREATE SCHEMA [$schema] AUTHORIZATION dbo" + if ($PSCmdlet.ShouldProcess($instance, "Creating schema $schema")) { + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + try { + $null = $sqlcmd.ExecuteNonQuery() + } catch { + Stop-Function -Continue -Message "Could not create $schema" -ErrorRecord $_ + } } } - } - } - # Automatically generate Table name if not specified, then prompt user to confirm - if ($table.length -eq 0) { - $table = [IO.Path]::GetFileNameWithoutExtension($csv[0]) + # Ensure table exists + $sql = "select count(*) from $Database.sys.tables where name = '$table' and schema_id=schema_id('$schema')" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - #Count the dots in the file name. - #1 dot, treat it as schema.table naming - #2 or more dots, really should catch it as bad practice, but the rest of the script appears to let it pass - if (($table.ToCharArray() | Where-Object {$_ -eq '.'} | Measure-Object).count -gt 0) { - if (($schema -ne $table.Split('.')[0]) -and ($schema -ne 'dbo')) { - $title = "Conflicting schema names specified" - $message = "Please confirm which schema you want to use." - $schemaA = New-Object System.Management.Automation.Host.ChoiceDescription "&A - $schema", "Use schema name $schema for import." - $schemaB = New-Object System.Management.Automation.Host.ChoiceDescription "&B - $($table.Split('.')[0])", "Use schema name $($table.Split('.')[0]) for import." - $options = [System.Management.Automation.Host.ChoiceDescription[]]($schemaA, $schemaB) - $result = $host.ui.PromptForChoice($title, $message, $options, 0) - if ($result -eq 1) { - $schema = $table.Split('.')[0] - $tmparray = $table.split('.') - $table = $tmparray[1..$tmparray.Length] -join '.' + # Create the table if required. Remember, this will occur within a transaction, so if the script fails, the + # new table will no longer exist. + if (($sqlcmd.ExecuteScalar()) -eq 0) { + if (-not $AutoCreateTable) { + Stop-Function -Continue -Message "Table $table does not exist and AutoCreateTable was not specified" } - } - - } else { - $title = "Table name not specified." - $message = "Would you like to use the automatically generated name: $table" - $yes = New-Object System.Management.Automation.Host.ChoiceDescription "&Yes", "Uses table name $table for import." - $no = New-Object System.Management.Automation.Host.ChoiceDescription "&No", "Allows you to specify an alternative table name." - $options = [System.Management.Automation.Host.ChoiceDescription[]]($yes, $no) - $result = $host.ui.PromptForChoice($title, $message, $options, 0) - if ($result -eq 1) { - do { - $table = Read-Host "Please enter a table name" + Write-Message -Level Verbose -Message "Table does not exist" + if ($PSCmdlet.ShouldProcess($instance, "Creating table $table")) { + New-SqlTable -Path $file -Delimiter $Delimiter -FirstRowHeader $FirstRowHeader -SqlConn $sqlconn -Transaction $transaction } - while ($table.Length -eq 0) - } - - } - } - - # If the shell has switched, decode the $query string. - if ($shellswitch -eq $true) { - $bytes = [System.Convert]::FromBase64String($Query) - $query = [System.Text.Encoding]::UTF8.GetString($bytes) - $csv = $csv -Split "," - } - - # Create columns based on first data row of first csv. - if ($SingleColumn -ne $true) { - Write-Output "[*] Calculating column names and datatypes" - $columns = Get-Columns -Csv $Csv -Delimiter $InternalDelimiter -FirstRowColumns $FirstRowColumns - if ($columns.count -gt 255 -and $safe -eq $true) { - throw "CSV must contain fewer than 256 columns." - } - } - - if ($SingleColumn -ne $true) { - $columntext = Get-ColumnText -Csv $Csv -Delimiter $InternalDelimiter - } - - # OLEDB method requires extra checks - if ($safe -eq $true) { - # Advanced SQL queries may not work (SqlBulkCopy likes a 1 to 1 mapping), so warn the user. - if ($Query -match "GROUP BY" -or $Query -match "COUNT") { - Write-Warning "Script doesn't really support the specified query. This probably won't work, but will be attempted anyway." - } - - # Check for proper SQL syntax, which for the purposes of this module must include the word "table" - if ($query.ToLower() -notmatch "\bcsv\b") { - throw "SQL statement must contain the word 'csv'. Please see this module's documentation for more details." - } - - # In order to ensure consistent results, a schema.ini file must be created. - # If a schema.ini already exists, it will be moved to TEMP temporarily. - Write-Verbose "Creating schema.ini" - $movedschemainis = Write-Schemaini -Csv $Csv -Columns $columns -Delimiter "$InternalDelimiter" -FirstRowColumns $FirstRowColumns -ColumnText $columntext - } - - # Display SQL Server Login info - if ($sqlcredential.count -gt 0) { - $username = "SQL login $($SqlCredential.UserName)" - } else { - $username = "Windows login $(whoami)" - } - # Open Connection to SQL Server - Write-Output "[*] Logging into $SqlInstance as $username" - $sqlconn = New-Object System.Data.SqlClient.SqlConnection - if ($SqlCredential.count -eq 0) { - $sqlconn.ConnectionString = "Data Source=$SqlInstance;Integrated Security=True;Connection Timeout=3; Initial Catalog=master" - } else { - $sqlconn.ConnectionString = "Data Source=$SqlInstance;User Id=$($SqlCredential.UserName); Password=$($SqlCredential.GetNetworkCredential().Password);Connection Timeout=3; Initial Catalog=master" - } - - try { - $sqlconn.Open() - } catch { - throw "Could not open SQL Server connection. Is $SqlInstance online?" - } - - # Everything will be contained within 1 transaction, even creating a new table if required - # and truncating the table, if specified. - $transaction = $sqlconn.BeginTransaction() - - # Ensure database exists - $sql = "select count(*) from master.dbo.sysdatabases where name = '$database'" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $dbexists = $sqlcmd.ExecuteScalar() - if ($dbexists -eq $false) { - throw "Database does not exist on $SqlInstance" - } - Write-Output "[*] Database exists" - - $sqlconn.ChangeDatabase($database) - - # Enure Schema exists - $sql = "select count(*) from $database.sys.schemas where name='$schema'" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $schemaexists = $sqlcmd.ExecuteScalar() - - # If Schema doesn't exist create it - # Defaulting to dbo. - if ($schemaexists -eq $false) { - Write-Output "[*] Creating schema $schema" - $sql = "CREATE SCHEMA [$schema] AUTHORIZATION dbo" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - try { - $null = $sqlcmd.ExecuteNonQuery() - } catch { - Write-Warning "Could not create $schema" - } - - } - - # Ensure table exists - $sql = "select count(*) from $database.sys.tables where name = '$table' and schema_id=schema_id('$schema')" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $tablexists = $sqlcmd.ExecuteScalar() - - # Create the table if required. Remember, this will occur within a transaction, so if the script fails, the - # new table will no longer exist. - if ($tablexists -eq $false) { - Write-Output "[*] Table does not exist" - Write-Output "[*] Creating table" - New-SqlTable -Csv $Csv -Delimiter $InternalDelimiter -Columns $columns -ColumnText $columntext -SqlConn $sqlconn -Transaction $transaction - } else { - Write-Output "[*] Table exists" - } - - # Truncate if specified. Remember, this will occur within a transaction, so if the script fails, the - # truncate will not be committed. - if ($truncate -eq $true) { - Write-Output "[*] Truncating table" - $sql = "TRUNCATE TABLE [$schema].[$table]" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - try { - $null = $sqlcmd.ExecuteNonQuery() - } catch { - Write-Warning "Could not truncate $schema.$table" - } - } - - # Get columns for column mapping - if ($null -eq $columnMappings) { - $olecolumns = ($columns | ForEach-Object { $_ -Replace "\[|\]" }) - $sql = "select name from sys.columns where object_id = object_id('$schema.$table') order by column_id" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $sqlcolumns = New-Object System.Data.DataTable - $sqlcolumns.Load($sqlcmd.ExecuteReader()) - } - - # Time to import! - $elapsed = [System.Diagnostics.Stopwatch]::StartNew() - - # Process each CSV file specified - foreach ($file in $csv) { - - # Dynamically set NotifyAfter if it wasn't specified - if ($notifyAfter -eq 0) { - if ($resultcount -is [int]) { - $notifyafter = $resultcount / 10 } else { - $notifyafter = 50000 + Write-Message -Level Verbose -Message "Table exists" } - } - - # Setup bulk copy - Write-Output "[*] Starting bulk copy for $(Split-Path $file -Leaf)" - # Setup bulk copy options - $bulkCopyOptions = @() - $options = "TableLock", "CheckConstraints", "FireTriggers", "KeepIdentity", "KeepNulls", "Default", "Truncate" - foreach ($option in $options) { - $optionValue = Get-Variable $option -ValueOnly -ErrorAction SilentlyContinue - if ($optionValue -eq $true) { - $bulkCopyOptions += "$option" + # Truncate if specified. Remember, this will occur within a transaction, so if the script fails, the + # truncate will not be committed. + if ($Truncate) { + $sql = "TRUNCATE TABLE [$schema].[$table]" + if ($PSCmdlet.ShouldProcess($instance, "Performing TRUNCATE TABLE [$schema].[$table] on $Database")) { + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + try { + $null = $sqlcmd.ExecuteNonQuery() + } catch { + Stop-Function -Continue -Message "Could not truncate $schema.$table" -ErrorRecord $_ + } + } } - } - $bulkCopyOptions = $bulkCopyOptions -join " & " - - # Create SqlBulkCopy using default options, or options specified in command line. - if ($bulkCopyOptions.count -gt 1) { - $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($oleconnstring, $bulkCopyOptions, $transaction) - } else { - $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($sqlconn, "Default", $transaction) - } - $bulkcopy.DestinationTableName = "[$schema].[$table]" - $bulkcopy.bulkcopyTimeout = 0 - $bulkCopy.BatchSize = $BatchSize - $bulkCopy.NotifyAfter = $NotifyAfter - - if ($safe -eq $true) { - # Setup bulkcopy mappings - for ($columnid = 0; $columnid -lt $sqlcolumns.rows.count; $columnid++) { - $null = $bulkCopy.ColumnMappings.Add($olecolumns[$columnid], $sqlcolumns.rows[$columnid].ItemArray[0]) + # Get columns for column mapping + if ($null -eq $columnMappings) { + $olecolumns = ($columns | ForEach-Object { + $_ -Replace "\[|\]" + }) + $sql = "select name from sys.columns where object_id = object_id('$schema.$table') order by column_id" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + $sqlcolumns = New-Object System.Data.DataTable + $sqlcolumns.Load($sqlcmd.ExecuteReader()) } - # Setup the connection string. Data Source is the directory that contains the csv. - # The file name is also the table name, but with a "#" instead of a "." - $datasource = Split-Path $file - $tablename = (Split-Path $file -leaf).Replace(".", "#") - $oleconnstring = "Provider=$provider;Data Source=$datasource;Extended Properties='text';" - - # To make command line queries easier, let the user just specify "csv" instead of the - # OleDbconnection formatted name (file.csv -> file#csv) - $sql = $Query -replace "\bcsv\b", " [$tablename]" - - # Setup the OleDbconnection - $oleconn = New-Object System.Data.OleDb.OleDbconnection - $oleconn.ConnectionString = $oleconnstring + # Setup bulk copy + Write-Message -Level Verbose -Message "Starting bulk copy for $(Split-Path $file -Leaf)" - # Setup the OleDBCommand - $olecmd = New-Object System.Data.OleDB.OleDBCommand - $olecmd.Connection = $oleconn - $olecmd.CommandText = $sql - - try { - $oleconn.Open() - } catch { - throw "Could not open OLEDB connection." - } - - # Attempt to get the number of results so that a nice progress bar can be displayed. - # This takes extra time, and files over 100MB take too long, so just skip them. - if ($sql -match "GROUP BY") { - Write-Warning -Message "Query contains GROUP BY clause. Skipping result count." - } else { - Write-Output "[*] Determining total rows to be copied. This may take a few seconds." + # Setup bulk copy options + $bulkCopyOptions = @() + $options = "TableLock", "CheckConstraints", "FireTriggers", "KeepIdentity", "KeepNulls", "Default", "Truncate" + foreach ($option in $options) { + $optionValue = Get-Variable $option -ValueOnly -ErrorAction SilentlyContinue + if ($optionValue -eq $true) { + $bulkCopyOptions += "$option" + } } + $bulkCopyOptions = $bulkCopyOptions -join " & " - if ($sql -match "\bselect top\b") { + if ($PSCmdlet.ShouldProcess($instance, "Performing import from $file")) { try { - $split = $sql -split "\bselect top \b" - $resultcount = [int]($split[1].Trim().Split()[0]) - Write-Output "[*] Attempting to fetch $resultcount rows" - } catch { - Write-Warning "Couldn't determine total rows to be copied." - } - } elseif ($sql -notmatch "GROUP BY") { - $filesize = (Get-ChildItem $file).Length / 1MB - if ($filesize -lt 100) { - try { - $split = $sql -split "\bfrom\b" - $sqlcount = "select count(*) from $($split[1])" - # Setup the OleDBCommand - $olecmd = New-Object System.Data.OleDB.OleDBCommand - $olecmd.Connection = $oleconn - $olecmd.CommandText = $sqlcount - $resultcount = [int]($olecmd.ExecuteScalar()) - Write-Output "[*] $resultcount rows will be copied" - } catch { - Write-Warning "Couldn't determine total rows to be copied" + # Create SqlBulkCopy using default options, or options specified in command line. + if ($bulkCopyOptions) { + $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($oleconnstring, $bulkCopyOptions, $transaction) + } else { + $bulkcopy = New-Object Data.SqlClient.SqlBulkCopy($sqlconn, "Default", $transaction) } - } else { - Write-Output "[*] File is too large for efficient result count; progress bar will not be shown." - } - } - } - # Write to server :D - try { - if ($safe -ne $true) { - # Check to ensure batchsize isn't equal to 0 - if ($batchsize -eq 0) { - write-warning "Invalid batchsize for this operation. Increasing to 50k" - $batchsize = 50000 - } - - # Open the text file from disk - $reader = New-Object System.IO.StreamReader($file) - if ($FirstRowColumns -eq $true) { - $null = $reader.readLine() + $bulkcopy.DestinationTableName = "[$schema].[$table]" + $bulkcopy.BulkCopyTimeout = 0 + $bulkCopy.BatchSize = $BatchSize + $bulkCopy.NotifyAfter = $NotifyAfter + $bulkCopy.EnableStreaming = $true + } catch { + Stop-Function -Continue -Message "Failure" -ErrorRecord $_ } - # Create the reusable datatable. Columns will be genereated using info from SQL. - $datatable = New-Object System.Data.DataTable + # Write to server :D + try { + # Open the text file from disk + # // or using (CsvReader csv = new CsvReader(File.OpenRead(path), false, Encoding.UTF8, addMark)) + # When addMark is true, consecutive null bytes will be replaced by [removed x null bytes] to indicate the removal + $reader = New-Object LumenWorks.Framework.IO.Csv.CsvReader((New-Object System.IO.StreamReader($file)), $FirstRowHeader, $Delimiter, 1) - # Get table column info from SQL Server - $sql = "SELECT c.name as colname, t.name as datatype, c.max_length, c.is_nullable FROM sys.columns c - JOIN sys.types t ON t.system_type_id = c.system_type_id - WHERE c.object_id = object_id('$schema.$table') and t.name != 'sysname' - order by c.column_id" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $sqlcolumns = New-Object System.Data.DataTable - $sqlcolumns.load($sqlcmd.ExecuteReader()) - - foreach ($sqlcolumn in $sqlcolumns) { - $datacolumn = $datatable.Columns.Add() - $colname = $sqlcolumn.colname - $datacolumn.AllowDBNull = $sqlcolumn.is_nullable - $datacolumn.ColumnName = $colname - $datacolumn.DefaultValue = [DBnull]::Value - $datacolumn.Datatype = [string] - - # The following data types can sometimes cause issues when they are null - # so we will treat them differently - $convert = "bigint", "DateTimeOffset", "UniqueIdentifier", "smalldatetime", "datetime" - if ($convert -notcontains $sqlcolumn.datatype -and $turbo -ne $true) { - $null = $bulkCopy.ColumnMappings.Add($datacolumn.ColumnName, $sqlcolumn.colname) - } - } - # For the columns that cause trouble, we'll add an additional column to the datatable - # which will perform a conversion. - # Setting $column.datatype alone doesn't work as well as setting+converting. - if ($turbo -ne $true) { - $calcolumns = $sqlcolumns | Where-Object { $convert -contains $_.datatype } - foreach ($calcolumn in $calcolumns) { - $colname = $calcolumn.colname - $null = $newcolumn = $datatable.Columns.Add() - $null = $newcolumn.ColumnName = "computed$colname" - switch ($calcolumn.datatype) { - "bigint" { - $netdatatype = "System.Int64"; - $newcolumn.Datatype = [int64] - } - "DateTimeOffset" { - $netdatatype = "System.DateTimeOffset"; - $newcolumn.Datatype = [DateTimeOffset] - } - "UniqueIdentifier" { - $netdatatype = "System.Guid"; - $newcolumn.Datatype = [Guid] - } - {"smalldatetime", "datetime" -contains $_ } { - $netdatatype = "System.DateTime"; - $newcolumn.Datatype = [DateTime] + # Add rowcount output + $bulkCopy.Add_SqlRowsCopied( { + $script:totalrows = $args[1].RowsCopied + if (-not $NoProgress) { + $timetaken = [math]::Round($elapsed.Elapsed.TotalSeconds, 2) + Write-ProgressHelper -StepNumber 1 -TotalSteps 2 -Activity "Importing from $file" -Message ([System.String]::Format("Progress: {0} rows in {2} seconds", $script:totalrows, $percent, $timetaken)) -ExcludePercent } - } - # Use a data column expression to facilitate actual conversion - $null = $newcolumn.Expression = "Convert($colname, $netdatatype)" - $null = $bulkCopy.ColumnMappings.Add($newcolumn.ColumnName, $calcolumn.colname) - } - } + }) - # Check to see if file has quote identified data (i.e. "first","second","third") - $quoted = $false - $checkline = Get-Content $file -Last 1 - $checkcolumns = $checkline.Split($InternalDelimiter) - foreach ($checkcolumn in $checkcolumns) { - if ($checkcolumn.StartsWith('"') -and $checkcolumn.EndsWith('"')) { - $quoted = $true + $bulkCopy.WriteToServer($reader) + if ($resultcount -is [int]) { + Write-Progress -id 1 -activity "Inserting $resultcount rows" -status "Complete" -Completed } - } - if ($quoted -eq $true) { - Write-Warning "The CSV file appears to use quoted identifiers. This may take a little longer." - # Thanks for this, Chris! http://www.schiffhauer.com/c-split-csv-values-with-a-regular-expression/ - $pattern = "((?<=`")[^`"]*(?=`"($InternalDelimiter|$)+)|(?<=$InternalDelimiter|^)[^$InternalDelimiter`"]*(?=$InternalDelimiter|$))" - } - if ($turbo -eq $true -and $first -eq 0) { - while ($null -ne ($line = $reader.ReadLine())) { - $i++ - if ($quoted -eq $true) { - $null = $datatable.Rows.Add(($line.TrimStart('"').TrimEnd('"')) -Split "`"$InternalDelimiter`"") - } else { - $row = $datatable.Rows.Add($line.Split($InternalDelimiter)) - } + $reader.Close() + $reader.Dispose() + $completed = $true + } catch { + $completed = $false - if (($i % $batchsize) -eq 0) { - $bulkcopy.WriteToServer($datatable) - Write-Output "[*] $i rows have been inserted in $([math]::Round($elapsed.Elapsed.TotalSeconds, 2)) seconds." - $datatable.Clear() - } + if ($resultcount -is [int]) { + Write-Progress -id 1 -activity "Inserting $resultcount rows" -status "Failed" -Completed } - } else { - if ($turbo -eq $true -and $first -gt 0) { Write-Warning -Message "Using -First makes turbo a little slower." } - # Start import! - while ($null -ne ($line = $reader.ReadLine())) { - $i++ - try { - if ($quoted -eq $true) { - $row = $datatable.Rows.Add(($line.TrimStart('"').TrimEnd('"')) -Split $pattern) - } else { - $row = $datatable.Rows.Add($line.Split($InternalDelimiter)) - } - } catch { - $row = $datatable.NewRow() - try { - $tempcolumn = $line.Split($InternalDelimiter) - $colnum = 0 - foreach ($column in $tempcolumn) { - if ($column.length -ne 0) { - $row.item($colnum) = $column - } else { - $row.item($colnum) = [DBnull]::Value - } - $colnum++ - } - #$newrow replaced with $null as it was identified as a unused variable - $null = $datatable.Rows.Add($row) - } catch { - Write-Warning "The following line ($i) is causing issues:" - Write-Output $line.Replace($InternalDelimiter, "`n") - if ($quoted -eq $true) { - Write-Warning "The import has failed, likely because the quoted data was a little too inconsistent. Try using the -Safe parameter." - } + # If possible, give more information about common errors. + $errormessage = $_.Exception.Message.ToString() + if ($errormessage -like "*for one or more required parameters*") { - Write-Verbose "Column datatypes:" - foreach ($c in $datatable.columns) { - Write-Verbose "$($c.columnname) = $($c.datatype)" - } - Write-Error $_.Exception.Message - break - } - } + Stop-Function -Continue -Message -Message "Looks like your SQL syntax may be invalid. `nCheck the documentation for more information or start with a simple -Query 'select top 10 * from csv'." + Stop-Function -Continue -Message -Message "Valid CSV columns are $columns." - if (($i % $batchsize) -eq 0 -or $i -eq $first) { - $bulkcopy.WriteToServer($datatable) - Write-Output "[*] $i rows have been inserted in $([math]::Round($elapsed.Elapsed.TotalSeconds, 2)) seconds." - $datatable.Clear() - if ($i -eq $first) { - break - } + } elseif ($errormessage -match "invalid column length") { + + # Get more information about malformed CSV input + $pattern = @("\d+") + $match = [regex]::matches($errormessage, @("\d+")) + $index = [int]($match.groups[1].Value) - 1 + $sql = "select name, max_length from sys.columns where object_id = object_id('$table') and column_id = $index" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + $datatable = New-Object System.Data.DataTable + $datatable.load($sqlcmd.ExecuteReader()) + $column = $datatable.name + $length = $datatable.max_length + + if ($safe -eq $true) { + Write-Message -Level Warning -Message "Column $index ($column) contains data with a length greater than $length." + Write-Message -Level Warning -Message "SqlBulkCopy makes it pretty much impossible to know which row caused the issue, but it's somewhere after row $($script:totalrows)." } - } - } - # Add in all the remaining rows since the last clear - if ($datatable.Rows.Count -gt 0) { - $bulkcopy.WriteToServer($datatable) - $datatable.Clear() - } - } else { - # Add rowcount output - $bulkCopy.Add_SqlRowscopied( { - $script:totalrows = $args[1].RowsCopied - if ($resultcount -is [int]) { - $percent = [int](($script:totalrows / $resultcount) * 100) - $timetaken = [math]::Round($elapsed.Elapsed.TotalSeconds, 2) - Write-Progress -id 1 -activity "Inserting $resultcount rows" -percentcomplete $percent -status ([System.String]::Format("Progress: {0} rows ({1}%) in {2} seconds", $script:totalrows, $percent, $timetaken)) + } elseif ($errormessage -match "does not allow DBNull" -or $errormessage -match "The given value of type") { + + if ($tablexists -eq $false) { + Stop-Function -Continue -Message "Looks like the datatype prediction didn't work out. Please create the table manually with proper datatypes then rerun the import script." } else { - Write-Host "$($script:totalrows) rows copied in $([math]::Round($elapsed.Elapsed.TotalSeconds, 2)) seconds." + $sql = "select name from sys.columns where object_id = object_id('$table') order by column_id" + $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) + $datatable = New-Object System.Data.DataTable + $datatable.Load($sqlcmd.ExecuteReader()) + $olecolumns = ($columns | ForEach-Object { + $_ -Replace "\[|\]" + }) -join ', ' + Write-Message -Level Warning -Message "Datatype mismatch." + Write-Message -Level Warning -Message "This is sometimes caused by null handling in SqlBulkCopy, quoted data, or the first row being column names and not data (-FirstRowHeader)." + Write-Message -Level Warning -Message "This could also be because the data types don't match or the order of the columns within the CSV/SQL statement " + Write-Message -Level Warning -Message "do not line up with the order of the table within the SQL Server.`n" + Write-Message -Level Warning -Message "CSV order: $olecolumns`n" + Write-Message -Level Warning -Message "SQL order: $($datatable.rows.name -join ', ')`n" + Write-Message -Level Warning -Message "If this is the case, you can reorder columns by using the -Query parameter or execute the import against a view.`n" + Write-Message -Level Warning -Message "You can also try running this import using the -Safe parameter, which handles quoted text well.`n" + Stop-Function -Continue -Message "`n$errormessage" } - }) - - $bulkCopy.WriteToServer($olecmd.ExecuteReader("SequentialAccess")) - if ($resultcount -is [int]) { - Write-Progress -id 1 -activity "Inserting $resultcount rows" -status "Complete" -Completed + } elseif ($errormessage -match "Input string was not in a correct format" -or $errormessage -match "The given ColumnName") { + Stop-Function -Continue -Message "CSV contents may be malformed. $errormessage" + } else { + Stop-Function -Continue -Message $errormessage + } } - } - $completed = $true - } catch { - # If possible, give more information about common errors. - if ($resultcount -is [int]) { Write-Progress -id 1 -activity "Inserting $resultcount rows" -status "Failed" -Completed } - $errormessage = $_.Exception.Message.ToString() - $completed = $false - if ($errormessage -like "*for one or more required parameters*") { - - Write-Error -Message "Looks like your SQL syntax may be invalid. `nCheck the documentation for more information or start with a simple -Query 'select top 10 * from csv'." - Write-Error -Message "Valid CSV columns are $columns." - - } elseif ($errormessage -match "invalid column length") { + if ($PSCmdlet.ShouldProcess($instance, "Committing transaction")) { + if ($completed) { + # "Note: This count does not take into consideration the number of rows actually inserted when Ignore Duplicates is set to ON." + $null = $transaction.Commit() + $rowscopied = [System.Data.SqlClient.SqlBulkCopyExtension]::RowsCopiedCount($bulkcopy) + Write-Message -Level Verbose -Message "$rowscopied total rows copied" - # Get more information about malformed CSV input - $pattern = @("\d+") - $match = [regex]::matches($errormessage, @("\d+")) - $index = [int]($match.groups[1].Value) - 1 - $sql = "select name, max_length from sys.columns where object_id = object_id('$table') and column_id = $index" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $datatable = New-Object System.Data.DataTable - $datatable.load($sqlcmd.ExecuteReader()) - $column = $datatable.name - $length = $datatable.max_length - - if ($safe -eq $true) { - Write-Warning "Column $index ($column) contains data with a length greater than $length." - Write-Warning "SqlBulkCopy makes it pretty much impossible to know which row caused the issue, but it's somewhere after row $($script:totalrows)." - } - } elseif ($errormessage -match "does not allow DBNull" -or $errormessage -match "The given value of type") { - - if ($tablexists -eq $false) { - Write-Error "Looks like the datatype prediction didn't work out. Please create the table manually with proper datatypes then rerun the import script." - } else { - $sql = "select name from sys.columns where object_id = object_id('$table') order by column_id" - $sqlcmd = New-Object System.Data.SqlClient.SqlCommand($sql, $sqlconn, $transaction) - $datatable = New-Object System.Data.DataTable - $datatable.Load($sqlcmd.ExecuteReader()) - $olecolumns = ($columns | ForEach-Object { $_ -Replace "\[|\]" }) -join ', ' - Write-Warning "Datatype mismatch." - Write-Output "[*] This is sometimes caused by null handling in SqlBulkCopy, quoted data, or the first row being column names and not data (-FirstRowColumns)." - Write-Output "[*] This could also be because the data types don't match or the order of the columns within the CSV/SQL statement " - Write-Output "[*] do not line up with the order of the table within the SQL Server.`n" - Write-Output "[*] CSV order: $olecolumns`n" - Write-Output "[*] SQL order: $($datatable.rows.name -join ', ')`n" - Write-Output "[*] If this is the case, you can reorder columns by using the -Query parameter or execute the import against a view.`n" - if ($safe -eq $false) { - Write-Output "[*] You can also try running this import using the -Safe parameter, which handles quoted text well.`n" + [pscustomobject]@{ + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + Database = $Database + Table = $table + Schema = $schema + RowsCopied = $rowscopied + Elapsed = [prettytimespan]$elapsed.Elapsed + Path = $file } - Write-Error "`n$errormessage" + } else { + Stop-Function -Message "Transaction rolled back. Was the proper delimiter specified? Is the first row the column name?" + return } + } - - } elseif ($errormessage -match "Input string was not in a correct format" -or $errormessage -match "The given ColumnName") { - Write-Warning "CSV contents may be malformed." - Write-Error $errormessage - } else { Write-Error $errormessage } - } - } - - if ($completed -eq $true) { - # "Note: This count does not take into consideration the number of rows actually inserted when Ignore Duplicates is set to ON." - $null = $transaction.Commit() - - if ($safe -eq $false) { - Write-Output "[*] $i total rows copied" - } else { - $total = [System.Data.SqlClient.SqlBulkCopyExtension]::RowsCopiedCount($bulkcopy) - Write-Output "[*] $total total rows copied" + # Close everything just in case & ignore errors + try { + $null = $sqlconn.close(); $null = $sqlconn.Dispose(); + $null = $bulkCopy.close(); $bulkcopy.dispose(); + $null = $reader.close(); $null = $reader.dispose() + } catch { + #here to avoid an empty catch + $null = 1 + } } - } else { - Write-Output "[*] Transaction rolled back." - Write-Output "[*] (Was the proper parameter specified? Is the first row the column name?)." } - - # Script is finished. Show elapsed time. - $totaltime = [math]::Round($elapsed.Elapsed.TotalSeconds, 2) - Write-Output "[*] Total Elapsed Time for bulk insert: $totaltime seconds" } - end { # Close everything just in case & ignore errors try { - if ($oleconn.connection) {$null = $oleconn.close(); $null = $oleconn.dispose()} - if ($olecmd.connection) {$null = $olecmd.close()} - $null = $sqlconn.close(); $null = $sqlconn.Dispose(); $null = $bulkCopy.close(); $bulkcopy.dispose(); $null = $reader.close(); $null = $reader.dispose() @@ -52046,35 +51354,11 @@ function Import-DbaCsvToSql { $null = 1 } - # Delete all the temp files - if ($SqlCredentialPath.length -gt 0) { - if ((Test-Path $SqlCredentialPath) -eq $true) { - $null = cmd /c "del $SqlCredentialPath" - } - } - - if ($shellswitch -eq $false -and $safe -eq $true) { - # Delete new schema files - Write-Verbose "Removing automatically generated schema.ini." - foreach ($file in $csv) { - $directory = Split-Path $file - $null = cmd /c "del $directory\schema.ini" | Out-Null - } - - # If a shell switch occured, delete the temporary module file. - if ((Test-Path "$env:TEMP\Import-DbaCsvToSql.psm1") -eq $true) { - cmd /c "del $env:TEMP\Import-DbaCsvToSql.psm1" | Out-Null - } + # Script is finished. Show elapsed time. + $totaltime = [math]::Round($scriptelapsed.Elapsed.TotalSeconds, 2) + Write-Message -Level Verbose -Message "Total Elapsed Time for everything: $totaltime seconds" - # Move original schema.ini's back if they existed - if ($movedschemainis.count -gt 0) { - foreach ($item in $movedschemainis) { - Write-Verbose "Moving $($item.keys) back to $($item.values)." - $null = cmd /c "move $($item.keys) $($item.values)" - } - } - Write-Output "[*] Finished at $(Get-Date)" - } + Test-DbaDeprecation -DeprecatedOn "1.0.0" -Alias Import-DbaCsvtoSql Test-DbaDeprecation -DeprecatedOn "1.0.0" -EnableException:$false -Alias Import-CsvToSql } } @@ -53453,7 +52737,7 @@ function Install-DbaSqlWatch { Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential) .PARAMETER Database - Specifies the database to install SqlWatch into. Defaults to master. + Specifies the database to install SqlWatch into. Defaults to SQLWATCH. .PARAMETER LocalFile Specifies the path to a local file to install SqlWatch from. This *should* be the zipfile as distributed by the maintainers. @@ -53486,7 +52770,7 @@ function Install-DbaSqlWatch { .EXAMPLE Install-DbaSqlWatch -SqlInstance server1 - Logs into server1 with Windows authentication and then installs SqlWatch in the master database. + Logs into server1 with Windows authentication and then installs SqlWatch in the SQLWATCH database. .EXAMPLE Install-DbaSqlWatch -SqlInstance server1\instance1 -Database DBA @@ -53501,20 +52785,20 @@ function Install-DbaSqlWatch { .EXAMPLE Install-DbaSqlWatch -SqlInstance sql2016\standardrtm, sql2016\sqlexpress, sql2014 - Logs into sql2016\standardrtm, sql2016\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the master database. + Logs into sql2016\standardrtm, sql2016\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the SQLWATCH database. .EXAMPLE $servers = "sql2016\standardrtm", "sql2016\sqlexpress", "sql2014" $servers | Install-DbaSqlWatch - Logs into sql2016\standardrtm, sql2016\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the master database. - #> + Logs into sql2016\standardrtm, sql2016\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the SQLWATCH database. + #> [CmdletBinding(SupportsShouldProcess, ConfirmImpact = "Low")] param ( [Parameter(Mandatory, ValueFromPipeline)] [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$SqlCredential, - [string]$Database = "master", + [string]$Database = "SQLWATCH", [string]$LocalFile, [switch]$Force, [switch]$EnableException @@ -54094,7 +53378,7 @@ function Invoke-DbaAdvancedRestore { .NOTES Tags: Restore, Backup - Author: Chrissy LeMaire (@cl), netnerds.net + Author: Stuart Moore (@napalmgram - http://stuart-moore.com) Website: https://dbatools.io Copyright: (c) 2018 by dbatools, licensed under MIT @@ -54115,7 +53399,7 @@ function Invoke-DbaAdvancedRestore { First generates just the T-SQL restore scripts so they can be sanity checked, and then if they are good perform the full restore. By reusing the BackupHistory object there is no need to rescan all the backup files again - #> + #> [CmdletBinding(SupportsShouldProcess = $true, ConfirmImpact = "Low")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", "AzureCredential", Justification = "For Parameter AzureCredential")] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "", Justification = "PSSA Rule Ignored by BOH")] @@ -54339,14 +53623,14 @@ function Invoke-DbaAdvancedRestore { RestoredFile = $((Split-Path $backup.FileList.PhysicalName -Leaf) | Sort-Object -Unique) -Join ',' RestoredFileFull = ($backup.Filelist.PhysicalName -Join ',') RestoreDirectory = $RestoreDirectory - BackupSize = if ([bool]($backup.psobject.Properties.Name -contains 'TotalSize')) { ($backup | Measure-Object -Property TotalSize -Sum).Sum } else { $null } - CompressedBackupSize = if ([bool]($backup.psobject.Properties.Name -contains 'CompressedBackupSize')) { ($backup | Measure-Object -Property CompressedBackupSize -Sum).Sum } else { $null } + BackupSize = if ([bool]($backup.psobject.Properties.Name -contains 'TotalSize')) { [dbasize](($backup | Measure-Object -Property TotalSize -Sum).Sum) } else { $null } + CompressedBackupSize = if ([bool]($backup.psobject.Properties.Name -contains 'CompressedBackupSize')) { [dbasize](($backup | Measure-Object -Property CompressedBackupSize -Sum).Sum) } else { $null } Script = $script BackupFileRaw = ($backups.Fullname) FileRestoreTime = New-TimeSpan -Seconds ((Get-Date) - $FileRestoreStartTime).TotalSeconds DatabaseRestoreTime = New-TimeSpan -Seconds ((Get-Date) - $DatabaseRestoreStartTime).TotalSeconds ExitError = $ExitError - } | Select-DefaultView -ExcludeProperty BackupSize, CompressedBackupSize, ExitError, BackupFileRaw, RestoredFileFull + } | Select-DefaultView -ExcludeProperty BackupSizeMB, CompressedBackupSizeMB, ExitError, BackupFileRaw, RestoredFileFull } else { $script } @@ -58226,7 +57510,9 @@ function Invoke-DbaDbShrink { Data - Just the Data files are shrunk using file shrink Log - Just the Log files are shrunk using file shrink - .PARAMETER StepSizeMB + .PARAMETER StepSize + Measured in bits - but no worries! PowerShell has a very cool way of formatting bits. Just specify something like: 1MB or 10GB. See the examples for more information. + If specified, this will chunk a larger shrink operation into multiple smaller shrinks. If shrinking a file by a large amount there are benefits of doing multiple smaller chunks. @@ -58273,7 +57559,7 @@ function Invoke-DbaDbShrink { Shrinks AdventureWorks2014 to have 50% free space. So let's say AdventureWorks2014 was 1GB and it's using 100MB space. The database free space would be reduced to 50MB. .EXAMPLE - PS C:\> Invoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50 -FileType Data -StepSizeMB 25 + PS C:\> Invoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50 -FileType Data -StepSize 25MB Shrinks AdventureWorks2014 to have 50% free space, runs shrinks in 25MB chunks for improved performance. @@ -58300,7 +57586,7 @@ function Invoke-DbaDbShrink { [string]$ShrinkMethod = "Default", [ValidateSet('All', 'Data', 'Log')] [string]$FileType = "All", - [int]$StepSizeMB, + [int]$StepSize, [int]$StatementTimeout = 0, [switch]$LogsOnly, [switch]$ExcludeIndexStats, @@ -58314,13 +57600,19 @@ function Invoke-DbaDbShrink { Test-DbaDeprecation -DeprecatedOn "1.0.0" -Parameter "LogsOnly" $FileType = 'Log' } - if (!$Database -and !$ExcludeDatabase -and !$AllUserDatabases) { + if (-not $Database -and -not $ExcludeDatabase -and -not $AllUserDatabases) { Stop-Function -Message "You must specify databases to execute against using either -Database, -Exclude or -AllUserDatabases" return } - $StepSizeKB = ($stepSizeMB * 1024) + if ((Test-Bound -ParameterName StepSize) -and $stepsize -lt 1024) { + Stop-Function -Message "StepSize is measured in bits. Did you mean $StepSize bits? If so, please use 1024 or above. If not, then use the PowerShell bit notation like $($StepSize)MB or $($StepSize)GB" + return + } + if ($stepsize) { + $StepSizeKB = ([dbasize]($StepSize)).Kilobyte + } $StatementTimeoutSeconds = $StatementTimeout * 60 $sql = "SELECT @@ -58379,11 +57671,11 @@ function Invoke-DbaDbShrink { $desiredFileSize = $spaceUsed + $desiredSpaceAvailable Write-Message -Level Verbose -Message "File: $($file.Name)" - Write-Message -Level Verbose -Message "Starting Size (KB): $([int]$startingSize)" + Write-Message -Level Verbose -Message "Initial Size (KB): $([int]$startingSize)" Write-Message -Level Verbose -Message "Space Used (KB): $([int]$spaceUsed)" - Write-Message -Level Verbose -Message "Starting Freespace (KB): $([int]$spaceAvailable)" - Write-Message -Level Verbose -Message "Desired Freespace (KB): $([int]$desiredSpaceAvailable)" - Write-Message -Level Verbose -Message "Desired FileSize (KB): $([int]$desiredFileSize)" + Write-Message -Level Verbose -Message "Initial Freespace (KB): $([int]$spaceAvailable)" + Write-Message -Level Verbose -Message "Target Freespace (KB): $([int]$desiredSpaceAvailable)" + Write-Message -Level Verbose -Message "Target FileSize (KB): $([int]$desiredFileSize)" if ($spaceAvailable -le $desiredSpaceAvailable) { Write-Message -Level Warning -Message "File size of ($startingSize) is less than or equal to the desired outcome ($desiredFileSize) for $($file.Name)" @@ -58404,12 +57696,12 @@ function Invoke-DbaDbShrink { $shrinkGap = ($startingSize - $desiredFileSize) Write-Message -Level Verbose -Message "ShrinkGap: $([int]$shrinkGap) KB" - Write-Message -Level Verbose -Message "Step Size: $([int]$StepSizeMB) MB" + Write-Message -Level Verbose -Message "Step Size: $(([dbasize]$StepSize).Megabyte) MB" if ($StepSizeKB -and ($shrinkGap -gt $stepSizeKB)) { for ($i = 1; $i -le [int](($shrinkGap) / $stepSizeKB); $i++) { Write-Message -Level Verbose -Message "Step: $i" - $shrinkSize = $startingSize - (($stepSizeMB * 1024) * $i) + $shrinkSize = $startingSize - (($StepSizeKB * 1024 * 1024) * $i) if ($shrinkSize -lt $desiredFileSize) { $shrinkSize = $desiredFileSize } @@ -58427,10 +57719,9 @@ function Invoke-DbaDbShrink { $file.Refresh() } $success = $true - $notes = "Database shrinks can cause massive index fragmentation and negatively impact performance. You should now run DBCC INDEXDEFRAG or ALTER INDEX ... REORGANIZE" } catch { $success = $false - Stop-Function -message "Shrink Failed: $($_.Exception.InnerException)" -EnableException $EnableException -ErrorRecord $_ -Continue + Stop-Function -message "Failure" -EnableException $EnableException -ErrorRecord $_ -Continue continue } $end = Get-Date @@ -58453,29 +57744,29 @@ function Invoke-DbaDbShrink { $elapsed = "{0:HH:mm:ss}" -f ([datetime]$ts.Ticks) $object = [PSCustomObject]@{ - ComputerName = $server.ComputerName - InstanceName = $server.ServiceName - SqlInstance = $server.DomainInstanceName - Database = $db.name - File = $file.name - Start = $start - End = $end - Elapsed = $elapsed - Success = $success - StartingTotalSize = [dbasize]($startingSize * 1024) - StartingUsed = [dbasize]($spaceUsed * 1024) - FinalTotalSize = [dbasize]($finalFileSize * 1024) - StartingAvailable = [dbasize]($spaceAvailable * 1024) - DesiredAvailable = [dbasize]($desiredSpaceAvailable * 1024) - FinalAvailable = [dbasize]($finalSpaceAvailable * 1024) - StartingAvgIndexFragmentation = [math]::Round($startingFrag, 1) - EndingAvgIndexFragmentation = [math]::Round($endingDefrag, 1) - StartingTopIndexFragmentation = [math]::Round($startingTopFrag, 1) - EndingTopIndexFragmentation = [math]::Round($endingTopDefrag, 1) - Notes = $notes + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + Database = $db.name + File = $file.name + Start = $start + End = $end + Elapsed = $elapsed + Success = $success + InitialSize = [dbasize]($startingSize * 1024) + InitialUsed = [dbasize]($spaceUsed * 1024) + InitialAvailable = [dbasize]($spaceAvailable * 1024) + TargetAvailable = [dbasize]($desiredSpaceAvailable * 1024) + FinalAvailable = [dbasize]($finalSpaceAvailable * 1024) + FinalSize = [dbasize]($finalFileSize * 1024) + InitialAverageFragmentation = [math]::Round($startingFrag, 1) + FinalAverageFragmentation = [math]::Round($endingDefrag, 1) + InitialTopFragmentation = [math]::Round($startingTopFrag, 1) + FinalTopFragmentation = [math]::Round($endingTopDefrag, 1) + Notes = "Database shrinks can cause massive index fragmentation and negatively impact performance. You should now run DBCC INDEXDEFRAG or ALTER INDEX ... REORGANIZE" } if ($ExcludeIndexStats) { - Select-DefaultView -InputObject $object -ExcludeProperty StartingAvgIndexFragmentation, EndingAvgIndexFragmentation, StartingTopIndexFragmentation, EndingTopIndexFragmentation + Select-DefaultView -InputObject $object -ExcludeProperty InitialAverageFragmentation, FinalAverageFragmentation, InitialTopFragmentation, FinalTopFragmentation } else { $object } @@ -59027,9 +58318,9 @@ function Invoke-DbaDiagnosticQuery { if (!$instanceOnly) { if (-not $Database) { - $databases = (Get-DbaDatabase -SqlInstance $server -ExcludeAllSystemDb -ExcludeDatabase $ExcludeDatabase).Name + $databases = (Get-DbaDatabase -SqlInstance $server -ExcludeSystem -ExcludeDatabase $ExcludeDatabase).Name } else { - $databases = (Get-DbaDatabase -SqlInstance $server -ExcludeAllSystemDb -Database $Database -ExcludeDatabase $ExcludeDatabase).Name + $databases = (Get-DbaDatabase -SqlInstance $server -ExcludeSystem -Database $Database -ExcludeDatabase $ExcludeDatabase).Name } } @@ -60129,7 +59420,7 @@ function Invoke-DbatoolsRenameHelper { Shows what would happen if the command would run. If the command would run and there were matches, the resulting changes would be written to disk as Ascii encoded. - #> + #> [CmdletBinding(SupportsShouldProcess = $true)] param ( [parameter(Mandatory, ValueFromPipeline)] @@ -60147,11 +59438,66 @@ function Invoke-DbatoolsRenameHelper { @{ "AliasName" = "UseLastBackups" "Definition" = "UseLastBackup" - } - , + }, @{ "AliasName" = "NetworkShare" "Definition" = "SharedPath" + }, + @{ + "AliasName" = "NoSystemLogins" + "Definition" = "ExcludeSystemLogins" + }, + @{ + "AliasName" = "NoJobSteps" + "Definition" = "ExcludeJobSteps" + }, + @{ + "AliasName" = "NoSystemObjects" + "Definition" = "ExcludeSystemObjects" + }, + @{ + "AliasName" = "NoJobs" + "Definition" = "ExcludeJobs" + }, + @{ + "AliasName" = "NoDatabases" + "Definition" = "ExcludeDatabases" + }, + @{ + "AliasName" = "NoDisabledJobs" + "Definition" = "ExcludeDisabledJobs" + }, + @{ + "AliasName" = "NoJobSteps" + "Definition" = "ExcludeJobSteps" + }, + @{ + "AliasName" = "NoSystem" + "Definition" = "ExcludeSystemLogins" + }, + @{ + "AliasName" = "NoSystemDb" + "Definition" = "ExcludeSystem" + }, + @{ + "AliasName" = "NoSystemObjects" + "Definition" = "ExcludeSystemObjects" + }, + @{ + "AliasName" = "NoSystemSpid" + "Definition" = "ExcludeSystemSpids" + }, + @{ + "AliasName" = "NoQueryTextColumn" + "Definition" = "ExcludeQueryTextColumn" + }, + @{ + "AliasName" = "ExcludeAllSystemDb" + "Definition" = "ExcludeSystem" + }, + @{ + "AliasName" = "ExcludeAllUserDb" + "Definition" = "ExcludeUser" } ) @@ -60164,7 +59510,8 @@ function Invoke-DbatoolsRenameHelper { foreach ($name in $allrenames) { if ((Select-String -Pattern $name.AliasName -Path $file)) { if ($Pscmdlet.ShouldProcess($file, "Replacing $($name.AliasName) with $($name.Definition)")) { - (Get-Content -Path $file -Raw).Replace($name.AliasName, $name.Definition) | Set-Content -Path $file -Encoding $Encoding + $content = (Get-Content -Path $file -Raw).Replace($name.AliasName, $name.Definition).Trim() + Set-Content -Path $file -Encoding $Encoding -Value $content [pscustomobject]@{ Path = $file Pattern = $name.AliasName @@ -61092,11 +60439,11 @@ function Measure-DbaBackupThroughput { Output looks like this: SqlInstance : sql2016 Database : SharePoint_Config - AvgThroughputMB : 1.07 - AvgSizeMB : 24.17 + AvgThroughput : 1.07 MB + AvgSize : 24.17 AvgDuration : 00:00:01.1000000 - MinThroughputMB : 0.02 - MaxThroughputMB : 2.26 + MinThroughput : 0.02 MB + MaxThroughput : 2.26 MB MinBackupDate : 8/6/2015 10:22:01 PM MaxBackupDate : 6/19/2016 12:57:45 PM BackupCount : 10 @@ -61162,9 +60509,9 @@ function Measure-DbaBackupThroughput { Processes the last log backups every backup for all databases on sql2005. .EXAMPLE - PS C:\> Measure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-7) + PS C:\> Measure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-7) | Where-Object { $_.MinThroughput.Gigabyte -gt 1 } - Gets backup calculations for the last week. + Gets backup calculations for the last week and filters results that have a minimum of 1GB throughput .EXAMPLE PS C:\> Measure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-365) -Database bigoldb @@ -61244,18 +60591,18 @@ function Measure-DbaBackupThroughput { $avgduration = $db.Group | ForEach-Object { New-TimeSpan -Start $_.Start -End $_.End } | Measure-Object -Average TotalSeconds [pscustomobject]@{ - ComputerName = $db.Group.ComputerName | Select-Object -First 1 - InstanceName = $db.Group.InstanceName | Select-Object -First 1 - SqlInstance = $db.Group.SqlInstance | Select-Object -First 1 - Database = $db.Name - AvgThroughputMB = [System.Math]::Round($measuremb.Average, 2) - AvgSizeMB = [System.Math]::Round($measuresize.Average, 2) - AvgDuration = [dbatimespan](New-TimeSpan -Seconds $avgduration.Average) - MinThroughputMB = [System.Math]::Round($measuremb.Minimum, 2) - MaxThroughputMB = [System.Math]::Round($measuremb.Maximum, 2) - MinBackupDate = [dbadatetime]$measurestart.Minimum - MaxBackupDate = [dbadatetime]$measureend.Maximum - BackupCount = $db.Count + ComputerName = $db.Group.ComputerName | Select-Object -First 1 + InstanceName = $db.Group.InstanceName | Select-Object -First 1 + SqlInstance = $db.Group.SqlInstance | Select-Object -First 1 + Database = $db.Name + AvgThroughput = [dbasize]([System.Math]::Round($measuremb.Average, 2) * 1024 * 1024) + AvgSize = [dbasize]([System.Math]::Round($measuresize.Average, 2) * 1024 * 1024) + AvgDuration = [dbatimespan](New-TimeSpan -Seconds $avgduration.Average) + MinThroughput = [dbasize]([System.Math]::Round($measuremb.Minimum, 2) * 1024 * 1024) + MaxThroughput = [dbasize]([System.Math]::Round($measuremb.Maximum, 2) * 1024 * 1024) + MinBackupDate = [dbadatetime]$measurestart.Minimum + MaxBackupDate = [dbadatetime]$measureend.Maximum + BackupCount = $db.Count } | Select-DefaultView -ExcludeProperty ComputerName, InstanceName } } @@ -64770,7 +64117,7 @@ function New-DbaComputerCertificate { .PARAMETER ClusterInstanceName When creating certs for a cluster, use this parameter to create the certificate for the cluster node name. Use ComputerName for each of the nodes. - .PARAMETER Password + .PARAMETER SecurePassword Password to encrypt/decrypt private key for export to remote machine .PARAMETER FriendlyName @@ -64853,7 +64200,8 @@ function New-DbaComputerCertificate { [string]$CaServer, [string]$CaName, [string]$ClusterInstanceName, - [securestring]$Password, + [Alias("Password")] + [securestring]$SecurePassword, [string]$FriendlyName = "SQL Server", [string]$CertificateTemplate = "WebServer", [int]$KeyLength = 1024, @@ -65079,7 +64427,7 @@ function New-DbaComputerCertificate { if (!$secondaryNode) { if ($PScmdlet.ShouldProcess("local", "Generating pfx and reading from disk")) { Write-Message -Level Output -Message "Exporting PFX with password to $tempPfx" - $certdata = $storedCert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::PFX, $password) + $certdata = $storedCert.Export([System.Security.Cryptography.X509Certificates.X509ContentType]::PFX, $SecurePassword) } if ($PScmdlet.ShouldProcess("local", "Removing cert from disk but keeping it in memory")) { @@ -65102,7 +64450,7 @@ function New-DbaComputerCertificate { if ($PScmdlet.ShouldProcess("local", "Connecting to $computer to import new cert")) { try { - Invoke-Command2 -ComputerName $computer -Credential $Credential -ArgumentList $certdata, $Password, $Store, $Folder -ScriptBlock $scriptblock -ErrorAction Stop | + Invoke-Command2 -ComputerName $computer -Credential $Credential -ArgumentList $certdata, $SecurePassword, $Store, $Folder -ScriptBlock $scriptblock -ErrorAction Stop | Select-DefaultView -Property DnsNameList, Thumbprint, NotBefore, NotAfter, Subject, Issuer } catch { Stop-Function -Message "Issue importing new cert on $computer" -ErrorRecord $_ -Target $computer -Continue @@ -65544,7 +64892,7 @@ function New-DbaCredential { .PARAMETER Identity The Credential Identity - .PARAMETER Password + .PARAMETER SecurePassword Secure string used to authenticate the Credential Identity .PARAMETER MappedClassType @@ -65586,14 +64934,14 @@ function New-DbaCredential { Suppresses all prompts to install but prompts to securely enter your password and creates a credential on Server1. .EXAMPLE - PS C:\> New-DbaCredential -SqlInstance Server1 -Name AzureBackupBlobStore -Identity '' -Password (ConvertTo-SecureString '' -AsPlainText -Force) + PS C:\> New-DbaCredential -SqlInstance Server1 -Name AzureBackupBlobStore -Identity '' -SecurePassword (ConvertTo-SecureString '' -AsPlainText -Force) Create credential on SQL Server 2012 CU2, SQL Server 2014 for use with BACKUP TO URL. CredentialIdentity needs to be supplied with the Azure Storage Account Name. Password needs to be one of the Access Keys for the account. .EXAMPLE - PS C:\> New-DbaCredential -SqlInstance Server1 -Name 'https://.blob.core.windows.net/' -Identity 'SHARED ACCESS SIGNATURE' -Password (ConvertTo-SecureString '' -AsPlainText -Force) + PS C:\> New-DbaCredential -SqlInstance Server1 -Name 'https://.blob.core.windows.net/' -Identity 'SHARED ACCESS SIGNATURE' -SecurePassword (ConvertTo-SecureString '' -AsPlainText -Force) Create Credential on SQL Server 2016 or higher for use with BACKUP TO URL. Name has to be the full URL for the blob store container that will be the backup target. @@ -65610,12 +64958,12 @@ function New-DbaCredential { [parameter(Mandatory)] [Alias("CredentialIdentity")] [string[]]$Identity, - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [ValidateSet('CryptographicProvider', 'None')] [string]$MappedClassType = "None", [string]$ProviderName, [switch]$Force, - [Alias('Silent')] [switch]$EnableException ) @@ -65627,7 +64975,7 @@ function New-DbaCredential { } process { - if (!$Password) { + if (!$SecurePassword) { Read-Host -AsSecureString -Prompt "Enter the credential password" } @@ -65656,7 +65004,7 @@ function New-DbaCredential { $credential = New-Object Microsoft.SqlServer.Management.Smo.Credential -ArgumentList $server, $name $credential.MappedClassType = $mappedclass $credential.ProviderName = $ProviderName - $credential.Create($Identity, $Password) + $credential.Create($Identity, $SecurePassword) Add-Member -Force -InputObject $credential -MemberType NoteProperty -Name ComputerName -value $server.ComputerName Add-Member -Force -InputObject $credential -MemberType NoteProperty -Name InstanceName -value $server.ServiceName @@ -66371,7 +65719,7 @@ function New-DbaDbCertificate { .PARAMETER ActiveForServiceBrokerDialog Optional secure string used to create the certificate. - .PARAMETER Password + .PARAMETER SecurePassword Optional password - if no password is supplied, the password will be protected by the master key .PARAMETER InputObject @@ -66417,7 +65765,8 @@ function New-DbaDbCertificate { [datetime]$StartDate = (Get-Date), [datetime]$ExpirationDate = $StartDate.AddYears(5), [switch]$ActiveForServiceBrokerDialog, - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [parameter(ValueFromPipeline)] [Microsoft.SqlServer.Management.Smo.Database[]]$InputObject, [switch]$EnableException @@ -66458,8 +65807,8 @@ function New-DbaDbCertificate { $smocert.ExpirationDate = $ExpirationDate $smocert.ActiveForServiceBrokerDialog = $ActiveForServiceBrokerDialog - if ($Password) { - $smocert.Create(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password)))) + if ($SecurePassword) { + $smocert.Create(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword)))) } else { $smocert.Create() } @@ -66501,7 +65850,7 @@ function New-DbaDbMasterKey { .PARAMETER Database The database where the master key will be created. Defaults to master. - .PARAMETER Password + .PARAMETER SecurePassword Secure string used to create the key. .PARAMETER InputObject @@ -66549,17 +65898,18 @@ function New-DbaDbMasterKey { [PSCredential]$SqlCredential, [PSCredential]$Credential, [string[]]$Database = "master", - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [parameter(ValueFromPipeline)] [Microsoft.SqlServer.Management.Smo.Database[]]$InputObject, [switch]$EnableException ) begin { if ($Credential) { - $Password = $Credential.Password + $SecurePassword = $Credential.Password } else { - if (-not $Password) { - $Password = Read-Host "Password" -AsSecureString + if (-not $SecurePassword) { + $SecurePassword = Read-Host "Password" -AsSecureString } } } @@ -66576,7 +65926,7 @@ function New-DbaDbMasterKey { if ($Pscmdlet.ShouldProcess($db.Parent.Name, "Creating master key for database '$($db.Name)'")) { try { $masterkey = New-Object Microsoft.SqlServer.Management.Smo.MasterKey $db - $masterkey.Create(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password)))) + $masterkey.Create(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword)))) Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name ComputerName -value $db.Parent.ComputerName Add-Member -Force -InputObject $masterkey -MemberType NoteProperty -Name InstanceName -value $db.Parent.ServiceName @@ -67475,7 +66825,7 @@ function New-DbaLogin { .PARAMETER Login The Login name(s) - .PARAMETER Password + .PARAMETER SecurePassword Secure string used to authenticate the Login .PARAMETER HashedPassword @@ -67591,7 +66941,8 @@ function New-DbaLogin { [Alias("Rename")] [hashtable]$LoginRenameHashtable, [parameter(ParameterSetName = "Password", Position = 3)] - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [Alias("Hash", "PasswordHash")] [parameter(ParameterSetName = "PasswordHash")] [string]$HashedPassword, @@ -67682,7 +67033,7 @@ function New-DbaLogin { $currentDisabled = $loginItem.IsDisabled #Get previous password - if ($loginType -eq 'SqlLogin' -and !($Password -or $HashedPassword)) { + if ($loginType -eq 'SqlLogin' -and !($SecurePassword -or $HashedPassword)) { $sourceServer = $loginItem.Parent switch ($sourceServer.versionMajor) { 0 { $sql = "SELECT CONVERT(VARBINARY(256),password) as hashedpass FROM master.dbo.syslogins WHERE loginname='$loginName'" } @@ -67770,8 +67121,8 @@ function New-DbaLogin { } #Requesting password if required - if ($loginItem.GetType().Name -ne 'Login' -and $loginType -eq 'SqlLogin' -and !($Password -or $HashedPassword)) { - $Password = Read-Host -AsSecureString -Prompt "Enter a new password for the SQL Server login(s)" + if ($loginItem.GetType().Name -ne 'Login' -and $loginType -eq 'SqlLogin' -and !($SecurePassword -or $HashedPassword)) { + $SecurePassword = Read-Host -AsSecureString -Prompt "Enter a new password for the SQL Server login(s)" } #verify if login exists on the server @@ -67835,8 +67186,8 @@ function New-DbaLogin { } #Generate hashed password if necessary - if ($Password) { - $currentHashedPassword = Get-PasswordHash $Password $server.versionMajor + if ($SecurePassword) { + $currentHashedPassword = Get-PasswordHash $SecurePassword $server.versionMajor } elseif ($HashedPassword) { $currentHashedPassword = $HashedPassword } @@ -67964,7 +67315,7 @@ function New-DbaServiceMasterKey { .PARAMETER SqlCredential Allows you to login to SQL Server using alternative credentials. - .PARAMETER Password + .PARAMETER SecurePassword Secure string used to create the key. .PARAMETER Credential @@ -68001,18 +67352,20 @@ function New-DbaServiceMasterKey { [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$SqlCredential, [PSCredential]$Credential, - [Security.SecureString]$Password, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [switch]$EnableException ) process { foreach ($instance in $SqlInstance) { if ($PSCmdlet.ShouldProcess("$instance", "Creating New MasterKey")) { - New-DbaDbMasterKey -SqlInstance $instance -Database master -Password $password -Credential $Credential + New-DbaDbMasterKey -SqlInstance $instance -Database master -SecurePassword $SecurePassword -Credential $Credential } } } } +#ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle# function New-DbaSsisCatalog { <# .SYNOPSIS @@ -68027,9 +67380,12 @@ function New-DbaSsisCatalog { .PARAMETER SqlCredential Credentials used to connect to the SQL Server - .PARAMETER Password + .PARAMETER SecurePassword Required password that will be used for the security key in SSISDB. + .PARAMETER Credential + Use a credential object instead of a securepassword + .PARAMETER SsisCatalog SSIS catalog name. By default, this is SSISDB. @@ -68056,32 +67412,41 @@ function New-DbaSsisCatalog { https://dbatools.io/New-DbaSsisCatalog .EXAMPLE - PS C:\> $password = ConvertTo-SecureString MyVisiblePassWord -AsPlainText -Force - PS C:\> New-DbaSsisCatalog -SqlInstance sql2016 -Password $password + PS C:\> $SecurePassword = Read-Host -AsSecureString -Prompt "Enter password" + PS C:\> New-DbaSsisCatalog -SqlInstance DEV01 -SecurePassword $SecurePassword Creates the SSIS Catalog on server DEV01 with the specified password. .EXAMPLE - PS C:\> $password = Read-Host -AsSecureString -Prompt "Enter password" - PS C:\> New-DbaSsisCatalog -SqlInstance DEV01 -Password $password - - Creates the SSIS Catalog on server DEV01 with the specified password. + PS C:\> New-DbaSsisCatalog -SqlInstance sql2016 -Credential usernamedoesntmatter + Creates the SSIS Catalog on server DEV01 with the specified password in the credential prompt. As the example username suggets the username does not matter. + This is simply an easier way to get a secure password. #> - [CmdletBinding(SupportsShouldProcess = $true)] + [CmdletBinding(SupportsShouldProcess)] param ( [parameter(Mandatory, ValueFromPipeline)] - [Alias("ServerInstance", "SqlServer")] [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$SqlCredential, - [parameter(Mandatory)] - [Security.SecureString]$Password, + [PSCredential]$Credential, + [Alias("Password")] + [Security.SecureString]$SecurePassword, [string]$SsisCatalog = "SSISDB", - [Alias('Silent')] [switch]$EnableException ) - + begin { + if (-not $SecurePassword -and -not $Credential) { + Stop-Function -Message "You must specify either -SecurePassword or -Credential" + return + } + if (-not $SecurePassword -and $Credential) { + $SecurePassword = $Credential.Password + } + } process { + if (Test-FunctionInterrupt) { + return + } foreach ($instance in $SqlInstance) { try { $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $SqlCredential -MinimumVersion 10 @@ -68092,16 +67457,18 @@ function New-DbaSsisCatalog { ## check if SSIS and Engine running on box $services = Get-DbaService -ComputerName $server.ComputerName - $ssisservice = $Services | Where-Object { $_.ServiceType -eq "SSIS" -and $_.State -eq "Running" } + $ssisservice = $Services | Where-Object { + $_.ServiceType -eq "SSIS" -and $_.State -eq "Running" + } if (-not $ssisservice) { Stop-Function -Message "SSIS is not running on $instance" -Continue -Target $instance } #if SQL 2012 or higher only validate databases with ContainmentType = NONE - $clrenabled = Get-DbaSpConfigure -SqlInstance $server -Config IsSqlClrEnabled + $clrenabled = Get-DbaSpConfigure -SqlInstance $server -Name IsSqlClrEnabled - if (!$clrenabled.RunningValue) { + if (-not $clrenabled.RunningValue) { Stop-Function -Message 'CLR Integration must be enabled. You can enable it by running Set-DbaSpConfigure -SqlInstance sql2012 -Config IsSqlClrEnabled -Value $true' -Continue -Target $instance } @@ -68112,14 +67479,17 @@ function New-DbaSsisCatalog { return } - if ($ssis.Catalogs[$SsisCatalog]) { - Stop-Function -Message "SSIS Catalog already exists" -Continue -Target $ssis.Catalogs[$SsisCatalog] + if ($ssis.Catalogs.Count -gt 0) { + Stop-Function -Message "SSIS Catalog already exists" -Continue -Target $ssis.Catalogs } else { if ($Pscmdlet.ShouldProcess($server, "Creating SSIS catalog: $SsisCatalog")) { try { - $ssisdb = New-Object Microsoft.SqlServer.Management.IntegrationServices.Catalog ($ssis, $SsisCatalog, $(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($password))))) + $ssisdb = New-Object Microsoft.SqlServer.Management.IntegrationServices.Catalog ($ssis, $SsisCatalog, $(([System.Runtime.InteropServices.marshal]::PtrToStringAuto([System.Runtime.InteropServices.marshal]::SecureStringToBSTR($SecurePassword))))) + } catch { + Stop-Function -Message "Failed to create SSIS Catalog: $_" -Target $_ -Continue + } + try { $ssisdb.Create() - [pscustomobject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName @@ -68128,7 +67498,11 @@ function New-DbaSsisCatalog { Created = $true } } catch { - Stop-Function -Message "Failed to create SSIS Catalog: $_" -Target $_ -Continue + $msg = $_.Exception.InnerException.InnerException.Message + if (-not $msg) { + $msg = $_ + } + Stop-Function -Message "$msg" -Target $_ -Continue } } } @@ -69622,9 +68996,9 @@ function Read-DbaBackupHeader { Also returns detailed information about each of the datafiles contained in the backupset. .EXAMPLE - PS C:\> "C:\temp\myfile.bak", "\backupserver\backups\myotherfile.bak" | Read-DbaBackupHeader -SqlInstance sql2016 + PS C:\> "C:\temp\myfile.bak", "\backupserver\backups\myotherfile.bak" | Read-DbaBackupHeader -SqlInstance sql2016 | Where-Object { $_.BackupSize.Megabyte -gt 100 } - Similar to running Read-DbaBackupHeader -SqlInstance sql2016 -Path "C:\temp\myfile.bak", "\backupserver\backups\myotherfile.bak" + Reads the two files and returns only backups larger than 100 MB .EXAMPLE PS C:\> Get-ChildItem \\nas\sql\*.bak | Read-DbaBackupHeader -SqlInstance sql2016 @@ -69636,7 +69010,7 @@ function Read-DbaBackupHeader { Gets the backup header information from the SQL Server backup file stored at https://dbatoolsaz.blob.core.windows.net/azbackups/restoretime/restoretime_201705131850.bak on Azure - #> + #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSAvoidUsingPlainTextForPassword", 'AzureCredential', Justification = "For Parameter AzureCredential")] [CmdletBinding()] param ( @@ -69685,31 +69059,27 @@ function Read-DbaBackupHeader { $device = New-Object Microsoft.SqlServer.Management.Smo.BackupDeviceItem $Path, $DeviceType $restore.Devices.Add($device) $dataTable = $restore.ReadBackupHeader($server) - $null = $dataTable.Columns.Add("FileList", [object]) - - $mb = $dataTable.Columns.Add("BackupSizeMB", [int]) - $mb.Expression = "BackupSize / 1024 / 1024" - $gb = $dataTable.Columns.Add("BackupSizeGB") - $gb.Expression = "BackupSizeMB / 1024" - - if ($null -eq $dataTable.Columns['CompressedBackupSize']) { - $formula = "0" - } else { - $formula = "CompressedBackupSize / 1024 / 1024" - } - - $cmb = $dataTable.Columns.Add("CompressedBackupSizeMB", [int]) - $cmb.Expression = $formula - $cgb = $dataTable.Columns.Add("CompressedBackupSizeGB") - $cgb.Expression = "CompressedBackupSizeMB / 1024" - $null = $dataTable.Columns.Add("SqlVersion") - $null = $dataTable.Columns.Add("BackupPath") foreach ($row in $dataTable) { $row.BackupPath = $Path + + $backupsize = $row.BackupSize + $null = $dataTable.Columns.Remove("BackupSize") + $null = $dataTable.Columns.Add("BackupSize", [dbasize]) + if ($backupsize -isnot [dbnull]) { + $row.BackupSize = [dbasize]$backupsize + } + + $cbackupsize = $row.CompressedBackupSize + $null = $dataTable.Columns.Remove("CompressedBackupSize") + $null = $dataTable.Columns.Add("CompressedBackupSize", [dbasize]) + if ($cbackupsize -isnot [dbnull]) { + $row.CompressedBackupSize = [dbasize]$cbackupsize + } + $restore.FileNumber = $row.Position <# Select-Object does a quick and dirty conversion from datatable to PS object #> $row.FileList = $restore.ReadFileList($server) | Select-Object * @@ -69815,7 +69185,7 @@ function Read-DbaBackupHeader { } } if ($Simple) { - $dataTable | Select-Object DatabaseName, BackupFinishDate, RecoveryModel, BackupSizeMB, CompressedBackupSizeMB, DatabaseCreationDate, UserName, ServerName, SqlVersion, BackupPath + $dataTable | Select-Object DatabaseName, BackupFinishDate, RecoveryModel, BackupSize, CompressedBackupSize, DatabaseCreationDate, UserName, ServerName, SqlVersion, BackupPath } elseif ($FileList) { $dataTable.filelist } else { @@ -72289,12 +71659,12 @@ function Remove-DbaDatabase { Does not prompt and swiftly removes containeddb on SQL Server sql2016 .EXAMPLE - PS C:\> Get-DbaDatabase -SqlInstance server\instance -ExcludeAllSystemDb | Remove-DbaDatabase + PS C:\> Get-DbaDatabase -SqlInstance server\instance -ExcludeSystem | Remove-DbaDatabase Removes all the user databases from server\instance .EXAMPLE - PS C:\> Get-DbaDatabase -SqlInstance server\instance -ExcludeAllSystemDb | Remove-DbaDatabase -Confirm:$false + PS C:\> Get-DbaDatabase -SqlInstance server\instance -ExcludeSystem | Remove-DbaDatabase -Confirm:$false Removes all the user databases from server\instance without any confirmation #> @@ -74511,14 +73881,12 @@ function Remove-DbaOrphanUser { } else { Write-Message -Level Verbose -Message "Validating users on database $db." - if ($User.Count -eq 0) { - #the third validation will remove from list sql users without login. The rule here is Sid with length higher than 16 - $User = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and (($_.Sid.Length -gt 16 -and $_.LoginType -eq [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin) -eq $false) } + if ($User.Count -ge 1) { + #the third validation will remove from list sql users without login or mapped to certificate. The rule here is Sid with length higher than 16 + $User = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and (($_.Sid.Length -gt 16 -and $_.LoginType -in @([Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin, [Microsoft.SqlServer.Management.Smo.LoginType]::Certificate)) -eq $false) } } else { - - #the fourth validation will remove from list sql users without login. The rule here is Sid with length higher than 16 - $User = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($User -contains $_.Name) -and (($_.Sid.Length -gt 16 -and $_.LoginType -eq [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin) -eq $false) } - + #the fourth validation will remove from list sql users without login or mapped to certificate. The rule here is Sid with length higher than 16 + $User = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($User -contains $_.Name) -and (($_.Sid.Length -gt 16 -and $_.LoginType -in @([Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin, [Microsoft.SqlServer.Management.Smo.LoginType]::Certificate)) -eq $false) } } } @@ -76684,12 +76052,10 @@ function Repair-DbaOrphanUser { if ($Users.Count -eq 0) { #the third validation will remove from list sql users without login. The rule here is Sid with length higher than 16 - $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($_.Sid.Length -gt 16 -and $_.LoginType -eq [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin) -eq $false } + $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and (($_.Sid.Length -gt 16 -and $_.LoginType -in @([Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin, [Microsoft.SqlServer.Management.Smo.LoginType]::Certificate)) -eq $false) } } else { - #the fourth validation will remove from list sql users without login. The rule here is Sid with length higher than 16 - $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($Users -contains $_.Name) -and (($_.Sid.Length -gt 16 -and $_.LoginType -eq [Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin) -eq $false) } - + $UsersToWork = $db.Users | Where-Object { $_.Login -eq "" -and ($_.ID -gt 4) -and ($Users -contains $_.Name) -and (($_.Sid.Length -gt 16 -and $_.LoginType -in @([Microsoft.SqlServer.Management.Smo.LoginType]::SqlLogin, [Microsoft.SqlServer.Management.Smo.LoginType]::Certificate)) -eq $false) } } if ($UsersToWork.Count -gt 0) { @@ -77056,6 +76422,9 @@ function Reset-DbaAdmin { .PARAMETER SqlInstance The target SQL Server instance or instances. SQL Server must be 2005 and above, and can be a clustered or stand-alone instance. + .PARAMETER SqlCredential + Instead of using Login and SecurePassword, you can just pass in a credential object. + .PARAMETER Login By default, the Login parameter is "sa" but any other SQL or Windows account can be specified. If a login does not currently exist, it will be added. @@ -77087,24 +76456,25 @@ function Reset-DbaAdmin { License: MIT https://opensource.org/licenses/MIT Requires: Admin access to server (not SQL Services), - Remoting must be enabled and accessible if $SqlInstance is not local + Remoting must be enabled and accessible if $instance is not local .LINK https://dbatools.io/Reset-DbaAdmin .EXAMPLE - PS C:\> Reset-DbaAdmin -SqlInstance sqlcluster + PS C:\> Reset-DbaAdmin -SqlInstance sqlcluster -SqlCredential sqladmin - Prompts for password, then resets the "sa" account password on sqlcluster. + Prompts for password, then resets the "sqladmin" account password on sqlcluster. .EXAMPLE - PS C:\> Reset-DbaAdmin -SqlInstance sqlserver\sqlexpress -Login ad\administrator - - Prompts user to confirm that they understand the SQL Service will be restarted. + PS C:\> Reset-DbaAdmin -SqlInstance sqlserver\sqlexpress -Login ad\administrator -Confirm:$false Adds the domain account "ad\administrator" as a sysadmin to the SQL instance. + If the account already exists, it will be added to the sysadmin role. + Does not prompt for a password since it is not a SQL login. Does not prompt for confirmation since -Confirm is set to $false. + .EXAMPLE PS C:\> Reset-DbaAdmin -SqlInstance sqlserver\sqlexpress -Login sqladmin -Force @@ -77117,12 +76487,11 @@ function Reset-DbaAdmin { param ( [Parameter(Mandatory)] [Alias("ServerInstance", "SqlServer")] - [DbaInstanceParameter] - $SqlInstance, + [DbaInstanceParameter]$SqlInstance, + [pscredential]$SqlCredential, [string]$Login = "sa", [SecureString]$SecurePassword, [switch]$Force, - [Alias('Silent')] [switch]$EnableException ) @@ -77138,8 +76507,7 @@ function Reset-DbaAdmin { [CmdletBinding()] param ( [Parameter(Mandatory)] - [Security.SecureString] - $Password + [Security.SecureString]$Password ) $marshal = [Runtime.InteropServices.Marshal] @@ -77157,12 +76525,12 @@ function Reset-DbaAdmin { param ( [Parameter(Mandatory)] [Alias("ServerInstance", "SqlServer")] - [DbaInstanceParameter] - $SqlInstance, - [string]$sql + [DbaInstanceParameter]$instance, + [string]$sql, + [switch]$EnableException ) try { - $connstring = "Data Source=$SqlInstance;Integrated Security=True;Connect Timeout=2;Application Name=Reset-DbaAdmin" + $connstring = "Data Source=$instance;Integrated Security=True;Connect Timeout=20;Application Name=Reset-DbaAdmin" $conn = New-Object System.Data.SqlClient.SqlConnection $connstring $conn.Open() $cmd = New-Object system.data.sqlclient.sqlcommand($null, $conn) @@ -77171,26 +76539,29 @@ function Reset-DbaAdmin { $cmd.Dispose() $conn.Close() $conn.Dispose() - return $true + $true } catch { - return $false + Stop-Function -Message "Failure" -ErrorRecord $_ } } #endregion Utility functions - } - - process { if ($Force) { $ConfirmPreference = "none" } - $baseaddress = $SqlInstance.ComputerName + if ($SqlCredential) { + $Login = $SqlCredential.UserName + $SecurePassword = $SqlCredential.Password + } + } - # Before we continue, we need confirmation. - if ($pscmdlet.ShouldProcess($baseaddress, "Reset-DbaAdmin (SQL Server instance $SqlInstance will restart)")) { + process { + foreach ($instance in $sqlinstance) { + $stepcounter = 0 + $baseaddress = $instance.ComputerName # Get hostname - if ($baseaddress -eq "." -or $baseaddress -eq $env:COMPUTERNAME -or $baseaddress -eq "localhost") { + if ($baseaddress.IsLocalHost) { $ipaddr = "." $hostname = $env:COMPUTERNAME $baseaddress = $env:COMPUTERNAME @@ -77201,7 +76572,7 @@ function Reset-DbaAdmin { # Test for WinRM #Test-WinRM neh winrm id -r:$baseaddress 2>$null | Out-Null if ($LastExitCode -ne 0) { - throw "Remote PowerShell access not enabled on on $source or access denied. Quitting." + Stop-Function -Continue -Message "Remote PowerShell access not enabled on on $instance or access denied. Quitting." } # Test Connection first using Test-Connection which requires ICMP access then failback to tcp if pings are blocked @@ -77216,34 +76587,41 @@ function Reset-DbaAdmin { $tcp.Close() $tcp.Dispose() } catch { - throw "Can't connect to $baseaddress either via ping or tcp (WMI port 135)" + Stop-Function -Continue -ErrorRecord $_ -Message "Can't connect to $baseaddress either via ping or tcp (WMI port 135)" } } Write-Message -Level Verbose -Message "Resolving IP address." try { $hostentry = [System.Net.Dns]::GetHostEntry($baseaddress) - $ipaddr = ($hostentry.AddressList | Where-Object { $_ -notlike '169.*' } | Select-Object -First 1).IPAddressToString + $ipaddr = ($hostentry.AddressList | Where-Object { + $_ -notlike '169.*' + } | Select-Object -First 1).IPAddressToString } catch { - throw "Could not resolve SqlServer IP or NetBIOS name" + Stop-Function -Continue -ErrorRecord $_ -Message "Could not resolve SqlServer IP or NetBIOS name" } Write-Message -Level Verbose -Message "Resolving NetBIOS name." try { - $hostname = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName $ipaddr).PSComputerName + # this is required otherwise, the ip is returned + $hostname = (Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Filter IPEnabled=TRUE -ComputerName $ipaddr -ErrorAction Stop).PSComputerName if ($null -eq $hostname) { - $hostname = (nbtstat -A $ipaddr | Where-Object { $_ -match '\<00\> UNIQUE' } | ForEach-Object { $_.SubString(4, 14) }).Trim() + $hostname = (nbtstat -A $ipaddr | Where-Object { + $_ -match '\<00\> UNIQUE' + } | ForEach-Object { + $_.SubString(4, 14) + }).Trim() } } catch { - throw "Could not access remote WMI object. Check permissions and firewall." + Stop-Function -Continue -ErrorRecord $_ -Message "Could not access remote WMI object. Check permissions and firewall." } } # Setup remote session if server is not local - if ($hostname -ne $env:COMPUTERNAME) { + if (-not $instance.IsLocalHost) { try { - $session = New-PSSession -ComputerName $hostname + $session = New-PSSession -ComputerName $hostname -ErrorAction Stop } catch { - throw "Can't access $hostname using PSSession. Check your firewall settings and ensure Remoting is enabled or run the script locally." + Stop-Function -Continue -ErrorRecord $_ -Message "Can't access $hostname using PSSession. Check your firewall settings and ensure Remoting is enabled or run the script locally." } } @@ -77270,41 +76648,44 @@ function Reset-DbaAdmin { } # If it's not a Windows login, it's a SQL login, so it needs a password. - if ($windowslogin -ne $true -and (Test-Bound -Not -ParameterName SecurePassword)) { + if (-not $windowslogin -and -not $SecurePassword) { Write-Message -Level Verbose -Message "SQL login detected" do { $Password = Read-Host -AsSecureString "Please enter a new password for $login" - } - while ($Password.Length -eq 0) + } while ($Password.Length -eq 0) } - If ((Test-Bound -ParameterName SecurePassword)) { + If ($SecurePassword) { $Password = $SecurePassword } # Get instance and service display name, then get services - $instance = $null - $instance = $SqlInstance.InstanceName - if (-not $instance) { - $instance = "MSSQLSERVER" + $instancename = $null + $instancename = $instance.InstanceName + if (-not $instancename) { + $instancename = "MSSQLSERVER" } - $displayName = "SQL Server ($instance)" + $displayName = "SQL Server ($instancename)" try { if ($hostname -eq $env:COMPUTERNAME) { - $instanceservices = Get-Service -ErrorAction Stop | Where-Object { $_.DisplayName -like "*($instance)*" -and $_.Status -eq "Running" } - $sqlservice = Get-Service -ErrorAction Stop | Where-Object DisplayName -eq "SQL Server ($instance)" + $instanceservices = Get-Service -ErrorAction Stop | Where-Object { + $_.DisplayName -like "*($instancename)*" -and $_.Status -eq "Running" + } + $sqlservice = Get-Service -ErrorAction Stop | Where-Object DisplayName -eq "SQL Server ($instancename)" } else { - $instanceservices = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object { $_.DisplayName -like "*($instance)*" -and $_.Status -eq "Running" } - $sqlservice = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object DisplayName -eq "SQL Server ($instance)" + $instanceservices = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object { + $_.DisplayName -like "*($instancename)*" -and $_.Status -eq "Running" + } + $sqlservice = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object DisplayName -eq "SQL Server ($instancename)" } } catch { - Stop-Function -Message "Cannot connect to WMI on $hostname or SQL Service does not exist. Check permissions, firewall and SQL Server running status." -ErrorRecord $_ -Target $SqlInstance + Stop-Function -Message "Cannot connect to WMI on $hostname or SQL Service does not exist. Check permissions, firewall and SQL Server running status." -ErrorRecord $_ -Target $instance return } if (-not $instanceservices) { - Stop-Function -Message "Couldn't find SQL Server instance. Check the spelling, ensure the service is running and try again." -Target $SqlInstance + Stop-Function -Message "Couldn't find SQL Server instance. Check the spelling, ensure the service is running and try again." -Target $instance return } @@ -77313,141 +76694,216 @@ function Reset-DbaAdmin { # Check to see if service is clustered. Clusters don't support -m (since the cluster service # itself connects immediately) or -f, so they are handled differently. try { - $checkcluster = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object { $_.Name -eq "ClusSvc" -and $_.Status -eq "Running" } + $checkcluster = Get-Service -ComputerName $ipaddr -ErrorAction Stop | Where-Object { + $_.Name -eq "ClusSvc" -and $_.Status -eq "Running" + } } catch { - Stop-Function -Message "Can't check services." -Target $SqlInstance -ErrorRecord $_ + Stop-Function -Message "Can't check services." -Target $instance -ErrorRecord $_ return } if ($null -ne $checkcluster) { $clusterResource = Get-DbaCmObject -ClassName "MSCluster_Resource" -Namespace "root\mscluster" -ComputerName $hostname | - Where-Object { $_.Name.StartsWith("SQL Server") -and $_.OwnerGroup -eq "SQL Server ($instance)" } - } - - # Take SQL Server offline so that it can be started in single-user mode - if ($clusterResource.count -gt 0) { - $isclustered = $true - try { - $clusterResource | Where-Object { $_.Name -eq "SQL Server" } | ForEach-Object { $_.TakeOffline(60) } - } catch { - $clusterResource | Where-Object { $_.Name -eq "SQL Server" } | ForEach-Object { $_.BringOnline(60) } - $clusterResource | Where-Object { $_.Name -ne "SQL Server" } | ForEach-Object { $_.BringOnline(60) } - Stop-Function -Message "Could not stop the SQL Service. Restarted SQL Service and quit." -ErrorRecord $_ -Target $SqlInstance - return - } - } else { - try { - Stop-Service -InputObject $sqlservice -Force -ErrorAction Stop - Write-Message -Level Verbose -Message "Successfully stopped SQL service." - } catch { - Start-Service -InputObject $instanceservices -ErrorAction Stop - Stop-Function -Message "Could not stop the SQL Service. Restarted SQL service and quit." -ErrorRecord $_ -Target $SqlInstance - return + Where-Object { + $_.Name.StartsWith("SQL Server") -and $_.OwnerGroup -eq "SQL Server ($instancename)" } } - # /mReset-DbaAdmin Starts an instance of SQL Server in single-user mode and only allows this script to connect. - Write-Message -Level Verbose -Message "Starting SQL Service from command line." - try { - if ($hostname -eq $env:COMPUTERNAME) { - $netstart = net start ""$displayname"" /mReset-DbaAdmin 2>&1 - if ("$netstart" -notmatch "success") { - throw + + if ($pscmdlet.ShouldProcess($baseaddress, "Stop $instance to restart in single-user mode")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Stopping $instance to restart in single-user mode" + # Take SQL Server offline so that it can be started in single-user mode + if ($clusterResource.count -gt 0) { + $isclustered = $true + try { + $clusterResource | Where-Object { + $_.Name -eq "SQL Server" + } | ForEach-Object { + $_.TakeOffline(60) + } + } catch { + $clusterResource | Where-Object { + $_.Name -eq "SQL Server" + } | ForEach-Object { + $_.BringOnline(60) + } + $clusterResource | Where-Object { + $_.Name -ne "SQL Server" + } | ForEach-Object { + $_.BringOnline(60) + } + Stop-Function -Message "Could not stop the SQL Service. Restarted SQL Service and quit." -ErrorRecord $_ -Target $instance + return } } else { - $netstart = Invoke-Command -ErrorAction Stop -Session $session -ArgumentList $displayname -ScriptBlock { net start ""$args"" /mReset-DbaAdmin } 2>&1 - foreach ($line in $netstart) { - if ($line.length -gt 0) { Write-Message -Level Verbose -Message $line } + try { + Stop-Service -InputObject $sqlservice -Force -ErrorAction Stop + Write-Message -Level Verbose -Message "Successfully stopped SQL service." + } catch { + Start-Service -InputObject $instanceservices -ErrorAction Stop + Stop-Function -Message "Could not stop the SQL Service. Restarted SQL service and quit." -ErrorRecord $_ -Target $instance + return } } - } catch { - Stop-Service -InputObject $sqlservice -Force -ErrorAction SilentlyContinue - - if ($isclustered) { - $clusterResource | Where-Object Name -eq "SQL Server" | ForEach-Object { $_.BringOnline(60) } - $clusterResource | Where-Object Name -ne "SQL Server" | ForEach-Object { $_.BringOnline(60) } - } else { - Start-Service -InputObject $instanceservices -ErrorAction SilentlyContinue - } - Stop-Function -Message "Couldn't execute net start command. Restarted services and quit." -ErrorRecord $_ - return } - try { - $null = Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql "SELECT 1" -ErrorAction Stop - } catch { + # /mReset-DbaAdmin Starts an instance of SQL Server in single-user mode and only allows this script to connect. + if ($pscmdlet.ShouldProcess($baseaddress, "Starting $instance in single-user mode")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Starting $instance in single-user mode" try { - Start-Sleep 3 - $null = Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql "SELECT 1" -ErrorAction Stop + if ($instance.IsLocalHost) { + $netstart = net start ""$displayname"" /mReset-DbaAdmin 2>&1 + if ("$netstart" -notmatch "success") { + Stop-Function -Message "Restart failure" -Continue + } + } else { + $netstart = Invoke-Command -ErrorAction Stop -Session $session -ArgumentList $displayname -ScriptBlock { + net start ""$args"" /mReset-DbaAdmin + } 2>&1 + foreach ($line in $netstart) { + if ($line.length -gt 0) { + Write-Message -Level Verbose -Message $line + } + } + } } catch { - Stop-Service Input-Object $sqlservice -Force -ErrorAction SilentlyContinue + Stop-Service -InputObject $sqlservice -Force -ErrorAction SilentlyContinue + if ($isclustered) { - $clusterResource | Where-Object { $_.Name -eq "SQL Server" } | ForEach-Object { $_.BringOnline(60) } - $clusterResource | Where-Object { $_.Name -ne "SQL Server" } | ForEach-Object { $_.BringOnline(60) } + $clusterResource | Where-Object Name -eq "SQL Server" | ForEach-Object { + $_.BringOnline(60) + } + $clusterResource | Where-Object Name -ne "SQL Server" | ForEach-Object { + $_.BringOnline(60) + } } else { Start-Service -InputObject $instanceservices -ErrorAction SilentlyContinue } - Stop-Function -Message "Could not stop the SQL Service. Restarted SQL Service and quit." -ErrorRecord $_ + Stop-Function -Message "Couldn't execute net start command. Restarted services and quit." -ErrorRecord $_ + return + } + } + + if ($pscmdlet.ShouldProcess($baseaddress, "Testing $instance to ensure it's back up")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Testing $instance to ensure it's back up" + try { + $null = Invoke-ResetSqlCmd -instance $instance -Sql "SELECT 1" -EnableException + } catch { + try { + Start-Sleep 3 + $null = Invoke-ResetSqlCmd -instance $instance -Sql "SELECT 1" -EnableException + } catch { + Stop-Service Input-Object $sqlservice -Force -ErrorAction SilentlyContinue + if ($isclustered) { + $clusterResource | Where-Object { + $_.Name -eq "SQL Server" + } | ForEach-Object { + $_.BringOnline(60) + } + $clusterResource | Where-Object { + $_.Name -ne "SQL Server" + } | ForEach-Object { + $_.BringOnline(60) + } + } else { + Start-Service -InputObject $instanceservices -ErrorAction SilentlyContinue + } + Stop-Function -Message "Could not stop the SQL Service. Restarted SQL Service and quit." -ErrorRecord $_ + } } } # Get login. If it doesn't exist, create it. - Write-Message -Level Verbose -Message "Adding login $login if it doesn't exist." - if ($windowslogin -eq $true) { - $sql = "IF NOT EXISTS (SELECT name FROM master.sys.server_principals WHERE name = '$login') + if ($pscmdlet.ShouldProcess($instance, "Adding login $login if it doesn't exist")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Adding login $login if it doesn't exist" + if ($windowslogin) { + $sql = "IF NOT EXISTS (SELECT name FROM master.sys.server_principals WHERE name = '$login') BEGIN CREATE LOGIN [$login] FROM WINDOWS END" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't create login." - } + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't create Windows login." + } - } elseif ($login -ne "sa") { - # Create new sql user - $sql = "IF NOT EXISTS (SELECT name FROM master.sys.server_principals WHERE name = '$login') + } elseif ($login -ne "sa") { + # Create new sql user + $sql = "IF NOT EXISTS (SELECT name FROM master.sys.server_principals WHERE name = '$login') BEGIN CREATE LOGIN [$login] WITH PASSWORD = '$(ConvertTo-PlainText $Password)', CHECK_POLICY = OFF, CHECK_EXPIRATION = OFF END" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't create login." + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't create SQL login." + } } } + # If $login is a SQL Login, Mixed mode authentication is required. if ($windowslogin -ne $true) { - Write-Message -Level Verbose -Message "Enabling mixed mode authentication." - Write-Message -Level Verbose -Message "Ensuring account is unlocked." - $sql = "EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't set to Mixed Mode." - } + if ($pscmdlet.ShouldProcess($instance, "Enabling mixed mode authentication for $login and ensuring account is unlocked")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Enabling mixed mode authentication for $login and ensuring account is unlocked" + $sql = "EXEC xp_instance_regwrite N'HKEY_LOCAL_MACHINE', N'Software\Microsoft\MSSQLServer\MSSQLServer', N'LoginMode', REG_DWORD, 2" + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't set to Mixed Mode." + } - $sql = "ALTER LOGIN [$login] WITH CHECK_POLICY = OFF + $sql = "ALTER LOGIN [$login] WITH CHECK_POLICY = OFF ALTER LOGIN [$login] WITH PASSWORD = '$(ConvertTo-PlainText $Password)' UNLOCK" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't unlock account." + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't unlock account." + } } } - Write-Message -Level Verbose -Message "Ensuring login is enabled." - $sql = "ALTER LOGIN [$login] ENABLE" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't enable login." + if ($pscmdlet.ShouldProcess($instance, "Enabling $login")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Ensuring login is enabled" + $sql = "ALTER LOGIN [$login] ENABLE" + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't enable login." + } } if ($login -ne "sa") { - Write-Message -Level Verbose -Message "Ensuring login exists within sysadmin role." - $sql = "EXEC sp_addsrvrolemember '$login', 'sysadmin'" - if ($(Invoke-ResetSqlCmd -SqlInstance $sqlinstance -Sql $sql) -eq $false) { - Write-Message -Level Warning -Message "Couldn't add to sysadmin role." + if ($pscmdlet.ShouldProcess($instance, "Ensuring $login exists within sysadmin role")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Ensuring $login exists within sysadmin role" + $sql = "EXEC sp_addsrvrolemember '$login', 'sysadmin'" + if (-not (Invoke-ResetSqlCmd -instance $instance -Sql $sql)) { + Write-Message -Level Warning -Message "Couldn't add to sysadmin role." + } } } - Write-Message -Level Verbose -Message "Finished with login tasks." - Write-Message -Level Verbose -Message "Restarting SQL Server." - Stop-Service -InputObject $sqlservice -Force -ErrorAction SilentlyContinue - if ($isclustered -eq $true) { - $clusterResource | Where-Object Name -eq "SQL Server" | ForEach-Object { $_.BringOnline(60) } - $clusterResource | Where-Object Name -ne "SQL Server" | ForEach-Object { $_.BringOnline(60) } - } else { - Start-Service -InputObject $instanceservices -ErrorAction SilentlyContinue + if ($pscmdlet.ShouldProcess($instance, "Finished with login tasks. Restarting")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Finished with login tasks. Restarting." + try { + Stop-Service -InputObject $sqlservice -Force -ErrorAction Stop + if ($isclustered -eq $true) { + $clusterResource | Where-Object Name -eq "SQL Server" | ForEach-Object { + $_.BringOnline(60) + } + $clusterResource | Where-Object Name -ne "SQL Server" | ForEach-Object { + $_.BringOnline(60) + } + } else { + Start-Service -InputObject $instanceservices -ErrorAction Stop + } + } catch { + Stop-Function -Message "Failure" -ErrorRecord $_ + } + } + + if ($pscmdlet.ShouldProcess($instance, "Logging in to get account information")) { + Write-ProgressHelper -StepNumber ($stepCounter++) -Message "Logging in to get account information" + if ($securePassword) { + $cred = New-Object System.Management.Automation.PSCredential ($Login, $securePassword) + Get-DbaLogin -SqlInstance $instance -SqlCredential $cred -Login $Login + } elseif ($SqlCredential) { + Get-DbaLogin -SqlInstance $instance -SqlCredential $SqlCredential -Login $Login + } else { + try { + Get-DbaLogin -SqlInstance $instance -SqlCredential $SqlCredential -Login $Login -EnableException + } catch { + Stop-Function -Message "Password not supplied, tried logging in with Integrated authentication and it failed. Either way, $Login should work now on $instance." -Continue + } + } } + } } end { @@ -78675,7 +78131,7 @@ function Restore-DbaDbCertificate { .PARAMETER Path The Path the contains the certificate and private key files. The path can be a directory or a specific certificate. - .PARAMETER Password + .PARAMETER SecurePassword Secure string used to decrypt the private key. .PARAMETER EncryptionPassword @@ -78707,12 +78163,12 @@ function Restore-DbaDbCertificate { https://dbatools.io/Restore-DbaDbCertificate .EXAMPLE - PS C:\> Restore-DbaDbCertificate -SqlInstance Server1 -Path \\Server1\Certificates -Password (ConvertTo-SecureString -Force -AsPlainText GoodPass1234!!) + PS C:\> Restore-DbaDbCertificate -SqlInstance Server1 -Path \\Server1\Certificates -SecurePassword (ConvertTo-SecureString -Force -AsPlainText GoodPass1234!!) Restores all the certificates in the specified path, password is used to both decrypt and encrypt the private key. .EXAMPLE - PS C:\> Restore-DbaDbCertificate -SqlInstance Server1 -Path \\Server1\Certificates\DatabaseTDE.cer -Password (ConvertTo-SecureString -force -AsPlainText GoodPass1234!!) + PS C:\> Restore-DbaDbCertificate -SqlInstance Server1 -Path \\Server1\Certificates\DatabaseTDE.cer -SecurePassword (ConvertTo-SecureString -force -AsPlainText GoodPass1234!!) Restores the DatabaseTDE certificate to Server1 and uses the MasterKey to encrypt the private key. @@ -78727,7 +78183,8 @@ function Restore-DbaDbCertificate { [object[]]$Path, [Security.SecureString]$EncryptionPassword, [string]$Database = "master", - [Security.SecureString]$Password = (Read-Host "Password" -AsSecureString), + [Alias("Password")] + [Security.SecureString]$SecurePassword = (Read-Host "Password" -AsSecureString), [switch]$EnableException ) process { @@ -84089,15 +83546,15 @@ function Set-DbaLogin { .PARAMETER Login The login that needs to be changed - .PARAMETER Password + .PARAMETER SecurePassword The new password for the login This can be either a credential or a secure string. .PARAMETER Unlock - Switch to unlock an account. This will only be used in conjunction with the -Password parameter. + Switch to unlock an account. This will only be used in conjunction with the -SecurePassword parameter. The default is false. .PARAMETER MustChange - Does the user need to change his/her password. This will only be used in conjunction with the -Password parameter. + Does the user need to change his/her password. This will only be used in conjunction with the -SecurePassword parameter. The default is false. .PARAMETER NewName @@ -84152,9 +83609,9 @@ function Set-DbaLogin { https://dbatools.io/Set-DbaLogin .EXAMPLE - PS C:\> $password = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force - PS C:\> $cred = New-Object System.Management.Automation.PSCredential ("username", $password) - PS C:\> Set-DbaLogin -SqlInstance sql1 -Login login1 -Password $cred -Unlock -MustChange + PS C:\> $SecurePassword = ConvertTo-SecureString "PlainTextPassword" -AsPlainText -Force + PS C:\> $cred = New-Object System.Management.Automation.PSCredential ("username", $SecurePassword) + PS C:\> Set-DbaLogin -SqlInstance sql1 -Login login1 -SecurePassword $cred -Unlock -MustChange Set the new password for login1 using a credential, unlock the account and set the option that the user must change password at next logon. @@ -84224,7 +83681,8 @@ function Set-DbaLogin { [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$SqlCredential, [string[]]$Login, - [object]$Password, + [Alias("Password")] + [object]$SecurePassword, #object so that it can accept credential or securestring [switch]$Unlock, [switch]$MustChange, [string]$NewName, @@ -84261,10 +83719,10 @@ function Set-DbaLogin { Stop-Function -Message 'You cannot use both -GrantLogin and -DenyLogin together' -Target $Login -Continue } - if (Test-bound -ParameterName 'Password') { - switch ($Password.GetType().Name) { - 'PSCredential' { $newPassword = $Password.Password } - 'SecureString' { $newPassword = $Password } + if (Test-bound -ParameterName 'SecurePassword') { + switch ($SecurePassword.GetType().Name) { + 'PSCredential' { $NewSecurePassword = $SecurePassword.Password } + 'SecureString' { $NewSecurePassword = $SecurePassword } default { Stop-Function -Message 'Password must be a PSCredential or SecureString' -Target $Login } @@ -84312,9 +83770,9 @@ function Set-DbaLogin { } # Change the password - if (Test-Bound -ParameterName 'Password') { + if (Test-bound -ParameterName 'SecurePassword') { try { - $l.ChangePassword($newPassword, $Unlock, $MustChange) + $l.ChangePassword($NewSecurePassword, $Unlock, $MustChange) $passwordChanged = $true } catch { $notes += "Couldn't change password" @@ -86294,16 +85752,16 @@ function Set-DbaTempdbConfig { .PARAMETER DataFileCount Specifies the number of data files to create. If this number is not specified, the number of logical cores of the host will be used. - .PARAMETER DataFileSizeMB + .PARAMETER DataFileSize Specifies the total data file size in megabytes. This is distributed across the total number of data files. - .PARAMETER LogFileSizeMB + .PARAMETER LogFileSize Specifies the log file size in megabytes. If not specified, this will be set to 25% of total data file size. - .PARAMETER DataFileGrowthMB + .PARAMETER DataFileGrowth Specifies the growth amount for the data file(s) in megabytes. The default is 512 MB. - .PARAMETER LogFileGrowthMB + .PARAMETER LogFileGrowth Specifies the growth amount for the log file in megabytes. The default is 512 MB. .PARAMETER DataPath @@ -86319,7 +85777,7 @@ function Set-DbaTempdbConfig { Specifies the filesystem path into which the generated T-SQL script will be saved. .PARAMETER DisableGrowth - If this switch is enabled, the tempdb files will be configured to not grow. This overrides -DataFileGrowthMB and -LogFileGrowthMB. + If this switch is enabled, the tempdb files will be configured to not grow. This overrides -DataFileGrowth and -LogFileGrowth. .PARAMETER WhatIf If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run. @@ -86344,192 +85802,180 @@ function Set-DbaTempdbConfig { https://dbatools.io/Set-DbaTempdbConfig .EXAMPLE - PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 + PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 Creates tempdb with a number of data files equal to the logical cores where each file is equal to 1000MB divided by the number of logical cores, with a log file of 250MB. .EXAMPLE - PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -DataFileCount 8 + PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -DataFileCount 8 Creates tempdb with 8 data files, each one sized at 125MB, with a log file of 250MB. .EXAMPLE - PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -OutputScriptOnly + PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -OutputScriptOnly Provides a SQL script output to configure tempdb according to the passed parameters. .EXAMPLE - PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -DisableGrowth + PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -DisableGrowth Disables the growth for the data and log files. .EXAMPLE - PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -OutputScriptOnly + PS C:\> Set-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -OutputScriptOnly Returns the T-SQL script representing tempdb configuration. #> - [CmdletBinding(SupportsShouldProcess = $true)] + [CmdletBinding(SupportsShouldProcess, ConfirmImpact = 'Medium')] [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseOutputTypeCorrectly", "", Justification = "PSSA Rule Ignored by BOH")] param ( [parameter(Mandatory)] [Alias("ServerInstance", "SqlServer")] - [DbaInstanceParameter]$SqlInstance, + [DbaInstanceParameter[]]$SqlInstance, [PSCredential]$SqlCredential, [int]$DataFileCount, [Parameter(Mandatory)] - [int]$DataFileSizeMB, - [int]$LogFileSizeMB, - [int]$DataFileGrowthMB = 512, - [int]$LogFileGrowthMB = 512, + [int]$DataFileSize, + [int]$LogFileSize, + [int]$DataFileGrowth = 512, + [int]$LogFileGrowth = 512, [string]$DataPath, [string]$LogPath, [string]$OutFile, [switch]$OutputScriptOnly, [switch]$DisableGrowth, - [Alias('Silent')] [switch]$EnableException ) - begin { - $sql = @() - $server = Connect-SqlInstance $sqlinstance -SqlCredential $SqlCredential - - if ($server.VersionMajor -lt 9) { - Stop-Function -Message "SQL Server 2000 is not supported" - return - } - } - process { + foreach ($instance in $SqlInstance) { + try { + $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $SqlCredential -MinimumVersion 9 - if (Test-FunctionInterrupt) { - return - } + } catch { + Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue + } - $cores = $server.Processors - if ($cores -gt 8) { - $cores = 8 - } + $cores = $server.Processors + if ($cores -gt 8) { + $cores = 8 + } - #Set DataFileCount if not specified. If specified, check against best practices. - if (-not $DataFileCount) { - $DataFileCount = $cores - Write-Message -Message "Data file count set to number of cores: $DataFileCount" -Level Verbose - } else { - if ($DataFileCount -gt $cores) { - Write-Message -Message "Data File Count of $DataFileCount exceeds the Logical Core Count of $cores. This is outside of best practices." -Level Warning + #Set DataFileCount if not specified. If specified, check against best practices. + if (-not $DataFileCount) { + $DataFileCount = $cores + Write-Message -Message "Data file count set to number of cores: $DataFileCount" -Level Verbose + } else { + if ($DataFileCount -gt $cores) { + Write-Message -Message "Data File Count of $DataFileCount exceeds the Logical Core Count of $cores. This is outside of best practices." -Level Warning + } + Write-Message -Message "Data file count set explicitly: $DataFileCount" -Level Verbose } - Write-Message -Message "Data file count set explicitly: $DataFileCount" -Level Verbose - } - $DataFilesizeSingleMB = $([Math]::Floor($DataFileSizeMB / $DataFileCount)) - Write-Message -Message "Single data file size (MB): $DataFilesizeSingleMB." -Level Verbose + $DataFilesizeSingle = $([Math]::Floor($DataFileSize / $DataFileCount)) + Write-Message -Message "Single data file size (MB): $DataFilesizeSingle." -Level Verbose - if ($DataPath) { - if ((Test-DbaPath -SqlInstance $server -Path $DataPath) -eq $false) { - Stop-Function -Message "$datapath is an invalid path." - return + if (Test-Bound -ParameterName DataPath) { + if ((Test-DbaPath -SqlInstance $server -Path $DataPath) -eq $false) { + Stop-Function -Message "$datapath is an invalid path." -Continue + } + } else { + $Filepath = $server.Databases['tempdb'].ExecuteWithResults('SELECT physical_name as FileName FROM sys.database_files WHERE file_id = 1').Tables[0].Rows[0].FileName + $DataPath = Split-Path $Filepath } - } else { - $Filepath = $server.Databases['tempdb'].ExecuteWithResults('SELECT physical_name as FileName FROM sys.database_files WHERE file_id = 1').Tables[0].Rows[0].FileName - $DataPath = Split-Path $Filepath - } - Write-Message -Message "Using data path: $datapath." -Level Verbose + Write-Message -Message "Using data path: $datapath." -Level Verbose - if ($LogPath) { - if ((Test-DbaPath -SqlInstance $server -Path $LogPath) -eq $false) { - Stop-Function -Message "$LogPath is an invalid path." - return + if (Test-Bound -ParameterName LogPath) { + if ((Test-DbaPath -SqlInstance $server -Path $LogPath) -eq $false) { + Stop-Function -Message "$LogPath is an invalid path." -Continue + } + } else { + $Filepath = $server.Databases['tempdb'].ExecuteWithResults('SELECT physical_name as FileName FROM sys.database_files WHERE file_id = 2').Tables[0].Rows[0].FileName + $LogPath = Split-Path $Filepath } - } else { - $Filepath = $server.Databases['tempdb'].ExecuteWithResults('SELECT physical_name as FileName FROM sys.database_files WHERE file_id = 2').Tables[0].Rows[0].FileName - $LogPath = Split-Path $Filepath - } - Write-Message -Message "Using log path: $LogPath." -Level Verbose + Write-Message -Message "Using log path: $LogPath." -Level Verbose - # Check if the file growth needs to be disabled - if ($DisableGrowth) { - $DataFileGrowthMB = 0 - $LogFileGrowthMB = 0 - } + # Check if the file growth needs to be disabled + if ($DisableGrowth) { + $DataFileGrowth = 0 + $LogFileGrowth = 0 + } - # Check current tempdb. Throw an error if current tempdb is larger than config. - $CurrentFileCount = $server.Databases['tempdb'].ExecuteWithResults('SELECT count(1) as FileCount FROM sys.database_files WHERE type=0').Tables[0].Rows[0].FileCount - $TooBigCount = $server.Databases['tempdb'].ExecuteWithResults("SELECT TOP 1 (size/128) as Size FROM sys.database_files WHERE size/128 > $DataFilesizeSingleMB AND type = 0").Tables[0].Rows[0].Size + # Check current tempdb. Throw an error if current tempdb is larger than config. + $CurrentFileCount = $server.Databases['tempdb'].ExecuteWithResults('SELECT count(1) as FileCount FROM sys.database_files WHERE type=0').Tables[0].Rows[0].FileCount + $TooBigCount = $server.Databases['tempdb'].ExecuteWithResults("SELECT TOP 1 (size/128) as Size FROM sys.database_files WHERE size/128 > $DataFilesizeSingle AND type = 0").Tables[0].Rows[0].Size - if ($CurrentFileCount -gt $DataFileCount) { - Stop-Function -Message "Current tempdb not suitable to be reconfigured. The current tempdb has a greater number of files ($CurrentFileCount) than the calculated configuration ($DataFileCount)." - return - } + if ($CurrentFileCount -gt $DataFileCount) { + Stop-Function -Message "Current tempdb in $instance is not suitable to be reconfigured. The current tempdb has a greater number of files ($CurrentFileCount) than the calculated configuration ($DataFileCount)." -Continue + } - if ($TooBigCount) { - Stop-Function -Message "Current tempdb not suitable to be reconfigured. The current tempdb ($TooBigCount MB) is larger than the calculated individual file configuration ($DataFilesizeSingleMB MB)." - return - } + if ($TooBigCount) { + Stop-Function -Message "Current tempdb in $instance is not suitable to be reconfigured. The current tempdb ($TooBigCount MB) is larger than the calculated individual file configuration ($DataFilesizeSingle MB)." -Continue + } - $EqualCount = $server.Databases['tempdb'].ExecuteWithResults("SELECT count(1) as FileCount FROM sys.database_files WHERE size/128 = $DataFilesizeSingleMB AND type = 0").Tables[0].Rows[0].FileCount + $EqualCount = $server.Databases['tempdb'].ExecuteWithResults("SELECT count(1) as FileCount FROM sys.database_files WHERE size/128 = $DataFilesizeSingle AND type = 0").Tables[0].Rows[0].FileCount - Write-Message -Message "tempdb configuration validated." -Level Verbose + Write-Message -Message "tempdb configuration validated." -Level Verbose - $DataFiles = $server.Databases['tempdb'].ExecuteWithResults("select f.name as Name, f.physical_name as FileName from sys.filegroups fg join sys.database_files f on fg.data_space_id = f.data_space_id where fg.name = 'PRIMARY' and f.type_desc = 'ROWS'").Tables[0]; + $DataFiles = $server.Databases['tempdb'].ExecuteWithResults("select f.name as Name, f.physical_name as FileName from sys.filegroups fg join sys.database_files f on fg.data_space_id = f.data_space_id where fg.name = 'PRIMARY' and f.type_desc = 'ROWS'").Tables[0]; - #Checks passed, process reconfiguration - for ($i = 0; $i -lt $DataFileCount; $i++) { - $File = $DataFiles.Rows[$i] - if ($File) { - $Filename = Split-Path $File.FileName -Leaf - $LogicalName = $File.Name - $NewPath = "$datapath\$Filename" - $sql += "ALTER DATABASE tempdb MODIFY FILE(name=$LogicalName,filename='$NewPath',size=$DataFilesizeSingleMB MB,filegrowth=$DataFileGrowthMB);" - } else { - $NewName = "tempdev$i.ndf" - $NewPath = "$datapath\$NewName" - $sql += "ALTER DATABASE tempdb ADD FILE(name=tempdev$i,filename='$NewPath',size=$DataFilesizeSingleMB MB,filegrowth=$DataFileGrowthMB);" + #Checks passed, process reconfiguration + for ($i = 0; $i -lt $DataFileCount; $i++) { + $File = $DataFiles.Rows[$i] + if ($File) { + $Filename = Split-Path $File.FileName -Leaf + $LogicalName = $File.Name + $NewPath = "$datapath\$Filename" + $sql += "ALTER DATABASE tempdb MODIFY FILE(name=$LogicalName,filename='$NewPath',size=$DataFilesizeSingle MB,filegrowth=$DataFileGrowth);" + } else { + $NewName = "tempdev$i.ndf" + $NewPath = "$datapath\$NewName" + $sql += "ALTER DATABASE tempdb ADD FILE(name=tempdev$i,filename='$NewPath',size=$DataFilesizeSingle MB,filegrowth=$DataFileGrowth);" + } } - } - if (-not $LogFileSizeMB) { - $LogFileSizeMB = [Math]::Floor($DataFileSizeMB / 4) - } + if (-not $LogFileSize) { + $LogFileSize = [Math]::Floor($DataFileSize / 4) + } - $logfile = $server.Databases['tempdb'].ExecuteWithResults("SELECT name, physical_name as FileName FROM sys.database_files WHERE file_id = 2").Tables[0].Rows[0]; - $Filename = Split-Path $logfile.FileName -Leaf - $LogicalName = $logfile.Name - $NewPath = "$LogPath\$Filename" - $sql += "ALTER DATABASE tempdb MODIFY FILE(name=$LogicalName,filename='$NewPath',size=$LogFileSizeMB MB,filegrowth=$LogFileGrowthMB);" + $logfile = $server.Databases['tempdb'].ExecuteWithResults("SELECT name, physical_name as FileName FROM sys.database_files WHERE file_id = 2").Tables[0].Rows[0]; + $Filename = Split-Path $logfile.FileName -Leaf + $LogicalName = $logfile.Name + $NewPath = "$LogPath\$Filename" + $sql += "ALTER DATABASE tempdb MODIFY FILE(name=$LogicalName,filename='$NewPath',size=$LogFileSize MB,filegrowth=$LogFileGrowth);" - Write-Message -Message "SQL Statement to resize tempdb." -Level Verbose - Write-Message -Message ($sql -join "`n`n") -Level Verbose + Write-Message -Message "SQL Statement to resize tempdb." -Level Verbose + Write-Message -Message ($sql -join "`n`n") -Level Verbose - if ($OutputScriptOnly) { - return $sql - } elseif ($OutFile) { - $sql | Set-Content -Path $OutFile - } else { - if ($Pscmdlet.ShouldProcess($SqlInstance, "Executing query and informing that a restart is required.")) { - try { - $server.Databases['master'].ExecuteNonQuery($sql) - Write-Message -Level Verbose -Message "tempdb successfully reconfigured." + if ($OutputScriptOnly) { + return $sql + } elseif ($OutFile) { + $sql | Set-Content -Path $OutFile + } else { + if ($Pscmdlet.ShouldProcess($instance, "Executing query and informing that a restart is required.")) { + try { + $server.Databases['master'].ExecuteNonQuery($sql) + Write-Message -Level Verbose -Message "tempdb successfully reconfigured." - [PSCustomObject]@{ - ComputerName = $server.ComputerName - InstanceName = $server.ServiceName - SqlInstance = $server.DomainInstanceName - DataFileCount = $DataFileCount - DataFileSizeMB = $DataFileSizeMB - SingleDataFileSizeMB = $DataFilesizeSingleMB - LogSizeMB = $LogFileSizeMB - DataPath = $DataPath - LogPath = $LogPath - DataFileGrowthMB = $DataFileGrowthMB - LogFileGrowthMB = $LogFileGrowthMB - } - - Write-Message -Level Output -Message "tempdb reconfigured. You must restart the SQL Service for settings to take effect." - } catch { - Stop-Function -Message "Unable to reconfigure tempdb. Exception: $_" -Target $sql -InnerErrorRecord $_ - return + [PSCustomObject]@{ + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + DataFileCount = $DataFileCount + DataFileSize = [dbasize]($DataFileSize * 1024 * 1024) + SingleDataFileSize = [dbasize]($DataFilesizeSingle * 1024 * 1024) + LogSize = [dbasize]($LogFileSize * 1024 * 1024) + DataPath = $DataPath + LogPath = $LogPath + DataFileGrowth = [dbasize]($DataFileGrowth * 1024 * 1024) + LogFileGrowth = [dbasize]($LogFileGrowth * 1024 * 1024) + } + + Write-Message -Level Output -Message "tempdb reconfigured. You must restart the SQL Service for settings to take effect." + } catch { + Stop-Function -Message "Unable to reconfigure tempdb. Exception: $_" -Target $sql -ErrorRecord $_ -Continue + } } } } @@ -87766,7 +87212,7 @@ function Start-DbaMigration { if ($Exclude -notcontains 'CentralManagementServer') { Write-Message -Level Verbose -Message "Migrating Central Management Server" - Copy-DbaCentralManagementServer -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force + Copy-DbaCmsRegServer -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force } if ($Exclude -notcontains 'BackupDevices') { @@ -87774,11 +87220,6 @@ function Start-DbaMigration { Copy-DbaBackupDevice -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force } - if ($Exclude -notcontains 'LinkedServers') { - Write-Message -Level Verbose -Message "Migrating linked servers" - Copy-DbaLinkedServer -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force - } - if ($Exclude -notcontains 'SystemTriggers') { Write-Message -Level Verbose -Message "Migrating System Triggers" Copy-DbaServerTrigger -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force @@ -87810,7 +87251,12 @@ function Start-DbaMigration { $null = Update-SqlDbOwner -Source $sourceserver -Destination $dest -DestinationSqlCredential $DestinationSqlCredential } } - + + if ($Exclude -notcontains 'LinkedServers') { + Write-Message -Level Verbose -Message "Migrating linked servers" + Copy-DbaLinkedServer -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force + } + if ($Exclude -notcontains 'DataCollector') { Write-Message -Level Verbose -Message "Migrating Data Collector collection sets" Copy-DbaDataCollector -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force @@ -87850,7 +87296,7 @@ function Start-DbaMigration { if ($Exclude -notcontains 'ExtendedEvents') { Write-Message -Level Verbose -Message "Migrating Extended Events" - Copy-DbaExtendedEvent -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force + Copy-DbaXESession -Source $sourceserver -Destination $Destination -DestinationSqlCredential $DestinationSqlCredential -Force:$Force } if ($Exclude -notcontains 'AgentServer') { @@ -89943,7 +89389,7 @@ function Sync-DbaAvailabilityGroup { if ($Exclude -notcontains "AgentCategory") { if ($PSCmdlet.ShouldProcess("Syncing Agent Categories from $primaryserver to $secondaryservers")) { Write-ProgressHelper -Activity $activity -StepNumber ($stepCounter++) -Message "Syncing Agent Categories" - Copy-DbaAgentCategory -Source $server -Destination $secondaries -Force:$force + Copy-DbaAgentJobCategory -Source $server -Destination $secondaries -Force:$force $secondaries.JobServer.JobCategories.Refresh() $secondaries.JobServer.OperatorCategories.Refresh() $secondaries.JobServer.AlertCategories.Refresh() @@ -89969,7 +89415,7 @@ function Sync-DbaAvailabilityGroup { if ($Exclude -notcontains "AgentProxy") { if ($PSCmdlet.ShouldProcess("Syncing Agent Proxy Accounts from $primaryserver to $secondaryservers")) { Write-ProgressHelper -Activity $activity -StepNumber ($stepCounter++) -Message "Syncing Agent Proxy Accounts" - Copy-DbaAgentProxyAccount -Source $server -Destination $secondaries -Force:$force + Copy-DbaAgentProxy -Source $server -Destination $secondaries -Force:$force $secondaries.JobServer.ProxyAccounts.Refresh() } } @@ -90355,16 +89801,16 @@ function Test-DbaBackupInformation { function Test-DbaBuild { <# .SYNOPSIS - Returns SQL Server Build "compliance" level on a build + Returns SQL Server Build "compliance" level on a build. .DESCRIPTION - Returns info about the specific build of a SQL instance, including the SP, the CU and the reference KB, End Of Support, wherever possible. It adds a Compliance property as true/false, and adds details about the "targeted compliance" + Returns info about the specific build of a SQL instance, including the SP, the CU and the reference KB, End Of Support, wherever possible. It adds a Compliance property as true/false, and adds details about the "targeted compliance". .PARAMETER Build Instead of connecting to a real instance, pass a string identifying the build to get the info back. .PARAMETER MinimumBuild - This is the build version to test "compliance" against. Anything below this is flagged as not compliant + This is the build version to test "compliance" against. Anything below this is flagged as not compliant. .PARAMETER MaxBehind Instead of using a specific MinimumBuild here you can pass "how many service packs and cu back" is the targeted compliance level. You can use xxSP or xxCU or both, where xx is a number. See the Examples for more information. @@ -90404,79 +89850,68 @@ function Test-DbaBuild { PS C:\> Test-DbaBuild -Build "12.0.5540" -MinimumBuild "12.0.5557" Returns information about a build identified by "12.0.5540" (which is SQL 2014 with SP2 and CU4), which is not compliant as the minimum required - build is "12.0.5557" (which is SQL 2014 with SP2 and CU8) + build is "12.0.5557" (which is SQL 2014 with SP2 and CU8). .EXAMPLE PS C:\> Test-DbaBuild -Build "12.0.5540" -MaxBehind "1SP" Returns information about a build identified by "12.0.5540", making sure it is AT MOST 1 Service Pack "behind". For that version, - that identifies an SP2, means accepting as the lowest compliance version as "12.0.4110", that identifies 2014 with SP1 + that identifies an SP2, means accepting as the lowest compliance version as "12.0.4110", that identifies 2014 with SP1. + + Output column CUTarget is not relevant (empty). SPTarget and BuildTarget are filled in the result. .EXAMPLE PS C:\> Test-DbaBuild -Build "12.0.5540" -MaxBehind "1SP 1CU" Returns information about a build identified by "12.0.5540", making sure it is AT MOST 1 Service Pack "behind", plus 1 CU "behind". For that version, that identifies an SP2 and CU, rolling back 1 SP brings you to "12.0.4110", but given the latest CU for SP1 is CU13, the target "compliant" build - will be "12.0.4511", which is 2014 with SP1 and CU12 + will be "12.0.4511", which is 2014 with SP1 and CU12. .EXAMPLE PS C:\> Test-DbaBuild -Build "12.0.5540" -MaxBehind "0CU" Returns information about a build identified by "12.0.5540", making sure it is the latest CU release. + Output columns CUTarget, SPTarget and BuildTarget are relevant. If the latest build is a service pack (not a CU), CUTarget will be empty. + .EXAMPLE PS C:\> Test-DbaBuild -Build "12.0.5540" -Latest - Same as previous, returns information about a build identified by "12.0.5540", making sure it is the latest build available. + Returns information about a build identified by "12.0.5540", making sure it is the latest build available. + + Output columns CUTarget and SPTarget are not relevant (empty), only the BuildTarget is. .EXAMPLE PS C:\> Test-DbaBuild -Build "12.00.4502" -MinimumBuild "12.0.4511" -Update - Same as before, but tries to fetch the most up to date index online. When the online version is newer, the local one gets overwritten + Same as before, but tries to fetch the most up to date index online. When the online version is newer, the local one gets overwritten. .EXAMPLE PS C:\> Test-DbaBuild -Build "12.0.4502","10.50.4260" -MinimumBuild "12.0.4511" - Returns information builds identified by these versions strings + Returns information builds identified by these versions strings. .EXAMPLE PS C:\> Get-DbaCmsRegServer -SqlInstance sqlserver2014a | Test-DbaBuild -MinimumBuild "12.0.4511" - Integrate with other cmdlets to have builds checked for all your registered servers on sqlserver2014a + Integrate with other cmdlets to have builds checked for all your registered servers on sqlserver2014a. #> [Diagnostics.CodeAnalysis.SuppressMessageAttribute("PSUseShouldProcessForStateChangingFunctions", "")] [CmdletBinding()] param ( - [version[]] - $Build, - - [version] - $MinimumBuild, - - [string] - $MaxBehind, - - [switch] - $Latest, - + [version[]]$Build, + [version]$MinimumBuild, + [string]$MaxBehind, + [switch] $Latest, [parameter(Mandatory = $false, ValueFromPipeline)] [Alias("ServerInstance", "SqlServer")] - [DbaInstanceParameter[]] - $SqlInstance, - + [DbaInstanceParameter[]]$SqlInstance, [Alias("Credential")] - [PSCredential] - $SqlCredential, - - [switch] - $Update, - - [switch] - $Quiet, - - [switch] - [Alias('Silent')]$EnableException + [PSCredential]$SqlCredential, + [switch]$Update, + [switch]$Quiet, + [switch][Alias('Silent')]$EnableException ) begin { @@ -90591,7 +90026,7 @@ function Test-DbaBuild { $targetedBuild = $IdxVersion[$IdxVersion.Length - 1] } else { if ($ParsedMaxBehind.ContainsKey('SP')) { - $AllSPs = $SPsAndCUs.SP | Select-Object -Unique + [string[]]$AllSPs = $SPsAndCUs.SP | Select-Object -Unique $targetSP = $AllSPs.Length - $ParsedMaxBehind['SP'] - 1 if ($targetSP -lt 0) { $targetSP = 0 @@ -92986,10 +92421,7 @@ function Test-DbaDiskAlignment { * System drives in versions previous to Windows Server 2008 cannot be aligned, but it is generally not recommended to place SQL Server databases on system drives. .PARAMETER ComputerName - The server(s) to check disk configuration on. - - .PARAMETER Detailed - Output all properties, will be deprecated in 1.0.0 release. + The target computer or computers. .PARAMETER Credential Specifies an alternate Windows account to use when enumerating drives on the server. May require Administrator privileges. To use: @@ -93047,12 +92479,10 @@ function Test-DbaDiskAlignment { param ( [parameter(Mandatory, ValueFromPipeline)] [Alias("ServerInstance", "SqlServer", "SqlInstance")] - [object[]]$ComputerName, - [switch]$Detailed, + [DbaInstanceParameter[]]$ComputerName, [System.Management.Automation.PSCredential]$Credential, [System.Management.Automation.PSCredential]$SqlCredential, [switch]$NoSqlCheck, - [Alias('Silent')] [switch]$EnableException ) begin { @@ -93174,8 +92604,6 @@ function Test-DbaDiskAlignment { #region Processing results Write-Message -Level Verbose -Message "Checking $($offsets.count) partitions." -FunctionName $FunctionName - - $allpartitions = @() foreach ($partition in $offsets) { # Unfortunately "Windows does not have a reliable way to determine stripe unit Sizes. These values are obtained from vendor disk management software or from your SAN administrator." # And this is the #1 most impactful issue with disk alignment :D @@ -93212,44 +92640,42 @@ function Test-DbaDiskAlignment { $isBestPractice = $false } - $output = [PSCustomObject]@{ - Server = $ComputerName - Name = "$($partition.Name)" - PartitonSizeInMB = $($partition.Size / 1MB) - PartitionType = $partition.Type - TestingStripeSizeKB = $size - OffsetModuluCalculationKB = $OffsetModuloKB - StartingOffsetKB = $offset - IsOffsetBestPractice = $IsOffsetBestPractice - IsBestPractice = $isBestPractice - NumberOfBlocks = $partition.NumberOfBlocks - BootPartition = $partition.BootPartition - PartitionBlockSize = $partition.BlockSize - IsDynamicDisk = $IsDynamicDisk + [PSCustomObject]@{ + ComputerName = $ogcomputer + Name = "$($partition.Name)" + PartitonSize = [dbasize]($($partition.Size / 1MB) * 1024 * 1024) + PartitionType = $partition.Type + TestingStripeSize = [dbasize]($size * 1024) + OffsetModuluCalculation = [dbasize]($OffsetModuloKB * 1024) + StartingOffset = [dbasize]($offset * 1024) + IsOffsetBestPractice = $IsOffsetBestPractice + IsBestPractice = $isBestPractice + NumberOfBlocks = $partition.NumberOfBlocks + BootPartition = $partition.BootPartition + PartitionBlockSize = $partition.BlockSize + IsDynamicDisk = $IsDynamicDisk } - $allpartitions += $output } } - #endregion Processing results - return $allpartitions } } process { foreach ($computer in $ComputerName) { + $computer = $ogcomputer = $computer.ComputerName Write-Message -Level VeryVerbose -Message "Processing: $computer." $computer = Resolve-DbaNetworkName -ComputerName $computer -Credential $Credential $Computer = $computer.FullComputerName - if (!$Computer) { + if (-not $Computer) { Stop-Function -Message "Couldn't resolve hostname. Skipping." -Continue } #region Connecting to server via Cim Write-Message -Level Verbose -Message "Creating CimSession on $computer over WSMan" - if (!$Credential) { + if (-not $Credential) { $cimsession = New-CimSession -ComputerName $Computer -ErrorAction Ignore } else { $cimsession = New-CimSession -ComputerName $Computer -ErrorAction Ignore -Credential $Credential @@ -93274,20 +92700,10 @@ function Test-DbaDiskAlignment { try { - $data = Get-DiskAlignment -CimSession $cimsession -NoSqlCheck $NoSqlCheck -ComputerName $Computer -ErrorAction Stop + Get-DiskAlignment -CimSession $cimsession -NoSqlCheck $NoSqlCheck -ComputerName $Computer -ErrorAction Stop } catch { Stop-Function -Message "Failed to process $($Computer): $($_.Exception.Message)" -Continue -InnerErrorRecord $_ -Target $Computer } - - if ($null -eq $data.Server) { - Stop-Function -Message "CIM query to $Computer failed." -Continue -Target $computer - } - - if ($data.Count -gt 1) { - $data.GetEnumerator() - } else { - $data - } } } } @@ -93786,7 +93202,7 @@ function Test-DbaIdentityUsage { .PARAMETER Threshold Allows you to specify a minimum % of the seed range being utilized. This can be used to ignore seeds that have only utilized a small fraction of the range. - .PARAMETER ExcludeSystemDb + .PARAMETER ExcludeSystem Allows you to suppress output on system databases .PARAMETER EnableException @@ -93833,14 +93249,14 @@ function Test-DbaIdentityUsage { [parameter(Position = 1, Mandatory = $false)] [int]$Threshold = 0, [parameter(Position = 2, Mandatory = $false)] - [Alias("ExcludeSystemDatabases")] - [switch]$ExcludeSystemDb, + [Alias("ExcludeSystemDb")] + [switch]$ExcludeSystem, [Alias('Silent')] [switch]$EnableException ) begin { - Test-DbaDeprecation -DeprecatedOn 1.0.0 -Parameter ExcludeSystemDatabases + Test-DbaDeprecation -DeprecatedOn 1.0.0 -Parameter ExcludeSystem $sql = ";WITH CT_DT AS ( @@ -93927,7 +93343,7 @@ function Test-DbaIdentityUsage { $dbs = $dbs | Where-Object Name -NotIn $ExcludeDatabase } - if ($ExcludeSystemDb) { + if ($ExcludeSystem) { $dbs = $dbs | Where-Object IsSystemObject -EQ $false } @@ -94476,7 +93892,7 @@ function Test-DbaLastBackup { $ogdbname = $dbname $restorelist = Read-DbaBackupHeader -SqlInstance $destserver -Path $lastbackup[0].Path -AzureCredential $AzureCredential - if ($MaxSize -and $MaxSize -lt $restorelist.BackupSizeMB) { + if ($MaxSize -and $MaxSize -lt $restorelist.BackupSize.Megabyte) { $success = "The backup size for $dbname ($mb MB) exceeds the specified maximum size ($MaxSize MB)." $dbccresult = "Skipped" } else { @@ -96724,6 +96140,7 @@ function Test-DbaSpn { } } } +#ValidationTags#Messaging,FlowControl,Pipeline,CodeStyle# function Test-DbaTempdbConfig { <# .SYNOPSIS @@ -96790,7 +96207,6 @@ function Test-DbaTempdbConfig { [DbaInstance[]]$SqlInstance, [PSCredential]$SqlCredential, [switch]$Detailed, - [Alias('Silent')] [switch]$EnableException ) begin { @@ -96798,50 +96214,27 @@ function Test-DbaTempdbConfig { } process { foreach ($instance in $SqlInstance) { - $result = @() - try { $server = Connect-SqlInstance -SqlInstance $instance -SqlCredential $SqlCredential -MinimumVersion 9 } catch { Stop-Function -Message "Failure" -Category ConnectionError -ErrorRecord $_ -Target $instance -Continue } - #test for TF 1118 - if ($server.VersionMajor -ge 13) { - $notes = 'SQL Server 2016 has this functionality enabled by default' - # DBA May have changed setting. May need to check. - $value = [PSCustomObject]@{ - ComputerName = $server.ComputerName - InstanceName = $server.ServiceName - SqlInstance = $server.DomainInstanceName - Rule = 'TF 1118 Enabled' - Recommended = $true - CurrentSetting = $true - } - } else { - $sql = "DBCC TRACEON (3604);DBCC TRACESTATUS(-1)" - $tfCheck = $server.Databases['tempdb'].Query($sql) - $notes = 'KB328551 describes how TF 1118 can benefit performance.' - - $value = [PSCustomObject]@{ - ComputerName = $server.ComputerName - InstanceName = $server.ServiceName - SqlInstance = $server.DomainInstanceName - Rule = 'TF 1118 Enabled' - Recommended = $true - CurrentSetting = ($tfCheck.TraceFlag -join ',').Contains('1118') - } - } + # removed previous assumption that 2016+ will have it enabled + $tfCheck = $server.Databases['tempdb'].Query("DBCC TRACEON (3604);DBCC TRACESTATUS(-1)") + $current = ($tfCheck.TraceFlag -join ',').Contains('1118') - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true + [PSCustomObject]@{ + ComputerName = $server.ComputerName + InstanceName = $server.ServiceName + SqlInstance = $server.DomainInstanceName + Rule = 'TF 1118 Enabled' + Recommended = $true + CurrentSetting = $current + IsBestPractice = $current -eq $true + Notes = 'KB328551 describes how TF 1118 can benefit performance. SQL Server 2016 has this functionality enabled by default.' } - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value $notes - $result += $value Write-Message -Level Verbose -Message "TF 1118 evaluated" #get files and log files @@ -96850,30 +96243,22 @@ function Test-DbaTempdbConfig { $logFiles = $tempdbFiles | Where-Object Type -eq 1 Write-Message -Level Verbose -Message "TempDB file objects gathered" - $value = [PSCustomObject]@{ + [PSCustomObject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName SqlInstance = $server.DomainInstanceName Rule = 'File Count' Recommended = [Math]::Min(8, $server.Processors) CurrentSetting = $dataFiles.Count + IsBestPractice = $dataFiles.Count -eq [Math]::Min(8, $server.Processors) + Notes = 'Microsoft recommends that the number of tempdb data files is equal to the number of logical cores up to 8.' } - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true - } - - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value 'Microsoft recommends that the number of tempdb data files is equal to the number of logical cores up to 8.' - $result += $value - Write-Message -Level Verbose -Message "File counts evaluated." #test file growth $percData = $dataFiles | Where-Object GrowthType -ne 'KB' | Measure-Object - $percLog = $logFiles | Where-Object GrowthType -ne 'KB' | Measure-Object + $percLog = $logFiles | Where-Object GrowthType -ne 'KB' | Measure-Object $totalCount = $percData.Count + $percLog.Count if ($totalCount -gt 0) { @@ -96882,25 +96267,17 @@ function Test-DbaTempdbConfig { $totalCount = $false } - $value = [PSCustomObject]@{ + [PSCustomObject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName SqlInstance = $server.DomainInstanceName Rule = 'File Growth in Percent' Recommended = $false CurrentSetting = $totalCount + IsBestPractice = $totalCount -eq $false + Notes = 'Set file growth to explicit values, not by percent.' } - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true - } - - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value 'Set file growth to explicit values, not by percent.' - $result += $value - Write-Message -Level Verbose -Message "File growth settings evaluated." #test file Location @@ -96911,25 +96288,17 @@ function Test-DbaTempdbConfig { $cdata = $false } - $value = [PSCustomObject]@{ + [PSCustomObject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName SqlInstance = $server.DomainInstanceName Rule = 'File Location' Recommended = $false CurrentSetting = $cdata + IsBestPractice = $cdata -eq $false + Notes = "Do not place your tempdb files on C:\." } - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true - } - - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value "Do not place your tempdb files on C:\." - $result += $value - Write-Message -Level Verbose -Message "File locations evaluated." #Test growth limits @@ -96940,29 +96309,21 @@ function Test-DbaTempdbConfig { $growthLimits = $false } - $value = [PSCustomObject]@{ + [PSCustomObject]@{ ComputerName = $server.ComputerName InstanceName = $server.ServiceName SqlInstance = $server.DomainInstanceName Rule = 'File MaxSize Set' Recommended = $false - CurrentSetting = $growthLimits - } - - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true + CurrentSetting = $growthLimits -eq $false + IsBestPractice = $cdata -eq $false + Notes = "Consider setting your tempdb files to unlimited growth." } - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value "Consider setting your tempdb files to unlimited growth." - $result += $value - Write-Message -Level Verbose -Message "MaxSize values evaluated." #Test Data File Size Equal - $distinctCountSizeDataFiles = ($dataFiles | Group-Object -Property Size | Measure-Object).Count + $distinctCountSizeDataFiles = ($dataFiles | Group-Object -Property Size | Measure-Object).Count if ($distinctCountSizeDataFiles -eq 1) { $equalSizeDataFiles = $true @@ -96977,21 +96338,10 @@ function Test-DbaTempdbConfig { Rule = 'Data File Size Equal' Recommended = $true CurrentSetting = $equalSizeDataFiles + IsBestPractice = $equalSizeDataFiles -eq $true + Notes = "Consider creating equally sized data files." } - - if ($value.Recommended -ne $value.CurrentSetting -and $null -ne $value.Recommended) { - $isBestPractice = $false - } else { - $isBestPractice = $true - } - - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name IsBestPractice -Value $isBestPractice - Add-Member -Force -InputObject $value -MemberType NoteProperty -Name Notes -Value "Consider creating equally sized data files." - $result += $value - Write-Message -Level Verbose -Message "Data File Size Equal evaluated." - - Select-DefaultView -InputObject $result -Property ComputerName, InstanceName, SqlInstance, Rule, Recommended, IsBestPractice } } end { @@ -97557,11 +96907,11 @@ function Update-DbaServiceAccount { .PARAMETER PreviousPassword An old password of the service account. Optional when run under local admin privileges. - .PARAMETER NewPassword + .PARAMETER SecurePassword New password of the service account. The function will ask for a password if not specified. MSAs and local system accounts will ignore the password. .PARAMETER Username - Username of the service account. Cannot be used with -ServiceCredential. For local service accounts use one of the following usernames omitting the -Password parameter: + Username of the service account. Cannot be used with -ServiceCredential. For local service accounts use one of the following usernames omitting the -SecurePassword parameter: LOCALSERVICE NETWORKSERVICE LOCALSYSTEM @@ -97588,8 +96938,8 @@ function Update-DbaServiceAccount { Requires Local Admin rights on destination computer(s). .EXAMPLE - PS C:\> $NewPassword = ConvertTo-SecureString 'Qwerty1234' -AsPlainText -Force - Update-DbaServiceAccount -ComputerName sql1 -ServiceName 'MSSQL$MYINSTANCE' -Password $NewPassword + PS C:\> $SecurePassword = ConvertTo-SecureString 'Qwerty1234' -AsPlainText -Force + Update-DbaServiceAccount -ComputerName sql1 -ServiceName 'MSSQL$MYINSTANCE' -SecurePassword $SecurePassword Changes the current service account's password of the service MSSQL$MYINSTANCE to 'Qwerty1234' @@ -97626,9 +96976,8 @@ function Update-DbaServiceAccount { [string]$Username, [PSCredential]$ServiceCredential, [securestring]$PreviousPassword = (New-Object System.Security.SecureString), - [Alias("Password")] - [securestring]$NewPassword = (New-Object System.Security.SecureString), - [Alias('Silent')] + [Alias("Password", "NewPassword")] + [securestring]$SecurePassword = (New-Object System.Security.SecureString), [switch]$EnableException ) begin { @@ -97653,16 +97002,16 @@ function Update-DbaServiceAccount { #System logins should not have a domain name, whitespaces or passwords $trimmedUsername = (Split-Path $Username -Leaf).Trim().Replace(' ', '') #Request password input if password was not specified and account is not MSA or system login - if ($NewPassword.Length -eq 0 -and $PSBoundParameters.Keys -notcontains 'NewPassword' -and $trimmedUsername -notin 'NETWORKSERVICE', 'LOCALSYSTEM', 'LOCALSERVICE' -and $Username.EndsWith('$') -eq $false -and $Username.StartsWith('NT Service\') -eq $false) { - $NewPassword = Read-Host -Prompt "Input new password for account $UserName" -AsSecureString + if ($SecurePassword.Length -eq 0 -and $PSBoundParameters.Keys -notcontains 'SecurePassword' -and $trimmedUsername -notin 'NETWORKSERVICE', 'LOCALSYSTEM', 'LOCALSERVICE' -and $Username.EndsWith('$') -eq $false -and $Username.StartsWith('NT Service\') -eq $false) { + $SecurePassword = Read-Host -Prompt "Input new password for account $UserName" -AsSecureString $NewPassword2 = Read-Host -Prompt "Repeat password" -AsSecureString - if ((New-Object System.Management.Automation.PSCredential ("user", $NewPassword)).GetNetworkCredential().Password -ne ` + if ((New-Object System.Management.Automation.PSCredential ("user", $SecurePassword)).GetNetworkCredential().Password -ne ` (New-Object System.Management.Automation.PSCredential ("user", $NewPassword2)).GetNetworkCredential().Password) { Stop-Function -Message "Passwords do not match" -Category InvalidArgument -EnableException $EnableException return } } - $currentCredential = New-Object System.Management.Automation.PSCredential ($Username, $NewPassword) + $currentCredential = New-Object System.Management.Automation.PSCredential ($Username, $SecurePassword) } elseif ($ServiceCredential) { $actionType = 'Account' $currentCredential = $ServiceCredential @@ -97714,7 +97063,7 @@ function Update-DbaServiceAccount { foreach ($svc in $svcCollection) { if ($serviceObject = Get-DbaService -ComputerName $svc.ComputerName -ServiceName $svc.ServiceName -Credential $Credential -EnableException:$EnableException) { $outMessage = $outStatus = $agent = $null - if ($actionType -eq 'Password' -and $NewPassword.Length -eq 0) { + if ($actionType -eq 'Password' -and $SecurePassword.Length -eq 0) { $currentPassword = Read-Host -Prompt "New password for $($serviceObject.StartName) ($($svc.ServiceName) on $($svc.ComputerName))" -AsSecureString $currentPassword2 = Read-Host -Prompt "Repeat password" -AsSecureString if ((New-Object System.Management.Automation.PSCredential ("user", $currentPassword)).GetNetworkCredential().Password -ne ` @@ -97722,7 +97071,7 @@ function Update-DbaServiceAccount { Stop-Function -Message "Passwords do not match. This service will not be updated" -Category InvalidArgument -EnableException $EnableException -Continue } } else { - $currentPassword = $NewPassword + $currentPassword = $SecurePassword } if ($serviceObject.ServiceType -eq 'Engine') { #Get SQL Agent running status @@ -99035,6 +98384,9 @@ function Connect-SqlInstance { .PARAMETER MinimumVersion The minimum version that the calling command will support + .PARAMETER StatementTimeout + Sets the number of seconds a statement is given to run before failing with a timeout error. + .EXAMPLE Connect-SqlInstance -SqlInstance sql2014 @@ -99049,6 +98401,7 @@ function Connect-SqlInstance { [object]$SqlCredential, [switch]$ParameterConnection, [switch]$RegularUser = $true, + [int]$StatementTimeout, [int]$MinimumVersion, [switch]$AzureUnsupported, [switch]$NonPooled @@ -99174,21 +98527,30 @@ function Connect-SqlInstance { $server = New-Object Microsoft.SqlServer.Management.Smo.Server $ConvertedSqlInstance.FullSmoName $server.ConnectionContext.ApplicationName = "dbatools PowerShell module - dbatools.io" if ($ConvertedSqlInstance.IsConnectionString) { $server.ConnectionContext.ConnectionString = $ConvertedSqlInstance.InputObject } - + try { + if (Test-Bound -ParameterName 'StatementTimeout') { + $server.ConnectionContext.StatementTimeout = $StatementTimeout + } $server.ConnectionContext.ConnectTimeout = [Sqlcollaborative.Dbatools.Connection.ConnectionHost]::SqlConnectionTimeout if ($null -ne $SqlCredential.UserName) { $username = ($SqlCredential.UserName).TrimStart("\") - - if ($username -like "*\*") { - $domain, $login = $username.Split("\") - $authtype = "Windows Authentication with Credential" - if ($domain) { - $formatteduser = "$login@$domain" + + # support both ad\username and username@ad + if ($username -like "*\*" -or $username -like "*@*") { + if ($username -like "*\*") { + $domain, $login = $username.Split("\") + $authtype = "Windows Authentication with Credential" + if ($domain) { + $formatteduser = "$login@$domain" + } else { + $formatteduser = $username.Split("\")[1] + } } else { - $formatteduser = $username.Split("\")[1] + $formatteduser = $SqlCredential.UserName } + $server.ConnectionContext.LoginSecure = $true $server.ConnectionContext.ConnectAsUser = $true $server.ConnectionContext.ConnectAsUserName = $formatteduser @@ -100748,7 +100110,7 @@ function Get-DecryptedObject { This function is heavily based on Antti Rantasaari's script at http://goo.gl/wpqSib Antti Rantasaari 2014, NetSPI License: BSD 3-Clause http://opensource.org/licenses/BSD-3-Clause - #> + #> param ( [Parameter(Mandatory)] [Microsoft.SqlServer.Management.Smo.Server]$SqlInstance, @@ -100854,14 +100216,14 @@ function Get-DecryptedObject { $sql = switch ($Type) { "LinkedServer" { "SELECT sysservers.srvname, - syslnklgns.Name, - substring(syslnklgns.pwdhash,5,$ivlen) iv, - substring(syslnklgns.pwdhash,$($ivlen + 5), - len(syslnklgns.pwdhash)-$($ivlen + 4)) pass - FROM master.sys.syslnklgns - inner join master.sys.sysservers - on syslnklgns.srvid=sysservers.srvid - WHERE len(pwdhash) > 0" + syslnklgns.Name, + substring(syslnklgns.pwdhash,5,$ivlen) iv, + substring(syslnklgns.pwdhash,$($ivlen + 5), + len(syslnklgns.pwdhash)-$($ivlen + 4)) pass + FROM master.sys.syslnklgns + inner join master.sys.sysservers + on syslnklgns.srvid=sysservers.srvid + WHERE len(pwdhash) > 0" } "Credential" { "SELECT QUOTENAME(name) AS name,credential_identity,substring(imageval,5,$ivlen) iv, substring(imageval,$($ivlen + 5),len(imageval)-$($ivlen + 4)) pass from sys.Credentials cred inner join sys.sysobjvalues obj on cred.credential_id = obj.objid where valclass=28 and valnum=2" @@ -100875,15 +100237,21 @@ function Get-DecryptedObject { $results = Invoke-Command2 -ErrorAction Stop -Raw -Credential $Credential -ComputerName $sourceNetBios -ArgumentList $connString, $sql { $connString = $args[0]; $sql = $args[1] $conn = New-Object System.Data.SqlClient.SQLConnection($connString) - $conn.open() - $cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn); + $cmd = New-Object System.Data.SqlClient.SqlCommand($sql, $conn) $dt = New-Object System.Data.DataTable + $conn.open() $dt.Load($cmd.ExecuteReader()) $conn.Close() $conn.Dispose() return $dt } } catch { + try { + $conn.Close() + $conn.Dispose() + } catch { + $null = 1 + } Stop-Function -Message "Can't establish local DAC connection on $sourcename." -Target $server -ErrorRecord $_ return } @@ -108589,11 +107957,13 @@ function Write-ProgressHelper { param ( [int]$StepNumber, [string]$Activity, - [string]$Message + [string]$Message, + [int]$TotalSteps, + [switch]$ExcludePercent ) - + $caller = (Get-PSCallStack)[1].Command - + if (-not $Activity) { $Activity = switch ($caller) { "Export-DbaInstance" { @@ -108617,12 +107987,21 @@ function Write-ProgressHelper { "Sync-DbaAvailabilityGroup" { "Syncing availability group" } + "Sync-DbaAvailabilityGroup" { + "Syncing availability group" + } default { - "Processing $caller" + "Executing $caller" } } } - - $TotalSteps = ([regex]::Matches((Get-Command -Module dbatools -Name $caller).Definition, "Write-ProgressHelper")).Count - Write-Progress -Activity $Activity -Status $Message -PercentComplete (($StepNumber / $TotalSteps) * 100) + + if (-not $TotalSteps) { + $TotalSteps = ([regex]::Matches((Get-Command -Module dbatools -Name $caller).Definition, "Write-ProgressHelper")).Count + } + if ($ExcludePercent) { + Write-Progress -Activity $Activity -Status $Message + } else { + Write-Progress -Activity $Activity -Status $Message -PercentComplete (($StepNumber / $TotalSteps) * 100) + } } diff --git a/bin/dbatools-index.json b/bin/dbatools-index.json index 44ccc6dadc..b6f9db3536 100644 --- a/bin/dbatools-index.json +++ b/bin/dbatools-index.json @@ -565,9 +565,9 @@ "" ], [ - "Password", + "SecurePassword", "The password for the certificate, if it is password protected.", - "", + "Password", false, "false", "" @@ -635,7 +635,7 @@ "Name": "Add-DbaComputerCertificate", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eAdd-DbaComputerCertificate -ComputerName Server1 -Path C:\\temp\\cert.cer\nAdds the local C:\\temp\\cert.cer to the remote server Server1 in LocalMachine\\My (Personal).\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eAdd-DbaComputerCertificate -Path C:\\temp\\cert.cer\nAdds the local C:\\temp\\cert.cer to the local computer\u0027s LocalMachine\\My (Personal) certificate store.", - "Syntax": "Add-DbaComputerCertificate [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Password] \u003cSecureString\u003e] [[-Certificate] \u003cX509Certificate2[]\u003e] [[-Path] \u003cString\u003e] [[-Store] \u003cString\u003e] [[-Folder] \u003cString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "Add-DbaComputerCertificate [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [[-SecurePassword] \u003cSecureString\u003e] [[-Certificate] \u003cX509Certificate2[]\u003e] [[-Path] \u003cString\u003e] [[-Store] \u003cString\u003e] [[-Folder] \u003cString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Add-DbaDbMirrorMonitor", @@ -1216,9 +1216,9 @@ "" ], [ - "Password", + "SecurePassword", "The password to encrypt the exported key. This must be a SecureString.", - "", + "Password", false, "false", "" @@ -1270,7 +1270,7 @@ "Name": "Backup-DbaDbMasterKey", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eBackup-DbaDbMasterKey -SqlInstance server1\\sql2016\n```\r\nComputerName : SERVER1\r\nInstanceName : SQL2016\r\nSqlInstance : SERVER1\\SQL2016\r\nDatabase : master\r\nFilename : E:\\MSSQL13.SQL2016\\MSSQL\\Backup\\server1$sql2016-master-20170614162311.key\r\nStatus : Success\r\n```\nPrompts for export password, then logs into server1\\sql2016 with Windows credentials then backs up all database keys to the default backup directory.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eBackup-DbaDbMasterKey -SqlInstance Server1 -Database db1 -Path \\\\nas\\sqlbackups\\keys\nLogs into sql2016 with Windows credentials then backs up db1\u0027s keys to the \\\\nas\\sqlbackups\\keys directory.", - "Syntax": "Backup-DbaDbMasterKey [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Database] \u003cString[]\u003e] [[-ExcludeDatabase] \u003cString[]\u003e] [[-Password] \u003cSecureString\u003e] [[-Path] \u003cString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "Backup-DbaDbMasterKey [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Database] \u003cString[]\u003e] [[-ExcludeDatabase] \u003cString[]\u003e] [[-SecurePassword] \u003cSecureString\u003e] [[-Path] \u003cString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Clear-DbaConnectionPool", @@ -1511,9 +1511,9 @@ "" ], [ - "Credential", - "Credential object used to connect to the SQL Server Instance as a different user. This can be a Windows or SQL Server account. Windows users are determined by the existence of a backslash, so if you \r\nare intending to use an alternative Windows connection instead of a SQL login, ensure it contains a backslash.", "SqlCredential", + "Credential object used to connect to the SQL Server Instance as a different user. This can be a Windows or SQL Server account. Windows users are determined by the existence of a backslash, so if you \r\nare intending to use an alternative Windows connection instead of a SQL login, ensure it contains a backslash.", + "Credential", false, "false", "" @@ -1582,14 +1582,6 @@ "false", "" ], - [ - "IsActiveDirectoryUniversalAuth", - "If this switch is enabled, the connection will be configured to use Azure Active Directory authentication.", - "", - false, - "false", - "False" - ], [ "LockTimeout", "Sets the time in seconds required for the connection to time out when the current transaction is locked.", @@ -1709,6 +1701,14 @@ false, "false", "False" + ], + [ + "DisableException", + "By default in most of our commands, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\nThis command, however, gifts you with \"sea of red\" exceptions, by default, because it is useful for advanced scripting.\nUsing this switch turns our \"nice by default\" feature on which makes errors into pretty warnings.", + "", + false, + "false", + "False" ] ], "Alias": "Connect-DbaServer,Get-DbaInstance", @@ -1716,8 +1716,8 @@ "Synopsis": "Creates a robust SMO SQL Server object.", "Name": "Connect-DbaInstance", "Links": "https://dbatools.io/Connect-DbaInstance", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eConnect-DbaInstance -SqlInstance sql2014\nCreates an SMO Server object that connects using Windows Authentication\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$wincred = Get-Credential ad\\sqladmin\nPS C:\\\u003e Connect-DbaInstance -SqlInstance sql2014 -Credential $wincred\nCreates an SMO Server object that connects using alternative Windows credentials\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003e$sqlcred = Get-Credential sqladmin\nPS C:\\\u003e $server = Connect-DbaInstance -SqlInstance sql2014 -Credential $sqlcred\nLogin to sql2014 as SQL login sqladmin.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -ClientName \"my connection\"\nCreates an SMO Server object that connects using Windows Authentication and uses the client name \"my connection\". So when you open up profiler or use extended events, you can search for \"my \r\nconnection\".\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -AppendConnectionString \"Packet Size=4096;AttachDbFilename=C:\\MyFolder\\MyDataFile.mdf;User Instance=true;\"\nCreates an SMO Server object that connects to sql2014 using Windows Authentication, then it sets the packet size (this can also be done via -PacketSize) and other connection attributes.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -NetworkProtocol TcpIp -MultiSubnetFailover\nCreates an SMO Server object that connects using Windows Authentication that uses TCP/IP and has MultiSubnetFailover enabled.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance sql2016 -ApplicationIntent ReadOnly\nConnects with ReadOnly ApplicationIntent.", - "Syntax": "Connect-DbaInstance [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-Credential] \u003cPSCredential\u003e] [[-Database] \u003cObject[]\u003e] [[-AccessToken] \u003cString\u003e] [[-ApplicationIntent] \u003cString\u003e] [[-BatchSeparator] \u003cString\u003e] [[-ClientName] \u003cString\u003e] [[-ConnectTimeout] \u003cInt32\u003e] [-EncryptConnection] [[-FailoverPartner] \u003cString\u003e] [-IsActiveDirectoryUniversalAuth] [[-LockTimeout] \u003cInt32\u003e] [[-MaxPoolSize] \u003cInt32\u003e] [[-MinPoolSize] \u003cInt32\u003e] [-MultipleActiveResultSets] [-MultiSubnetFailover] [[-NetworkProtocol] \u003cString\u003e] [-NonPooledConnection] [[-PacketSize] \u003cInt32\u003e] [[-PooledConnectionLifetime] \u003cInt32\u003e] \r\n[[-SqlExecutionModes] \u003cString\u003e] [[-StatementTimeout] \u003cInt32\u003e] [-TrustServerCertificate] [[-WorkstationId] \u003cString\u003e] [[-AppendConnectionString] \u003cString\u003e] [-SqlConnectionOnly] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eConnect-DbaInstance -SqlInstance sql2014\nCreates an SMO Server object that connects using Windows Authentication\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$wincred = Get-Credential ad\\sqladmin\nPS C:\\\u003e Connect-DbaInstance -SqlInstance sql2014 -SqlCredential $wincred\nCreates an SMO Server object that connects using alternative Windows credentials\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003e$sqlcred = Get-Credential sqladmin\nPS C:\\\u003e $server = Connect-DbaInstance -SqlInstance sql2014 -SqlCredential $sqlcred\nLogin to sql2014 as SQL login sqladmin.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -ClientName \"my connection\"\nCreates an SMO Server object that connects using Windows Authentication and uses the client name \"my connection\". So when you open up profiler or use extended events, you can search for \"my \r\nconnection\".\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -AppendConnectionString \"Packet Size=4096;AttachDbFilename=C:\\MyFolder\\MyDataFile.mdf;User Instance=true;\"\nCreates an SMO Server object that connects to sql2014 using Windows Authentication, then it sets the packet size (this can also be done via -PacketSize) and other connection attributes.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance -SqlInstance sql2014 -NetworkProtocol TcpIp -MultiSubnetFailover\nCreates an SMO Server object that connects using Windows Authentication that uses TCP/IP and has MultiSubnetFailover enabled.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003e$server = Connect-DbaInstance sql2016 -ApplicationIntent ReadOnly\nConnects with ReadOnly ApplicationIntent.", + "Syntax": "Connect-DbaInstance [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cObject[]\u003e] [[-AccessToken] \u003cString\u003e] [[-ApplicationIntent] \u003cString\u003e] [[-BatchSeparator] \u003cString\u003e] [[-ClientName] \u003cString\u003e] [[-ConnectTimeout] \u003cInt32\u003e] [-EncryptConnection] [[-FailoverPartner] \u003cString\u003e] [[-LockTimeout] \u003cInt32\u003e] [[-MaxPoolSize] \u003cInt32\u003e] [[-MinPoolSize] \u003cInt32\u003e] [-MultipleActiveResultSets] [-MultiSubnetFailover] [[-NetworkProtocol] \u003cString\u003e] [-NonPooledConnection] [[-PacketSize] \u003cInt32\u003e] [[-PooledConnectionLifetime] \u003cInt32\u003e] [[-SqlExecutionModes] \u003cString\u003e] \r\n[[-StatementTimeout] \u003cInt32\u003e] [-TrustServerCertificate] [[-WorkstationId] \u003cString\u003e] [[-AppendConnectionString] \u003cString\u003e] [-SqlConnectionOnly] [-DisableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "ConvertTo-DbaDataTable", @@ -1969,119 +1969,6 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentAlert -Source sqlserver2014a -Destination sqlcluster\nCopies all alerts from sqlserver2014a to sqlcluster using Windows credentials. If alerts with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentAlert -Source sqlserver2014a -Destination sqlcluster -Alert PSAlert -SourceSqlCredential $cred -Force\nCopies a only the alert named PSAlert from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If an alert with the same name exists on \r\nsqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentAlert -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", "Syntax": "Copy-DbaAgentAlert [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Alert] \u003cObject[]\u003e] [[-ExcludeAlert] \u003cObject[]\u003e] [-IncludeDefaults] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, - { - "CommandName": "Copy-DbaAgentCategory", - "Description": "By default, all SQL Agent categories for Jobs, Operators and Alerts are copied.\n\nThe -OperatorCategories parameter is auto-populated for command-line completion and can be used to copy only specific operator categories.\nThe -AgentCategories parameter is auto-populated for command-line completion and can be used to copy only specific agent categories.\nThe -JobCategories parameter is auto-populated for command-line completion and can be used to copy only specific job categories.\n\nIf the category already exists on the destination, it will be skipped unless -Force is used.", - "Tags": [ - "Migration", - "Agent" - ], - "Params": [ - [ - "Source", - "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "SourceSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "Destination", - "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "DestinationSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "CategoryType", - "Specifies the Category Type to migrate. Valid options are \"Job\", \"Alert\" and \"Operator\". When CategoryType is specified, all categories from the selected type will be migrated. For granular \r\nmigrations, use the three parameters below.", - "", - false, - "false", - "" - ], - [ - "JobCategory", - "This parameter is auto-populated for command-line completion and can be used to copy only specific job categories.", - "", - false, - "false", - "" - ], - [ - "AgentCategory", - "This parameter is auto-populated for command-line completion and can be used to copy only specific agent categories.", - "", - false, - "false", - "" - ], - [ - "OperatorCategory", - "This parameter is auto-populated for command-line completion and can be used to copy only specific operator categories.", - "", - false, - "false", - "" - ], - [ - "Force", - "If this switch is enabled, the Category will be dropped and recreated on Destination.", - "", - false, - "false", - "False" - ], - [ - "EnableException", - "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", - false, - "false", - "False" - ], - [ - "WhatIf", - "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", - "wi", - false, - "false", - "" - ], - [ - "Confirm", - "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", - "cf", - false, - "false", - "" - ] - ], - "Alias": "Copy-SqlAgentCategory", - "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Copy-DbaAgentCategory migrates SQL Agent categories from one SQL Server to another. This is similar to sp_add_category.\n\nhttps://msdn.microsoft.com/en-us/library/ms181597.aspx", - "Name": "Copy-DbaAgentCategory", - "Links": "https://dbatools.io/Copy-DbaAgentCategory", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster\nCopies all operator categories from sqlserver2014a to sqlcluster using Windows authentication. If operator categories with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster -OperatorCategory PSOperator -SourceSqlCredential $cred -Force\nCopies a single operator category, the PSOperator operator category from sqlserver2014a to sqlcluster using SQL credentials to authenticate to sqlserver2014a and Windows credentials for sqlcluster. \r\nIf an operator category with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentCategory -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", - "Syntax": "Copy-DbaAgentCategory -Source \u003cDbaInstanceParameter\u003e [-SourceSqlCredential \u003cPSCredential\u003e] -Destination \u003cDbaInstanceParameter[]\u003e [-DestinationSqlCredential \u003cPSCredential\u003e] [-JobCategory \u003cString[]\u003e] [-AgentCategory \u003cString[]\u003e] [-OperatorCategory \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nCopy-DbaAgentCategory -Source \u003cDbaInstanceParameter\u003e [-SourceSqlCredential \u003cPSCredential\u003e] -Destination \u003cDbaInstanceParameter[]\u003e [-DestinationSqlCredential \u003cPSCredential\u003e] [-CategoryType \u003cString[]\u003e] [-JobCategory \u003cString[]\u003e] [-AgentCategory \u003cString[]\u003e] [-OperatorCategory \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" - }, { "CommandName": "Copy-DbaAgentJob", "Description": "By default, all jobs are copied. The -Job parameter is auto-populated for command-line completion and can be used to copy only specific jobs.\n\nIf the job already exists on the destination, it will be skipped unless -Force is used.", @@ -2197,12 +2084,11 @@ "Syntax": "Copy-DbaAgentJob [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Job] \u003cObject[]\u003e] [[-ExcludeJob] \u003cObject[]\u003e] [-DisableOnSource] [-DisableOnDestination] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { - "CommandName": "Copy-DbaAgentOperator", - "Description": "By default, all operators are copied. The -Operators parameter is auto-populated for command-line completion and can be used to copy only specific operators.\n\nIf the associated credentials for the operator do not exist on the destination, it will be skipped. If the operator already exists on the destination, it will be skipped unless -Force is used.", + "CommandName": "Copy-DbaAgentJobCategory", + "Description": "By default, all SQL Agent categories for Jobs, Operators and Alerts are copied.\n\nThe -OperatorCategories parameter is auto-populated for command-line completion and can be used to copy only specific operator categories.\nThe -AgentCategories parameter is auto-populated for command-line completion and can be used to copy only specific agent categories.\nThe -JobCategories parameter is auto-populated for command-line completion and can be used to copy only specific job categories.\n\nIf the category already exists on the destination, it will be skipped unless -Force is used.", "Tags": [ "Migration", - "Agent", - "Operator" + "Agent" ], "Params": [ [ @@ -2238,113 +2124,32 @@ "" ], [ - "Operator", - "The operator(s) to process. This list is auto-populated from the server. If unspecified, all operators will be processed.", - "", - false, - "false", - "" - ], - [ - "ExcludeOperator", - "The operators(s) to exclude. This list is auto-populated from the server.", - "", - false, - "false", - "" - ], - [ - "Force", - "If this switch is enabled, the Operator will be dropped and recreated on Destination.", - "", - false, - "false", - "False" - ], - [ - "EnableException", - "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", - false, - "false", - "False" - ], - [ - "WhatIf", - "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", - "wi", - false, - "false", - "" - ], - [ - "Confirm", - "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", - "cf", - false, - "false", - "" - ] - ], - "Alias": "Copy-SqlOperator", - "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Copy-DbaAgentOperator migrates operators from one SQL Server to another.", - "Name": "Copy-DbaAgentOperator", - "Links": "https://dbatools.io/Copy-DbaAgentOperator", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster\nCopies all operators from sqlserver2014a to sqlcluster using Windows credentials. If operators with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster -Operator PSOperator -SourceSqlCredential $cred -Force\nCopies only the PSOperator operator from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If an operator with the same name exists on \r\nsqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", - "Syntax": "Copy-DbaAgentOperator [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Operator] \u003cObject[]\u003e] [[-ExcludeOperator] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" - }, - { - "CommandName": "Copy-DbaAgentProxyAccount", - "Description": "By default, all proxy accounts are copied. The -ProxyAccounts parameter is auto-populated for command-line completion and can be used to copy only specific proxy accounts.\n\nIf the associated credential for the account does not exist on the destination, it will be skipped. If the proxy account already exists on the destination, it will be skipped unless -Force is used.", - "Tags": [ - "Migration", - "Agent" - ], - "Params": [ - [ - "Source", - "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "SourceSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "CategoryType", + "Specifies the Category Type to migrate. Valid options are \"Job\", \"Alert\" and \"Operator\". When CategoryType is specified, all categories from the selected type will be migrated. For granular \r\nmigrations, use the three parameters below.", "", false, "false", "" ], [ - "Destination", - "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "DestinationSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "JobCategory", + "This parameter is auto-populated for command-line completion and can be used to copy only specific job categories.", "", false, "false", "" ], [ - "ProxyAccount", - "Only migrate specific proxy accounts", + "AgentCategory", + "This parameter is auto-populated for command-line completion and can be used to copy only specific agent categories.", "", false, "false", "" ], [ - "ExcludeProxyAccount", - "Migrate all proxy accounts except the ones explicitly excluded", + "OperatorCategory", + "This parameter is auto-populated for command-line completion and can be used to copy only specific operator categories.", "", false, "false", @@ -2352,7 +2157,7 @@ ], [ "Force", - "If this switch is enabled, the Operator will be dropped and recreated on Destination.", + "If this switch is enabled, the Category will be dropped and recreated on Destination.", "", false, "false", @@ -2383,21 +2188,21 @@ "" ] ], - "Alias": "Copy-SqlProxyAccount", + "Alias": "Copy-DbaAgentCategory,Copy-SqlAgentCategory", "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Copy-DbaAgentProxyAccount migrates proxy accounts from one SQL Server to another.", - "Name": "Copy-DbaAgentProxyAccount", - "Links": "https://dbatools.io/Copy-DbaAgentProxyAccount", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster\nCopies all proxy accounts from sqlserver2014a to sqlcluster using Windows credentials. If proxy accounts with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster -ProxyAccount PSProxy -SourceSqlCredential $cred -Force\nCopies only the PSProxy proxy account from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If a proxy account with the same name exists \r\non sqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxyAccount -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", - "Syntax": "Copy-DbaAgentProxyAccount [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-ProxyAccount] \u003cString[]\u003e] [[-ExcludeProxyAccount] \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Synopsis": "Copy-DbaAgentJobCategory migrates SQL Agent categories from one SQL Server to another. This is similar to sp_add_category.\n\nhttps://msdn.microsoft.com/en-us/library/ms181597.aspx", + "Name": "Copy-DbaAgentJobCategory", + "Links": "https://dbatools.io/Copy-DbaAgentJobCategory", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster\nCopies all operator categories from sqlserver2014a to sqlcluster using Windows authentication. If operator categories with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster -OperatorCategory PSOperator -SourceSqlCredential $cred -Force\nCopies a single operator category, the PSOperator operator category from sqlserver2014a to sqlcluster using SQL credentials to authenticate to sqlserver2014a and Windows credentials for sqlcluster. \r\nIf an operator category with the same name exists on sqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentJobCategory -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", + "Syntax": "Copy-DbaAgentJobCategory -Source \u003cDbaInstanceParameter\u003e [-SourceSqlCredential \u003cPSCredential\u003e] -Destination \u003cDbaInstanceParameter[]\u003e [-DestinationSqlCredential \u003cPSCredential\u003e] [-JobCategory \u003cString[]\u003e] [-AgentCategory \u003cString[]\u003e] [-OperatorCategory \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nCopy-DbaAgentJobCategory -Source \u003cDbaInstanceParameter\u003e [-SourceSqlCredential \u003cPSCredential\u003e] -Destination \u003cDbaInstanceParameter[]\u003e [-DestinationSqlCredential \u003cPSCredential\u003e] [-CategoryType \u003cString[]\u003e] [-JobCategory \u003cString[]\u003e] [-AgentCategory \u003cString[]\u003e] [-OperatorCategory \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { - "CommandName": "Copy-DbaAgentServer", - "Description": "A wrapper function that calls the associated Copy command for each of the object types seen in SSMS under SQL Server Agent. This also copies all of the the SQL Agent properties (job history max rows, DBMail profile name, etc.).\n\nYou must have sysadmin access and server version must be SQL Server version 2000 or greater.", + "CommandName": "Copy-DbaAgentOperator", + "Description": "By default, all operators are copied. The -Operators parameter is auto-populated for command-line completion and can be used to copy only specific operators.\n\nIf the associated credentials for the operator do not exist on the destination, it will be skipped. If the operator already exists on the destination, it will be skipped unless -Force is used.", "Tags": [ "Migration", - "SqlServerAgent", - "SqlAgent" + "Agent", + "Operator" ], "Params": [ [ @@ -2433,24 +2238,24 @@ "" ], [ - "DisableJobsOnDestination", - "If this switch is enabled, the jobs will be disabled on Destination after copying.", + "Operator", + "The operator(s) to process. This list is auto-populated from the server. If unspecified, all operators will be processed.", "", false, "false", - "False" + "" ], [ - "DisableJobsOnSource", - "If this switch is enabled, the jobs will be disabled on Source after copying.", + "ExcludeOperator", + "The operators(s) to exclude. This list is auto-populated from the server.", "", false, "false", - "False" + "" ], [ "Force", - "If this switch is enabled, existing objects on Destination with matching names from Source will be dropped, then copied.", + "If this switch is enabled, the Operator will be dropped and recreated on Destination.", "", false, "false", @@ -2481,16 +2286,113 @@ "" ] ], - "Alias": "Copy-DbaSqlServerAgent,Copy-SqlServerAgent", + "Alias": "Copy-SqlOperator", "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Copy SQL Server Agent from one server to another.", - "Name": "Copy-DbaAgentServer", - "Links": "https://dbatools.io/Copy-DbaAgentServer", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster\nCopies all job server objects from sqlserver2014a to sqlcluster using Windows credentials for authentication. If job objects with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all job objects from sqlserver2014a to sqlcluster using SQL credentials to authentication to sqlserver2014a and Windows credentials to authenticate to sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.", - "Syntax": "Copy-DbaAgentServer [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [-DisableJobsOnDestination] [-DisableJobsOnSource] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Synopsis": "Copy-DbaAgentOperator migrates operators from one SQL Server to another.", + "Name": "Copy-DbaAgentOperator", + "Links": "https://dbatools.io/Copy-DbaAgentOperator", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster\nCopies all operators from sqlserver2014a to sqlcluster using Windows credentials. If operators with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster -Operator PSOperator -SourceSqlCredential $cred -Force\nCopies only the PSOperator operator from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If an operator with the same name exists on \r\nsqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentOperator -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", + "Syntax": "Copy-DbaAgentOperator [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Operator] \u003cObject[]\u003e] [[-ExcludeOperator] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { - "CommandName": "Copy-DbaAgentSharedSchedule", + "CommandName": "Copy-DbaAgentProxy", + "Description": "By default, all proxy accounts are copied. The -ProxyAccounts parameter is auto-populated for command-line completion and can be used to copy only specific proxy accounts.\n\nIf the associated credential for the account does not exist on the destination, it will be skipped. If the proxy account already exists on the destination, it will be skipped unless -Force is used.", + "Tags": [ + "Migration", + "Agent" + ], + "Params": [ + [ + "Source", + "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "SourceSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "Destination", + "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "DestinationSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "ProxyAccount", + "Only migrate specific proxy accounts", + "", + false, + "false", + "" + ], + [ + "ExcludeProxyAccount", + "Migrate all proxy accounts except the ones explicitly excluded", + "", + false, + "false", + "" + ], + [ + "Force", + "If this switch is enabled, the Operator will be dropped and recreated on Destination.", + "", + false, + "false", + "False" + ], + [ + "EnableException", + "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", + "Silent", + false, + "false", + "False" + ], + [ + "WhatIf", + "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", + "wi", + false, + "false", + "" + ], + [ + "Confirm", + "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", + "cf", + false, + "false", + "" + ] + ], + "Alias": "Copy-DbaAgentProxyAccount,Copy-SqlProxyAccount", + "Author": "Chrissy LeMaire (@cl), netnerds.net", + "Synopsis": "Copy-DbaAgentProxy migrates proxy accounts from one SQL Server to another.", + "Name": "Copy-DbaAgentProxy", + "Links": "https://dbatools.io/Copy-DbaAgentProxy", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster\nCopies all proxy accounts from sqlserver2014a to sqlcluster using Windows credentials. If proxy accounts with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster -ProxyAccount PSProxy -SourceSqlCredential $cred -Force\nCopies only the PSProxy proxy account from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If a proxy account with the same name exists \r\non sqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentProxy -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", + "Syntax": "Copy-DbaAgentProxy [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-ProxyAccount] \u003cString[]\u003e] [[-ExcludeProxyAccount] \u003cString[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + }, + { + "CommandName": "Copy-DbaAgentSchedule", "Description": "All shared job schedules are copied.\n\nIf the associated credential for the account does not exist on the destination, it will be skipped. If the shared job schedule already exists on the destination, it will be skipped unless -Force is used.", "Tags": [ "Migration", @@ -2562,13 +2464,111 @@ "" ] ], - "Alias": "Copy-SqlSharedSchedule", + "Alias": "Copy-DbaAgentSharedSchedule,Copy-SqlSharedSchedule", + "Author": "Chrissy LeMaire (@cl), netnerds.net", + "Synopsis": "Copy-DbaAgentSchedule migrates shared job schedules from one SQL Server to another.", + "Name": "Copy-DbaAgentSchedule", + "Links": "https://dbatools.io/Copy-DbaAgentSchedule", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster\nCopies all shared job schedules from sqlserver2014a to sqlcluster using Windows credentials. If shared job schedules with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentSchedule -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", + "Syntax": "Copy-DbaAgentSchedule [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + }, + { + "CommandName": "Copy-DbaAgentServer", + "Description": "A wrapper function that calls the associated Copy command for each of the object types seen in SSMS under SQL Server Agent. This also copies all of the the SQL Agent properties (job history max rows, DBMail profile name, etc.).\n\nYou must have sysadmin access and server version must be SQL Server version 2000 or greater.", + "Tags": [ + "Migration", + "SqlServerAgent", + "SqlAgent" + ], + "Params": [ + [ + "Source", + "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "SourceSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "Destination", + "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "DestinationSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "DisableJobsOnDestination", + "If this switch is enabled, the jobs will be disabled on Destination after copying.", + "", + false, + "false", + "False" + ], + [ + "DisableJobsOnSource", + "If this switch is enabled, the jobs will be disabled on Source after copying.", + "", + false, + "false", + "False" + ], + [ + "Force", + "If this switch is enabled, existing objects on Destination with matching names from Source will be dropped, then copied.", + "", + false, + "false", + "False" + ], + [ + "EnableException", + "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", + "Silent", + false, + "false", + "False" + ], + [ + "WhatIf", + "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", + "wi", + false, + "false", + "" + ], + [ + "Confirm", + "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", + "cf", + false, + "false", + "" + ] + ], + "Alias": "Copy-DbaSqlServerAgent,Copy-SqlServerAgent", "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Copy-DbaAgentSharedSchedule migrates shared job schedules from one SQL Server to another.", - "Name": "Copy-DbaAgentSharedSchedule", - "Links": "https://dbatools.io/Copy-DbaAgentSharedSchedule", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentSharedSchedule -Source sqlserver2014a -Destination sqlcluster\nCopies all shared job schedules from sqlserver2014a to sqlcluster using Windows credentials. If shared job schedules with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentSharedSchedule -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", - "Syntax": "Copy-DbaAgentSharedSchedule [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Synopsis": "Copy SQL Server Agent from one server to another.", + "Name": "Copy-DbaAgentServer", + "Links": "https://dbatools.io/Copy-DbaAgentServer", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster\nCopies all job server objects from sqlserver2014a to sqlcluster using Windows credentials for authentication. If job objects with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all job objects from sqlserver2014a to sqlcluster using SQL credentials to authentication to sqlserver2014a and Windows credentials to authenticate to sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaAgentServer -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.", + "Syntax": "Copy-DbaAgentServer [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [-DisableJobsOnDestination] [-DisableJobsOnSource] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Copy-DbaBackupDevice", @@ -2660,8 +2660,8 @@ "Syntax": "Copy-DbaBackupDevice [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-BackupDevice] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { - "CommandName": "Copy-DbaCentralManagementServer", - "Description": "Copy-DbaCentralManagementServer copies all groups, subgroups, and server instances from one SQL Server to another.", + "CommandName": "Copy-DbaCmsRegServer", + "Description": "Copy-DbaCmsRegServer copies all groups, subgroups, and server instances from one SQL Server to another.", "Tags": "Migration", "Params": [ [ @@ -2697,9 +2697,9 @@ "" ], [ + "Group", + "This is an auto-populated array that contains your Central Management Server top-level groups on Source. You can specify one, many or none.\nIf Group is not specified, all groups in your Central Management Server will be copied.", "CMSGroup", - "This is an auto-populated array that contains your Central Management Server top-level groups on Source. You can specify one, many or none.\nIf CMSGroup is not specified, all groups in your Central Management Server will be copied.", - "", false, "false", "" @@ -2723,7 +2723,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -2745,13 +2745,13 @@ "" ] ], - "Alias": "Copy-SqlCentralManagementServer", + "Alias": "Copy-DbaCentralManagementServer,Copy-SqlCentralManagementServer", "Author": "Chrissy LeMaire (@cl), netnerds.net", "Synopsis": "Migrates SQL Server Central Management groups and server instances from one SQL Server to another.", - "Name": "Copy-DbaCentralManagementServer", - "Links": "https://dbatools.io/Copy-DbaCentralManagementServer", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster\nAll groups, subgroups, and server instances are copied from sqlserver2014a CMS to sqlcluster CMS.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster -CMSGroup Group1,Group3\nTop-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaCentralManagementServer -Source sqlserver2014a -Destination sqlcluster -CMSGroup Group1,Group3 -SwitchServerName -SourceSqlCredential $SourceSqlCredential -DestinationSqlCredential \r\n$DestinationSqlCredential\nTop-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster. When adding sql instances to sqlcluster, if the server name of the \r\nmigrating instance is \"sqlcluster\", it will be switched to \"sqlserver\".\nIf SwitchServerName is not specified, \"sqlcluster\" will be skipped.", - "Syntax": "Copy-DbaCentralManagementServer [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-CMSGroup] \u003cObject[]\u003e] [-SwitchServerName] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Name": "Copy-DbaCmsRegServer", + "Links": "https://dbatools.io/Copy-DbaCmsRegServer", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster\nAll groups, subgroups, and server instances are copied from sqlserver2014a CMS to sqlcluster CMS.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster -Group Group1,Group3\nTop-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaCmsRegServer -Source sqlserver2014a -Destination sqlcluster -Group Group1,Group3 -SwitchServerName -SourceSqlCredential $SourceSqlCredential -DestinationSqlCredential \r\n$DestinationSqlCredential\nTop-level groups Group1 and Group3 along with their subgroups and server instances are copied from sqlserver to sqlcluster. When adding sql instances to sqlcluster, if the server name of the \r\nmigrating instance is \"sqlcluster\", it will be switched to \"sqlserver\".\nIf SwitchServerName is not specified, \"sqlcluster\" will be skipped.", + "Syntax": "Copy-DbaCmsRegServer [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Group] \u003cString[]\u003e] [-SwitchServerName] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Copy-DbaCredential", @@ -3512,6 +3512,108 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaDbMail -Source sqlserver2014a -Destination sqlcluster\nCopies all database mail objects from sqlserver2014a to sqlcluster using Windows credentials. If database mail objects with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaDbMail -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all database mail objects from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaDbMail -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eCopy-DbaDbMail -Source sqlserver2014a -Destination sqlcluster -EnableException\nPerforms execution of function, and will throw a terminating exception if something breaks", "Syntax": "Copy-DbaDbMail -Source \u003cDbaInstanceParameter\u003e -Destination \u003cDbaInstanceParameter[]\u003e [-SourceSqlCredential \u003cPSCredential\u003e] [-DestinationSqlCredential \u003cPSCredential\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nCopy-DbaDbMail -Source \u003cDbaInstanceParameter\u003e -Destination \u003cDbaInstanceParameter[]\u003e [-Type \u003cString[]\u003e] [-SourceSqlCredential \u003cPSCredential\u003e] [-DestinationSqlCredential \u003cPSCredential\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, + { + "CommandName": "Copy-DbaDbQueryStoreOption", + "Description": "Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases.", + "Tags": "QueryStore", + "Params": [ + [ + "Source", + "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2016 or higher.", + "", + true, + "true (ByValue)", + "" + ], + [ + "SourceSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "SourceDatabase", + "Specifies the database to copy the Query Store configuration from.", + "", + true, + "true (ByValue)", + "" + ], + [ + "Destination", + "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2016 or higher.", + "", + true, + "true (ByValue)", + "" + ], + [ + "DestinationSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "DestinationDatabase", + "Specifies a list of databases that will receive a copy of the Query Store configuration of the SourceDatabase.", + "", + false, + "false", + "" + ], + [ + "Exclude", + "Specifies a list of databases which will NOT receive a copy of the Query Store configuration.", + "", + false, + "false", + "" + ], + [ + "AllDatabases", + "If this switch is enabled, the Query Store configuration will be copied to all databases on the destination instance.", + "", + false, + "false", + "False" + ], + [ + "EnableException", + "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", + "Silent", + false, + "false", + "False" + ], + [ + "WhatIf", + "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", + "wi", + false, + "false", + "" + ], + [ + "Confirm", + "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", + "cf", + false, + "false", + "" + ] + ], + "Alias": "Copy-DbaQueryStoreConfig", + "Author": "Enrico van de Laar (@evdlaar)", + "Synopsis": "Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases.", + "Name": "Copy-DbaDbQueryStoreOption", + "Links": "https://dbatools.io/Copy-QueryStoreConfig", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaDbQueryStoreOption -Source ServerA\\SQL -SourceDatabase AdventureWorks -Destination ServerB\\SQL -AllDatabases\nCopy the Query Store configuration of the AdventureWorks database in the ServerA\\SQL instance and apply it on all user databases in the ServerB\\SQL Instance.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaDbQueryStoreOption -Source ServerA\\SQL -SourceDatabase AdventureWorks -Destination ServerB\\SQL -DestinationDatabase WorldWideTraders\nCopy the Query Store configuration of the AdventureWorks database in the ServerA\\SQL instance and apply it to the WorldWideTraders database in the ServerB\\SQL Instance.", + "Syntax": "Copy-DbaDbQueryStoreOption [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-SourceDatabase] \u003cObject\u003e [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-DestinationDatabase] \u003cObject[]\u003e] [[-Exclude] \u003cObject[]\u003e] [-AllDatabases] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + }, { "CommandName": "Copy-DbaDbTableData", "Description": "Copies data between SQL Server tables using SQL Bulk Copy.\nThe same can be achieved also doing\n$sourcetable = Invoke-DbaQuery -SqlInstance instance1 ... -As DataTable\nWrite-DbaDataTable -SqlInstance ... -InputObject $sourcetable\nbut it will force buffering the contents on the table in memory (high RAM usage for large tables).\nWith this function, a streaming copy will be done in the most speedy and least resource-intensive way.", @@ -3807,104 +3909,6 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaEndpoint -Source sqlserver2014a -Destination sqlcluster\nCopies all server endpoints from sqlserver2014a to sqlcluster, using Windows credentials. If endpoints with the same name exist on sqlcluster, they will be skipped.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaEndpoint -Source sqlserver2014a -SourceSqlCredential $cred -Destination sqlcluster -Endpoint tg_noDbDrop -Force\nCopies only the tg_noDbDrop endpoint from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster. If an endpoint with the same name exists on \r\nsqlcluster, it will be dropped and recreated because -Force was used.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaEndpoint -Source sqlserver2014a -Destination sqlcluster -WhatIf -Force\nShows what would happen if the command were executed using force.", "Syntax": "Copy-DbaEndpoint [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Endpoint] \u003cObject[]\u003e] [[-ExcludeEndpoint] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, - { - "CommandName": "Copy-DbaExtendedEvent", - "Description": "Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health.\n\nBy default, all non-system Extended Events are migrated.", - "Tags": [ - "Migration", - "ExtendedEvent", - "XEvent" - ], - "Params": [ - [ - "Source", - "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "Destination", - "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", - "", - true, - "false", - "" - ], - [ - "SourceSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "DestinationSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "XeSession", - "The Extended Event Session(s) to process. This list is auto-populated from the server. If unspecified, all Extended Event Sessions will be processed.", - "", - false, - "false", - "" - ], - [ - "ExcludeXeSession", - "The Extended Event Session(s) to exclude. This list is auto-populated from the server.", - "", - false, - "false", - "" - ], - [ - "Force", - "If this switch is enabled, existing Extended Events sessions on Destination with matching names from Source will be dropped.", - "", - false, - "false", - "False" - ], - [ - "EnableException", - "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", - false, - "false", - "False" - ], - [ - "WhatIf", - "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", - "wi", - false, - "false", - "" - ], - [ - "Confirm", - "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", - "cf", - false, - "false", - "" - ] - ], - "Alias": "Copy-SqlExtendedEvent", - "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health.", - "Name": "Copy-DbaExtendedEvent", - "Links": "https://dbatools.io/Copy-DbaExtendedEvent", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster\nCopies all Extended Event sessions from sqlserver2014a to sqlcluster using Windows credentials.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all Extended Event sessions from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eCopy-DbaExtendedEvent -Source sqlserver2014a -Destination sqlcluster -XeSession CheckQueries, MonitorUserDefinedException\nCopies only the Extended Events named CheckQueries and MonitorUserDefinedException from sqlserver2014a to sqlcluster.", - "Syntax": "Copy-DbaExtendedEvent [-Source] \u003cDbaInstanceParameter\u003e [-Destination] \u003cDbaInstanceParameter[]\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-XeSession] \u003cObject[]\u003e] [[-ExcludeXeSession] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" - }, { "CommandName": "Copy-DbaLinkedServer", "Description": "By using password decryption techniques provided by Antti Rantasaari (NetSPI, 2014), this script migrates SQL Server Linked Servers from one server to another, while maintaining username and password.\n\nCredit: https://blog.netspi.com/decrypting-mssql-database-link-server-passwords/", @@ -4282,108 +4286,6 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaPolicyManagement -Source sqlserver2014a -Destination sqlcluster\nCopies all policies and conditions from sqlserver2014a to sqlcluster, using Windows credentials.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaPolicyManagement -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all policies and conditions from sqlserver2014a to sqlcluster, using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaPolicyManagement -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eCopy-DbaPolicyManagement -Source sqlserver2014a -Destination sqlcluster -Policy \u0027xp_cmdshell must be disabled\u0027\nCopies only one policy, \u0027xp_cmdshell must be disabled\u0027 from sqlserver2014a to sqlcluster. No conditions are migrated.", "Syntax": "Copy-DbaPolicyManagement [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-Policy] \u003cObject[]\u003e] [[-ExcludePolicy] \u003cObject[]\u003e] [[-Condition] \u003cObject[]\u003e] [[-ExcludeCondition] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, - { - "CommandName": "Copy-DbaQueryStoreConfig", - "Description": "Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases.", - "Tags": "QueryStore", - "Params": [ - [ - "Source", - "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2016 or higher.", - "", - true, - "true (ByValue)", - "" - ], - [ - "SourceSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "SourceDatabase", - "Specifies the database to copy the Query Store configuration from.", - "", - true, - "true (ByValue)", - "" - ], - [ - "Destination", - "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2016 or higher.", - "", - true, - "true (ByValue)", - "" - ], - [ - "DestinationSqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", - "", - false, - "false", - "" - ], - [ - "DestinationDatabase", - "Specifies a list of databases that will receive a copy of the Query Store configuration of the SourceDatabase.", - "", - false, - "false", - "" - ], - [ - "Exclude", - "Specifies a list of databases which will NOT receive a copy of the Query Store configuration.", - "", - false, - "false", - "" - ], - [ - "AllDatabases", - "If this switch is enabled, the Query Store configuration will be copied to all databases on the destination instance.", - "", - false, - "false", - "False" - ], - [ - "EnableException", - "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", - false, - "false", - "False" - ], - [ - "WhatIf", - "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", - "wi", - false, - "false", - "" - ], - [ - "Confirm", - "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", - "cf", - false, - "false", - "" - ] - ], - "Alias": "", - "Author": "Enrico van de Laar (@evdlaar)", - "Synopsis": "Copies the configuration of a Query Store enabled database and sets the copied configuration on other databases.", - "Name": "Copy-DbaQueryStoreConfig", - "Links": "https://dbatools.io/Copy-QueryStoreConfig", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaQueryStoreConfig -Source ServerA\\SQL -SourceDatabase AdventureWorks -Destination ServerB\\SQL -AllDatabases\nCopy the Query Store configuration of the AdventureWorks database in the ServerA\\SQL instance and apply it on all user databases in the ServerB\\SQL Instance.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaQueryStoreConfig -Source ServerA\\SQL -SourceDatabase AdventureWorks -Destination ServerB\\SQL -DestinationDatabase WorldWideTraders\nCopy the Query Store configuration of the AdventureWorks database in the ServerA\\SQL instance and apply it to the WorldWideTraders database in the ServerB\\SQL Instance.", - "Syntax": "Copy-DbaQueryStoreConfig [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-SourceDatabase] \u003cObject\u003e [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-DestinationDatabase] \u003cObject[]\u003e] [[-Exclude] \u003cObject[]\u003e] [-AllDatabases] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" - }, { "CommandName": "Copy-DbaResourceGovernor", "Description": "By default, all non-system resource pools are migrated. If the pool already exists on the destination, it will be skipped unless -Force is used.\n\nThe -ResourcePool parameter is auto-populated for command-line completion and can be used to copy only specific objects.", @@ -5068,6 +4970,104 @@ "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaSysDbUserObject -Source $sourceServer -Destination $destserver\nCopies user objects from source to destination", "Syntax": "Copy-DbaSysDbUserObject [-Source] \u003cDbaInstanceParameter\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [-Destination] \u003cDbaInstanceParameter[]\u003e [[-DestinationSqlCredential] \u003cPSCredential\u003e] [-Force] [-Classic] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, + { + "CommandName": "Copy-DbaXESession", + "Description": "Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health.\n\nBy default, all non-system Extended Events are migrated.", + "Tags": [ + "Migration", + "ExtendedEvent", + "XEvent" + ], + "Params": [ + [ + "Source", + "Source SQL Server. You must have sysadmin access and server version must be SQL Server version 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "Destination", + "Destination SQL Server. You must have sysadmin access and the server must be SQL Server 2000 or higher.", + "", + true, + "false", + "" + ], + [ + "SourceSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "DestinationSqlCredential", + "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "", + false, + "false", + "" + ], + [ + "XeSession", + "The Extended Event Session(s) to process. This list is auto-populated from the server. If unspecified, all Extended Event Sessions will be processed.", + "", + false, + "false", + "" + ], + [ + "ExcludeXeSession", + "The Extended Event Session(s) to exclude. This list is auto-populated from the server.", + "", + false, + "false", + "" + ], + [ + "Force", + "If this switch is enabled, existing Extended Events sessions on Destination with matching names from Source will be dropped.", + "", + false, + "false", + "False" + ], + [ + "EnableException", + "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", + "Silent", + false, + "false", + "False" + ], + [ + "WhatIf", + "If this switch is enabled, no actions are performed but informational messages will be displayed that explain what would happen if the command were to run.", + "wi", + false, + "false", + "" + ], + [ + "Confirm", + "If this switch is enabled, you will be prompted for confirmation before executing any operations that change state.", + "cf", + false, + "false", + "" + ] + ], + "Alias": "Copy-DbaExtendedEvent,Copy-SqlExtendedEvent", + "Author": "Chrissy LeMaire (@cl), netnerds.net", + "Synopsis": "Migrates SQL Extended Event Sessions except the two default sessions, AlwaysOn_health and system_health.", + "Name": "Copy-DbaXESession", + "Links": "https://dbatools.io/Copy-DbaXESession", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eCopy-DbaXESession -Source sqlserver2014a -Destination sqlcluster\nCopies all Extended Event sessions from sqlserver2014a to sqlcluster using Windows credentials.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eCopy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -SourceSqlCredential $cred\nCopies all Extended Event sessions from sqlserver2014a to sqlcluster using SQL credentials for sqlserver2014a and Windows credentials for sqlcluster.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eCopy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -WhatIf\nShows what would happen if the command were executed.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eCopy-DbaXESession -Source sqlserver2014a -Destination sqlcluster -XeSession CheckQueries, MonitorUserDefinedException\nCopies only the Extended Events named CheckQueries and MonitorUserDefinedException from sqlserver2014a to sqlcluster.", + "Syntax": "Copy-DbaXESession [-Source] \u003cDbaInstanceParameter\u003e [-Destination] \u003cDbaInstanceParameter[]\u003e [[-SourceSqlCredential] \u003cPSCredential\u003e] [[-DestinationSqlCredential] \u003cPSCredential\u003e] [[-XeSession] \u003cObject[]\u003e] [[-ExcludeXeSession] \u003cObject[]\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + }, { "CommandName": "Copy-DbaXESessionTemplate", "Description": "Copies non-Microsoft templates from the dbatools template repository (\\bin\\xetemplates\\) to $home\\Documents\\SQL Server Management Studio\\Templates\\XEventTemplates.\n\nUseful for when you want to use the SSMS GUI.", @@ -10729,17 +10729,17 @@ "" ], [ - "ExcludeAllUserDb", - "If this switch is enabled, only databases which are not User databases will be processed.\nThis parameter cannot be used with -ExcludeAllSystemDb.", - "SystemDbOnly,NoUserDb", + "ExcludeUser", + "If this switch is enabled, only databases which are not User databases will be processed.\nThis parameter cannot be used with -ExcludeSystem.", + "SystemDbOnly,NoUserDb,ExcludeAllUserDb", false, "false", "False" ], [ - "ExcludeAllSystemDb", - "If this switch is enabled, only databases which are not System databases will be processed.\nThis parameter cannot be used with -ExcludeAllUserDb.", - "UserDbOnly,NoSystemDb", + "ExcludeSystem", + "If this switch is enabled, only databases which are not System databases will be processed.\nThis parameter cannot be used with -ExcludeUser.", + "UserDbOnly,NoSystemDb,ExcludeAllSystemDb", false, "false", "False" @@ -10846,8 +10846,8 @@ "Synopsis": "Gets SQL Database information for each database that is present on the target instance(s) of SQL Server.", "Name": "Get-DbaDatabase", "Links": "https://dbatools.io/Get-DbaDatabase", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost\nReturns all databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost -ExcludeAllUserDb\nReturns only the system databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost -ExcludeAllSystemDb\nReturns only the user databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e\u0027localhost\u0027,\u0027sql2016\u0027 | Get-DbaDatabase\nReturns databases on multiple instances piped into the function.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -RecoveryModel full,Simple\nReturns only the user databases in Full or Simple recovery model from SQL Server instance SQL1\\SQLExpress.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -Status Normal\nReturns only the user databases with status \u0027normal\u0027 from SQL Server instance SQL1\\SQLExpress.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -IncludeLastUsed\nReturns the databases from SQL Server instance SQL1\\SQLExpress and includes the last used information\r\nfrom the sys.dm_db_index_usage_stats DMV.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -ExcludeDatabase model,master\nReturns all databases except master and model from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 9 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -Encrypted\nReturns only databases using TDE from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 10 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -Access ReadOnly\nReturns only read only databases from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 11 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL2,SQL3 -Database OneDB,OtherDB\nReturns databases \u0027OneDb\u0027 and \u0027OtherDB\u0027 from SQL Server instances SQL2 and SQL3 if databases by those names exist on those instances.", - "Syntax": "Get-DbaDatabase [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [-ExcludeAllUserDb] [-ExcludeAllSystemDb] [-Owner \u003cString[]\u003e] [-Encrypted] [-Status \u003cString[]\u003e] [-Access \u003cString\u003e] [-RecoveryModel \u003cString[]\u003e] [-NoFullBackup] [-NoFullBackupSince \u003cDateTime\u003e] [-NoLogBackup] [-NoLogBackupSince \u003cDateTime\u003e] [-EnableException] [-IncludeLastUsed] [-OnlyAccessible] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost\nReturns all databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost -ExcludeUser\nReturns only the system databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance localhost -ExcludeSystem\nReturns only the user databases on the local default SQL Server instance.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e\u0027localhost\u0027,\u0027sql2016\u0027 | Get-DbaDatabase\nReturns databases on multiple instances piped into the function.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -RecoveryModel full,Simple\nReturns only the user databases in Full or Simple recovery model from SQL Server instance SQL1\\SQLExpress.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -Status Normal\nReturns only the user databases with status \u0027normal\u0027 from SQL Server instance SQL1\\SQLExpress.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress -IncludeLastUsed\nReturns the databases from SQL Server instance SQL1\\SQLExpress and includes the last used information\r\nfrom the sys.dm_db_index_usage_stats DMV.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -ExcludeDatabase model,master\nReturns all databases except master and model from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 9 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -Encrypted\nReturns only databases using TDE from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 10 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL1\\SQLExpress,SQL2 -Access ReadOnly\nReturns only read only databases from SQL Server instances SQL1\\SQLExpress and SQL2.\n-------------------------- EXAMPLE 11 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance SQL2,SQL3 -Database OneDB,OtherDB\nReturns databases \u0027OneDb\u0027 and \u0027OtherDB\u0027 from SQL Server instances SQL2 and SQL3 if databases by those names exist on those instances.", + "Syntax": "Get-DbaDatabase [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [-ExcludeUser] [-ExcludeSystem] [-Owner \u003cString[]\u003e] [-Encrypted] [-Status \u003cString[]\u003e] [-Access \u003cString\u003e] [-RecoveryModel \u003cString[]\u003e] [-NoFullBackup] [-NoFullBackupSince \u003cDateTime\u003e] [-NoLogBackup] [-NoLogBackupSince \u003cDateTime\u003e] [-EnableException] [-IncludeLastUsed] [-OnlyAccessible] [\u003cCommonParameters\u003e]" }, { "CommandName": "Get-DbaDbAssembly", @@ -12862,7 +12862,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -12873,8 +12873,8 @@ "Synopsis": "Returns database file space information for database files on a SQL instance.", "Name": "Get-DbaDbSpace", "Links": "https://dbatools.io/Get-DbaDbSpace", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost\nReturns all user database files and free space information for the localhost.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost | Where-Object {$_.PercentUsed -gt 80}\nReturns all user database files and free space information for the local host. Filters the output object by any files that have a percent used of greater than 80%.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003e\u0027localhost\u0027,\u0027localhost\\namedinstance\u0027 | Get-DbaDbSpace\nReturns all user database files and free space information for the localhost and localhost\\namedinstance SQL Server instances. Processes data via the pipeline.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost -Database db1, db2\nReturns database files and free space information for the db1 and db2 on localhost.", - "Syntax": "Get-DbaDbSpace [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cObject[]\u003e] [[-ExcludeDatabase] \u003cObject[]\u003e] [-IncludeSystemDBs] [-EnableException] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost\nReturns all user database files and free space information for the localhost.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost | Where-Object {$_.PercentUsed -gt 80}\nReturns all user database files and free space information for the local host. Filters the output object by any files that have a percent used of greater than 80%.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003e\u0027localhost\u0027,\u0027localhost\\namedinstance\u0027 | Get-DbaDbSpace\nReturns all user database files and free space information for the localhost and localhost\\namedinstance SQL Server instances. Processes data via the pipeline.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost -Database db1, db2 | Where-Object { $_.SpaceUntilMaxSize.Megabyte -lt 1 }\nReturns database files and free space information for the db1 and db2 on localhost where there is only 1MB left until the space is maxed out\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-DbaDbSpace -SqlInstance localhost -Database db1, db2 | Where-Object { $_.SpaceUntilMaxSize.Gigabyte -lt 1 }\nReturns database files and free space information for the db1 and db2 on localhost where there is only 1GB left until the space is maxed out", + "Syntax": "Get-DbaDbSpace [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cString[]\u003e] [[-ExcludeDatabase] \u003cString[]\u003e] [-IncludeSystemDBs] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Get-DbaDbState", @@ -15034,18 +15034,10 @@ "false", "" ], - [ - "Simple", - "Shows a simplified set of counters. Excludes only totals for Plancounters and BufManpagecounters", - "", - false, - "false", - "False" - ], [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -15056,8 +15048,8 @@ "Synopsis": "Get amount of memory in use by *all* SQL Server components and instances", "Name": "Get-DbaMemoryUsage", "Links": "https://dbatools.io/Get-DbaMemoryUsage", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaMemoryUsage -ComputerName ServerA\nReturns a custom object displaying Server, counter instance, counter, number of pages, memory in KB, memory in MB\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaMemoryUsage -ComputerName ServerA\\sql987 -Simple\nReturns a custom object with Server, counter instance, counter, number of pages, memory in KB, memory in MB\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-DbaMemoryUsage -ComputerName ServerA\\sql987 | Out-Gridview\nReturns a gridview displaying Server, counter instance, counter, number of pages, memory in KB, memory in MB", - "Syntax": "Get-DbaMemoryUsage [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [-Simple] [-EnableException] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaMemoryUsage -ComputerName sql2017\nReturns a custom object displaying Server, counter instance, counter, number of pages, memory\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaMemoryUsage -ComputerName sql2017\\sqlexpress -SqlCredential sqladmin | Where-Object { $_.Memory.Megabyte -gt 100 }\nLogs into the sql2017\\sqlexpress as sqladmin using SQL Authentication then returns results only where memory exceeds 100 MB\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003e$servers | Get-DbaMemoryUsage | Out-Gridview\nGets results from an array of $servers then diplays them in a gridview.", + "Syntax": "Get-DbaMemoryUsage [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Get-DbaModule", @@ -16478,36 +16470,28 @@ }, { "CommandName": "Get-DbaProductKey", - "Description": "Using a string of servers, a text file, or Central Management Server to provide a list of servers, this script will go to each server and get the product key for all installed instances. Clustered instances are supported as well. Requires regular user access to the SQL instances, SMO installed locally, Remote Registry enabled and accessible by the account running the script.\n\nUses key decoder by Jakob Bindslet (http://goo.gl/1jiwcB)", + "Description": "This command find the product key for all installed instances. Clustered instances are supported as well.\n\nUses key decoder by Jakob Bindslet (http://goo.gl/1jiwcB)", "Tags": "ProductKey", "Params": [ [ - "SqlInstance", + "ComputerName", "The target SQL Server instance or instances.", - "ServerInstance,SqlServer,SqlInstances", + "SqlInstance", true, "true (ByValue)", "" ], [ "SqlCredential", - "Login to the target instance using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", + "This command logs into the SQL instance to gather additional information.\nUse this parameter to connect to the discovered SQL instances using alternative credentials. Windows and SQL Authentication supported. Accepts credential objects (Get-Credential)", "", false, "false", "" ], [ - "SqlCms", - "Deprecated, pipe in from Get-DbaCmsRegServer", - "", - false, - "false", - "" - ], - [ - "ServersFromFile", - "Deprecated, pipe in from Get-Content", + "Credential", + "Login to the target Windows instance using alternative credentials. Windows Authentication supported. Accepts credential objects (Get-Credential)", "", false, "false", @@ -16524,11 +16508,11 @@ ], "Alias": "Get-DbaSqlProductKey,Get-SqlServerKey", "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Gets SQL Server Product Keys from local or destination SQL Servers. Works with SQL Server 2005-2016", + "Synopsis": "Gets SQL Server Product Keys from local or destination SQL Servers. Works with SQL Server 2005-2017", "Name": "Get-DbaProductKey", "Links": "https://dbatools.io/Get-DbaProductKey", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaProductKey -SqlInstance winxp, sqlservera, sqlserver2014a, win2k8\nGets SQL Server versions, editions and product keys for all instances within each server or workstation.", - "Syntax": "Get-DbaProductKey [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-SqlCms] \u003cString\u003e] [[-ServersFromFile] \u003cString\u003e] [-EnableException] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaProductKey -ComputerName winxp, sqlservera, sqlserver2014a, win2k8\nGets SQL Server versions, editions and product keys for all instances within each server or workstation.", + "Syntax": "Get-DbaProductKey [-ComputerName] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Get-DbaQueryExecutionTime", @@ -16595,9 +16579,9 @@ "500" ], [ - "ExcludeSystemDatabases", + "ExcludeSystem", "Allows you to suppress output on system databases", - "", + "ExcludeSystemDatabases", false, "false", "False" @@ -16617,7 +16601,7 @@ "Name": "Get-DbaQueryExecutionTime", "Links": "https://dbatools.io/Get-DbaQueryExecutionTime", "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eGet-DbaQueryExecutionTime -SqlInstance sql2008, sqlserver2012\nReturn the top 100 slowest stored procedures or statements for servers sql2008 and sqlserver2012.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eGet-DbaQueryExecutionTime -SqlInstance sql2008 -Database TestDB\nReturn the top 100 slowest stored procedures or statements on server sql2008 for only the TestDB database.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-DbaQueryExecutionTime -SqlInstance sql2008 -Database TestDB -MaxResultsPerDb 100 -MinExecs 200 -MinExecMs 1000\nReturn the top 100 slowest stored procedures or statements on server sql2008 for only the TestDB database, limiting results to queries with more than 200 total executions and an execution time over \r\n1000ms or higher.", - "Syntax": "Get-DbaQueryExecutionTime [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [[-MaxResultsPerDb] \u003cInt32\u003e] [[-MinExecs] \u003cInt32\u003e] [[-MinExecMs] \u003cInt32\u003e] [[-ExcludeSystemDatabases]] [-EnableException] [\u003cCommonParameters\u003e]" + "Syntax": "Get-DbaQueryExecutionTime [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [[-MaxResultsPerDb] \u003cInt32\u003e] [[-MinExecs] \u003cInt32\u003e] [[-MinExecMs] \u003cInt32\u003e] [[-ExcludeSystem]] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Get-DbaRegistryRoot", @@ -19665,22 +19649,25 @@ "Syntax": "Import-DbaCmsRegServer [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Path] \u003cString[]\u003e] [[-InputObject] \u003cObject[]\u003e] [[-Group] \u003cObject\u003e] [-EnableException] [\u003cCommonParameters\u003e]" }, { - "CommandName": "Import-DbaCsvToSql", - "Description": "Import-DbaCsvToSql takes advantage of .NET\u0027s super fast SqlBulkCopy class to import CSV files into SQL Server at up to 90,000 rows a second.\n\nThe entire import is contained within a transaction, so if a failure occurs or the script is aborted, no changes will persist.\n\nIf the table specified does not exist, it will be automatically created using best guessed data types. In addition, the destination table can be truncated prior to import.\n\nThe Query parameter will be used to import only the data returned from a SQL Query executed against the CSV file(s). This function supports a number of bulk copy options. Please see parameter list for details.", - "Tags": "Migration", + "CommandName": "Import-DbaCsv", + "Description": "Import-DbaCsv takes advantage of .NET\u0027s super fast SqlBulkCopy class to import CSV files into SQL Server.\n\nThe entire import is performed within a transaction, so if a failure occurs or the script is aborted, no changes will persist.\n\nIf the table specified does not exist and -AutoCreateTable, it will be automatically created using slow and efficient but accomodating data types.", + "Tags": [ + "Migration", + "Import" + ], "Params": [ [ - "Csv", - "Specifies path to the CSV file(s) to be imported. Multiple files may be imported if they are formatted similarly.\nIf no file is specified, a dialog box will appear to select your file(s).", - "", + "Path", + "Specifies path to the CSV file(s) to be imported. Multiple files may be imported at once.", + "Csv,FullPath", false, - "false", + "true (ByValue)", "" ], [ "SqlInstance", "The SQL Server Instance to import data into.", - "ServerInstance,SqlServer", + "", true, "false", "" @@ -19693,9 +19680,17 @@ "false", "" ], + [ + "Database", + "Specifies the name of the database the CSV will be imported into. Options for this this parameter are auto-populated from the server.", + "", + true, + "false", + "" + ], [ "Table", - "Specifies the SQL table or view where CSV will be imported into.\nIf a table name is not specified, the table name will be automatically determined from the filename, and a prompt will appear to confirm the table name.\nIf a table does not currently exist, it will created. SQL datatypes are determined from the first row of the CSV that contains data (skips first row if -FirstRowColumns is specified). Datatypes used \r\nare: bigint, numeric, datetime and varchar(MAX).\nIf the automatically generated table datatypes do not work for you, please create the table prior to import.", + "Specifies the SQL table or view where CSV will be imported into.\nIf a table name is not specified, the table name will be automatically determined from the filename.\nIf the table specified does not exist and -AutoCreateTable, it will be automatically created using slow and efficient but accomodating data types.\nIf the automatically generated table datatypes do not work for you, please create the table prior to import.", "", false, "false", @@ -19727,132 +19722,124 @@ ], [ "SingleColumn", - "Specifies that the file contains a single column of data", + "Specifies that the file contains a single column of data. Otherwise, the delimiter check bombs.", "", false, "false", "False" ], [ - "FirstRowColumns", - "If this switch is enabled, the first row in the file will be used as column names for the data being imported.\nIf the first row does not contain column names and -Query is specified, use field names \"column1, column2, column3\" and so on.", + "BatchSize", + "Specifies the batch size for the import. Defaults to 50000.", "", false, "false", - "False" + "50000" ], [ - "Turbo", - "If this switch is enabled, a Table Lock will be created for the import to make the import run as fast as possible. Depending upon the number of columns and datatypes, this may be over 90,000 records \r\nper second.\nThis switch cannot be used in conjunction with -Query.\nRemember the Turbo button? This one actually works. Turbo is mega fast, but may not handle some datatypes as well as other methods.\nIf your CSV file is rather vanilla and doesn\u0027t have a ton of NULLs, Turbo may work well for you.", + "NotifyAfter", + "Specifies the import row count interval for reporting progress. A notification will be shown after each group of this many rows has been imported.", "", false, "false", - "False" + "50000" ], [ - "Safe", - "If this switch is enabled, OleDb is used to import the records. By default, Import-DbaCsvToSql uses StreamReader for imports. StreamReader is super fast, but may not properly parse some files.\nWhen using OleDb the import will be slower but more predictable when it comes to parsing CSV files. A schema.ini is automatically generated for best results. If schema.ini currently exists in the \r\ndirectory, it will be moved to a temporary location, then moved back.\nOleDB also enables the script to use the -Query parameter, which enables you to import specific subsets of data within a CSV file. OleDB imports at up to 21,000 rows/sec.", + "TableLock", + "If this switch is enabled, the SqlBulkCopy option to acquire a table lock will be used. This is automatically used if -Turbo is enabled.\nPer Microsoft \"Obtain a bulk update lock for the duration of the bulk copy operation. When not\r\nspecified, row locks are used.\"", "", false, "false", "False" ], [ - "First", - "Specifies the number of rows to import. If this parameter is omitted, the entire file is imported. Row counts start at the top of the file, but skip the first row if -FirstRowColumns is specified.\nUse -Query if you need advanced First (TOP) functionality.", - "", - false, - "false", - "0" - ], - [ - "Query", - "Specifies a query to execute against the CSV data to select/modify the data being imported.\nTo make command line queries easy, this module will convert the word \"csv\" to the actual CSV formatted table name. If the FirstRowColumns switch is not used, the query should use column1, column2, \r\ncolumn3, etc.\nCannot be used in conjunction with -Turbo or -First. When -Query is specified, the slower import method, OleDb, will be used.", + "CheckConstraints", + "If this switch is enabled, the SqlBulkCopy option to check constraints will be used.\nPer Microsoft \"Check constraints while data is being inserted. By default, constraints are not checked.\"", "", false, "false", - "select * from csv" + "False" ], [ - "BatchSize", - "Specifies the batch size for the import. Defaults to 50000.", + "FireTriggers", + "If this switch is enabled, the SqlBulkCopy option to allow insert triggers to be executed will be used.\nPer Microsoft \"When specified, cause the server to fire the insert triggers for the rows being inserted into the database.\"", "", false, "false", - "50000" + "False" ], [ - "NotifyAfter", - "Specifies the import row count interval for reporting progress. A notification will be shown after each group of this many rows has been imported.", + "KeepIdentity", + "If this switch is enabled, the SqlBulkCopy option to keep identity values from the source will be used.\nPer Microsoft \"Preserve source identity values. When not specified, identity values are assigned by the destination.\"", "", false, "false", - "0" + "False" ], [ - "TableLock", - "If this switch is enabled, the SqlBulkCopy option to acquire a table lock will be used. This is automatically used if -Turbo is enabled.\nPer Microsoft \"Obtain a bulk update lock for the duration of the bulk copy operation. When not\r\nspecified, row locks are used.\"", + "KeepNulls", + "If this switch is enabled, the SqlBulkCopy option to keep NULL values in the table will be used.\nPer Microsoft \"Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable.\"", "", false, "false", "False" ], [ - "CheckConstraints", - "If this switch is enabled, the SqlBulkCopy option to check constraints will be used.\nPer Microsoft \"Check constraints while data is being inserted. By default, constraints are not checked.\"", + "AutoCreateTable", + "If this switch is enabled, the table will be created if it does not already exist. The table will be created with sub-optimal data types such as nvarchar(max)", "", false, "false", "False" ], [ - "FireTriggers", - "If this switch is enabled, the SqlBulkCopy option to allow insert triggers to be executed will be used.\nPer Microsoft \"When specified, cause the server to fire the insert triggers for the rows being inserted into the database.\"", + "NoProgress", + "The progress bar is pretty but can slow down imports. Use this parameter to quietly import.", "", false, "false", "False" ], [ - "KeepIdentity", - "If this switch is enabled, the SqlBulkCopy option to keep identity values from the source will be used.\nPer Microsoft \"Preserve source identity values. When not specified, identity values are assigned by the destination.\"", + "NoHeaderRow", + "By default, the first row is used to determine column names for the data being imported.\nUse this switch if the first row contains data and not column names.", "", false, "false", "False" ], [ - "KeepNulls", - "If this switch is enabled, the SqlBulkCopy option to keep NULL values in the table will be used.\nPer Microsoft \"Preserve null values in the destination table regardless of the settings for default values. When not specified, null values are replaced by default values where applicable.\"", + "EnableException", + "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", "", false, "false", "False" ], [ - "shellswitch", - "[Parameter(DontShow)]", - "", + "WhatIf", + "Shows what would happen if the command were to run. No actions are actually performed.", + "wi", false, "false", - "False" + "" ], [ - "SqlCredentialPath", - "[Parameter(DontShow)]", - "", + "Confirm", + "Prompts you for confirmation before executing any changing operations within the command.", + "cf", false, "false", "" ] ], - "Alias": "", + "Alias": "Import-DbaCsvToSql", "Author": "Chrissy LeMaire (@cl), netnerds.net", - "Synopsis": "Efficiently imports very large (and small) CSV files into SQL Server using only the .NET Framework and PowerShell.", - "Name": "Import-DbaCsvToSql", - "Links": "https://blog.netnerds.net/2015/09/Import-DbaCsvtosql-super-fast-csv-to-sql-server-import-powershell-module/", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv C:\\temp\\housing.csv -SqlInstance sql001 -Database markets\nImports the entire comma-delimited housing.csv to the SQL \"markets\" database on a SQL Server named sql001.\nSince a table name was not specified, the table name is automatically determined from filename as \"housing\" and a prompt will appear to confirm table name.\nThe first row is not skipped, as it does not contain column names.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv .\\housing.csv -SqlInstance sql001 -Database markets -Table housing -First 100000 -Safe -Delimiter \"`t\" -FirstRowColumns\nImports the first 100,000 rows of the tab delimited housing.csv file to the \"housing\" table in the \"markets\" database on a SQL Server named sql001. Since -Safe was specified, the OleDB method will be \r\nused for the bulk import. The first row is skipped, as it contains column names.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -csv C:\\temp\\huge.txt -SqlInstance sqlcluster -Database locations -Table latitudes -Delimiter \"|\" -Turbo\nImports all records from the pipe delimited huge.txt file using the fastest method possible into the latitudes table within the locations database. Obtains a table lock for the duration of the bulk \r\ncopy operation. This specific command has been used\r\nto import over 10.5 million rows in 2 minutes.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv C:\\temp\\housing.csv, .\\housing2.csv -SqlInstance sql001 -Database markets -Table housing -Delimiter \"`t\" -query \"select top 100000 column1, column3 from csv\" -Truncate\nTruncates the \"housing\" table, then imports columns 1 and 3 of the first 100000 rows of the tab-delimited housing.csv in the C:\\temp directory, and housing2.csv in the current directory. Since the \r\nquery is executed against both files, a total of 200,000 rows will be imported.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv C:\\temp\\housing.csv -SqlInstance sql001 -Database markets -Table housing -query \"select address, zip from csv where state = \u0027Louisiana\u0027\" -FirstRowColumns -Truncate \r\n-FireTriggers\nUses the first line to determine CSV column names. Truncates the \"housing\" table on the SQL Server, then imports the address and zip columns from all records in the housing.csv where the state equals \r\nLouisiana.\nTriggers are fired for all rows. Note that this does slightly slow down the import.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv c:\\temp\\SingleColumn.csv -SqlInstance sql001 -Database markets -Table TempTable -SingleColumn\nUpload the single column Csv SingleColumn.csv to Temptable which has just one column\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv \"\\\\FileServer\\To Import\\housing.csv\" -SqlInstance sql001 -Database markets\nImports the entire comma-delimited housing.csv located in the share named \"To Import\" on FileServer to the SQL \"markets\" database on a SQL Server named sql001.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eImport-DbaCsvToSql -Csv \u0027\\\\FileServer\\R$\\To Import\\housing.csv\u0027 -SqlInstance sql001 -Database markets\nImports the entire comma-delimited housing.csv located in the directory R:\\To Import on FileServer using the administrative share to the SQL \"markets\" database on a SQL Server named sql001.", - "Syntax": "Import-DbaCsvToSql [-Csv \u003cString[]\u003e] -SqlInstance \u003cDbaInstanceParameter\u003e [-SqlCredential \u003cObject\u003e] [-Table \u003cString\u003e] [-Schema \u003cString\u003e] [-Truncate] [-Delimiter \u003cString\u003e] [-SingleColumn] [-FirstRowColumns] [-First \u003cInt32\u003e] [-BatchSize \u003cInt32\u003e] [-NotifyAfter \u003cInt32\u003e] [-TableLock] [-CheckConstraints] [-FireTriggers] [-KeepIdentity] [-KeepNulls] [-shellswitch] [-SqlCredentialPath \u003cString\u003e] [\u003cCommonParameters\u003e]\nImport-DbaCsvToSql [-Csv \u003cString[]\u003e] -SqlInstance \u003cDbaInstanceParameter\u003e [-SqlCredential \u003cObject\u003e] [-Table \u003cString\u003e] [-Schema \u003cString\u003e] [-Truncate] [-Delimiter \u003cString\u003e] [-SingleColumn] [-FirstRowColumns] [-Turbo] [-First \u003cInt32\u003e] [-BatchSize \u003cInt32\u003e] [-NotifyAfter \u003cInt32\u003e] [-TableLock] [-CheckConstraints] [-FireTriggers] [-KeepIdentity] [-KeepNulls] [-shellswitch] [-SqlCredentialPath \u003cString\u003e] [\u003cCommonParameters\u003e]\nImport-DbaCsvToSql [-Csv \u003cString[]\u003e] -SqlInstance \u003cDbaInstanceParameter\u003e [-SqlCredential \u003cObject\u003e] [-Table \u003cString\u003e] [-Schema \u003cString\u003e] [-Truncate] [-Delimiter \u003cString\u003e] [-SingleColumn] [-FirstRowColumns] [-Safe] [-First \u003cInt32\u003e] [-Query \u003cString\u003e] [-BatchSize \u003cInt32\u003e] [-NotifyAfter \u003cInt32\u003e] [-TableLock] [-CheckConstraints] [-FireTriggers] [-KeepIdentity] [-KeepNulls] [-shellswitch] [-SqlCredentialPath \u003cString\u003e] [\u003cCommonParameters\u003e]" + "Synopsis": "Efficiently imports very large (and small) CSV files into SQL Server.", + "Name": "Import-DbaCsv", + "Links": "https://dbatools.io/Import-DbaCsv", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eImport-DbaCsv -Path C:\\temp\\housing.csv -SqlInstance sql001 -Database markets\nImports the entire comma-delimited housing.csv to the SQL \"markets\" database on a SQL Server named sql001, using the first row as column names.\nSince a table name was not specified, the table name is automatically determined from filename as \"housing\".\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eImport-DbaCsv -Path .\\housing.csv -SqlInstance sql001 -Database markets -Table housing -Delimiter \"`t\" -NoHeaderRow\nImports the entire comma-delimited housing.csv, including the first row which is not used for colum names, to the SQL markets database, into the housing table, on a SQL Server named sql001.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eImport-DbaCsv -Path C:\\temp\\huge.txt -SqlInstance sqlcluster -Database locations -Table latitudes -Delimiter \"|\"\nImports the entire pipe-delimited huge.txt to the locations database, into the latitudes table on a SQL Server named sqlcluster.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eImport-DbaCsv -Path c:\\temp\\SingleColumn.csv -SqlInstance sql001 -Database markets -Table TempTable -SingleColumn\nImports the single column CSV into TempTable\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-ChildItem -Path \\\\FileServer\\csvs | Import-DbaCsv -SqlInstance sql001, sql002 -Database tempdb -AutoCreateTable\nImports every CSV in the \\\\FileServer\\csvs path into both sql001 and sql002\u0027s tempdb database. Each CSV will be imported into an automatically determined table name.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eGet-ChildItem -Path \\\\FileServer\\csvs | Import-DbaCsv -SqlInstance sql001, sql002 -Database tempdb -AutoCreateTable -WhatIf\nShows what would happen if the command were to be executed", + "Syntax": "Import-DbaCsv [[-Path] \u003cObject[]\u003e] [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [-Database] \u003cString\u003e [[-Table] \u003cString\u003e] [[-Schema] \u003cString\u003e] [-Truncate] [[-Delimiter] \u003cString\u003e] [-SingleColumn] [[-BatchSize] \u003cInt32\u003e] [[-NotifyAfter] \u003cInt32\u003e] [-TableLock] [-CheckConstraints] [-FireTriggers] [-KeepIdentity] [-KeepNulls] [-AutoCreateTable] [-NoProgress] [-NoHeaderRow] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Import-DbaPfDataCollectorSetTemplate", @@ -20486,11 +20473,11 @@ ], [ "Database", - "Specifies the database to install SqlWatch into. Defaults to master.", + "Specifies the database to install SqlWatch into. Defaults to SQLWATCH.", "", false, "false", - "master" + "SQLWATCH" ], [ "LocalFile", @@ -20538,7 +20525,7 @@ "Synopsis": "Installs or updates SqlWatch.", "Name": "Install-DbaSqlWatch", "Links": "https://dbatools.io/Install-DbaSqlWatch", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\nLogs into server1 with Windows authentication and then installs SqlWatch in the master database.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\\instance1 -Database DBA\nLogs into server1\\instance1 with Windows authentication and then installs SqlWatch in the DBA database.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\\instance1 -Database DBA -SqlCredential $cred\nLogs into server1\\instance1 with SQL authentication and then installs SqlWatch in the DBA database.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance sql2016\\standardrtm, sql2016\\sqlexpress, sql2014\nLogs into sql2016\\standardrtm, sql2016\\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the master database.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003e$servers = \"sql2016\\standardrtm\", \"sql2016\\sqlexpress\", \"sql2014\"\n$servers | Install-DbaSqlWatch\nLogs into sql2016\\standardrtm, sql2016\\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the master database.", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\nLogs into server1 with Windows authentication and then installs SqlWatch in the SQLWATCH database.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\\instance1 -Database DBA\nLogs into server1\\instance1 with Windows authentication and then installs SqlWatch in the DBA database.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance server1\\instance1 -Database DBA -SqlCredential $cred\nLogs into server1\\instance1 with SQL authentication and then installs SqlWatch in the DBA database.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInstall-DbaSqlWatch -SqlInstance sql2016\\standardrtm, sql2016\\sqlexpress, sql2014\nLogs into sql2016\\standardrtm, sql2016\\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the SQLWATCH database.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003e$servers = \"sql2016\\standardrtm\", \"sql2016\\sqlexpress\", \"sql2014\"\n$servers | Install-DbaSqlWatch\nLogs into sql2016\\standardrtm, sql2016\\sqlexpress and sql2014 with Windows authentication and then installs SqlWatch in the SQLWATCH database.", "Syntax": "Install-DbaSqlWatch [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cString\u003e] [[-LocalFile] \u003cString\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { @@ -20831,7 +20818,7 @@ ] ], "Alias": "", - "Author": "Chrissy LeMaire (@cl), netnerds.net", + "Author": "Stuart Moore (@napalmgram - http://stuart-moore.com)", "Synopsis": "Allows the restore of modified BackupHistory Objects\nFor 90% of users Restore-DbaDatabase should be your point of access to this function. The other 10% use it at their own risk", "Name": "Invoke-DbaAdvancedRestore", "Links": "https://dbatools.io/Invoke-DbaAdvancedRestore", @@ -22311,8 +22298,8 @@ "All" ], [ - "StepSizeMB", - "If specified, this will chunk a larger shrink operation into multiple smaller shrinks.\r\nIf shrinking a file by a large amount there are benefits of doing multiple smaller chunks.", + "StepSize", + "Measured in bits - but no worries! PowerShell has a very cool way of formatting bits. Just specify something like: 1MB or 10GB. See the examples for more information.\nIf specified, this will chunk a larger shrink operation into multiple smaller shrinks.\r\nIf shrinking a file by a large amount there are benefits of doing multiple smaller chunks.", "", false, "false", @@ -22380,8 +22367,8 @@ "Synopsis": "Shrinks all files in a database. This is a command that should rarely be used.\n\n- Shrinks can cause severe index fragmentation (to the tune of 99%)\n- Shrinks can cause massive growth in the database\u0027s transaction log\n- Shrinks can require a lot of time and system resources to perform data movement", "Name": "Invoke-DbaDbShrink", "Links": "https://dbatools.io/Invoke-DbaDbShrink", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2016 -Database Northwind,pubs,Adventureworks2014\nShrinks Northwind, pubs and Adventureworks2014 to have as little free space as possible.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50\nShrinks AdventureWorks2014 to have 50% free space. So let\u0027s say AdventureWorks2014 was 1GB and it\u0027s using 100MB space. The database free space would be reduced to 50MB.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50 -FileType Data -StepSizeMB 25\nShrinks AdventureWorks2014 to have 50% free space, runs shrinks in 25MB chunks for improved performance.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2012 -AllUserDatabases\nShrinks all databases on SQL2012 (not ideal for production)", - "Syntax": "Invoke-DbaDbShrink [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cObject[]\u003e] [[-ExcludeDatabase] \u003cObject[]\u003e] [-AllUserDatabases] [[-PercentFreeSpace] \u003cInt32\u003e] [[-ShrinkMethod] \u003cString\u003e] [[-FileType] \u003cString\u003e] [[-StepSizeMB] \u003cInt32\u003e] [[-StatementTimeout] \u003cInt32\u003e] [-LogsOnly] [-ExcludeIndexStats] [-ExcludeUpdateUsage] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2016 -Database Northwind,pubs,Adventureworks2014\nShrinks Northwind, pubs and Adventureworks2014 to have as little free space as possible.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50\nShrinks AdventureWorks2014 to have 50% free space. So let\u0027s say AdventureWorks2014 was 1GB and it\u0027s using 100MB space. The database free space would be reduced to 50MB.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2014 -Database AdventureWorks2014 -PercentFreeSpace 50 -FileType Data -StepSize 25MB\nShrinks AdventureWorks2014 to have 50% free space, runs shrinks in 25MB chunks for improved performance.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eInvoke-DbaDbShrink -SqlInstance sql2012 -AllUserDatabases\nShrinks all databases on SQL2012 (not ideal for production)", + "Syntax": "Invoke-DbaDbShrink [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Database] \u003cObject[]\u003e] [[-ExcludeDatabase] \u003cObject[]\u003e] [-AllUserDatabases] [[-PercentFreeSpace] \u003cInt32\u003e] [[-ShrinkMethod] \u003cString\u003e] [[-FileType] \u003cString\u003e] [[-StepSize] \u003cInt32\u003e] [[-StatementTimeout] \u003cInt32\u003e] [-LogsOnly] [-ExcludeIndexStats] [-ExcludeUpdateUsage] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Invoke-DbaDbUpgrade", @@ -23552,7 +23539,7 @@ }, { "CommandName": "Measure-DbaBackupThroughput", - "Description": "Returns backup history details for one or more databases on a SQL Server.\n\nOutput looks like this:\nSqlInstance : sql2016\nDatabase : SharePoint_Config\nAvgThroughputMB : 1.07\nAvgSizeMB : 24.17\nAvgDuration : 00:00:01.1000000\nMinThroughputMB : 0.02\nMaxThroughputMB : 2.26\nMinBackupDate : 8/6/2015 10:22:01 PM\nMaxBackupDate : 6/19/2016 12:57:45 PM\nBackupCount : 10", + "Description": "Returns backup history details for one or more databases on a SQL Server.\n\nOutput looks like this:\nSqlInstance : sql2016\nDatabase : SharePoint_Config\nAvgThroughput : 1.07 MB\nAvgSize : 24.17\nAvgDuration : 00:00:01.1000000\nMinThroughput : 0.02 MB\nMaxThroughput : 2.26 MB\nMinBackupDate : 8/6/2015 10:22:01 PM\nMaxBackupDate : 6/19/2016 12:57:45 PM\nBackupCount : 10", "Tags": [ "Backup", "Database" @@ -23636,7 +23623,7 @@ "Synopsis": "Determines how quickly SQL Server is backing up databases to media.", "Name": "Measure-DbaBackupThroughput", "Links": "https://dbatools.io/Measure-DbaBackupThroughput", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016\nParses every backup in msdb\u0027s backuphistory for stats on all databases.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Database AdventureWorks2014\nParses every backup in msdb\u0027s backuphistory for stats on AdventureWorks2014.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2005 -Last\nProcesses the last full, diff and log backups every backup for all databases on sql2005.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2005 -Last -Type Log\nProcesses the last log backups every backup for all databases on sql2005.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-7)\nGets backup calculations for the last week.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-365) -Database bigoldb\nGets backup calculations, limited to the last year and only the bigoldb database", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016\nParses every backup in msdb\u0027s backuphistory for stats on all databases.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Database AdventureWorks2014\nParses every backup in msdb\u0027s backuphistory for stats on AdventureWorks2014.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2005 -Last\nProcesses the last full, diff and log backups every backup for all databases on sql2005.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2005 -Last -Type Log\nProcesses the last log backups every backup for all databases on sql2005.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-7) | Where-Object { $_.MinThroughput.Gigabyte -gt 1 }\nGets backup calculations for the last week and filters results that have a minimum of 1GB throughput\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eMeasure-DbaBackupThroughput -SqlInstance sql2016 -Since (Get-Date).AddDays(-365) -Database bigoldb\nGets backup calculations, limited to the last year and only the bigoldb database", "Syntax": "Measure-DbaBackupThroughput [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [-Since \u003cDateTime\u003e] [-Last] [-Type \u003cString\u003e] [-DeviceType \u003cString[]\u003e] [-EnableException] [\u003cCommonParameters\u003e]" }, { @@ -25299,9 +25286,9 @@ "" ], [ - "Password", + "SecurePassword", "Password to encrypt/decrypt private key for export to remote machine", - "", + "Password", false, "false", "" @@ -25393,7 +25380,7 @@ "Name": "New-DbaComputerCertificate", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaComputerCertificate\nCreates a computer certificate signed by the local domain CA for the local machine with the keylength of 1024.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaComputerCertificate -ComputerName Server1\nCreates a computer certificate signed by the local domain CA _on the local machine_ for server1 with the keylength of 1024.\nThe certificate is then copied to the new machine over WinRM and imported.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eNew-DbaComputerCertificate -ComputerName sqla, sqlb -ClusterInstanceName sqlcluster -KeyLength 4096\nCreates a computer certificate for sqlcluster, signed by the local domain CA, with the keylength of 4096.\nThe certificate is then copied to sqla _and_ sqlb over WinRM and imported.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eNew-DbaComputerCertificate -ComputerName Server1 -WhatIf\nShows what would happen if the command were run\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eNew-DbaComputerCertificate -SelfSigned\nCreates a self-signed certificate", - "Syntax": "New-DbaComputerCertificate [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [[-CaServer] \u003cString\u003e] [[-CaName] \u003cString\u003e] [[-ClusterInstanceName] \u003cString\u003e] [[-Password] \u003cSecureString\u003e] [[-FriendlyName] \u003cString\u003e] [[-CertificateTemplate] \u003cString\u003e] [[-KeyLength] \u003cInt32\u003e] [[-Store] \u003cString\u003e] [[-Folder] \u003cString\u003e] [[-Dns] \u003cString[]\u003e] [-SelfSigned] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "New-DbaComputerCertificate [[-ComputerName] \u003cDbaInstanceParameter[]\u003e] [[-Credential] \u003cPSCredential\u003e] [[-CaServer] \u003cString\u003e] [[-CaName] \u003cString\u003e] [[-ClusterInstanceName] \u003cString\u003e] [[-SecurePassword] \u003cSecureString\u003e] [[-FriendlyName] \u003cString\u003e] [[-CertificateTemplate] \u003cString\u003e] [[-KeyLength] \u003cInt32\u003e] [[-Store] \u003cString\u003e] [[-Folder] \u003cString\u003e] [[-Dns] \u003cString[]\u003e] [-SelfSigned] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaConnectionString", @@ -25773,9 +25760,9 @@ "" ], [ - "Password", + "SecurePassword", "Secure string used to authenticate the Credential Identity", - "", + "Password", false, "false", "" @@ -25807,7 +25794,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -25834,8 +25821,8 @@ "Synopsis": "Creates a new SQL Server credential", "Name": "New-DbaCredential", "Links": null, - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1\nYou will be prompted to securely enter your password, then a credential will be created in the master database on server1 if it does not exist.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Confirm:$false\nSuppresses all prompts to install but prompts to securely enter your password and creates a credential on Server1.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Name AzureBackupBlobStore -Identity \u0027\u003cAzure Storage Account Name\u003e\u0027 -Password (ConvertTo-SecureString \u0027\u003cAzure Storage Account Access Key\u003e\u0027 -AsPlainText \r\n-Force)\nCreate credential on SQL Server 2012 CU2, SQL Server 2014 for use with BACKUP TO URL.\r\nCredentialIdentity needs to be supplied with the Azure Storage Account Name.\r\nPassword needs to be one of the Access Keys for the account.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Name \u0027https://\u003cAzure Storage Account Name\u003e.blob.core.windows.net/\u003cBlob Store Container Name\u003e\u0027 -Identity \u0027SHARED ACCESS SIGNATURE\u0027 -Password \r\n(ConvertTo-SecureString \u0027\u003cShared Access Token\u003e\u0027 -AsPlainText -Force)\nCreate Credential on SQL Server 2016 or higher for use with BACKUP TO URL.\r\nName has to be the full URL for the blob store container that will be the backup target.\r\nPassword needs to be passed the Shared Access Token (SAS Key).", - "Syntax": "New-DbaCredential [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Name] \u003cObject[]\u003e] [-Identity] \u003cString[]\u003e [[-Password] \u003cSecureString\u003e] [[-MappedClassType] \u003cString\u003e] [[-ProviderName] \u003cString\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1\nYou will be prompted to securely enter your password, then a credential will be created in the master database on server1 if it does not exist.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Confirm:$false\nSuppresses all prompts to install but prompts to securely enter your password and creates a credential on Server1.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Name AzureBackupBlobStore -Identity \u0027\u003cAzure Storage Account Name\u003e\u0027 -SecurePassword (ConvertTo-SecureString \u0027\u003cAzure Storage Account Access Key\u003e\u0027 \r\n-AsPlainText -Force)\nCreate credential on SQL Server 2012 CU2, SQL Server 2014 for use with BACKUP TO URL.\r\nCredentialIdentity needs to be supplied with the Azure Storage Account Name.\r\nPassword needs to be one of the Access Keys for the account.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eNew-DbaCredential -SqlInstance Server1 -Name \u0027https://\u003cAzure Storage Account Name\u003e.blob.core.windows.net/\u003cBlob Store Container Name\u003e\u0027 -Identity \u0027SHARED ACCESS SIGNATURE\u0027 -SecurePassword \r\n(ConvertTo-SecureString \u0027\u003cShared Access Token\u003e\u0027 -AsPlainText -Force)\nCreate Credential on SQL Server 2016 or higher for use with BACKUP TO URL.\r\nName has to be the full URL for the blob store container that will be the backup target.\r\nPassword needs to be passed the Shared Access Token (SAS Key).", + "Syntax": "New-DbaCredential [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Name] \u003cObject[]\u003e] [-Identity] \u003cString[]\u003e [[-SecurePassword] \u003cSecureString\u003e] [[-MappedClassType] \u003cString\u003e] [[-ProviderName] \u003cString\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaDacOption", @@ -26241,9 +26228,9 @@ "False" ], [ - "Password", + "SecurePassword", "Optional password - if no password is supplied, the password will be protected by the master key", - "", + "Password", false, "false", "" @@ -26287,7 +26274,7 @@ "Name": "New-DbaDbCertificate", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaDbCertificate -SqlInstance Server1\nYou will be prompted to securely enter your password, then a certificate will be created in the master database on server1 if it does not exist.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaDbCertificate -SqlInstance Server1 -Database db1 -Confirm:$false\nSuppresses all prompts to install but prompts to securely enter your password and creates a certificate in the \u0027db1\u0027 database", - "Syntax": "New-DbaDbCertificate [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Name] \u003cString[]\u003e] [[-Database] \u003cString[]\u003e] [[-Subject] \u003cString[]\u003e] [[-StartDate] \u003cDateTime\u003e] [[-ExpirationDate] \u003cDateTime\u003e] [-ActiveForServiceBrokerDialog] [[-Password] \u003cSecureString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "New-DbaDbCertificate [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Name] \u003cString[]\u003e] [[-Database] \u003cString[]\u003e] [[-Subject] \u003cString[]\u003e] [[-StartDate] \u003cDateTime\u003e] [[-ExpirationDate] \u003cDateTime\u003e] [-ActiveForServiceBrokerDialog] [[-SecurePassword] \u003cSecureString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaDbMasterKey", @@ -26327,9 +26314,9 @@ "master" ], [ - "Password", + "SecurePassword", "Secure string used to create the key.", - "", + "Password", false, "false", "" @@ -26373,7 +26360,7 @@ "Name": "New-DbaDbMasterKey", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaDbMasterKey -SqlInstance Server1\nYou will be prompted to securely enter your password, then a master key will be created in the master database on server1 if it does not exist.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaDbMasterKey -SqlInstance Server1 -Credential usernamedoesntmatter\nYou will be prompted by a credential interface to securely enter your password, then a master key will be created in the master database on server1 if it does not exist.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eNew-DbaDbMasterKey -SqlInstance Server1 -Database db1 -Confirm:$false\nSuppresses all prompts to install but prompts in th console to securely enter your password and creates a master key in the \u0027db1\u0027 database", - "Syntax": "New-DbaDbMasterKey [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Database] \u003cString[]\u003e] [[-Password] \u003cSecureString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "New-DbaDbMasterKey [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Database] \u003cString[]\u003e] [[-SecurePassword] \u003cSecureString\u003e] [[-InputObject] \u003cDatabase[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaDbSnapshot", @@ -26851,9 +26838,9 @@ "" ], [ - "Password", + "SecurePassword", "Secure string used to authenticate the Login", - "", + "Password", false, "false", "" @@ -26985,7 +26972,7 @@ "Name": "New-DbaLogin", "Links": "https://dbatools.io/New-DbaLogin", "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaLogin -SqlInstance Server1,Server2 -Login Newlogin\nYou will be prompted to securely enter the password for a login [Newlogin]. The login would be created on servers Server1 and Server2 with default parameters.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$securePassword = Read-Host \"Input password\" -AsSecureString\nPS C:\\\u003e New-DbaLogin -SqlInstance Server1\\sql1 -Login Newlogin -Password $securePassword -PasswordPolicy -PasswordExpiration\nCreates a login on Server1\\sql1 with a predefined password. The login will have password and expiration policies enforced onto it.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eGet-DbaLogin -SqlInstance sql1 -Login Oldlogin | New-DbaLogin -SqlInstance sql1 -LoginRenameHashtable @{Oldlogin = \u0027Newlogin\u0027} -Force -NewSid -Disabled:$false\nCopies a login [Oldlogin] to the same instance sql1 with the same parameters (including password). New login will have a new sid, a new name [Newlogin] and will not be disabled. Existing login \r\n[Newlogin] will be removed prior to creation.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaLogin -SqlInstance sql1 -Login Login1,Login2 | New-DbaLogin -SqlInstance sql2 -PasswordPolicy -PasswordExpiration -DefaultDatabase tempdb -Disabled\nCopies logins [Login1] and [Login2] from instance sql1 to instance sql2, but enforces password and expiration policies for the new logins. New logins will also have a default database set to [tempdb] \r\nand will be created in a disabled state.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eNew-DbaLogin -SqlInstance sql1 -Login domain\\user\nCreates a new Windows Authentication backed login on sql1. The login will be part of the public server role.", - "Syntax": "New-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [[-Login] \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [[-Password] \u003cSecureString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-DefaultDatabase \u003cString\u003e] [-Language \u003cString\u003e] [-PasswordExpiration] [-PasswordPolicy] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-MapToAsymmetricKey \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-MapToCertificate \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-HashedPassword \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-DefaultDatabase \u003cString\u003e] [-Language \u003cString\u003e] [-PasswordExpiration] [-PasswordPolicy] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "New-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [[-Login] \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [[-SecurePassword] \u003cSecureString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-DefaultDatabase \u003cString\u003e] [-Language \u003cString\u003e] [-PasswordExpiration] [-PasswordPolicy] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-MapToAsymmetricKey \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-MapToCertificate \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nNew-DbaLogin [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Login \u003cString[]\u003e] [-InputObject \u003cObject[]\u003e] [-LoginRenameHashtable \u003cHashtable\u003e] [-HashedPassword \u003cString\u003e] [-MapToCredential \u003cString\u003e] [-Sid \u003cObject\u003e] [-DefaultDatabase \u003cString\u003e] [-Language \u003cString\u003e] [-PasswordExpiration] [-PasswordPolicy] [-Disabled] [-NewSid] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaScriptingOption", @@ -27036,9 +27023,9 @@ "" ], [ - "Password", + "SecurePassword", "Secure string used to create the key.", - "", + "Password", false, "false", "" @@ -27074,7 +27061,7 @@ "Name": "New-DbaServiceMasterKey", "Links": null, "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eNew-DbaServiceMasterKey -SqlInstance Server1\nYou will be prompted to securely enter your Service Key password, then a master key will be created in the master database on server1 if it does not exist.", - "Syntax": "New-DbaServiceMasterKey [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-Password] \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Syntax": "New-DbaServiceMasterKey [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-SecurePassword] \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbaSsisCatalog", @@ -27088,7 +27075,7 @@ [ "SqlInstance", "SQL Server you wish to run the function on.", - "ServerInstance,SqlServer", + "", true, "true (ByValue)", "" @@ -27102,10 +27089,18 @@ "" ], [ - "Password", - "Required password that will be used for the security key in SSISDB.", + "Credential", + "Use a credential object instead of a securepassword", "", - true, + false, + "false", + "" + ], + [ + "SecurePassword", + "Required password that will be used for the security key in SSISDB.", + "Password", + false, "false", "" ], @@ -27120,7 +27115,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -27147,8 +27142,8 @@ "Synopsis": "Enables the SSIS Catalog on a SQL Server 2012+", "Name": "New-DbaSsisCatalog", "Links": "https://dbatools.io/New-DbaSsisCatalog", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$password = ConvertTo-SecureString MyVisiblePassWord -AsPlainText -Force\nPS C:\\\u003e New-DbaSsisCatalog -SqlInstance sql2016 -Password $password\nCreates the SSIS Catalog on server DEV01 with the specified password.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$password = Read-Host -AsSecureString -Prompt \"Enter password\"\nPS C:\\\u003e New-DbaSsisCatalog -SqlInstance DEV01 -Password $password\nCreates the SSIS Catalog on server DEV01 with the specified password.", - "Syntax": "New-DbaSsisCatalog [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [-Password] \u003cSecureString\u003e [[-SsisCatalog] \u003cString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$SecurePassword = Read-Host -AsSecureString -Prompt \"Enter password\"\nPS C:\\\u003e New-DbaSsisCatalog -SqlInstance DEV01 -SecurePassword $SecurePassword\nCreates the SSIS Catalog on server DEV01 with the specified password.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eNew-DbaSsisCatalog -SqlInstance sql2016 -Credential usernamedoesntmatter\nCreates the SSIS Catalog on server DEV01 with the specified password in the credential prompt. As the example username suggets the username does not matter.\r\nThis is simply an easier way to get a secure password.", + "Syntax": "New-DbaSsisCatalog [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Credential] \u003cPSCredential\u003e] [[-SecurePassword] \u003cSecureString\u003e] [[-SsisCatalog] \u003cString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "New-DbatoolsSupportPackage", @@ -28066,7 +28061,7 @@ "Synopsis": "Reads and displays detailed information about a SQL Server backup.", "Name": "Read-DbaBackupHeader", "Links": "https://dbatools.io/Read-DbaBackupHeader", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance sql2016 -Path S:\\backups\\mydb\\mydb.bak\nLogs into sql2016 using Windows authentication and reads the local file on sql2016, S:\\backups\\mydb\\mydb.bak.\nIf you are running this command on a workstation and connecting remotely, remember that sql2016 cannot access files on your own workstation.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance sql2016 -Path \\\\nas\\sql\\backups\\mydb\\mydb.bak, \\\\nas\\sql\\backups\\otherdb\\otherdb.bak\nLogs into sql2016 and reads two backup files - mydb.bak and otherdb.bak. The SQL Server service account must have rights to read this file.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak -Simple\nLogs into the local workstation (or computer) and shows simplified output about C:\\temp\\myfile.bak. The SQL Server service account must have rights to read this file.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e$backupinfo = Read-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak\nPS C:\\\u003e $backupinfo.FileList\nDisplays detailed information about each of the datafiles contained in the backupset.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak -FileList\nAlso returns detailed information about each of the datafiles contained in the backupset.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003e\"C:\\temp\\myfile.bak\", \"\\backupserver\\backups\\myotherfile.bak\" | Read-DbaBackupHeader -SqlInstance sql2016\nSimilar to running Read-DbaBackupHeader -SqlInstance sql2016 -Path \"C:\\temp\\myfile.bak\", \"\\backupserver\\backups\\myotherfile.bak\"\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eGet-ChildItem \\\\nas\\sql\\*.bak | Read-DbaBackupHeader -SqlInstance sql2016\nGets a list of all .bak files on the \\\\nas\\sql share and reads the headers using the server named \"sql2016\". This means that the server, sql2016, must have read access to the \\\\nas\\sql share.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -Path https://dbatoolsaz.blob.core.windows.net/azbackups/restoretime/restoretime_201705131850.bak -AzureCredential AzureBackupUser\nGets the backup header information from the SQL Server backup file stored at https://dbatoolsaz.blob.core.windows.net/azbackups/restoretime/restoretime_201705131850.bak on Azure", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance sql2016 -Path S:\\backups\\mydb\\mydb.bak\nLogs into sql2016 using Windows authentication and reads the local file on sql2016, S:\\backups\\mydb\\mydb.bak.\nIf you are running this command on a workstation and connecting remotely, remember that sql2016 cannot access files on your own workstation.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance sql2016 -Path \\\\nas\\sql\\backups\\mydb\\mydb.bak, \\\\nas\\sql\\backups\\otherdb\\otherdb.bak\nLogs into sql2016 and reads two backup files - mydb.bak and otherdb.bak. The SQL Server service account must have rights to read this file.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak -Simple\nLogs into the local workstation (or computer) and shows simplified output about C:\\temp\\myfile.bak. The SQL Server service account must have rights to read this file.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003e$backupinfo = Read-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak\nPS C:\\\u003e $backupinfo.FileList\nDisplays detailed information about each of the datafiles contained in the backupset.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -SqlInstance . -Path C:\\temp\\myfile.bak -FileList\nAlso returns detailed information about each of the datafiles contained in the backupset.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003e\"C:\\temp\\myfile.bak\", \"\\backupserver\\backups\\myotherfile.bak\" | Read-DbaBackupHeader -SqlInstance sql2016 | Where-Object { $_.BackupSize.Megabyte -gt 100 }\nReads the two files and returns only backups larger than 100 MB\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eGet-ChildItem \\\\nas\\sql\\*.bak | Read-DbaBackupHeader -SqlInstance sql2016\nGets a list of all .bak files on the \\\\nas\\sql share and reads the headers using the server named \"sql2016\". This means that the server, sql2016, must have read access to the \\\\nas\\sql share.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eRead-DbaBackupHeader -Path https://dbatoolsaz.blob.core.windows.net/azbackups/restoretime/restoretime_201705131850.bak -AzureCredential AzureBackupUser\nGets the backup header information from the SQL Server backup file stored at https://dbatoolsaz.blob.core.windows.net/azbackups/restoretime/restoretime_201705131850.bak on Azure", "Syntax": "Read-DbaBackupHeader [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-SqlCredential] \u003cPSCredential\u003e] [-Path] \u003cObject[]\u003e [-Simple] [-FileList] [[-AzureCredential] \u003cString\u003e] [-EnableException] [\u003cCommonParameters\u003e]" }, { @@ -29562,7 +29557,7 @@ "Synopsis": "Drops a database, hopefully even the really stuck ones.", "Name": "Remove-DbaDatabase", "Links": "https://dbatools.io/Remove-DbaDatabase", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb\nPrompts then removes the database containeddb on SQL Server sql2016\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb, mydb\nPrompts then removes the databases containeddb and mydb on SQL Server sql2016\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb -Confirm:$false\nDoes not prompt and swiftly removes containeddb on SQL Server sql2016\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance server\\instance -ExcludeAllSystemDb | Remove-DbaDatabase\nRemoves all the user databases from server\\instance\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance server\\instance -ExcludeAllSystemDb | Remove-DbaDatabase -Confirm:$false\nRemoves all the user databases from server\\instance without any confirmation", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb\nPrompts then removes the database containeddb on SQL Server sql2016\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb, mydb\nPrompts then removes the databases containeddb and mydb on SQL Server sql2016\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eRemove-DbaDatabase -SqlInstance sql2016 -Database containeddb -Confirm:$false\nDoes not prompt and swiftly removes containeddb on SQL Server sql2016\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance server\\instance -ExcludeSystem | Remove-DbaDatabase\nRemoves all the user databases from server\\instance\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eGet-DbaDatabase -SqlInstance server\\instance -ExcludeSystem | Remove-DbaDatabase -Confirm:$false\nRemoves all the user databases from server\\instance without any confirmation", "Syntax": "Remove-DbaDatabase [-SqlCredential \u003cPSCredential\u003e] [-IncludeSystemDb] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nRemove-DbaDatabase -SqlInstance \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] -Database \u003cObject[]\u003e [-IncludeSystemDb] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nRemove-DbaDatabase [-SqlCredential \u003cPSCredential\u003e] -InputObject \u003cDatabase[]\u003e [-IncludeSystemDb] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { @@ -31498,6 +31493,14 @@ "false", "" ], + [ + "SqlCredential", + "Instead of using Login and SecurePassword, you can just pass in a credential object.", + "", + false, + "false", + "" + ], [ "Login", "By default, the Login parameter is \"sa\" but any other SQL or Windows account can be specified. If a login does not currently exist, it will be added.\nWhen adding a Windows login to remote servers, ensure the SQL Server can add the login (ie, don\u0027t add WORKSTATION\\Admin to remoteserver\\instance. Domain users and Groups are valid input.", @@ -31525,7 +31528,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -31552,8 +31555,8 @@ "Synopsis": "This function allows administrators to regain access to SQL Servers in the event that passwords or access was lost.\n\nSupports SQL Server 2005 and above. Windows administrator access is required.", "Name": "Reset-DbaAdmin", "Links": "https://dbatools.io/Reset-DbaAdmin", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlcluster\nPrompts for password, then resets the \"sa\" account password on sqlcluster.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlserver\\sqlexpress -Login ad\\administrator\nPrompts user to confirm that they understand the SQL Service will be restarted.\nAdds the domain account \"ad\\administrator\" as a sysadmin to the SQL instance.\r\nIf the account already exists, it will be added to the sysadmin role.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlserver\\sqlexpress -Login sqladmin -Force\nSkips restart confirmation, prompts for password, then adds a SQL Login \"sqladmin\" with sysadmin privileges.\r\nIf the account already exists, it will be added to the sysadmin role and the password will be reset.", - "Syntax": "Reset-DbaAdmin [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-Login] \u003cString\u003e] [[-SecurePassword] \u003cSecureString\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlcluster -SqlCredential sqladmin\nPrompts for password, then resets the \"sqladmin\" account password on sqlcluster.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlserver\\sqlexpress -Login ad\\administrator -Confirm:$false\nAdds the domain account \"ad\\administrator\" as a sysadmin to the SQL instance.\nIf the account already exists, it will be added to the sysadmin role.\nDoes not prompt for a password since it is not a SQL login. Does not prompt for confirmation since -Confirm is set to $false.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eReset-DbaAdmin -SqlInstance sqlserver\\sqlexpress -Login sqladmin -Force\nSkips restart confirmation, prompts for password, then adds a SQL Login \"sqladmin\" with sysadmin privileges.\r\nIf the account already exists, it will be added to the sysadmin role and the password will be reset.", + "Syntax": "Reset-DbaAdmin [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-Login] \u003cString\u003e] [[-SecurePassword] \u003cSecureString\u003e] [-Force] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Resolve-DbaNetworkName", @@ -32211,9 +32214,9 @@ "master" ], [ - "Password", + "SecurePassword", "Secure string used to decrypt the private key.", - "", + "Password", false, "false", "(Read-Host \"Password\" -AsSecureString)" @@ -32248,8 +32251,8 @@ "Synopsis": "Imports certificates from .cer files using SMO.", "Name": "Restore-DbaDbCertificate", "Links": "https://dbatools.io/Restore-DbaDbCertificate", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRestore-DbaDbCertificate -SqlInstance Server1 -Path \\\\Server1\\Certificates -Password (ConvertTo-SecureString -Force -AsPlainText GoodPass1234!!)\nRestores all the certificates in the specified path, password is used to both decrypt and encrypt the private key.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRestore-DbaDbCertificate -SqlInstance Server1 -Path \\\\Server1\\Certificates\\DatabaseTDE.cer -Password (ConvertTo-SecureString -force -AsPlainText GoodPass1234!!)\nRestores the DatabaseTDE certificate to Server1 and uses the MasterKey to encrypt the private key.", - "Syntax": "Restore-DbaDbCertificate [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-SqlCredential] \u003cPSCredential\u003e] [-Path] \u003cObject[]\u003e [[-EncryptionPassword] \u003cSecureString\u003e] [[-Database] \u003cString\u003e] [[-Password] \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eRestore-DbaDbCertificate -SqlInstance Server1 -Path \\\\Server1\\Certificates -SecurePassword (ConvertTo-SecureString -Force -AsPlainText GoodPass1234!!)\nRestores all the certificates in the specified path, password is used to both decrypt and encrypt the private key.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eRestore-DbaDbCertificate -SqlInstance Server1 -Path \\\\Server1\\Certificates\\DatabaseTDE.cer -SecurePassword (ConvertTo-SecureString -force -AsPlainText GoodPass1234!!)\nRestores the DatabaseTDE certificate to Server1 and uses the MasterKey to encrypt the private key.", + "Syntax": "Restore-DbaDbCertificate [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-SqlCredential] \u003cPSCredential\u003e] [-Path] \u003cObject[]\u003e [[-EncryptionPassword] \u003cSecureString\u003e] [[-Database] \u003cString\u003e] [[-SecurePassword] \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Restore-DbaDbSnapshot", @@ -35162,16 +35165,16 @@ "" ], [ - "Password", + "SecurePassword", "The new password for the login This can be either a credential or a secure string.", - "", + "Password", false, "false", "" ], [ "Unlock", - "Switch to unlock an account. This will only be used in conjunction with the -Password parameter.\r\nThe default is false.", + "Switch to unlock an account. This will only be used in conjunction with the -SecurePassword parameter.\r\nThe default is false.", "", false, "false", @@ -35179,7 +35182,7 @@ ], [ "MustChange", - "Does the user need to change his/her password. This will only be used in conjunction with the -Password parameter.\r\nThe default is false.", + "Does the user need to change his/her password. This will only be used in conjunction with the -SecurePassword parameter.\r\nThe default is false.", "", false, "false", @@ -35287,8 +35290,8 @@ "Synopsis": "Set-DbaLogin makes it possible to make changes to one or more logins.", "Name": "Set-DbaLogin", "Links": "https://dbatools.io/Set-DbaLogin", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$password = ConvertTo-SecureString \"PlainTextPassword\" -AsPlainText -Force\nPS C:\\\u003e $cred = New-Object System.Management.Automation.PSCredential (\"username\", $password)\r\nPS C:\\\u003e Set-DbaLogin -SqlInstance sql1 -Login login1 -Password $cred -Unlock -MustChange\nSet the new password for login1 using a credential, unlock the account and set the option\r\nthat the user must change password at next logon.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -Enable\nEnable the login\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1, login2, login3, login4 -Enable\nEnable multiple logins\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1, sql2, sql3 -Login login1, login2, login3, login4 -Enable\nEnable multiple logins on multiple instances\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -Disable\nDisable the login\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -DenyLogin\nDeny the login to connect to the instance\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -GrantLogin\nGrant the login to connect to the instance\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -PasswordPolicyEnforced\nEnforces the password policy on a login\n-------------------------- EXAMPLE 9 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -PasswordPolicyEnforced:$false\nDisables enforcement of the password policy on a login\n-------------------------- EXAMPLE 10 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login test -AddRole serveradmin\nAdd the server role \"serveradmin\" to the login\n-------------------------- EXAMPLE 11 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login test -RemoveRole bulkadmin\nRemove the server role \"bulkadmin\" to the login\n-------------------------- EXAMPLE 12 --------------------------\nPS C:\\\u003e$login = Get-DbaLogin -SqlInstance sql1 -Login test\nPS C:\\\u003e $login | Set-DbaLogin -Disable\nDisable the login from the pipeline", - "Syntax": "Set-DbaLogin [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Login] \u003cString[]\u003e] [[-Password] \u003cObject\u003e] [-Unlock] [-MustChange] [[-NewName] \u003cString\u003e] [-Disable] [-Enable] [-DenyLogin] [-GrantLogin] [-PasswordPolicyEnforced] [[-AddRole] \u003cString[]\u003e] [[-RemoveRole] \u003cString[]\u003e] [[-InputObject] \u003cLogin[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$SecurePassword = ConvertTo-SecureString \"PlainTextPassword\" -AsPlainText -Force\nPS C:\\\u003e $cred = New-Object System.Management.Automation.PSCredential (\"username\", $SecurePassword)\r\nPS C:\\\u003e Set-DbaLogin -SqlInstance sql1 -Login login1 -SecurePassword $cred -Unlock -MustChange\nSet the new password for login1 using a credential, unlock the account and set the option\r\nthat the user must change password at next logon.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -Enable\nEnable the login\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1, login2, login3, login4 -Enable\nEnable multiple logins\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1, sql2, sql3 -Login login1, login2, login3, login4 -Enable\nEnable multiple logins on multiple instances\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -Disable\nDisable the login\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -DenyLogin\nDeny the login to connect to the instance\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -GrantLogin\nGrant the login to connect to the instance\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -PasswordPolicyEnforced\nEnforces the password policy on a login\n-------------------------- EXAMPLE 9 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login login1 -PasswordPolicyEnforced:$false\nDisables enforcement of the password policy on a login\n-------------------------- EXAMPLE 10 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login test -AddRole serveradmin\nAdd the server role \"serveradmin\" to the login\n-------------------------- EXAMPLE 11 --------------------------\nPS C:\\\u003eSet-DbaLogin -SqlInstance sql1 -Login test -RemoveRole bulkadmin\nRemove the server role \"bulkadmin\" to the login\n-------------------------- EXAMPLE 12 --------------------------\nPS C:\\\u003e$login = Get-DbaLogin -SqlInstance sql1 -Login test\nPS C:\\\u003e $login | Set-DbaLogin -Disable\nDisable the login from the pipeline", + "Syntax": "Set-DbaLogin [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [[-Login] \u003cString[]\u003e] [[-SecurePassword] \u003cObject\u003e] [-Unlock] [-MustChange] [[-NewName] \u003cString\u003e] [-Disable] [-Enable] [-DenyLogin] [-GrantLogin] [-PasswordPolicyEnforced] [[-AddRole] \u003cString[]\u003e] [[-RemoveRole] \u003cString[]\u003e] [[-InputObject] \u003cLogin[]\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Set-DbaMaxDop", @@ -36134,7 +36137,7 @@ "0" ], [ - "DataFileSizeMB", + "DataFileSize", "Specifies the total data file size in megabytes. This is distributed across the total number of data files.", "", true, @@ -36142,7 +36145,7 @@ "0" ], [ - "LogFileSizeMB", + "LogFileSize", "Specifies the log file size in megabytes. If not specified, this will be set to 25% of total data file size.", "", false, @@ -36150,7 +36153,7 @@ "0" ], [ - "DataFileGrowthMB", + "DataFileGrowth", "Specifies the growth amount for the data file(s) in megabytes. The default is 512 MB.", "", false, @@ -36158,7 +36161,7 @@ "512" ], [ - "LogFileGrowthMB", + "LogFileGrowth", "Specifies the growth amount for the log file in megabytes. The default is 512 MB.", "", false, @@ -36199,7 +36202,7 @@ ], [ "DisableGrowth", - "If this switch is enabled, the tempdb files will be configured to not grow. This overrides -DataFileGrowthMB and -LogFileGrowthMB.", + "If this switch is enabled, the tempdb files will be configured to not grow. This overrides -DataFileGrowth and -LogFileGrowth.", "", false, "false", @@ -36208,7 +36211,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -36235,8 +36238,8 @@ "Synopsis": "Sets tempdb data and log files according to best practices.", "Name": "Set-DbaTempdbConfig", "Links": "https://dbatools.io/Set-DbaTempdbConfig", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000\nCreates tempdb with a number of data files equal to the logical cores where each file is equal to 1000MB divided by the number of logical cores, with a log file of 250MB.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -DataFileCount 8\nCreates tempdb with 8 data files, each one sized at 125MB, with a log file of 250MB.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -OutputScriptOnly\nProvides a SQL script output to configure tempdb according to the passed parameters.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -DisableGrowth\nDisables the growth for the data and log files.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSizeMB 1000 -OutputScriptOnly\nReturns the T-SQL script representing tempdb configuration.", - "Syntax": "Set-DbaTempdbConfig [-SqlInstance] \u003cDbaInstanceParameter\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-DataFileCount] \u003cInt32\u003e] [-DataFileSizeMB] \u003cInt32\u003e [[-LogFileSizeMB] \u003cInt32\u003e] [[-DataFileGrowthMB] \u003cInt32\u003e] [[-LogFileGrowthMB] \u003cInt32\u003e] [[-DataPath] \u003cString\u003e] [[-LogPath] \u003cString\u003e] [[-OutFile] \u003cString\u003e] [-OutputScriptOnly] [-DisableGrowth] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000\nCreates tempdb with a number of data files equal to the logical cores where each file is equal to 1000MB divided by the number of logical cores, with a log file of 250MB.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -DataFileCount 8\nCreates tempdb with 8 data files, each one sized at 125MB, with a log file of 250MB.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -OutputScriptOnly\nProvides a SQL script output to configure tempdb according to the passed parameters.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -DisableGrowth\nDisables the growth for the data and log files.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eSet-DbaTempdbConfig -SqlInstance localhost -DataFileSize 1000 -OutputScriptOnly\nReturns the T-SQL script representing tempdb configuration.", + "Syntax": "Set-DbaTempdbConfig [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [[-SqlCredential] \u003cPSCredential\u003e] [[-DataFileCount] \u003cInt32\u003e] [-DataFileSize] \u003cInt32\u003e [[-LogFileSize] \u003cInt32\u003e] [[-DataFileGrowth] \u003cInt32\u003e] [[-LogFileGrowth] \u003cInt32\u003e] [[-DataPath] \u003cString\u003e] [[-LogPath] \u003cString\u003e] [[-OutFile] \u003cString\u003e] [-OutputScriptOnly] [-DisableGrowth] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Set-DbatoolsConfig", @@ -38314,7 +38317,7 @@ }, { "CommandName": "Test-DbaBuild", - "Description": "Returns info about the specific build of a SQL instance, including the SP, the CU and the reference KB, End Of Support, wherever possible. It adds a Compliance property as true/false, and adds details about the \"targeted compliance\"", + "Description": "Returns info about the specific build of a SQL instance, including the SP, the CU and the reference KB, End Of Support, wherever possible. It adds a Compliance property as true/false, and adds details about the \"targeted compliance\".", "Tags": [ "SqlBuild", "Version" @@ -38330,7 +38333,7 @@ ], [ "MinimumBuild", - "This is the build version to test \"compliance\" against. Anything below this is flagged as not compliant", + "This is the build version to test \"compliance\" against. Anything below this is flagged as not compliant.", "", false, "false", @@ -38395,10 +38398,10 @@ ], "Alias": "Test-DbaSqlBuild", "Author": "Simone Bizzotto (@niphold) | Friedrich Weinmann (@FredWeinmann)", - "Synopsis": "Returns SQL Server Build \"compliance\" level on a build", + "Synopsis": "Returns SQL Server Build \"compliance\" level on a build.", "Name": "Test-DbaBuild", "Links": "https://dbatools.io/Test-DbaBuild", - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MinimumBuild \"12.0.5557\"\nReturns information about a build identified by \"12.0.5540\" (which is SQL 2014 with SP2 and CU4), which is not compliant as the minimum required\r\nbuild is \"12.0.5557\" (which is SQL 2014 with SP2 and CU8)\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"1SP\"\nReturns information about a build identified by \"12.0.5540\", making sure it is AT MOST 1 Service Pack \"behind\". For that version,\r\nthat identifies an SP2, means accepting as the lowest compliance version as \"12.0.4110\", that identifies 2014 with SP1\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"1SP 1CU\"\nReturns information about a build identified by \"12.0.5540\", making sure it is AT MOST 1 Service Pack \"behind\", plus 1 CU \"behind\". For that version,\r\nthat identifies an SP2 and CU, rolling back 1 SP brings you to \"12.0.4110\", but given the latest CU for SP1 is CU13, the target \"compliant\" build\r\nwill be \"12.0.4511\", which is 2014 with SP1 and CU12\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"0CU\"\nReturns information about a build identified by \"12.0.5540\", making sure it is the latest CU release.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -Latest\nSame as previous, returns information about a build identified by \"12.0.5540\", making sure it is the latest build available.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.00.4502\" -MinimumBuild \"12.0.4511\" -Update\nSame as before, but tries to fetch the most up to date index online. When the online version is newer, the local one gets overwritten\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.4502\",\"10.50.4260\" -MinimumBuild \"12.0.4511\"\nReturns information builds identified by these versions strings\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eGet-DbaCmsRegServer -SqlInstance sqlserver2014a | Test-DbaBuild -MinimumBuild \"12.0.4511\"\nIntegrate with other cmdlets to have builds checked for all your registered servers on sqlserver2014a", + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MinimumBuild \"12.0.5557\"\nReturns information about a build identified by \"12.0.5540\" (which is SQL 2014 with SP2 and CU4), which is not compliant as the minimum required\r\nbuild is \"12.0.5557\" (which is SQL 2014 with SP2 and CU8).\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"1SP\"\nReturns information about a build identified by \"12.0.5540\", making sure it is AT MOST 1 Service Pack \"behind\". For that version,\r\nthat identifies an SP2, means accepting as the lowest compliance version as \"12.0.4110\", that identifies 2014 with SP1.\nOutput column CUTarget is not relevant (empty). SPTarget and BuildTarget are filled in the result.\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"1SP 1CU\"\nReturns information about a build identified by \"12.0.5540\", making sure it is AT MOST 1 Service Pack \"behind\", plus 1 CU \"behind\". For that version,\r\nthat identifies an SP2 and CU, rolling back 1 SP brings you to \"12.0.4110\", but given the latest CU for SP1 is CU13, the target \"compliant\" build\r\nwill be \"12.0.4511\", which is 2014 with SP1 and CU12.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -MaxBehind \"0CU\"\nReturns information about a build identified by \"12.0.5540\", making sure it is the latest CU release.\nOutput columns CUTarget, SPTarget and BuildTarget are relevant. If the latest build is a service pack (not a CU), CUTarget will be empty.\n-------------------------- EXAMPLE 5 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.5540\" -Latest\nReturns information about a build identified by \"12.0.5540\", making sure it is the latest build available.\nOutput columns CUTarget and SPTarget are not relevant (empty), only the BuildTarget is.\n-------------------------- EXAMPLE 6 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.00.4502\" -MinimumBuild \"12.0.4511\" -Update\nSame as before, but tries to fetch the most up to date index online. When the online version is newer, the local one gets overwritten.\n-------------------------- EXAMPLE 7 --------------------------\nPS C:\\\u003eTest-DbaBuild -Build \"12.0.4502\",\"10.50.4260\" -MinimumBuild \"12.0.4511\"\nReturns information builds identified by these versions strings.\n-------------------------- EXAMPLE 8 --------------------------\nPS C:\\\u003eGet-DbaCmsRegServer -SqlInstance sqlserver2014a | Test-DbaBuild -MinimumBuild \"12.0.4511\"\nIntegrate with other cmdlets to have builds checked for all your registered servers on sqlserver2014a.", "Syntax": "Test-DbaBuild [[-Build] \u003cVersion[]\u003e] [[-MinimumBuild] \u003cVersion\u003e] [[-MaxBehind] \u003cString\u003e] [-Latest] [[-SqlInstance] \u003cDbaInstanceParameter[]\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [-Update] [-Quiet] [-EnableException] [\u003cCommonParameters\u003e]" }, { @@ -39160,20 +39163,12 @@ "Params": [ [ "ComputerName", - "The server(s) to check disk configuration on.", + "The target computer or computers.", "ServerInstance,SqlServer,SqlInstance", true, "true (ByValue)", "" ], - [ - "Detailed", - "Output all properties, will be deprecated in 1.0.0 release.", - "", - false, - "false", - "False" - ], [ "Credential", "Specifies an alternate Windows account to use when enumerating drives on the server. May require Administrator privileges. To use:\n$cred = Get-Credential, then pass $cred object to the -Credential parameter.", @@ -39201,7 +39196,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -39213,7 +39208,7 @@ "Name": "Test-DbaDiskAlignment", "Links": "https://dbatools.io/Test-DbaDiskAlignment", "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eTest-DbaDiskAlignment -ComputerName sqlserver2014a\nTests the disk alignment of a single server named sqlserver2014a\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eTest-DbaDiskAlignment -ComputerName sqlserver2014a, sqlserver2014b, sqlserver2014c\nTests the disk alignment of multiple servers", - "Syntax": "Test-DbaDiskAlignment [-ComputerName] \u003cObject[]\u003e [-Detailed] [[-Credential] \u003cPSCredential\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [-NoSqlCheck] [-EnableException] [\u003cCommonParameters\u003e]" + "Syntax": "Test-DbaDiskAlignment [-ComputerName] \u003cDbaInstanceParameter[]\u003e [[-Credential] \u003cPSCredential\u003e] [[-SqlCredential] \u003cPSCredential\u003e] [-NoSqlCheck] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Test-DbaDiskAllocation", @@ -39454,9 +39449,9 @@ "0" ], [ - "ExcludeSystemDb", + "ExcludeSystem", "Allows you to suppress output on system databases", - "ExcludeSystemDatabases", + "ExcludeSystemDb", false, "false", "False" @@ -39476,7 +39471,7 @@ "Name": "Test-DbaIdentityUsage", "Links": "https://dbatools.io/Test-DbaIdentityUsage", "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003eTest-DbaIdentityUsage -SqlInstance sql2008, sqlserver2012\nCheck identity seeds for servers sql2008 and sqlserver2012.\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003eTest-DbaIdentityUsage -SqlInstance sql2008 -Database TestDB\nCheck identity seeds on server sql2008 for only the TestDB database\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eTest-DbaIdentityUsage -SqlInstance sql2008 -Database TestDB -Threshold 20\nCheck identity seeds on server sql2008 for only the TestDB database, limiting results to 20% utilization of seed range or higher", - "Syntax": "Test-DbaIdentityUsage [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [[-Threshold] \u003cInt32\u003e] [[-ExcludeSystemDb]] [-EnableException] [\u003cCommonParameters\u003e]" + "Syntax": "Test-DbaIdentityUsage [-SqlInstance] \u003cDbaInstanceParameter[]\u003e [-SqlCredential \u003cPSCredential\u003e] [-Database \u003cObject[]\u003e] [-ExcludeDatabase \u003cObject[]\u003e] [[-Threshold] \u003cInt32\u003e] [[-ExcludeSystem]] [-EnableException] [\u003cCommonParameters\u003e]" }, { "CommandName": "Test-DbaJobOwner", @@ -40480,7 +40475,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -40699,7 +40694,7 @@ ], [ "Username", - "Username of the service account. Cannot be used with -ServiceCredential. For local service accounts use one of the following usernames omitting the -Password parameter:\r\nLOCALSERVICE\r\nNETWORKSERVICE\r\nLOCALSYSTEM", + "Username of the service account. Cannot be used with -ServiceCredential. For local service accounts use one of the following usernames omitting the -SecurePassword parameter:\r\nLOCALSERVICE\r\nNETWORKSERVICE\r\nLOCALSYSTEM", "User", false, "false", @@ -40722,9 +40717,9 @@ "(New-Object System.Security.SecureString)" ], [ - "NewPassword", + "SecurePassword", "New password of the service account. The function will ask for a password if not specified. MSAs and local system accounts will ignore the password.", - "Password", + "Password,NewPassword", false, "false", "(New-Object System.Security.SecureString)" @@ -40732,7 +40727,7 @@ [ "EnableException", "By default, when something goes wrong we try to catch it, interpret it and give you a friendly warning message.\r\nThis avoids overwhelming you with \"sea of red\" exceptions, but is inconvenient because it basically disables advanced scripting.\r\nUsing this switch turns this \"nice by default\" feature off and enables you to catch exceptions with your own try/catch.", - "Silent", + "", false, "false", "False" @@ -40759,8 +40754,8 @@ "Synopsis": "Changes service account (or just its password) of the SQL Server service.", "Name": "Update-DbaServiceAccount", "Links": null, - "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$NewPassword = ConvertTo-SecureString \u0027Qwerty1234\u0027 -AsPlainText -Force\nUpdate-DbaServiceAccount -ComputerName sql1 -ServiceName \u0027MSSQL$MYINSTANCE\u0027 -Password $NewPassword\nChanges the current service account\u0027s password of the service MSSQL$MYINSTANCE to \u0027Qwerty1234\u0027\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$cred = Get-Credential\nPS C:\\\u003e Get-DbaService sql1 -Type Engine,Agent -Instance MYINSTANCE | Update-DbaServiceAccount -ServiceCredential $cred\nRequests credentials from the user and configures them as a service account for the SQL Server engine and agent services of the instance sql1\\MYINSTANCE\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eUpdate-DbaServiceAccount -ComputerName sql1,sql2 -ServiceName \u0027MSSQLSERVER\u0027,\u0027SQLSERVERAGENT\u0027 -Username NETWORKSERVICE\nConfigures SQL Server engine and agent services on the machines sql1 and sql2 to run under Network Service system user.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaService sql1 -Type Engine -Instance MSSQLSERVER | Update-DbaServiceAccount -Username \u0027MyDomain\\sqluser1\u0027\nConfigures SQL Server engine service on the machine sql1 to run under MyDomain\\sqluser1. Will request user to input the account password.", - "Syntax": "Update-DbaServiceAccount [-ComputerName \u003cDbaInstanceParameter[]\u003e] [-Credential \u003cPSCredential\u003e] [-ServiceName] \u003cString[]\u003e [-Username \u003cString\u003e] [-ServiceCredential \u003cPSCredential\u003e] [-PreviousPassword \u003cSecureString\u003e] [-NewPassword \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nUpdate-DbaServiceAccount [-Credential \u003cPSCredential\u003e] -InputObject \u003cObject[]\u003e [-Username \u003cString\u003e] [-ServiceCredential \u003cPSCredential\u003e] [-PreviousPassword \u003cSecureString\u003e] [-NewPassword \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" + "Examples": "-------------------------- EXAMPLE 1 --------------------------\nPS C:\\\u003e$SecurePassword = ConvertTo-SecureString \u0027Qwerty1234\u0027 -AsPlainText -Force\nUpdate-DbaServiceAccount -ComputerName sql1 -ServiceName \u0027MSSQL$MYINSTANCE\u0027 -SecurePassword $SecurePassword\nChanges the current service account\u0027s password of the service MSSQL$MYINSTANCE to \u0027Qwerty1234\u0027\n-------------------------- EXAMPLE 2 --------------------------\nPS C:\\\u003e$cred = Get-Credential\nPS C:\\\u003e Get-DbaService sql1 -Type Engine,Agent -Instance MYINSTANCE | Update-DbaServiceAccount -ServiceCredential $cred\nRequests credentials from the user and configures them as a service account for the SQL Server engine and agent services of the instance sql1\\MYINSTANCE\n-------------------------- EXAMPLE 3 --------------------------\nPS C:\\\u003eUpdate-DbaServiceAccount -ComputerName sql1,sql2 -ServiceName \u0027MSSQLSERVER\u0027,\u0027SQLSERVERAGENT\u0027 -Username NETWORKSERVICE\nConfigures SQL Server engine and agent services on the machines sql1 and sql2 to run under Network Service system user.\n-------------------------- EXAMPLE 4 --------------------------\nPS C:\\\u003eGet-DbaService sql1 -Type Engine -Instance MSSQLSERVER | Update-DbaServiceAccount -Username \u0027MyDomain\\sqluser1\u0027\nConfigures SQL Server engine service on the machine sql1 to run under MyDomain\\sqluser1. Will request user to input the account password.", + "Syntax": "Update-DbaServiceAccount [-ComputerName \u003cDbaInstanceParameter[]\u003e] [-Credential \u003cPSCredential\u003e] [-ServiceName] \u003cString[]\u003e [-Username \u003cString\u003e] [-ServiceCredential \u003cPSCredential\u003e] [-PreviousPassword \u003cSecureString\u003e] [-SecurePassword \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]\nUpdate-DbaServiceAccount [-Credential \u003cPSCredential\u003e] -InputObject \u003cObject[]\u003e [-Username \u003cString\u003e] [-ServiceCredential \u003cPSCredential\u003e] [-PreviousPassword \u003cSecureString\u003e] [-SecurePassword \u003cSecureString\u003e] [-EnableException] [-WhatIf] [-Confirm] [\u003cCommonParameters\u003e]" }, { "CommandName": "Update-Dbatools",