Writing variable value only in Powershell - powershell

I'm trying to collect 4 values into variables, then write those values to the screen so it would look like this:
value1,value2,value3,value4
Instead, I'm getting the following:
#{name=value1},#{domain=value2},#{domainrole=value3},#{workgroup=value3}
Here's my code. Any feedback will be most appreciated. Thanks.
$name = Get-CimInstance -ClassName Win32_ComputerSystem | select name
$domain = Get-CimInstance -ClassName Win32_ComputerSystem | select domain
$domainrole = Get-CimInstance -ClassName Win32_ComputerSystem | select domainrole
$workgroup = Get-CimInstance -ClassName Win32_ComputerSystem | select workgroup
write-host "$name,$domain,$domainrole,$workgroup"

You have some options to achieve this. One would be to use the parameter -ExpandProperty of Select-Object to turn objects with properties in string ... like this:
$name = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty name
$domain = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty domain
$domainrole = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty domainrole
$workgroup = Get-CimInstance -ClassName Win32_ComputerSystem | Select-Object -ExpandProperty workgroup
"$name,$domain,$domainrole,$workgroup"
Or you could keep the objects and acces their properties with the dot notation:
$name = Get-CimInstance -ClassName Win32_ComputerSystem
$domain = Get-CimInstance -ClassName Win32_ComputerSystem
$domainrole = Get-CimInstance -ClassName Win32_ComputerSystem
$workgroup = Get-CimInstance -ClassName Win32_ComputerSystem
"$name.name,$domain.domain,$domainrole.domainrole,$workgroup.workgroup"
I'd recommend the latter one because you can still use the objects for further steps in your code without loosing their properties. ;-)

This is a very command question. I like using foreach-object or % for short:
[pscustomobject]#{name='joe'} | % name
joe

Related

Not able to format output as CSV [duplicate]

This question already has an answer here:
Get WMI Data From Multiple Computers and Export to CSV
(1 answer)
Closed 3 years ago.
Am not able to convert PS output to CSV format using echo function. I need to collect hardware information about multiple servers and got this script from internet. I modified it to collect only the necessary information such as Computername,HDD space, CPU details and RAM.
Below is my code:
$ArrComputers = "PC17"
Clear-Host
foreach ($Computer in $ArrComputers) {
$computerSystemRam = Get-WmiObject Win32_ComputerSystem -Computer $Computer |
select #{n="Ram";e={[math]::Round($_.TotalPhysicalMemory/1GB,2)}} |
FT -HideTableHeaders -AutoSize
$computerCPU = Get-WmiObject Win32_Processor -Computer $Computer |
select Name |
FT -HideTableHeaders
$computerCPUCores = Get-WmiObject Win32_Processor -Computer $Computer |
select NumberOfLogicalProcessors |
FT -HideTableHeaders -AutoSize
$computerC = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'C:'" -ComputerName $Computer |
select #{n="Size";e={[math]::Round($_.Size/1GB,2)}} |
FT -HideTableHeaders -AutoSize
$computerD = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'D:'" -ComputerName $Computer |
select #{n="Size";e={[math]::Round($_.Size/1GB,2)}} |
FT -HideTableHeaders -AutoSize
$computerE = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'E:'" -ComputerName $Computer |
select #{n="Size";e={[math]::Round($_.Size/1GB,2)}} |
FT -HideTableHeaders -AutoSize
echo $computer,$computerC,$computerD,$computerE,$computerSystemRam,$computerCPU,$computerCPUCores
}
and my output is coming as
PC17
99.9
12
537.11
15.98
Intel(R) Xeon(R) CPU E5-2630 0 # 2.30GHz
12
What I need is to get this outputs as a comma separated value like below
PC17,99.9,12,537.11,15.98,Intel(R) Xeon(R) CPU E5-2630 0 # 2.30GHz,12
so that I can open it in Excel. Please let me know what the problem here is? Or any other alternative solution to so as to get the output as .csv.
Remove the Format-Table, use ExpandProperty and choose the right property from the array,
Also, I used -f to format the csv, see the differences:
foreach ($Computer in $ArrComputers)
{
$computerSystemRam = get-wmiobject Win32_ComputerSystem -Computer $Computer | select #{n="Ram";e={[math]::Round($_.TotalPhysicalMemory/1GB,2)}}
$computerCPU = get-wmiobject Win32_Processor -Computer $Computer | select -ExpandProperty Name
$computerCPUCores = get-wmiobject Win32_Processor -Computer $Computer | select -ExpandProperty NumberOfLogicalProcessors
$computerC = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'C:'" -ComputerName $Computer | select #{n="Size";e={[math]::Round($_.Size/1GB,2)}}
$computerD = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'D:'" -ComputerName $Computer | select #{n="Size";e={[math]::Round($_.Size/1GB,2)}}
$computerE = Get-WmiObject -Class Win32_LogicalDisk -Filter "DeviceID= 'E:'" -ComputerName $Computer | select #{n="Size";e={[math]::Round($_.Size/1GB,2)}}
"{0},{1},{2},{3},{4},{5},{6}" -f $computer,$computerC.Size,$computerD.Size,$computerE.Size,$computerSystemRam.Ram,$computerCPU,$computerCPUCores
}

