Full output hidden on console - powershell

I don't get full output of the following code I made.
For Example:
DriveSpace : {174, 0, 98, 171...}
Notice the ellipses (...) after 171. It is skipping the rest of the output after that. You can run the following script to see my output.
#Start of script
$cpu = gwmi -Class Win32_Processor | Select-Object NumberOfCores,NumberOfLogicalProcessors
$memory = gwmi -class win32_physicalmemory | Select-Object {[math]::truncate($_.capacity / 1GB)}
$HostDescription= gwmi -Class Win32_OperatingSystem
$fqdn = "$env:computername.$env:userdnsdomain"
$OS = (gwmi Win32_OperatingSystem)
$OSarchitecture = (gwmi Win32_OperatingSystem)
$disk = gwmi Win32_LogicalDisk | Select-Object DeviceID, volumeName, {[math]::truncate($_.size / 1GB)}
$timezone = [System.TimeZone]::CurrentTimeZone
$fire = netsh advfirewall show publicprofile | select-string state
$firematch = $fire -match "off"
$slmgrResult = cscript c:\windows\system32\slmgr.vbs /dli | Select-string "License Status"
$activation = $slmgrResult -match "Licensed"
$apps = gp HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* |Select DisplayName, DisplayVersion, Publisher, InstallDate
$network = Get-WmiObject win32_networkadapterconfiguration -filter "ipenabled = 'True'" | select-object IPAddress, DefaultIPGateway, DNSDomain, IPSubnet
$props = #{
NumberOfCores = $cpu.NumberOfCores
NumberOfLogicalProcessors = $cpu.NumberOfLogicalProcessors
Memory = $memory.{[math]::truncate($_.capacity / 1GB)}
HostDescription = $HostDescription.Description
FQDN = "$env:computername.$env:userdnsdomain"
OS = (gwmi Win32_OperatingSystem).Name
OSarchitecture = $OSarchitecture.OSArchitecture
DriveLetters = $disk.DeviceID
DriveLabels = $disk.volumeName
DriveSpace = $disk.{[math]::truncate($_.size / 1GB)}
timezone = [System.TimeZone]::CurrentTimeZone.StandardName
FirewallDisabled = $firematch
Licensed = $activation
Applications = $apps
IPAddress_Gateway_DNSDomain_subnet = $network.IPAddress, $network.DefaultIPGateway, $network.DNSDomain, $network.IPSubnet
}
New-Object PSObject -Property $props
#End of script

