PowerShell runtime execption in remote call - sql-server

I intend to install remotely a sql-instance. I have a share with sql-binaries and a config-file.
My script is:
import-module sqlserver -DisableNameChecking
$setupDrive = "\\sqlshare\sql_source\ISO\Setup\SW_DVD9_NTRL_SQL_Svr_Ent_Core_2019Dec2019_64Bit_English_OEM_VL_X22-22120"
$fileExe = "$setupDrive", "setup.exe" -join("\")
$configurationFile = "\\sqlshare\sql_source\ISO\ConfigurationFileMSSQLSERVER.ini"
$session = New-PSSession -ComputerName "xxxx_yyyy"
Invoke-Command -ScriptBlock{& $args[0] /CONFIGURATIONFILE=$args[1]} -Session $session
-ArgumentList $fileExe, $configurationFile
I'm still getting an error and don't know how to interpret it:
An error occurred while creating the pipeline.
+ CategoryInfo : NotSpecified: (:) [], RuntimeException
+ FullyQualifiedErrorId : RuntimeException
+ PSComputerName : xxxx_yyyy
I have a PS-script on the server A:(C:\temp\script.ps1) with this content:
import-module sqlserver -DisableNameChecking
& ("\\server1-ssp1102.my.domain\sql_source\Setup\setup.exe
/CONFIGURATIONFILE=\\server1-ssp1102.my.domain\sql_source\SQLUnattended\ConfigurationFileMSSQLSERVER.ini")
I want to execute this script on the server B (installs a sql server).
This doesn't work:
invoke-command -computer ServerB -FilePath C:\C:\temp\script.ps1 -credentials (get-credential)
Update once again:
The complete call looks like following:
# A sample target computer.
$computer = 'myComputer'
# Obtain the credentials for the remote session and store them in a
variable.
$cred = Get-Credential my\user
Invoke-Command -ComputerName $computer -Credential $cred {
$setup = '\\myShare-xxxx.my.domain\sql_source\Setup\setup.exe'
$config = '\\myShare-yyy- xxx.my.domain\sql_source\SQLUnattendedInstallation\ConfigurationFileMSSQLSERVER.ini'
$cu = '\\my-domain-xxxx.my.domain\sql_source\SQLUnattendedInstallation2019\CU'
$null = New-PSDrive -Credential $using:cred -Name cu -Root $cu -PSProvider FileSystem
$null = New-PSDrive -Credential $using:cred -Name setup -Root (Split-Path -Parent $setup) -PSProvider FileSystem
$null = New-PSDrive -Credential $using:cred -Name config -Root (Split-Path -Parent $config) -PSProvider FileSystem
& $using:setup /CONFIGURATIONFILE=$using:config
}
Update:2
I've created a file (test5.ps1) with this content:
import-module sqlserver -DisableNameChecking
$setup = '\\xxx-xxx-xxx.xxx.xxx\sql_source\Setup\setup.exe'
$config = '\\xxx-xxx- xxx.xxx.xxx\sql_source\SQLUnattendedInstallation2019\ConfigurationFileMSSQLSERVER.ini'
$cu = '\\xxx-xxx-xxx.xxx.xxx\sql_source\SQLUnattendedInstallation2019\CU\SQLServer2019-KB5014353-x64.exe'
$null = New-PSDrive -Credential $using:cred -Name cu -Root (Split-
Path $cu) -PSProvider FileSystem
$null = New-PSDrive -Credential $using:cred -Name setup -Root
(Split-Path -Parent $setup) -PSProvider FileSystem
$null = New-PSDrive -Credential $using:cred -Name config -Root
(Split-Path -Parent $config) -PSProvider FileSystem
& $setup /CONFIGURATIONFILE=$config
and then I'm calling this script like this:
Invoke-Command -ComputerName xxx-sql-yyy -FilePath
C:\Users\xxx\Documents\test\test5.ps1 -Credential (Get-Credential
my\user)
then the script begins to install the sql server on the remote machine, but still I get an error (in the summary.txt from the sql server installation on the remote machine):
Access is denied.
Error result: -2061762559
Result facility code: 1308
Result error code: 1
meaning: still a problem with the credentials.
Update 3:
The script (test5.ps1) stays untouched
on the caller-site:
$cred = get-credential
Invoke-Command -ComputerName xxx-sql-yyy -FilePath
C:\Users\xxx\Documents\test\test5.ps1 -Credential $cred
Unfortunately the same error: Access denied etc.

the tricky problem was inside of the configuration.ini file for unattended sql server installation, namely:
;SQLSVCACCOUNT="myDomain\theServiceAccount$" # originally
SQLSVCACCOUNT="NT Service\MSSQLServer" # changed
;AGTSVCACCOUNT="myDomain\theAgentAccount$" # originally
AGTSVCACCOUNT="NT Service\SQLServerAgent" # changed
The error-message "Access denied" was all about those accounts.
After the installation I have to change the service accounts for the sql- and agent services and that's all.

Related

Getting MSSQL Instance Version in Powershell

From running the following I can see that there are 4 MSSQL instances running on this machine:
$Hostname = (Get-WmiObject Win32_OperatingSystem).CSName
$GetSQLInstance = Get-Service -ComputerName $Hostname | Where-Object { ($_.Name -eq 'mssqlserver' -or $_.Name -like 'mssql$*') -and $_.DisplayName -like 'SQL Server*'}
$GetSQLInstance
Status Name DisplayName
------ ---- -----------
Running MSSQL$INSTANCE01 SQL Server (INSTANCE01)
Running MSSQL$INSTANCE02 SQL Server (INSTANCE02)
Running MSSQL$INSTANCE03 SQL Server (INSTANCE03)
Running MSSQL$INSTANCE04 SQL Server (INSTANCE04)
I am trying to ascertain the MSSQL version of these instances, what would be the best way to do so? I thought to use Get-SqlInstance, but it doesn't seem to be installed on this machine:
Get-SqlInstance
Get-SqlInstance : The term 'Get-SqlInstance' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path is correct and try again.
At line:1 char:1
+ Get-SqlInstance
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-SqlInstance:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I use a modified version of this solution here. This is nice since you can run this remotely from your machine and it writes the info to a CSV.
Invoke-Command -ComputerName (Get-Content 'C:\Powershell\machines.txt') -ScriptBlock {
$SQLInstance = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances
foreach ($Install in $SQLInstance)
{
$Path = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\Instance Names\SQL').$Install
return (Get-ItemProperty "HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server\$Path\Setup")
}
} | Select-Object -Property PSComputerName,Edition,PatchLevel | Export-CSV -Path 'C:\Powershell\output.csv' -NoTypeInformation

Windows Server 2012R2/2016: HOWTO Check for the Active Directory PowerShell Module using Get-WindowsFeature

Windows Server 2012R2/2016: HOWTO Check for the Active Directory PowerShell Module using Get-WindowsFeature
I need a means to ensure the Windows 2012R2/2016 server I run an AD script on has Imported Active-Directory, and install it if not
#Check if AD is still installed
if (Import-Module ActiveDirectory -Proxy proxy.verizon.com:80 -ErrorAction Continue -Verbose)
{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Import-Module ActiveDirectory -Proxy proxy.verizon.com:80
}
else {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Get-WindowsFeature -Name RSAT-AD-PowerShell|Install-Windowsfeature -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
Import-Module ActiveDirectory -Proxy proxy.verizon.com:80
}
Blockquote
Will this work? My testing does not indicate a "true" response at '(Import-Module ActiveDirectory -Proxy proxy.verizon.com:80 -ErrorAction Continue -Verbose)'
Windows Server 2012R2/2016: HOWTO Check for the Active Directory PowerShell Module using Get-WindowsFeature
#Check if AD is still installed
$installed = Get-WindowsFeature -LogPath $log -InformationAction Continue -Name RSAT-AD-PowerShell
if ($installed.Installed)
{
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Import-Module ActiveDirectory -Verbose -NoClobber -WarningAction Continue -InformationAction Continue -ErrorAction Continue
}
else {
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12
Get-WindowsFeature $log -Name RSAT-AD-PowerShell|Install-Windowsfeature -WarningAction SilentlyContinue -ErrorAction SilentlyContinue
Import-Module ActiveDirectory -Verbose -NoClobber -WarningAction Continue -InformationAction Continue -ErrorAction Continue
}
#The $log is set in your script header, like this:
"$date = get-date -uformat "%m%d%y-%H"
$day = Get-Date -Format yyyyMMdd
$Service = "ServiceNameHere"
$log = ".\logs\start-$service-$date.log"'

Run multiple *.sql query files log to file

My goal is to have a PowerShell script run several Sqlquery.sql files against a specific SQL server and then log the output to a log file.
I can't get the logging to work and I don't know what I'm missing. My log file is always empty and I'm at a loss for that I am missing.
Contents of C:\Temp:
Build1.SQL
Build2.SQL
Build3.sql
Build4.sql
Build5.SQL
Build6.SQL
$PatchPostConvSQLScripts = Get-ChildItem -Path C::\Temp -Filter *.sql -Name
$Queries = $PatchPostConvSQLScripts
foreach ($query in $Queries){
Write-Host "Starting: $query"
Invoke-Sqlcmd -ServerInstance $DBServer -InputFile $query |
Out-File "C:\TEMP\scriptResults.log"
Write-Host "Completed: $query"
}
Once I get it logging to a file, I'll need to get a newline each time with a `n`r, but baby steps right now.
Is there a better way to do this that I just don't know?
The main reason you got nothing in log file is that Output-File rewrite whole data in it on each run. Try to use -Verbose as mentioned in answer by TechSpud to collect print/server statements, or write output to temp file and Add-Content to main log file:
$DBServer = "MYPC\SQLEXPRESS"
$sqlPath = "C:\TEMP\"
$log = "scriptResults.log"
$tempOut = "temp.log"
$files = Get-ChildItem -Path $sqlPath -Filter *.sql -Name
foreach ($file in $files){
Write-Host "Starting: $file"
Invoke-SQLcmd -ServerInstance $DBServer -InputFile $sqlPath$file | Out-File $sqlPath$tempOut
Get-Content $sqlPath$tempOut | Add-Content $sqlPath$log
Write-Host "Completed: $file"
}
Firstly, as #Ben Thul has mentioned in his comment, check that your SQL files actually output something (a resultset, or messages), by running them in Management Studio.
Then, you'll need to use the -Verbose flag, as this command will tell you.
Get-Help Invoke-Sqlcmd -Full
Invoke-Sqlcmd does not return SQL Server message output, such as the
output of PRINT statements, unless you use the PowerShell -Verbose parameter.
$Queries = Get-ChildItem -Path C::\Temp -Filter *.sql -Name
Clear-Content -Path "C:\TEMP\scriptResults.log" -Force
foreach ($query in $Queries){
Write-Host "Starting: $query"
Invoke-Sqlcmd -ServerInstance $DBServer -InputFile $query -Verbose |
Add-Content -Path "C:\TEMP\scriptResults.log"
Write-Host "Completed: $query"
}

Powershell Script using Invoke-SQL command,needed for SQL job, the SQL Server version of Powershell is somewhat crippled, is there a workaround?

Full Question: Have Powershell Script using Invoke SQL command, using snappins, I need them to be included in a SQL job, the SQL Server version of Powershell is somewhat crippled, does anyone know a workaround?
From what I have gathered, SQL Management Studio's version of powershell is underpowered, not allowing for the use of snappins, as such it does not recognize the cmdlets that I used in the script. I have tried running it in the job as a command line prompt rather than a Powershell script, which causes the code to work somewhat, however I check the history on the job and it says that invoke-sql is still not a recognized cmdlet. I speculate that because I am running the code on a remote server, with different credentials than my standard my profile with the snappins preloaded isn't being loaded, though this is somewhat doubtful.
Also, as I am a powershell rookie, any advice on better coding practices/streamlining my code would be much appreciated!
Code is as follows:
# define parameters
param
(
$file = "\\server\folder\file.ps1"
)
"invoke-sqlcmd -query """ | out-file "\\server\folder\file.ps1"
# retrieve set of table objects
$path = invoke-sqlcmd -query "select TableName from table WITH (NoLock)" -database db -server server
[reflection.assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
$so = New-Object Microsoft.SqlServer.Management.Smo.ScriptingOptions
$so.DriPrimaryKey = $false
$so.Nocollation = $true
$so.IncludeIfNotExists = $true
$so.NoIdentities = $true
$so.AnsiPadding = $false
# script each table
foreach ($table in $path)
{
#$holder = $table
$table = get-item sqlserver:\sql\server\default\databases\database\tables\dbo.$($table.TableName)
$table.script($so) | out-file -append $file
}
(get-content "\\server\folder\file.ps1") -notmatch "ANSI_NULLS" | out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -notmatch " AS "| out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -notmatch "Quoted_" | out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -replace "\) ON \[PRIMARY\].*", ")" | out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -replace "\[text\]", "[nvarchar](max)" | out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -replace " SPARSE ", "" | out-file "\\server\folder\file.ps1"
(get-content "\\server\folder\file.ps1") -replace "COLUMN_SET FOR ALL_SPARSE_COLUMNS", "" | out-file "\\server\folder\file.ps1"
""" -database database -server server" | out-file "\\server\folder\file.ps1" -append
So I figured out the answer to my own question. Using this site: http://www.mssqltips.com/tip.asp?tip=1684 and
http://www.mssqltips.com/tip.asp?tip=1199
I figured out that he was able to do so using a SQL Server Agent Proxy, so I followed the yellow brick road, and basically I set up a proxy to my account and was able to use the external powershell through a feature. A note, you need to create a credential under the securities tab in object explorer prior to being able to select one when creating the proxy. Basically I ended up creating a proxy named powershell, using the powershell subsystem, and use my login info to create a credential. VOILA!
You have to add the snapins each time. In your editor you likely already have them loaded from another script/tab/session. In SQL Server you will need to add something like this to the beginning of the script:
IF ( (Get-PSSnapin -Name sqlserverprovidersnapin100 -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin sqlserverprovidersnapin100
}
IF ( (Get-PSSnapin -Name sqlservercmdletsnapin100 -ErrorAction SilentlyContinue) -eq $null )
{
Add-PsSnapin sqlservercmdletsnapin100
}
I'm not sure the error you are trying to workaround - can you post that?
Have you tried this from a PowerShell prompt?
Add-PSSnapin SqlServerCmdletSnapin100

How to get an variable output from remote pssession

I have a script to get virtual harddisk info from vmm, im executing it remotely from a server, currently im unable to get the variable value outside of the pssession in the local host, could you please help me out with achieveing the same.
PS C:\Windows\system32> enter-pssession iscvmm02
[iscvmm02]: PS C:\Users\su\Documents>Add-PSSnapin Microsoft.SystemCenter.VirtualMachineManager
[iscvmm02]: PS C:\Users\su\Documents>$hide= Get-VMMServer -ComputerName "iscvmm02.corp.avanade.org"
[iscvmm02]: PS C:\Users\su\Documents>$VM = Get-VM | where { $_.ComputerNameString -contains "idpsm02.corp.air.org" }
[iscvmm02]: PS C:\Users\su\Documents>$harddisk=$VM.VirtualHardDisks
[iscvmm02]: PS C:\Users\su\Documents>$h=$harddisk.length
[iscvmm02]: PS C:\Users\su\Documents>for($i=0;$i-lt$h;$i++){
New-Variable -Name "HardDiskType_$i" -value $harddisk[$i].vhdtype
New-Variable -Name "HardDiskLocation_$i" -value $harddisk[$i].Location
}
[iadpscvmm02]: PS C:\Users\su\Documents>Exit-PSSession
PS C:\Windows\system32>$harddisktype_0
PS C:\Windows\system32>$harddisklocation_0
as you can see both the variable output's give null value, im unable to retain the values
This example gets listing from remote computer's C drive and assigns it into a local variable. So tune your VMM script accordingly.
$session = New-PSSession -ComputerName RemoteSystem
Invoke-Command -Session $session -ScriptBlock { $remoteC = gci c:\ }
# This shouldn't print anything.
$localC
# Print the result on remote computer an assing its output to localC variable
$localC = Invoke-Command -Session $session -ScriptBlock { $remoteC }
# Print the local variable, it should contain remoteC data.
$localC

Resources