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

Time:07-13

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:

enter image description here

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:

enter image description here

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?

CodePudding user response:

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:

enter image description here

CodePudding user response:

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
  • Related