This is not an official answer as I think the OP needs to be clear on what output he is expecting. This is a start nonetheless
While I have not found official documentation to support this you are just seeing how PowerShell handles console output. Consider the following example which is a collection of varying sizes of arrays.
[pscustomobject]#{
data = "1","2","3","4","5"
}
Would produce the following list style output.
data : {1, 2, 3, 4...}
Notice the fifth element of the 5 property now has the ellipses. The data is still there. It has just been truncated on the console to make the output more terse and easier to read. In this case it seems folly to do so but with some objects complicated output PowerShell has to draw the line somewhere.
Prevent the ellipses
As PetSerAL pointed out you can just use the following line of code before your output.
$FormatEnumerationLimit=-1
If you look at about_Preference_Variables you will see that, by default, this is set to 4. That would support the output you are seeing. Set that value to something higher or -1 and see if it helps.
Other Potential Issues
Like in my comments I want to draw attention to the variable you created called $disk. The output is below. Note this is from my own machine and wont match yours. Still, you should get the picture
DeviceID volumeName [math]::truncate($_.size / 1GB)
-------- ---------- -------------------------------
C: 111
D: Data 499
E: Multimedia 1362
F: 0
G: CentOS 7 x86_64 3
M: Media 2794
Z: 0
Without any other information I can only assume that you want a series of free space values to display. Given that we could break those results out of the array by casting them to string. Also want to update the line that populates the variable.
$disk = gwmi Win32_LogicalDisk | Select-Object DeviceID, volumeName, #{Label="Size(GB)";Expression={[math]::truncate($_.size / 1GB)}}
Gives us the following in $disk`
DeviceID volumeName Size(GB)
-------- ---------- --------
C: 111
D: Data 499
E: Multimedia 1362
F: 0
G: CentOS 7 x86_64 3
M: Media 2794
Z: 0
Then when you build your hashtable you can cast the array to a single space delimited string like this:
DriveSpace = [string]($disk."Size(GB)")
Fairly sure there will be more questions to come from this but it is at least a start. Welcome to SO. It is always a good idea when possible to show us desired output in cases like this so we know what you are trying to achieve. Even if you think it is obvious.
Side notes
You have other properties other that $disk that might have the same issues like Applications which is a complex object. If you do have issues with those as well solving this one might get you in the right direction.
You have many calls to gwmi Win32_OperatingSystem. You should save the results of that into a variable that you can refer to whenever you need it. Right now you are losing time calling it and getting the same results. For example:
$wmiOS = gwmi Win32_OperatingSystem

This is the default formatting of Powershell at work, as provided by Out-Default. It is truncating the DriveSpace array to display in a table in your console, but the information is still there. For example, if you type:
$props.DriveSpace
... you will see the full array displayed. The default formatting behaves differently when it's handling a simple array as opposed to when it's handling a complex object like the $props one you've created.
See also:
How Powershell Outputting and Formatting REALLY works

Related

PowerShell ForEach-Object within Pipeline

I'm just learning powershell and trying to understand how looping works on ForEach Object. I was able to make this script work that detect USB Storage attached to a device
Get-CimInstance -ClassName Win32_DiskDrive |
where {$_.InterfaceType -eq 'USB'} |
ForEach-Object{"`n`n",$_ } |
Format-list -Property DeviceId,Model,Size
Output:
DeviceId : \\.\PHYSICALDRIVE1Model : WD My Passport 0740 USB DeviceSize : 1000169372160
DeviceId : \\.\PHYSICALDRIVE2Model : TOSHIBA TransMemory USB DeviceSize : 7748213760
However I'm having hardtime targeting the value of each to move it to the next line. the result should be something like this
If I ran the script in Powershell console by using format-list it display perfect however on a webpage it won't display accordingly. How can I use the backtick (`n) so that the result of DeviceID, Model and Size will be on a separate line.
I will appreciate any help. thank you guys
Please use select-object instead of For-each object
Get-CimInstance -ClassName Win32_DiskDrive | where{$.InterfaceType -eq 'USB'} |Select-object -Property DeviceId,Model,Size
#You can filter at CIM level, no need to do it at shell level, also you can specify the list of properties to retrieve
$data = Get-CimInstance -query "Select DeviceId,Model,Size from Win32_DiskDrive where InterfaceType='usb'"
#If you want a string with the format: [PropertyName]:[PropertyValue]`n[PropertyName]:[PropertyValue]...
$stringArray = #(
$data | %{
"DeviceId: $($_.DeviceId)`nModel: $($_.Model)`nSize: $($_.Size)"
}
)
Output ($stringArray):
DeviceId: \\.\PHYSICALDRIVE1
Model: Generic USB Flash Disk USB Device
Size: 15512878080
#Maybe convertto-html is of use for you?
$data | ConvertTo-Html

How to exclude part of an output in Powershell?

i am writing a script that accepts the device ID as an argument to check the used percentage of a disk. Here is my code.
$device_id = $args[0]
Get-WmiObject -Class Win32_LogicalDisk |
Select-Object -Property DeviceID,
#{label='UsedPercentage'; expression={[Math]::Round((($_.Size - $_.FreeSpace)/$_.Size) * 100, 2)}} |
findstr $device_id
Here is my output. i am passing an argument to see usage of the device by device ID.
PS D:\Development\Powershell> .\disk-usage.ps1 D:
D: 57.69
What i want to do is to just output that number. How do i do this?
There's no need to use findstr to filter the output. Instead, use the parameter argument to filter your WMI query:
$device_id = $args[0]
# use argument to filter WMI query
Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID = '$device_id'" |ForEach-Object {
# output the free space calculation, nothing else
[Math]::Round((($_.Size - $_.FreeSpace)/$_.Size) * 100, 2)
}
You can add the 'used percentage' as a property to the WMI object you get back from your query:
$deviceID = args[0]
$diskUsage = Get-WmiObject -Query "SELECT FreeSpace, Size FROM Win32_LogicalDisk WHERE DeviceID = '$deviceID'" |
Add-Member -MemberType ScriptProperty -Name 'UsedPercentage' -Value {[Math]::Round((($this.Size - $this.FreeSpace)/$this.Size) * 100, 2)} -PassThru
Now, $diskUsage is a WMI object with Size, FreeSpace and UsedPercentage properties (as well as some WMI metadata properties you can ignore). You can output the value of any of them by refering to the one you want:
$diskUsage.UsedPercentage
15.3
Or show them in a neat table:
$diskUsage | Format-Table Size, FreeSpace, UsedPercentage -AutoSize
Size FreeSpace UsedPercentage
---- --------- --------------
1013310287872 858247196672 15.3

