0

Im writing a big script that scans WMI info from computers in AD. I have functions for diskinfo, raminfo and videocardinfo where disk and videocard have similar output styles. Problem is that depending on the order which the script runs them either ones output is blank. Here is the two functions:

function Get-DiskInfo {

$disk = Get-WMIObject Win32_Logicaldisk -ComputerName $computer |
        Select  @{Name="Computer";Expression={$computer}}, DeviceID,
        @{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
        @{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
        Write-Host $Computer
        $disk

}

and:

function Get-VRamInfo {

$vram = Get-WmiObject win32_videocontroller -ComputerName $computer | 
        Select @{Name="Computer";Expression={$computer}},
        @{Name="VideoRAM";Expression={$_.adapterram / 1MB}},
        Name
        Write-Host $computer
        $vram

}

One will get the output intended but the one that is run later in the script will output only computer names but no info

here is the full script: https://gist.github.com/ErkkaKorpi/f1b10a62ac79763fa38082b6c25e8f1b

What could be the problem?

2 Answers2

1

For some obscure reasons, Write-Output cmdlet remembers properties of a custom object from its first/previous use for any next use, even applied to another (differently defined) custom object. Unfortunately, I don't know how to reset remembered properties.

There is a workaround: use Format-Table as follows. (Note that I added SizeGB note property in Get-VRamInfo for better understanding.)

Function Get-DiskInfo {
$disk = Get-WMIObject Win32_Logicaldisk -ComputerName $computer |
            Select-Object  @{Name="Computer";Expression={$computer}}, 
                DeviceID,
                @{Name="SizeGB";Expression={$_.Size/1GB -as [int]}},
                @{Name="FreeGB";Expression={[math]::Round($_.Freespace/1GB,2)}}
        #Write-Host $Computer -ForegroundColor Magenta
        $disk
}

Function Get-VRamInfo {
$vram = Get-WmiObject win32_videocontroller -ComputerName $computer | 
            Select-Object @{Name="Computer";Expression={$computer}},
                @{Name="VideoRAM";Expression={$_.adapterram / 1MB -as [int]}},
                @{Name="SizeGB";Expression={$_.adapterram/1GB -as [int]}},
                Name
        #Write-Host $computer -ForegroundColor Cyan
        $vram
}

$computer = '.'
"`nshrunk output #1"
Get-VRamInfo
Get-DiskInfo
"`nfull output"
Get-VRamInfo | Format-Table
Get-DiskInfo | Format-Table
"`nshrunk output #2"
Get-DiskInfo
Get-VRamInfo

Output:

PS D:\PShell> D:\PShell\SF\884809.ps1

shrunk output #1

Computer VideoRAM SizeGB Name                 
-------- -------- ------ ----                 
.            2048      2 NVIDIA GeForce GT 740
.                    111                      
.                    932                      
.                      0                      

full output

Computer VideoRAM SizeGB Name                 
-------- -------- ------ ----                 
.            2048      2 NVIDIA GeForce GT 740


Computer DeviceID SizeGB FreeGB
-------- -------- ------ ------
.        C:          111  58.06
.        D:          932 856.47
.        E:            0      0

shrunk output #2

Computer DeviceID SizeGB FreeGB
-------- -------- ------ ------
.        C:          111  58.06
.        D:          932 856.47
.        E:            0      0
.                      2       

Write-Output cmdlet is typically used in scripts to display strings and other objects on the console. However, because the default behavior is to display the objects at the end of a pipeline, it is generally not necessary to use the cmdlet.
For instance, Get-Process | Write-Output is equivalent to Get-Process.

JosefZ
  • 1,514
  • 1
  • 10
  • 18
0

Looking at your scripts, you don't define $computer, so it should error out straight away for any of those functions. When defined, I can confirm the second function returns adapters just fine when used on Windows 10 1703:

enter image description here

As you can see from the output, $vram already contains your computername, so you might want to skip Write-Host $Computer part.

As I see you seem to be inspecting lots of machines simultaneously, it makes sense for you to look at PowerShell Workflows, which allow for parallel execution of your tasks, so you might use your functions in a ForEach -Parallel loop and get them executed much faster.

Grigory Sergeev
  • 661
  • 4
  • 12
  • $computer is defined if you check out the full script from the link – Erkka Korpi Nov 23 '17 at 10:57
  • I made modifications to the script like this: function Get-VRamInfo { $vram = Get-WmiObject win32_videocontroller -ComputerName $computer | Select @{Name="Computer";Expression={$computer}}, @{Name="VideoRAM";Expression={$_.adapterram / 1MB}}, Name Write-Host $vram but im getting the same result – Erkka Korpi Nov 23 '17 at 11:05
  • @ErkkaKorpi I checked that briefly, but didn't read the full script, and haven't noticed it. It will help if you include all relevant information on the question on Serverfault and use links as additional bot not necessary information. This makes sense, especially when you consider that links get broken and some people hesitate to leave the site and consider the question ill formed if it relies on external resources. – Grigory Sergeev Nov 23 '17 at 11:05
  • @ErkkaKorpi as I've already mentioned, your script does work alright without modifications. Try running just `Get-WmiObject win32_videocontroller -ComputerName $computer` against the box that has the problem to troubleshoot. – Grigory Sergeev Nov 23 '17 at 11:09