Can not convert output to string - string

I cannot format this command to string. The code below returns $r as an empty string. Why?
$f = gwmi -ComputerName PCname -Class Win32_Process -Filter "name='process.exe'"|
select {$_.WorkingSetSize/1MB}|fl
$r = $f.ToString()

If you check the object type returned by Format-List you will see that it is an array of System.Object.
$f = gwmi -ComputerName PCname -Class Win32_Process -Filter "name='process.exe'"| `
select {$_.WorkingSetSize/1MB}|fl
$r | get-member
If you just need the values of working set, try this:
gwmi -ComputerName PCname -Class Win32_Process -Filter "name='process.exe'" | `
select #{label='WorkingSetSize';expression={$_.WorkingSetSize/1MB}}| `
select -expandproperty WorkingSetSize

Format-List produces an array of strings, not a single string, so $f.ToString() should give you System.Object[]. To convert an array to a single string you can pipe it into the Out-String cmdlet:
$f = gwmi -ComputerName PCname -Class Win32_Process -Filter "name='process.exe'" |
select {$_.WorkingSetSize/1MB} | fl
$g = $f | Out-String
However, as mentioned above, you should at least get System.Object[], not an empty string, so double-check the value of $f.

What I find is that -Filter "name='process.exe'" does not work for me. So I substituted
| where {$_.name -match "Process"}
This is my result, I also substituted LocalHost for PCname and removed |fl
$r = gwmi -ComputerName localhost -Class Win32_Process | where {$_.name -match "Process"} |
select #{label='WorkingSetSize';expression={$_.WorkingSetSize/1MB}} |
select -expandproperty WorkingSetSize
$r.ToString()

Related

Powershell export CSV looks weird

