Where-Object : Cannot bind parameter 'FilterScript' - powershell

I have one problem with two questions. I have following powercli cmd:
$snapLst = Get-VM vmindev |Get-Snapshot |Select VM, Name, Description, `
#{Name='Created'; Expression={{$_.Created.ToString("yyMMdd")}}, `
#{Name='SizeMB'; Expression={[int] $_.SizeMB}}
$resultLst=$snapLst| where SizeMB -gt 1000 |Sort-Object SizeMB |`
Select #{Name='Type'; Expression={'BIG'}},*
When run in my DEV env (powercli session on my desktop connecting to the vSphere sever), everything is fine. When run in PRODUCTION (ie. powercli session on the vSphere server), I get the following error:
Where-Object : Cannot bind parameter 'FilterScript'. Cannot convert the "SizeMB" value of type "System.String" to type System.Management.Automation.ScriptBlock".
At C:\Users\kness\Scripts\sn2.ps1:32 char:27
+ $resultLst=$snapLst| where <<<< SizeMB -gt 1000 |Sort-Object SizeMB |Select
#{Name='Type'; Expression={'BIG'}},
+ CategoryInfo : InvalidArgument: (:) [Where-Object], ParameterBindingException
+ FullyQualifiedErrorId : CannotConvertArgumentNoMessage,Microsoft.PowerShell.Commands.WhereObjectCommand
Q1: What - in the environment setup - would make the script behaves differently? I checked the versions of the powercli ... they're exactly the same.
Q2: Because the above error, I look into the property of the list by running this cmd:
$snapLst = Get-VM vmindev |Get-Snapshot |Get-Member |Findstr Size
SizeGB Property System.Nullable`1[[System.Decimal, mscorlib, Ve...
SizeMB Property System.Decimal SizeMB {get;}
SizeMB is a "decimal" type; why the error complains that it is a "string"?
Thx in advance!

I got it resolved with helps fr TessellatingHeckler.
A1. Although my PowerCLI package is the same, it operates on two different Powershell installation. On my desktop, PSVersion is 4.0 and on the production server, it is 2.0
A2. This is related to A1. In PS 4.0, the cmdlet where is translated properly to Where-Object {...}. Whereas in PS 2.0, it is a syntax error. The complain about SizeMB being System.String is just a red herring following the "where" syntax error.
By changing where SizeMB -gt 1000 to Where-Object {$_.SizeMB -gt 1000} the script is now working. I guess, the alternative would be to upgrade the PS on the vSphere server ... but I dont want to go there. Thanks for your helps everyone.

Related

Using PowerShell Invoke-Command not providing same IIS info when commands ran locally trying to get SSLBinding

I can't for the life of me figure out how to get my code to work remotely to show the same information it's showing when ran locally.
For example, if I run the command locally on a web server:
Get-ChildItem IIS:SSLBindings
I get the following results:
But if I run the command remotely using the following code:
Invoke-command -computer $Computer { Import-Module WebAdministration; Get-Childitem -Path IIS:\SslBindings }
I get this result:
I don't understand why the Sites info is blank, or just showing '...'.
I've tried all sorts of different variations/scriptblocks, but the results are always the same.
Anyone have any idea as to what I'm doing wrong or how I can remotely pull this information correctly?
I feel like there may be a better way to do this because this feels a bit clunky, but regardless, it works...
Here's the command I am using to gather this info remotely:
$SSLCertInUseInfo = Invoke-command -computer $Computer {
Import-Module WebAdministration; Get-Childitem -Path IIS:\SslBindings | Select IPAddress, Host, Port, Store,
#{ Name = 'Site'; Expression = { $_ | select -property Sites -expandproperty Sites | Select-Object -ExpandProperty "Value" } }
} | Select -Property * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
The result is:
Why this particular property is an issue: The cause for this is how the value for Sites is generated. This particular property happens to be a "ScriptProperty," which means it's pulled by a script defined in the WebAdministration module. That script is executed behind the scenes transparently. Unfortunately, ScriptProperties often don't survive the deserialization process when accessed through PSRemoting.
So, how do you find out if the property is a ScriptProperty? Check the member definitions by piping your command to Get-Member.
When run locally, you can see that the Sites member type is a ScriptProperty and the definition shows the start of the script it runs to fetch the data.
PS C:\> Get-Childitem -Path IIS:\SslBindings | Get-Member Sites
TypeName: System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Sites ScriptProperty System.Object Sites {get=$ip = [string]::empty...
When run remotely, you can see the type changes to one prefixed with "Deserialized," the member type is now a NoteProperty, and the definition changes to a string with no value.
PS C:\> Invoke-Command -ComputerName $Computer { Import-Module WebAdministration;Get-Childitem -Path IIS:\SslBindings } | Get-Member Sites
TypeName: Deserialized.System.Management.Automation.PSCustomObject
Name MemberType Definition
---- ---------- ----------
Sites NoteProperty System.String Sites=
How to solve the problem: The easiest way to get the desired value is to use calculated properties to convert the output to something that can be sent back. Similar to this answer, but a little more compact:
Invoke-Command -ComputerName $Computer {
Import-Module WebAdministration; Get-Childitem -Path IIS:\SslBindings |
Select-Object IPAddress, Port, Host, Store, #{Name="Sites"; Expression={($_).Sites.Value}} } |
Select-Object * -ExcludeProperty PSComputerName, RunSpaceID, PSShowComputerName
Output:
IPAddress : ::
Port : 443
Host :
Store : MY
Sites :
IPAddress : 0.0.0.0
Port : 443
Host :
Store : My
Sites : Default Web Site

Get-DnsServerResourceRecord not working on 2016 server

I have a powershell that utilizes the function Get-DnsServerResourceRecord. I have it working on a couple of different servers for testing, but on the server that I want it to run from I get this error:
Get-DnsServerResourceRecord : The term 'Get-DnsServerResourceRecord'
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:2
char:3
+ Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneNam ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Get-DnsServerResourceRecord:String) [], CommandNotF oundException
+ FullyQualifiedErrorId : CommandNotFoundException
All of my googling has told me that since I am running this on a Windows Server 2016 (DataCenter) that this should just work. What am I missing in order for this to run?
How I am actually running it:
$DNSServer = "dnsservername"
$dnsrecord = Get-DnsServerResourceRecord -ComputerName $DNSServer -ZoneName 'db.local' -RRType CName | Where-Object {$_.RecordData.HostNameAlias -like "*" -and $_.HostName -like "*.*"}
$Datatable = New-Object System.Data.DataTable
[void]$Datatable.Columns.Add("CName")
[void]$Datatable.Columns.Add("HostNameAlias")
Foreach ($record in $dnsrecord)
{
[void]$Datatable.Rows.Add($record.HostName, $record.RecordData.HostNameAlias)
}
You need to install DNS server Tools module.
run below powershell command
Install-WindowsFeature rsat-dns-server
(As of 2022)
List Installed Windows Features on Win10 (Powershell)
Get-WindowsOptionalFeature -Online | Where Name -Match "RSAT.*" | Format-Table -Autosize
Install RSAT.DNS.TOOLS
Add-WindowsCapability -Online -Name Rsat.Dns.Tools

When removing software "you cannot call a method on a null-valued expressions" error

I know there are other threads with this question but they all involve code that I don't understand. I know very little of scripting and I'm looking for someone to help me with an easy to understand answer.
I am trying to remove a program with PowerShell (the program doesn't have an uninstaller file).
I can remove it with Control Panel → Programs and Features, but I would like to do this remotely with a PSSession. So after some searching on Google I found the following script.
I first run
Get-WmiObject -Class Win32_Product | Select-Object -Property Name
Which gets me the name of the program I want to delete: "OpenOTP-CP (64 bit)"
I then run the script:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -match "OpenOTP-CP (64 bit)"
}
$app.Uninstall()
I then get the following error
You cannot call a method on a null-valued expression.
At C:\Users\Administrator\Desktop\Remote2.ps1:4 char:1
+ $app.Uninstall()
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Could someone maybe help me by telling me what is wrong or providing me with the correct code?
OS: Windows Server 2012 R2
Source for the script: http://lifeofageekadmin.com/how-to-uninstall-programs-using-powershell/
It sounds like $app may be an empty variable. I would add a temporary write-host "app is: $app" before you call $app.uninstall() to check if that is the case.
Alternatively, you could add some logic like this:
If ($app){
$app.Uninstall()
}else{
write-host "app was not found"
}
The reason $app might be empty is because the -match operator uses regular expressions, so it's likely treating the brackets as special characters. Try using -like instead of -match and surrounding it with asterisks:
$app = Get-WmiObject -Class Win32_Product | Where-Object {
$_.Name -like "*OpenOTP-CP (64 bit)*"
}
You could do it this way and it would be faster. I'm assume it's an msi provider.
get-package "*OpenOTP-CP (64 bit)*" | uninstall-package

Exchange PowerShell: Exporting mailbox folder AccessRights

With PowerShell, I want to make an export of all the mailboxes in an Exchange environment of users in a specific OU where the level of AccessRights of the user "Default" on the folder level does not equal "None". For this I am using the following command:
$AllMailbox = Get-Mailbox -OrganizationalUnit "DNofOU" -ResultSize Unlimited
$ResultData = foreach ($Mailbox in $AllMailbox)
{
Get-MailboxFolderPermission $Mailbox | Where-Object {$_.User -Match "Default" -AND $_.AccessRights -NotMatch "None"} | Select-Object Identity,AccessRights,#{Name="Name"; Expression={$Mailbox.Name}}
}
$ResultData | Export-CSV -Path C:\temp\MailboxFolderPermissions.csv
However, when running this command I get the following error:
Cannot process argument transformation on parameter 'Identity'. Cannot convert the "DisplayNameOfMailbox" value of type "Deserialized.Microsoft.Exc
hange.Data.Directory.Management.Mailbox" to type "Microsoft.Exchange.Configuration.Tasks.MailboxFolderIdParameter".
+ CategoryInfo : InvalidData: (:) [Get-MailboxFolderPermission], ParameterBindin...mationException
+ FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-MailboxFolderPermission
+ PSComputerName : FQDNofExchangeServer
The environment is based on Exchange 2010 on a Windows Server 2008 R2 server with PowerShell version 2.0. It is also possible to execute this from a Windows Server 2012 R2 server with PowerShell version 4.0 when remote connecting to the Exchange server.
For me, it worked better to use the full Canonical name of the object.
Like so:
$mailboxArray = Get-Mailbox -OrganizationalUnit "example.com/Accounts" -ResultSize Unlimited
I Wasn't sure if this for have found the answer or not yet, but wanted to provide my input on how you could possibly get all the mailboxes in an organizational Unit.

PowerShell: Get-Service w/ Get-Content, -name and select

I am trying to get the status of a specific service on 2008 R2 servers listed in a text file.
I once was able to successfully run the following:
$servers = Get-Content "C:\scripts\Computers.txt"
Get-Service -ComputerName $servers -Name MrT |
Select Name, MachineName, Status
As shown here:
Now when I run the same script I get the following error:
Get-Service : Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
At line:3 char:27
+ Get-Service -ComputerName $servers -Name MrT |
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Get-Service], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.GetServiceCommand
Technically to get past this, I could run the following but would rather run against a list of servers.
Get-Service -ComputerName 3b, 4b, 7b -Name MrT | Select Name, MachineName, Status
What am I doing wrong and how did it work once and not work again?
As the error message points it out, the $servers variable probably doesn't contain any items. Check the output by running:
Get-Content "C:\scripts\Computers.txt"