Powershell - how to replace OS Version number with String

I am querying remote servers for their operating system. I know that I can return the Version, but I want to replace these values with the friendly name. The code I have so far is:
$Computer = (gc c:\servers.txt)
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $Computer -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
If ({$BuildVersion.Version -match "5.2.3790"})
{$Build="2003"}
Elseif ({$BuildVersion.Version -match "6.1.7601"})
{$Build="2008"}
Elseif ({$BuildVersion.Version -like "6.3.9600"})
{$Build="2012"}
But this doesn't seem to work and only returns "2003" regardless. Please help, I'm fairly new to PS and coding.
thanks
The problem is your if statements. Putting the Boolean expression inside squiggly brackets makes it a script block, and that's going to get cast as a string before being cast as a Boolean. Strings cast to Booleans always evaluate to true unless they're empty.
PS C:\> {$BuildVersion.Version -match "5.2.3790"}
$BuildVersion.Version -match "5.2.3790"
PS C:\> ({$BuildVersion.Version -match "5.2.3790"}) -as [bool]
True
PS C:\> $BuildVersion.Version -match "5.2.3790"
False
PS C:\> ($BuildVersion.Version -match "5.2.3790") -as [bool]
False
So what you're running is essentially:
if ([bool]'$BuildVersion.Version -match "5.2.3790"') [...]
And that's always going to be true.
Try:
$Computer = (gc c:\servers.txt)
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $Computer -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
If ($BuildVersion.Version -match "5.2.3790")
{
$Build = "2003"
}
Elseif ($BuildVersion.Version -match "6.1.7601")
{
$Build = "2008"
}
Elseif ($BuildVersion.Version -like "6.3.9600")
{
$Build = "2012"
}
Bottom line is that squiggly brackets are not parentheses and you can't use them like they are.
However, there's also a major logic error here. You're potentially fetching an array for $BuildVersion because you're reading from a file, but then you treat it like a single value. You never loop through $BuildVersion. However, I do not have enough information about what you're actually trying to do with your script (like what you do with $Build) to be able to fix that.
I originally said this, but I've since changed my mind
The reason this is only returning 2003 is that you're only running your If code on a single entry in the list.
Wrong
As TessellatingHeckler says, the reason your if wasn't working is that you had too many curly braces, so PowerShell wasn't actually evaluating your logic.
However, you still need to step through each of the computers to do what you're trying to do. We'll do that by adding in a ForEach loop. I also went ahead and replaced your If {} logic with a Switch statement, which I think is easier to understand for a scenario like this with multiple clauses. If's just get way too verbose.
Finally, I'm assuming you want to output the results too, so I added a custom object here, which is just a way of choosing which properties we want to display.
$Computer = (gc c:\servers.txt)
ForEach ($system in $computer){
$BuildVersion = Get-WmiObject -Class Win32_OperatingSystem -Property Version, CSName -ComputerName $system -ErrorAction SilentlyContinue
$Build=$BuildVersion.version
switch ($build){
"5.2.3790" {$Build="2003"}
"6.1.7601" {$Build="2008"}
"6.3.9600" {$Build="2012"}
}
#output results
[pscustomobject]#{Server=$system;OSVersion=$build;CSName=$buildVersion.CSname}
}#EndOfForEach
Output
>Server OSVersion CSName
------ --------- ------
dc2012 2012 DC2012
sccm1511 2012 SCCM1511
You can use this:
Get-WmiObject -Class Win32_OperatingSystem | Select-Object -ExpandProperty Caption
Additionally you can see everything this WMI object holds like this:
Get-WmiObject -Class Win32_OperatingSystem | fl *
Edit: if you want to remove some text from the string, you can use -replace:
(Get-WmiObject -Class Win32_OperatingSystem |
Select-Object -ExpandProperty Caption) -replace "Microsoft Windows Server ",""