I have an issue with my CSV export to Excel with powershell. When I import it looks like pretty bad and I can't find any information that helps me to solve it.
Here I attach an image of the import and the code. I see other CSV imports and it looks normal with its categories spaced by rows in Excel, but I don't know how to do it.
Image of my workbook
$Computers = Get-ADComputer -Filter {OperatingSystem -like "*Server*"} -Properties OperatingSystem | Select-Object -ExpandProperty Name
Foreach($computer in $computers){
if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{write-host "cannot reach $computer offline" -f red}
else {
$outtbl = #()
Try{
$sr=Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$Xr=Get-WmiObject –class Win32_processor -ComputerName $computer -ErrorAction Stop
$ld=get-adcomputer $computer -properties Name,Lastlogondate,operatingsystem,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
$r="{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $computer |Measure-Object Capacity -Sum).Sum / 1GB)
$x = gwmi win32_computersystem -ComputerName $computer |select #{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other something else'}}},Manufacturer,#{Name = "Model";Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}},username -ErrorAction Stop
$t= New-Object PSObject -Property #{
serialnumber = $sr.serialnumber
computername = $ld.name
Ipaddress=$ld.ipv4Address
Enabled=$ld.Enabled
Description=$ld.description
Ou=$ld.DistinguishedName.split(',')[1].split('=')[1]
Type = $x.type
Manufacturer=$x.Manufacturer
Model=$x.Model
Ram=$R
ProcessorName=($xr.name | Out-String).Trim()
NumberOfCores=($xr.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors=($xr.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth=($xr.Addresswidth | Out-String).Trim()
Operatingsystem=$ld.operatingsystem
Lastlogondate=$ld.lastlogondate
LoggedinUser=$x.username
}
$outtbl += $t
}
catch [Exception]
{
"Error communicating with $computer, skipping to next"
}
$outtbl | select Computername,enabled,description,ipAddress,Ou,Type,Serialnumber,Manufacturer,Model,Ram,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,loggedinuser,Lastlogondate |export-csv -Append C:\temp\VerynewAdinventory.csv -nti
}
}
As commented, your locale computer uses a different delimiter character that Export-Csv by default uses (that is the comma).
You can check what character your computer (and thus your Excel) uses like this:
[cultureinfo]::CurrentCulture.TextInfo.ListSeparator
To use Export-Csv in a way that you can simply double-click the output csv file to open in Excel, you need to either append switch -UseCulture to it, OR tell it what the delimiter should be if not a comma by appending parameter -Delimiter followed by the character you got from the above code line.
That said, your code does not produce the full table, because the export to the csv file is in the wrong place. As Palle Due commented, you could have seen that if you would indent your code properly.
Also, I would advise to use more self-describing variable names, so not $r or $x, but $memory and $machine for instance.
Nowadays, you should use Get-CimInstance rather than Get-WmiObject
AND adding to an array with += should be avoided as it is both time and memory consuming. (on every addition to an array, which is of fixed size, the entire array has to be rebuilt in memory).
Your code revised:
# set the $ErrorActionPreference to Stop, so you don't have to add -ErrorAction Stop everywhere in the script
# remember the currens value, so you can restore that afterwards.
$oldErrorPref = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
# get an array of computers, gathering all properties you need
$computers = Get-ADComputer -Filter "OperatingSystem -like '*Server*'" -Properties OperatingSystem, LastLogonDate, IPv4Address, Description
$result = foreach ($computer in $computers) {
$serverName = $computer.Name
if(!(Test-Connection -ComputerName $serverName -BufferSize 16 -Count 1 -ErrorAction SilentlyContinue -Quiet)) {
Write-Host "cannot reach $serverName offline" -ForegroundColor Red
continue # skip this computer and proceed with the next one
}
try {
# instead of Get-WmiObject, nowadays you should use Get-CimInstance
$bios = Get-WmiObject -Class Win32_bios -ComputerName $serverName
$processor = Get-WmiObject -Class Win32_Processor -ComputerName $serverName
$memory = Get-WmiObject -Class Win32_PhysicalMemory -ComputerName $serverName
$disks = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $serverName
$machine = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $serverName |
Select-Object #{Name = "Type"; Expression = {
if ($_.pcsystemtype -eq '2') {'Laptop'} else {'Desktop Or Other something else'}}
},
Manufacturer,
#{Name = "Model"; Expression = {
if (!$_.model) {'Virtual'} else {$_.model}}
},
UserName
# output an object to be collected in variable $result
# put the properties in the order you would like in the output
[PsCustomObject] #{
ComputerName = $serverName
Enabled = $computer.Enabled
Description = $computer.description
IpAddress = $computer.IPv4Address
Ou = $computer.DistinguishedName.split(',')[1].split('=')[1]
Type = $machine.type
SerialNumber = $bios.serialnumber
Manufacturer = $machine.Manufacturer
Model = $machine.Model
Ram = '{0} GB' -f (($memory | Measure-Object Capacity -Sum).Sum / 1GB)
ProcessorName = $processor.Name
NumberOfCores = $processor.NumberOfCores
NumberOfLogicalProcessors = $processor.NumberOfLogicalProcessors
Addresswidth = $processor.Addresswidth
OperatingSystem = $computer.OperatingSystem
# {0:N2} returns the number formatted with two decimals
TotalFreeDiskSpace = '{0:N2} GB' -f (($disks | Measure-Object FreeSpace -Sum).Sum / 1GB)
LoggedInUser = $machine.UserName
Lastlogondate = $computer.LastLogonDate
}
}
catch {
Write-Warning "Error communicating with computer $serverName, skipping to next"
}
}
# restore the ErrorActionPreference to its former value
$ErrorActionPreference = $oldErrorPref
# output the completed array in a CSV file
# (using the delimiter characer your local machine has set as ListSeparator)
$result | Export-Csv -Path 'C:\temp\VerynewAdinventory.csv' -UseCulture -NoTypeInformation

PowerShell export "Get-volume" to excel/csv

I used the below one it gives somewhat different in excel ,please help me on this
#Disk Space
Get-Volume
$results = Get-Volume | Export-Csv -Path C:\temp\software1.csv
Note: I need health check , Drive Name, Free space , size, disk type in excel
Thanks in advance friends :)
Generally speaking, when you run a powershell command it only shows what sections are deemed as important. If you take the same command and pipe it to format-list (or "ft" for short) you will get everything.
Get-Volume | ft
When exporting it exports everything.
Also, you need to add the paramater -NoTypeInformation to get rid of the first row.
To only get certain values, you will just pipe it using select.. something like this:
Get-Volume | select HealthStatus, DriveLetter, SizeRemaining,DriveType | Export-Csv -NoTypeInformation -Path C:\temp\software1.csv
Also, there is no need to do $results = get-volume... This pushes the output into the variable $results. This would be applicable if you wanted to recall the variable later. So, you could also do something like this..
$results = Get-Volume
$results | select HealthStatus, DriveLetter, SizeRemaining, DriveType | Export-Csv -NoTypeInformation -Path C:\temp\software1.csv
Keep in mind you need to have the Import-Excel Module loaded but you should be able to use this to output to Excel.
#check-DiskSpace_FSs.ps1
import-module activedirectory
$dc = "domainController09"
$currentDate = get-date -Format yyyyMMdd_HHmm
$path = "\\UNC\export\FileServer_DiskSpace\FileServer_DiskSpace_$currentDate.xlsx"
$smtpServer = "10.10.10.10"
$from = "me#somewhere.com"
$to = "me#somewhere.com"
$subject = "Server FS diskspace - $date"
$ServerFSs = get-adcomputer -Server $dc -SearchBase "OU=fs,OU=Server,DC=somewhere,DC=com" -filter * | select name | sort Name
$DriveSize = foreach ($FS in $somewhereFSs)
{
get-WmiObject win32_logicaldisk -ComputerName $FS.name -Filter "Drivetype=3" | select SystemName,DeviceID,#{n="TotalSize(GB)";e={$_.Size / 1gb -as [int] }}`
,#{n="FreeSize(GB)";e={$_.freespace / 1gb -as [int] }}`
,#{n="FreeSize(%)";e={[int]($_.Freespace*100/$_.Size)}},VolumeName | Export-Excel -Path $path -append -FreezeTopRow -BoldTopRow -AutoSize -AutoFilter
}
Send-Mailmessage -smtpServer $smtpServer -from $from -to $to -subject $subject -Attachments $path -priority High