PowerShell WMI/WQL to get information from SCCM - optimisation

This is a case where what I have works fine but I can't help but feel there must be a faster way to do this. I'm doubting my structure here. Do you see a faster way this could be done? The foreach takes a while since it has to query many times. The goal is to have an array that shows the computer's ($poste) collections (name and objectpath).
$poste = "p1234"
$SiteCode = "PRX"
$SiteServer = "SSX"
$ResourceID = Get-WmiObject -Namespace root\sms\site_$SiteCode -Computer $SiteServer -Class SMS_R_SYSTEM -Filter "Name='$poste'" |
 Select-Object -ExpandProperty ResourceID
$CollectionIDs = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class sms_fullcollectionmembership -Filter "ResourceID ='$resourceID'" |
 Select-Object -expand CollectionID
foreach ($CollectionID in $CollectionIDs) {
$query = #"
SELECT * FROM SMS_Collection
WHERE SMS_Collection.CollectionID='$CollectionID'
"#
[array]$CollectionNamesPath += Get-WmiObject -Namespace root\sms\site_$SiteCode -Computer $SiteServer -Query $query |
Select-Object name,ObjectPath |
Sort-Object -Property Name
}
$CollectionNamesPath | Out-GridView
This is likely the cleanest version of your existing code:
$poste = "p1234"
$SiteCode = "PRX"
$SiteServer = "SSX"
$ResourceID = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class SMS_R_SYSTEM -Filter "Name='$poste'" -Property ResourceID | Select-Object -ExpandProperty ResourceID
$CollectionIDs = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class sms_fullcollectionmembership -Filter "ResourceID='$resourceID'" -Property CollectionID | Select-Object -ExpandProperty CollectionID
$CollectionNamesPath = foreach ($CollectionID in $CollectionIDs) {
$Query = "Select Name, ObjectPath From SMS_Collection Where SMS_Collection.CollectionID='$CollectionID'"
Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Query $Query | Select-Object Name, ObjectPath | Sort-Object -Property Name
}
$CollectionNamesPath | Out-GridView
You could also try this, though I'm not sure how well WQL supports it:
$poste = "p1234"
$SiteCode = "PRX"
$SiteServer = "SSX"
$ResourceID = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class SMS_R_SYSTEM -Filter "Name='$poste'" -Property ResourceID | Select-Object -ExpandProperty ResourceID
$CollectionIDs = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class sms_fullcollectionmembership -Filter "ResourceID='$resourceID'" -Property CollectionID | Select-Object -ExpandProperty CollectionID
$Query = "Select CollectionID, Name, ObjectPath From SMS_Collection Where" + $($($CollectionIDs | ForEach-Object { " SMS_Collection.CollectionID='$_' " }) -join 'or')
$CollectionNamesPath = Get-WmiObject -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Query $Query |
Sort-Object -Property CollectionID, Name |
Select-Object Name, ObjectPath
$CollectionNamesPath | Out-GridView
You may be able to do something like this:
Get-CimInstance -Namespace root\sms\site_$SiteCode -ComputerName $SiteServer -Class SMS_R_SYSTEM -Filter "Name='$poste'" -KeyOnly |
Get-CimAssociatedInstance -ComputerName $SiteServer -ResultClassName sms_fullcollectionmembership -KeyOnly |
Get-CimAssociatedInstance -ComputerName $SiteServer -ResultClassName SMS_Collection |
Sort-Object -Property CollectionID, Name |
Select-Object Name, ObjectPath
When it works it's fantastic. However, in my experience working with Get-CimAssociatedInstance is an uneven experience at best, doubly so when working on remote computers.