powershell how to remove `{}#` from output. Is there a special command to do it?

I entered gwmi win32_product | select -property name | select -first 1 and output to a file. My result was #{name=Google Talk Plugin}.
How can I get rid of #{}, and name. I only want it to show Google Talk Plugin?
#{} means your exporting an object with properties. Try the -ExpandProperty parameter in Select-Object. You could also combine both select-object commands, like:
gwmi win32_product | select -expandproperty name -first 1
I ran into a problem similar with
$drive = Get-WmiObject Win32_LogicalDisk -ComputerName $servername | Select-Object DeviceID
$drive comes up as #{DeviceID=C:}, #{DeviceID=D:}, ...
Here is my brute force hack at it.
The second Trim statement was because for some reason if I put it in the first Trim it starts to Trim the letters in the Drive =D: becomes :
enter code here
$Asdrive = #() #declared before to get rid of null pointer issue, also to tell PS this is an array not a string
#Write-Host "Trimming for Get-WmiObject"
for($i=0;$i -lt $drive.length; $i++) {
[string]$sdrive = $drive[$i]
[string]$sdrive1 = $sdrive.Trim("#","{","}","D","e","v","i","c","e","I","D")
[string]$sdrive2 = $sdrive1.Trim("=")
$Asdrive += $sdrive2
}
If you're running at least Version 3, you can also use the member enumeration feature and then array slicing to take the first one, instead of using select:
(gwmi win32_product).name[0]
I add some code as I found this question with google.
Frode F. solution is the best one.
If you write out something like:
Get-ADComputer -Filter * -SearchBase $OU | Select-Object Name
you get a proper List of all Computers in an OU. You can also pipe that to a CVS/HTML file and its still nice.
| Export-CSV "mylist.csv"
But if you store it into a variable (array) every name will be wrapped in #{}.
In my case I needed computer names in a variable. Here is the solution thanks to Frodo:
$computerList = Get-ADComputer -Filter * -SearchBase $OU | Select-Object -ExpandProperty Name
Hope it helps someone.
(would add it as comment under the right solution, but I don't have enough reputation to do so)

Change powershell script to output without ellipses (...)

I need some help with the output of the following script so the output doesn't show with the ellipses (...).
I tried to insert | Format-Table -Wrap -AutoSize but I just can't seem to get it right.
clear-host Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
$services = new-object system.collections.sortedlist
$servers = (get-spfarm).servers
foreach ($server in $servers) {
foreach($service in $server.serviceinstances)
{
if ($service.status = "Online")
{
$s = $service.typename
if ($services.contains($s))
{
$serverlist = $services[$s]
$servername = $server.name
$services[$s] = "$serverlist - $servername"
}
else
{
$services[$s] = $server.name
}
}
} }
$services
output:
Name Value
---- -----
Access Database Service SE5APP - SE5FE - SE7FE - FAQ3
Application Discovery **and L...** SE5APP - SE5FE - SE7FE - FAQ3
Application Registry Service SE5APP - SE5FE - SE7FE - FAQ3
Either Format-List (fl) or Format-Table -auto (ft -auto) should help here.
$services | fl
OR
$services | ft -auto
I came across this post and would like to add some information, as the accepted solution did not resolve my problem and I'm sure others may find the following information useful:
Quick Story: Running commands using Microsoft Online Services Module with Powershell, much of the results were continually be retrieved as truncated with data cutoff and missing as an ellipsis (...).
The fix: As explained in this post by Greig, I inevitably came to the conclusion $FormatEnumerationLimit=-1 is the unlimate solution to the problem. Using any variant of Format-Wide, Format-List, Format-Table, Format-Custom, -AutoSize, Out-String -Width, etc. require a hefty amount of additional considerations/code. In the case where all you want is to see all the data being returned, regardless of columns, arrays, etc., $FormatEnumerationLimit=-1 ensures you will get everything and you don't need to mess around.
Additional information, as credited in Greig's post include:
PowerShell Quick Tip: Creating wide tables with PowerShell, where the author explains:
If you have a specific property that contains a collection of items,
that property may still show an ellipsis in the file produced here if
the number of items in that collection exceeds the number assigned to
the built-in $FormatEnumerationLimit variable.
...and that "passing the results to | Format-Table -Property * [will] show all of the columns." But content from the columns may still be truncated ("PowerShell truncates table output by default"), and that even using | Format-Table -Property * -AutoSize will be limited by your screen buffer
("Auto-sized tables are limited to the width of your screen buffer"). The solution offered, before the absolute $FormatEnumerationLimit=-1, seems to be using | Format-Table -Property * -AutoSize in conjunction with | Out-String -Width 4096 or whatever width you require.
Using Format Commands to Change Output View provides some more delailed documentation on the Format cmdlets: Format-Wide, Format-List, and Format-Table.
What I do in this situation is to create a format description then use that as an argument to my Format-Table command. I've developed a function (Get-MaxLength) to examine the data field with the longest data (helps to have this at the end of the format description) and set the width in the format description with the value it returns. You can see the calculations in the code below. Notice the Number value for the Intel(4) Management Engine Interface. Also notice the use of -Wrap on the Format-Table command. This concept can be modified to calculate all fields widths or just the last one, it's just a little math.
Function Get-MaxLength {
<#
.SYNOPSIS
Finds the length of the longest item in collection.
.DESCRIPTION
Use this Function to get the length of the longest item in a
collection for use in format strings or other places where
needed.
.PARAMETER TestObj
The qualified object to be tested. See example!
.Parameter MinLen
The minimum length of the item (if using for formatting) which
should be the Label (title) length. Note if the object item
being tested does not have a Length property you MUST specify
the label length!
.OUTPUTS
Returns a numerical value
.EXAMPLE
$NameLen = Get-MaxLength -TestObj $DotNet.PSChildName
$VerLen = Get-MaxLength -TestObj $DotNet.Version
$RNLen = Get-MaxLength -TestObj $DotNet.Release -MinLen 11
#--- .Net Information ---
$fmtDotNet =
#{Expression={$_.PSChildName};Label=".Net Type";Width=$NameLen},
#{Expression={$_.Version};Label="Version No:";Width=$VerLen},
#{Expression={$_.Release};Label="Release No:";Width=$RNLen}
$Dotnet | Format-Table $fmtDotNet
#>
Param(
[Parameter(Mandatory=$True)]
[object] $TestObj,
[Parameter(Mandatory=$False)]
[int] $MinLen = 0,
[Parameter(Mandatory=$False)]
[int] $MaxLen = 0
)
$ErrorActionPreference = "SilentlyContinue"
foreach ($x in $TestObj) {
If ($x.Trim().length -gt $MinLen) {
$MinLen = $x.Trim().length
}
}
If ($MaxLen -ne 0) {
If ($MinLen -gt $MaxLen) {
$MinLen = $MaxLen
}
}
$ErrorActionPreference = "Continue"
Return ,$MinLen
} #End Function ----------- Get-MaxLength -------------------
$OstrWidth = 80
$DriverInfo =
Get-CimInstance -ClassName 'Win32_PNPSignedDriver' |
Where-Object -Property DriverProviderName -ne "Microsoft" |
Where-Object -Property DeviceName -ne -Value $Null |
Sort-Object -Property DeviceName -Unique
$DriverCnt = $DriverInfo.Count
$DVLen =
Get-MaxLength -TestObj $DriverInfo.DriverVersion -MinLen 14
$DDLen = $OstrWidth - $DVLen
$fmtDRVR = #{Label="`nDriver Description";Width=$DDLen;
Expression={$_.DeviceName}},
#{Label="Version Number"; Width=$DVLen;
Expression={$_.DriverVersion}}
$DrvTitle = "$($DriverCnt) Non-Windows Unique Drivers and " +
"Version Numbers:" | Out-String
$DriverInfo =
$DriverInfo | Format-Table -Property $fmtDRVR -Wrap |
Out-String -Width $OStrWidth
Sample Output:
Driver Description Number
------------------- -------------
Alcor Micro USB 2.0 Card Reader 2.0.150.10135
ASMedia USB3.1 eXtensible Host Controller 1.16.42.1
...
Intel(R) HD Graphics 630 21.20.16.4550
Intel(R) Management Engine Interface 1914.12.0.125
6
Intel(R) Ready Mode Technology Device 1.2.0.0
...
Realtek Audio 6.0.1.8248
Samsung NVMe Controller 3.0.0.1802