How to export output of batch file/Powershell Script in a Excel Spreadsheet

I have been asked to go around the entire building and document the serial numbers, and system information on all of the PC's in the network. As I was doing it I realized that I could of just wrote a batch file or Powershell Script to do this for me. I typed in the command "wmic bios get serialnumber" and it gave me the serial number for my machine. Is there a way to Get all of the information such as the processor, memory, ip address, and serial number and output it in a excel spreadsheet ? If it can only be exported in a text file that is fine. I would like to save it on my server. I don't know how I can save it all to one text file. I realize that I could have the batch file make a text file of its own with the >> %COMPUTERNAME%.txt command.
Any help or suggestions would be great!
Thanks!
Get-WmiObject win32_processor | Findstr ('Name') | Format-List
$env:COMPUTERNAME | Format-List
wmic bios get serialnumber /Format
Get-WmiObject -Class Win32_ComputerSystem | Findstr ('Model') | Format-List
Get-WmiObject -Class Win32_ComputerSystem | Findstr ('Manufacturer') | Format-List
Get-WmiObject -Class Win32_ComputerSystem | Findstr ('Name') | Format-List
(systeminfo | Select-String 'Total Physical Memory:').ToString().Split(':')[1].Trim() | Format-List
Export-CSV -Path C:\Users\ars001\%COMPUTERNAME%.csv | Format-List
Ok, you evidently put in some effort to get the commands to at least gather the info and what classes you'd need for what details, so I'll give you this much...
$Computers = Get-Content C:\Path\To\ComputerList.txt
[array]$Results = $Record = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $PC | select Model,Manufacturer,Name,TotalPhysicalMemory
$Results[0] | Add-Member 'Processor' $(Get-WmiObject win32_processor -ComputerName $PC | % Name)
$Results[0] | Add-Member 'SerialNumber' $(Get-WmiObject bios -ComputerName $PC |% serialnumber)
ForEach($PC in $Computers){
If(!(Test-Connection $PC -Quiet) -or $PC -eq $env:COMPUTERNAME){Continue}
$Record = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $PC | select Model,Manufacturer,Name,TotalPhysicalMemory
$Record | Add-Member 'Processor' $(Get-WmiObject win32_processor -ComputerName $PC | % Name)
$Results += $Record | Add-Member 'SerialNumber' $(Get-WmiObject bios -ComputerName $PC |% serialnumber) -PassThru
}
$Results | Export-Csv c:\Path\To\Output.csv -NoTypeInformation
Then you just need to edit the paths, and have a list of computers saved as a text file. If you have the AD module installed you can query AD for that info instead.

Output server information to Excel file

I've a PowerShell script that can generate server status info to me. My problem now is I want to output result to an Excel file.
PowerShell code:
function getwmiinfo ($svr) {
gwmi -Query "select * from Win32_ComputerSystem" -ComputerName $svr |
select Name, Model, Manufacturer, Description, DNSHostName, Domain,
DomainRole, PartOfDomain, NumberOfProcessors, SystemType,
TotalPhysicalMemory, UserName, Workgroup |
Format-Table -Property * -Autosize | Out-String -Width 10000
gwmi -Query "select * from Win32_OperatingSystem" -ComputerName $svr |
select Name, Version, FreePhysicalMemory, OSLanguage, OSProductSuite,
OSType, ServicePackMajorVersion, ServicePackMinorVersion |
Format-Table -Property * -Autosize | Out-String -Width 10000
gwmi -Query "select * from Win32_PhysicalMemory" -ComputerName $svr |
select Name, Capacity, DeviceLocator, Tag |
Format-Table -Autosize
gwmi -Query "select * from Win32_LogicalDisk where DriveType=3" -ComputerName $svr |
select Name, FreeSpace, Size |
Format-Table -Autosize
}
$servers = Get-Content 'servers.txt'
foreach ($server in $servers) {
$results = gwmi -query "select StatusCode from Win32_PingStatus where Address = '$server'"
$responds = $false
foreach ($result in $results) {
if ($result.statuscode -eq 0) {
$responds = $true
break
}
}
if ($responds) {
getwmiinfo $server
} else {
Write-Output "$server does not respond"
}
}
Output to Excel:
You can use Export-Csv (Export-Csv file path -NoTypeInformation). This is the command.
If you want to use array then you will have to define that. You can check this question.
E.g. $variable | Export-Csv c:\output.csv -notypeinformtion

