Script output works fine on console/file but not when redirected to a variable

Hello Guys,

I am a powershell novice, learning on V3. After learning all those tutorials, finally I have manged to make an advanced function. It may be ugly but works absolutely fine when I see the output on the console/redirect to CSV. When I want to redirect/capture the output into a variable, the console output is fine, BUT when I lookup the variable, iot is messed up. I don’t know what I am doing wrong and I hope I have explained it better.

So, this function is to collect the partition information on multiple remote machines. My environment has mixed OS.

In this test case, I am using 3 remote servers -

server1 - online server
offline - an offline server
linux - a linux server (running get-wmiobject to this server will return RPCunavailable error)

I made this script to try with several credentials, but I am not using any of those techniques in this test case.

Here is my script -

function Get-Logicaldiskinfo
{

[cmdletbinding()]
Param
(
    [Parameter(Mandatory = $false,Position=0)]
        [string[]]$ComputerName = $env:COMPUTERNAME,
    [Parameter(Mandatory = $false)]
        [System.Management.Automation.Credential()]$Credential = [System.Management.Automation.PSCredential]::Empty,
    [Parameter()]
    [switch]$Localpassword
)

Begin
{
    $domain = 'company'
    try
    {
        if ( $ComputerName -ne $env:COMPUTERNAME -and $env:USERDOMAIN -ne $domain -and $Credential.UserName -eq $null )
        {
            $Credential = Get-Credential -Message "Please provide the credentials to be used to be used for remote connection" -ErrorAction SilentlyContinue
        }
    }
    catch
    {
        #do nothing
    }
    if ( $Localpassword )
    {
        $altpassword = Read-Host -AsSecureString -Prompt "Please enter the local admin password"
    }


    # create a dummy set for the report
    $report_dummy = [pscustomobject]@{
                                    Host = '-'
                                    Status = '-'
                                    Partition = '-'
                                    TotalSize = '-'
                                    Freespace = '-'
                                    OSversion = '-'
                }
}#end begin

Process
{
    foreach ($server in $ComputerName)
    {
        if ( Test-Connection $server -Count 1 -Quiet)
        {
            #try with currently loggedon(domain) user
            try 
            {
                $wmiparams = @{
                    'Class'        = 'win32_logicaldisk';
                    'Filter'       = 'Drivetype=3';
                    'ComputerName' = $server;
                    'Erroraction'  = 'Stop';
                    'Credential'   = $Credential;
                }               
                if ($server -eq $env:COMPUTERNAME)
                {
                    $wmiparams.Remove('credential')
                    $partitions = Get-WmiObject @wmiparams
                    $wmiparams.Remove('Filter')
                    $wmiparams.class = 'win32_operatingsystem'
                    $os = Get-WmiObject @wmiparams
                }
                else
                {
                    $partitions = Get-WmiObject @wmiparams
                    $wmiparams.Remove('Filter')
                    $wmiparams.class = 'win32_operatingsystem'
                    $os = Get-WmiObject @wmiparams
                }

                foreach ($partition in $partitions){
                            $report = [pscustomobject]@{
                                        Host = $server
                                        Status = 'online'
                                        Partition = $partition.Name
                                        TotalSize = "{0:N2}" -f ($partition.Size/1GB) -as [decimal]
                                        Freespace = "{0:N2}" -f ($partition.Freespace/1GB) -as [decimal]
                                        OSVersion = $os.caption  + ' ' + $os.csdversion
                            }                 
                $report
                }                
            } #end try
            # Access denied with domain credetials
            catch [System.UnauthorizedAccessException]
            {
                if ($altpassword)
                {
                    #try with support password
                    try 
                    {
                        $support = New-Object pscredential -ArgumentList "$server\support",$altpassword
                        $wmiparams.Credential = $support
                        $partitions = Get-WmiObject @wmiparams
                        $wmiparams.Remove('Filter')
                        $wmiparams.Class = 'win32_operatingsystem'
                        $os = Get-WmiObject @wmiparams
    
                        foreach ($partition in $partitions){
                                $report = [pscustomobject]@{
                                            Host = $server
                                            Status = 'online'
                                            Partition = $partition.Name
                                            TotalSize = "{0:N2}" -f ($partition.Size/1GB) -as [decimal]
                                            Freespace = "{0:N2}" -f ($partition.Freespace/1GB) -as [decimal]
                                            OSVersion = $os.caption  + ' ' + $os.csdversion
                                            }
                        }
                        $report
                    }
                    #Access denied with support credential
                    catch [System.UnauthorizedAccessException]
                    {
                        #try with administrator password
                        try 
                        {
                            $administrator = New-Object pscredential -ArgumentList "$server\administrator",$altpassword
                            $wmiparams.Credential = $administrator
                            $partitions = Get-WmiObject @wmiparams
                            $wmiparams.Remove('Filter')
                            $wmiparams.Class = 'win32_operatingsystem'
                            $os = Get-WmiObject @wmiparams
    
                            foreach ($partition in $partitions){
                                    $report = [pscustomobject]@{
                                                Host = $server
                                                Status = 'online'
                                                Partition = $partition.Name
                                                TotalSize = "{0:N2}" -f ($partition.Size/1GB) -as [decimal]
                                                Freespace = "{0:N2}" -f ($partition.Freespace/1GB) -as [decimal]
                                                OSVersion = $os.caption  + ' ' + $os.csdversion
                                                }
                            }
                            $report
                        }
                        #Access denied with all three credentials
                        catch
                        {
                            $report = $report_dummy
                            $report.host = $server
                            $report.status = 'Access Denied'
                            $report    
                        }
                    }
                }
                else
                {
                    $report = $report_dummy
                    $report.host = $server
                    $report.status = 'Access Denied'
                    $report
                }
            }
            # GWMI RPC unavailable error
            catch [System.Runtime.InteropServices.COMException]
            {
                $report = $report_dummy
                $report.host = $server
                $report.status = 'RPC Server Unavailable'
                $report                   
            }
            # all other errors
            catch
            {
                $report = $report_dummy
                $report.host = $server
                $report.status = 'Unknown Error'
                $report
            }
        } # end if test-connection
        else
        {  
            $report = $report_dummy
            $report.host = $server
            $report.status = 'Unreachable'
            $report
        }
    } # end foreach
} # end process
}

