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

This topic contains 17 replies, has 7 voices, and was last updated by Profile photo of GJ GJ 1 year, 11 months ago.

  • Author
    Posts
  • #21623
    Profile photo of GJ
    GJ
    Participant

    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.

    [img]{http://postimg.org/image/tjkn4lmip/}[/img]

  • #21626
    Profile photo of Will Anderson
    Will Anderson
    Keymaster

    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> 
  • #21627
    Profile photo of Will Anderson
    Will Anderson
    Keymaster

    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. 🙂

  • #21631
    Profile photo of GJ
    GJ
    Participant

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

  • #21635
    Profile photo of Stephen Owen
    Stephen Owen
    Participant

    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.

  • #21637
    Profile photo of GJ
    GJ
    Participant

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

  • #21640
    Profile photo of Will Anderson
    Will Anderson
    Keymaster

    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. 🙂

  • #21641
    Profile photo of GJ
    GJ
    Participant

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

  • #21664
    Profile photo of Will Anderson
    Will Anderson
    Keymaster

    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!

    • #21671
      Profile photo of GJ
      GJ
      Participant

      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
      
      
  • #21673
    Profile photo of Don Jones
    Don Jones
    Keymaster

    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.

  • #21678
    Profile photo of Stephen Owen
    Stephen Owen
    Participant

    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.

  • #21679
    Profile photo of Richard Siddaway
    Richard Siddaway
    Moderator

    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

    • #21685
      Profile photo of GJ
      GJ
      Participant

      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
      
      
  • #21683
    Profile photo of Jason Helmick
    Jason Helmick
    Keymaster

    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.

  • #21688
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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.

  • #21689
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    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
    
  • #21705
    Profile photo of GJ
    GJ
    Participant

    Awesome, Thank you Dave. You caught the issue. Replacing [u]$report = $report_dummy[/u] with [u]$report = $report_dummy | Select-Object *[/u] 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.

You must be logged in to reply to this topic.