Output Value from select-object calculated value

I've used a hash table to calculate some values for my VMWare inventory script, but now when I output the data, it records it as a key/value pair. I'd like to dump just the value. When I simply take what I'm handed that works fine, but when I get picky PS starts to stonewall me. :-)
Here is the relevant part of the script.
foreach ($machine in $vmList) {
$vmname = $machine.Name
$properties = #{
'Name'=Get-VM $vmname | Select -ExpandProperty Name
'RAM'=Get-VM $vmname | Select -ExpandProperty MemoryGB
'CpuCount'=Get-VM $vmname | Select -ExpandProperty NumCpu
'UsedDiskGB'=Get-VM $vmname | Select-Object #{n="UsedDiskGB"; e={[math]::Round( $_.UsedSpaceGB, 3 )}}
'TotalDiskGB'=Get-VM $vmname | Select-Object #{n="TotalDiskGB"; e={[math]::Round((Get-HardDisk -vm $_ | Measure-Object -Sum CapacityGB).Sum)}}
'Networks'=Get-VM $vmname | Select-Object #{n="Networks"; e={(Get-NetworkAdapter -VM $_ |Sort-Object NetworkName |Select -Unique -Expand NetworkName) -join '; '}}
'OS'=(Get-VM -Name $vmname | Get-View).summary.config.guestFullName
}
$object=New-Object -TypeName PSObject -Prop $properties
Export-Csv -Path $WorkDir\vms.csv -Append -Encoding UTF8 -InputObject $Object
Write-Output $Object
}
How do I get UsedDiskGB, Networks and TotalDiskGB to display just the value instead of something like '#{TotalDiskGB=80}'? Ram, OS, CpuCount and Name work exactly as desired already.
Also, suggestions on doing this in a faster way are welcome. I'm sure all these calls can be done better. I had it done in a single line, but then they asked for OS to be added and that changed everything.
Easy, but bad way:
In the expression pipe to |Select -ExpandProperty <property name> to get just the value. Such as:
'TotalDiskGB'=Get-VM $vmname | Select-Object #{n="TotalDiskGB"; e={[math]::Round((Get-HardDisk -vm $_ | Measure-Object -Sum CapacityGB).Sum)}}|select -expand totaldiskgb
The better way:
Structure your properties better to start with. Try this:
'TotalDiskGB'= [math]::Round((Get-HardDisk -vm (Get-VM $vmname) | Measure-Object -Sum CapacityGB).Sum)
The reason you're having issues is because you are creating a PSCustomObject with your Select, and Totaldiskgb is a property of that object. You don't want to make an object, you just want the value of that property.
Edit: Thank you to #briantist for pointing out that Get-VM $vmname should be called once, and stored as an object to be used later, rather than called for each time it is needed for a member of $Properties. For example:
foreach ($machine in $vmList) {
$vmname = $machine.Name
$vmobject = Get-VM $vmname
$properties = #{
'Name'=$vmobject | Select -ExpandProperty Name
'RAM'=$vmobject | Select -ExpandProperty MemoryGB
'CpuCount'=$vmobject | Select -ExpandProperty NumCpu
'UsedDiskGB'=[math]::Round( $vmobject.UsedSpaceGB, 3 )
'TotalDiskGB'=[math]::Round((Get-HardDisk -vm $vmobject | Measure-Object -Sum CapacityGB).Sum)
'Networks'=(Get-NetworkAdapter -VM $vmobject |Sort-Object NetworkName |Select -Unique -Expand NetworkName) -join '; '
'OS'=($vmobject | Get-View).summary.config.guestFullName
}
$object=New-Object -TypeName PSObject -Prop $properties
Export-Csv -Path $WorkDir\vms.csv -Append -Encoding UTF8 -InputObject $Object
Write-Output $Object
}

Resources