My sample output -
As you can see the the redirected variable output is messed up. (For formatting purpose I have used autosize in ft, otherwise I just use ft so that I can see the script running against each host and its output)

PS [9:52:52 PM] C:\> $output

PS [9:52:54 PM] C:\> Get-Logicaldiskinfo Linux, server1, offline | Tee-Object -Variable output | ft -AutoSize

Host       Status                 Partition TotalSize Freespace OSversion                                                                
----       ------                 --------- --------- --------- ---------                                                                
Linux  	   RPC Server Unavailable -         -         -         -                                                                        
server1    online                 C:        114.99    97.73     Microsoft(R) Windows(R) Server 2003 Enterprise x64 Edition Service Pack 2
offline    Unreachable            -         -         -         -                                                                        


PS [9:53:32 PM] C:\> $output | ft

Host                                  Status                                Partition                             TotalSize                            Freespace                            OSversion                           
----                                  ------                                ---------                             ---------                            ---------                            ---------                           
offline                               Unreachable                           -                                     -                                    -                                    -                                   
server1                    		      online                                C:                                    114.99                               97.73                                Microsoft(R) Windows(R) Server 20...
offline                               Unreachable                           -                                     -                                    -                                    -                                   



PS [9:53:37 PM] C:\> Get-Logicaldiskinfo server1, offline, Linux | Tee-Object -Variable output | ft -AutoSize

Host       Status                 Partition TotalSize Freespace OSVersion                                                                
----       ------                 --------- --------- --------- ---------                                                                
server1    online                 C:           114.99     97.73 Microsoft(R) Windows(R) Server 2003 Enterprise x64 Edition Service Pack 2
offline    Unreachable            -                 -         - -                                                                        
Linux      RPC Server Unavailable -                 -         - -                                                                        



PS [9:54:13 PM] C:\> $output | ft

Host                                  Status                                Partition                                                        TotalSize                            Freespace OSVersion                           
----                                  ------                                ---------                                                        ---------                            --------- ---------                           
server1                              online                                C:                                                                  114.99                                97.73 Microsoft(R) Windows(R) Server 20...
Linux                                RPC Server Unavailable                -                                                                        -                                    - -                                   
Linux                                RPC Server Unavailable                -                                                                        -                                    - -                                   


