I am using the below script to get the SQL instance name and then perform some tasks related to it. I am unable to get it working can you help me figure out how to fix the issue?
$SQLInstances = (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SQL Server').InstalledInstances
foreach ($sql in $SQLInstances) {
[PSCustomObject]#{
InstanceName = $sql
}
}
Write-Host "The following SQL Instances were detected on the server $env:Computername $SQLInstances" -ForegroundColor Yellow
If ($SQLInstances -ne "MSSQLSERVER")
{Write-Host $($env:Computername)\$($SQLInstances)
$serverName = $($env:Computername)\$($SQLInstances)}
Else {Write-Host "Standard SQL Instance was found, proceeding with the script."
$ServerName = $env:Computername}
So the above code doesn't work, Write-Host displays"ComputerName(SPACE)\InstanceName" so there is an extra space there that i want to get rid off, plus $serverName = $($env:Computername)\$($SQLInstances)} throws " unexpected token / expression
How Do i fix this?
You are seeing this issue with Write-Host because of how the parser is interpreting tokens. () or $() (unless () or $() is part of a string) is going to be treated as one argument in expression mode. Since the default separator for Write-Host is a space, you get the extra space between each of your processed arguments. If you surround your entire value with double quotes, it will be parsed as a single token.
Write-Host "$($env:Computername)\$SQLInstances"
Regarding the $serverName assignment, it is also a parsing issue. When assigning to a variable, the parser is in expression mode. Therefore, the value must be a valid expression. The \ character is what throws the error. Double quotes will also suffice here.
$serverName = "$($env:Computername)\$SQLInstances"
Try the Get-SqlInstance cmdlet from module sqlserver:
Import-Module sqlserver
If (Get-SQLInstance -ServerInstance "MSSQLSERVER"){
# Instance found
}
Else {
# Instance not found
Related
Not sure what's wrong with this script
$SSODelete= "Delete"
$SSOfiles = "SSo.xml"
$channlename = "INC8-Patch"
write-host $channlename
if ($channelname -like *INC8*){
$SSOarg = "$SSODelete $SSOfiles"
Write-Host $SSOarg
}
It throws following error:
You must provide a value expression following the '*' operator.
At line:5 char:25
+ if ($channelname -like *INC8*){
+ ~~~~~
Unexpected token 'INC8*' in expression or statement.
Tried using "*INC8*" and '*INC8' but it then it does not qualify if statement.
Adding screenshot for script and it's results
Simple Script and results
The PowerShell -like operator should be used with the matching string quoted, e.g., $variable -like "*pattern*". -like accepts the simple wildcard (*) only; you can compare against regular expressions (regexps) by using -match. See Get-Help about_Comparison_Operators.
Thanks , it was due to variable name i was comparing ... i need to be more cautious
I would like to invoke an arbitrary expression and redirect std error to a variable without redirection to a file.
For example, in Powershell it is possible to redirect standard error using 2> operator. Using a temporary file, I can easily get what I want:
#$expr = "1/0" # with std error
#$expr = "2+2" # without stderror
#$expr = "Get-Service invalidsvc" # with stderror
$expr = "try { throw '111' } catch { }" # without std error
$ans = Invoke-Expression $expr -ErrorVariable ev 2> C:\log\stderr.txt
if(cat C:\log\stderr){
Write-Host "Error $ev"
}
How can I do the same, but without creation of a temporal output file?
Wrong solutions:
Using -ErrorVariable switch. Counter example:
Invoke-Expression $expr -ErrorVariable ev 2> C:\aaa\file1.txt
$expr = "try { throw '111' } catch { }"
Write-Host "Error $ev" # will output error, but std error is empty
$LASTEXITCODE and $? check. Counter example:
Get-Service invalidservice
$lastexitcode is equal to 0, $? is equal to True, but std error is not empty
The idea is simple: save the "red" (std error) text in Powershell console in a variable. The command I receive is an arbitrary string.
Examples:
When I write "try { throw '111' } catch { }" in Powershell console there will be no red (error) text in PS console (despite the fact $error is not empty). So if I invoke that expression in my code I get no error saved in some variable.
When I write "Get-Service notexistingservice", or "1/0", or "Write-Error 111" there will red (error) text and non-null $error. So if I invoke that expression in my code I would like to get error saved in some variable.
Save standard output and standard error to separate variables. It won't work without the dollar sign (from Windows Powershell in Action).
$err = $( $output = get-childitem foo3 ) 2>&1
The way to do it is the -errorvariable common parameter. Your counter example is only valid (and I only hesitantly use that word) because you have explicitly coded for it to not output an error with the use of the Try/Catch and not including anything coding in your catch. You are basically complaining that you told PowerShell to send error cases to the Catch scriptblock, where you did not output anything, and then having an issue when nothing is output. An error still occurs, it is logged in the errorvariable as you stated it should be, and also stored in $Error, but since you did not output anything in your Catch block there's nothing for your StdErr redirect to do.
If you want $ev to not contain an error because you corrected the issue in your Catch block, then also clear the variable in the catch block.
$expr = 'try{ throw "1111"}catch{Remove-Variable ev}'
Or if you want StdErr to contain the error text, make sure you include that output in your Catch block:
$expr = 'try{ throw "1111"}catch{Write-Error $_.Exception.Message}'
I know this is a very old question but I had the same problem and wanted to share what I ended up with.
$error.clear()
$List = New-Object PSObject
Invoke-Command -ComputerName $server -ScriptBlock {
$smbv1 = (Get-SmbServerConfiguration | Select EnableSMB1Protocol)
$smbv1 | Select-Object EnableSMB1Protocol} -OutVariable List
foreach($item in $list.EnableSMB1Protocol){
if($error -ne $null){
$item = "unknown"
$msg = $error.Exception.Message
ac .\smb1errors.txt "$Server, $msg"
}
Since the $error variable is a .NET object in order to clear it I needed to pass it parameter (). I then executed my code, in this case checking for SMBv1 service, and testing if $error is still $null. If the $error variable has content I grabed it in a variable. $msg = $error.Exception.Message
I am using the following in the start of a function that is meant to query a computer for various wmi objects. If just get_volumes is ran alone it should use 127.0.0.1. It seems that when I run get_volumes without any string this it passes right on to the else segment. What is the proper or a better way to accomplish this?
PS> function get_volumes([string]$a){
if ($a -eq $null){
write-host 'Using localhost'
$a = '127.0.0.1'
}else{ write-host 'Using' $a}
}
PS>get_volumes
Using
Thanks
$a is an empty string and not $null. Try this instead:
function Get-Volumes([string]$IPAddress = '127.0.0.1'){
Write-Host "Using $IPAddress"
}
Note that you can set a default value for when the user doesn't supply an argument for a parameter.
I have many oracle forms in one folder and I want to compile those forms through frmcmp command in powershell script.
I have written a powershell script which is following
$module="module="
get-childitem "C:\forms\fortest" -recurse |
where { $_.extension -eq ".fmb" } |
foreach {
C:\Oracle\Middleware\Oracle_FRHome1\BIN\frmcmp $module $_.FullName userid=xyz/xyz#xyz Output_File=C:\forms\11\common\fmx\$_.BaseName+'.fmx'
}
but this one is not working. i am new in powershell.
but when I try to compile a single form through command prompt its working like following.
frmcmp module=C:\forms\src\xyz.fmb userid=xyz/xyz#xyz Output_File=C:\forms\11\common\fmx\xyz.fmx
When you want to use variables inside a string in PowerShell you have different options. To start with, you will always need to use " as opposed to ' to wrap the string, if you want variables in your string.
$myVariable = "MyPropertyValue"
Write-Host "The variable has the value $MyVariable"
The above code would yield the output:
The variable has the value MyPropertyValue
If you want to use a property of a variable (or any expression) and insert it into the string, you need to wrap it in the string with $(expression goes here), e.g.
$MyVariable = New-Object PSObject -Property #{ MyPropertyName = 'MyPropertyValue' }
# The following will fail getting the property since it will only consider
# the variable name as code, not the dot or the property name. It will
# therefore ToString the object and append the literal string .MyPropertyName
Write-Host "Failed property value retrieval: $MyVariable.MyPropertyName"
# This will succeed, since it's wrapped as code.
Write-Host "Successful property value retrieval: $($MyVariable.MyPropertyName)"
# You can have any code in those wrappers, for example math.
Write-Host "Maths calculating: 3 * 27 = $( 3 * 27 )"
The above code would yield the following output:
Failed property value retrieval: #{MyPropertyName=MyPropertyValue}.MyPropertyName
Successful property value retrieval: MyPropertyValue
Maths calculating: 3 * 27 = 81
I generally try to use the Start-Process cmdlet when I start processes in PowerShell, since it gives me the possibility of additional control over the process started. This means that you could use something similar to the following.
Get-ChildItem "C:\forms\fortest" -Filter "*.fmb" -recurse | Foreach {
$FormPath = $_.FullName
$ResultingFileName = $_.BaseName
Start-Process -FilePath "C:\Oracle\Middleware\Oracle_FRHome1\BIN\frmcmp.exe" -ArgumentList "module=$FormPath", "userid=xyz/xyz#xyz", "Output_File=C:\forms\11\common\fmx\$ResultingFileName.fmx"
}
You could also add the -Wait parameter to the Start-Process command, if you want to wait with compilation of the next item until the current compilation has completed.
I'm writing a script to load computer names from a CSV file, then look up their IP addresses.
The script creates an error when using the name from the CSV.
If I run the script in ISE, the error shows up, but the result still comes though. If I run the script from powershell, it errors and the result is null.
If I substitute the $PCname = $_.System for $PCname = "Computer01" everything works fine.
If I write-host $_.System it displays "Computer01". How can I get this to work in powershell?
$file = "\\server.contoso.net\private$\Systems.csv";
$CSV = Import-CSV $file;
$CSV | %{
if ($_.Skip -eq 0)
{
$PCname = $_.System
# $PCname = "Computer01"
write-host $PCname
try
{
$ipaddress = [System.Net.Dns]::GetHostByName($PCname).AddressList[0].IpAddressToString
}
Catch [system.exception]
{
if(1)
{ $error[0].tostring() }
}
}
}
Error displayed is:
Exception calling "GetHostByName" with "1" argument(s): "The requested name is valid, but no data of the requested type was found"
Turns out that the values in the CSV at some point had whitespace added after them, which caused a name look up error. I'm not sure why ISE would still be able to look up the host, but removing the whitespace fixed the issue.
Thanks to sha, his recommendation helped me see the whitespace.