Powershell script to get number of Physical CPU's

I tried to get the number of physical CPU's using below script however could not able to get the required resul.
get-wmiobject Win32_ComputerSystem
Is there any command to get Number of Physical CPU's ?
Starting in PowerShell 3.0, Get-WmiObject has been superseded by Get-CimInstance.
Number of physical CPUs (a.k.a. sockets)
#(Get-CimInstance -ClassName Win32_Processor).Count
or:
(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfProcessors
Number of physical cores
(Get-CimInstance -ClassName Win32_Processor | Measure-Object -Property NumberOfCores -Sum).Sum
Number of logical cores
(Get-CimInstance -ClassName Win32_Processor | Measure-Object -Property NumberOfLogicalProcessors -Sum).Sum
or:
(Get-CimInstance -ClassName Win32_ComputerSystem).NumberOfLogicalProcessors
If your're looking for properties always use get-member to list them:
get-wmiobject win32_processor | get-member
This way you can find properties like:
NumberOfCores
NumberOfLogicalProcessors
get-wmiobject win32_processor | select-object NumberOfCores, NumberOfLogicalProcessors
Don Jones in his "Creating HTML Reports in Powershell" Link book achieved it this way:
$cs = Get-WmiObject -class Win32_ComputerSystem
$Sockets=$cs.numberofprocessors
$Cores=$cs.numberoflogicalprocessors
The output on my pc is:
$Sockets
1
$Cores
4
In a single line of code:
$(Get-WmiObject Win32_ComputerSystem).NumberOfProcessors
There are also other parameters which might interest you such as: NumberOfCores and NumberOfEnabledCore.
For retrieving the all the properties you can run
Get-WmiObject Win32_ComputerSystem | Select-Object *
Get-WmiObject Win32_Processor | Select-Object *
For further reference about each parameter you can check:
https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-processor\
https://learn.microsoft.com/en-us/windows/win32/cimwin32prov/win32-computersystem
Use Get-WmiObject or short gwmi
To get the instances of the Win32_Processor class and then simply count them.
$(gwmi Win32_Processor).count

How to format 1-liner for printing an object property

How can I write a quick 1-liner for write-host'ing an object property (let's say Name)? Here is the object I want to print the Name of ...
Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2"
I tried ...
write-host $_.name | Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2"
But this seems to still print all object properties. What can I do to fix this command?
You can use the -ExpandProperty parameter of the Select-Object cmdlet to retrieve just the computer name, then pipe that to Write-Host (formatted as multiple lines for readability):
Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2" `
| Select-Object -ExpandProperty 'Name' `
| Write-Host;
Alternatively, use the ForEach-Object cmdlet to get the Name property:
Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2" `
| ForEach-Object { $_.Name; } `
| Write-Host;
This is not a one-liner, but another approach similar to what you tried:
$computer = Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2";
Write-Host $computer.Name;
Note that since you only care about the Name property of Win32_ComputerSystem, it's a good idea to communicate that to Get-WmiObject using the -Property parameter so it doesn't bother returning information that will be discarded anyways:
Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2" -Property 'Name'
In addition to the answer from BACON, another option is this (needs PowerShell v3 or higher):
Write-Host (Get-WmiObject -Class win32_ComputerSystem -namespace "root\CIMV2").Name

Querying partitions/drives on a remote server with WMI

I do the following to check for local drives/partitions on a remote computer:
Get-WmiObject -Class Win32_Share -ComputerName SERVERNAME -Filter "Description='Default share'"
but the command also returns CD-roms etc.
Is there a command to only return disk/partitions?
Get-WmiObject -Class Win32_LogicalDisk -Filter "DriveType=3" |
Foreach-Object {$_.DeviceID}
Try this:
Get-WMIObject Win32_DiskPartition -computername remotecomp |
ForEach-Object {
$info = #{}
$info.Disk = $_.DiskIndex
$info.Partition = $_.Index
$info.DriveLetter = $_.psbase.GetRelated('Win32_LogicalDisk') |
Select-Object -ExpandProperty DeviceID
New-Object PSObject -Property $info
}
$info # contains partions number and unit letter as hashtable
Get-WmiObject -query "Select * from Win32_DiskPartition" ... maybe?