Sorry again for a really lengthy post. Please suggest.

EDIT - Attaching the screenshot.

Hey there GJ,

I was able to get it to work from a PowerShell 4.0 instance. Do you have a PS4.0 machine you can try from?

PS C:\Windows\System32\WindowsPowerShell\v1.0> Get-Logicaldiskinfo -ComputerName server01,server02,server03 | Tee-Object -Variable Output | Format-Table -AutoSize

Host         Status      Partition TotalSize Freespace OSVersion                              
----         ------      --------- --------- --------- ---------                              
server01 online      C:            59.51     39.55 Microsoft Windows Server 2012 Standard 
server01 online      D:            20.00     19.40 Microsoft Windows Server 2012 Standard 
server02 Unreachable -                 -         - -                                      
server03 online      C:            59.51     45.21 Microsoft Windows Server 2012 Standard 
server03 online      E:            20.00      0.37 Microsoft Windows Server 2012 Standard 



PS C:\Windows\System32\WindowsPowerShell\v1.0> $output


Host      : server01
Status    : online
Partition : C:
TotalSize : 59.51
Freespace : 39.55
OSVersion : Microsoft Windows Server 2012 Standard 

Host      : server01
Status    : online
Partition : D:
TotalSize : 20.00
Freespace : 19.40
OSVersion : Microsoft Windows Server 2012 Standard 

Host      : server02
Status    : Unreachable
Partition : -
TotalSize : -
Freespace : -
OSversion : -

Host      : server03
Status    : online
Partition : C:
TotalSize : 59.51
Freespace : 45.21
OSVersion : Microsoft Windows Server 2012 Standard 

Host      : server03
Status    : online
Partition : E:
TotalSize : 20.00
Freespace : 0.37
OSVersion : Microsoft Windows Server 2012 Standard 




PS C:\Windows\System32\WindowsPowerShell\v1.0> 

You know, I might not be seeing the issue since it seems that the code snippet tool is having an issue with the formatting. Could you perhaps post a screenshot? With the server names fuzzied out of course. :slight_smile:

Thank you Will. I have updated the post with the output screenshot now.

Try running it outside of the ISE, or in a new tab (control+T instead of Control+N) to launch a new PowerShell instance. I can’t replicate this problem either, but I’ve seen strange problems when running some code from within the ISE due to variable Scoping.

Thank you Steve. That’s a good suggestion. I tried to run it in the powershell console, unfortunately still having the same issue :frowning:

Just for grins, what happens if you take out the Linux machine from the list? There’s also a lot of duplicate code in the script. We might be able to streamline some of it. I’ll see what I can do tonight after I hang my shelves. :slight_smile:

Thank you Will. I removed the linux server and tried with 2 offline servers. It still has some problem. Attached that error screenshot too.

Can you post your $PSVersionTable results? I’d like to do a comparison between what you’ve got and what my test machines are running. Thanks!

Thanks Will.

Here is my psversion info.

PS C:\> $PSVersionTable

Name                           Value
----                           -----
PSVersion                      3.0
WSManStackVersion              3.0
SerializationVersion           1.1.0.1
CLRVersion                     4.0.30319.18449
BuildVersion                   6.2.9200.17065
PSCompatibleVersions           {1.0, 2.0, 3.0}
PSRemotingProtocolVersion      2.2

Yeah, I’m not able to replicate this either, unfortunately. I’ve not the time today to dig in this and debug it line-by-line, but that’s what it’s going to take - and you may have to be the one to do it, since if nobody else can reproduce it, we won’t “see” the bug.

I’ve gone through line-by-line now. I want to give you kudos for clean code, it was pretty easy to read!

That being said, I’ve got no idea why you’re getting this output.

I’ve tested this and can’t reproduce the problem.

Looking at the original output it seems the dashes are being mis-interpreted when displaying. What culture and UICluture settings are you using? What language settings do you have enabled

I just did a quick test and it ran fine as well – curios as to the answer for Richard Siddaway. Will look deeper at it later today.

Thank you Don, Richard & Jason for jumping in.

@Don - I have already gone through the code once line by line and did the debugging. The code spits the output fine when printed on the console/ or redirected to a file/csv.

I have attached another image with this reply post which may be additionally helpful.

@Richard - This system is running with a Windows 2012 server OS with English - United States regional settings.
With regard to the dash misinterpretation in my original output text, I guess that’s how this websites formats the data. Attached images may be helpful to see the actual problem.
Here is my culture info -

PS C:\> Get-Culture | select *


Parent                         : en
LCID                           : 1033
KeyboardLayoutId               : 1033
Name                           : en-US
IetfLanguageTag                : en-US
DisplayName                    : English (United States)
NativeName                     : English (United States)
EnglishName                    : English (United States)
TwoLetterISOLanguageName       : en
ThreeLetterISOLanguageName     : eng
ThreeLetterWindowsLanguageName : ENU
CompareInfo                    : CompareInfo - en-US
TextInfo                       : TextInfo - en-US
IsNeutralCulture               : False
CultureTypes                   : SpecificCultures, InstalledWin32Cultures, FrameworkCultures
NumberFormat                   : System.Globalization.NumberFormatInfo
DateTimeFormat                 : System.Globalization.DateTimeFormatInfo
Calendar                       : System.Globalization.GregorianCalendar
OptionalCalendars              : {System.Globalization.GregorianCalendar, System.Globalization.GregorianCalendar}
UseUserOverride                : True
IsReadOnly                     : False



PS C:\> Get-UICulture | select *


Parent                         : en
LCID                           : 1033
KeyboardLayoutId               : 1033
Name                           : en-US
IetfLanguageTag                : en-US
DisplayName                    : English (United States)
NativeName                     : English (United States)
EnglishName                    : English (United States)
TwoLetterISOLanguageName       : en
ThreeLetterISOLanguageName     : eng
ThreeLetterWindowsLanguageName : ENU
CompareInfo                    : CompareInfo - en-US
TextInfo                       : TextInfo - en-US
IsNeutralCulture               : False
CultureTypes                   : SpecificCultures, InstalledWin32Cultures, FrameworkCultures
NumberFormat                   : System.Globalization.NumberFormatInfo
DateTimeFormat                 : System.Globalization.DateTimeFormatInfo
Calendar                       : System.Globalization.GregorianCalendar
OptionalCalendars              : {System.Globalization.GregorianCalendar, System.Globalization.GregorianCalendar}
UseUserOverride                : True
IsReadOnly                     : False

Your use of $report_dummy looks a bit fishy to me. Every time you assign $report = $report_dummy, update properties, and output $report, you’re actually sending a reference to the same object (which you’ve modified later on.) The reason you don’t notice this when you’re just allowing the output to be displayed at the console is that the output happens before you come back and modify the object again later.

One way that you can get around this is to replace all of the instances of:

$report = $report_dummy

#With this:

$report = $report_dummy | Select-Object *

That will create a copy of the $report_dummy object which has all of the same properties, but isn’t actually a reference to the same instance in memory. Alternatively, just get rid of $report_dummy completely and have new [pscustomobject] code each time you were using it.

On a side note, there are a couple of places where you’re looping over partitions, but only outputting the $report object outside of the loop (meaning you’ll only see information for the very last partition, rather than all of them). For example:

                                foreach ($partition in $partitions){
                                    $report = [pscustomobject]@{
                                        Host = $server
                                        Status = 'online'
                                        Partition = $partition.Name
                                        TotalSize = "{0:N2}" -f ($partition.Size/1GB) -as [decimal]
                                        Freespace = "{0:N2}" -f ($partition.Freespace/1GB) -as [decimal]
                                        OSVersion = $os.caption  + ' ' + $os.csdversion
                                    }
                                }

                                # This line should be inside the foreach loop
                                $report

Awesome, Thank you Dave. You caught the issue. Replacing $report = $report_dummy with $report = $report_dummy | Select-Object * solved the issue. I will get rid of this approach as suggested by you.

At the beginning I was also suspecting on $report_dummy usage but did not take it seriously as I was seeing the desired output in the console. I thought simply assigning a variable to another variable (both being same object type with same properties) will replace the properties from RHS(right hand side) variable to LHS variable. Also I was under the impression that the outvariable / tee-object variable will catch each object it receives and builds it up, ie, whatever I see on the console. Thanks for clarifying.

I’ve attached the current output as well. Strange others were unable to replicate the issue!

Thanks again on your side note too. I did not notice this error earlier.

Thanks to Will, Stephen, Don, Richard & Jason as well.