Powershell: Foreach Input - powershell

I'm stuck on something that I know is really simple but for the life of me can't figure out.
I'm trying to import a .txt file with a list of hostnames, which once retrived, the script returns the amount of totalphysicalmemory installed.
so far I have this:
function get
{
$boxes = Get-Content C:\Temp\hostnamesforRAM.txt
foreach($box in $boxes)
{
Get-WmiObject Win32_ComputerSystem | select TotalPhysicalMemory
}
}
get
however, it just simply returns this:
4151570432
4151570432
4151570432
4151570432
4151570432
Any ideas?
Thanks

You need to pass the current hostname ($box) to the computerName parameter, without it you're getting the value from your own computer.
function get
{
$boxes = Get-Content C:\Temp\hostnamesforRAM.txt
foreach($box in $boxes)
{
Get-WmiObject Win32_ComputerSystem -ComputerName $box | select TotalPhysicalMemory
}
}
get
Another way, more shorter, would be to pass the content of the file to the ComputerName parameter. The ComputerName parameter accepts a collection of names:
Get-WmiObject Win32_ComputerSystem -ComputerName (Get-Content C:\Temp\hostnamesforRAM.txt) |
Select-Object Name,TotalPhysicalMemory

This is TotalPhysicalMemory in bytes, to get special computer info add computername to command Get-WmiObject with proper variable name ($box in your case):
Get-WmiObject -computername $box Win32_ComputerSystem

Try
function get
{
$boxes = Get-Content C:\Temp\hostnamesforRAM.txt
foreach($box in $boxes)
{
"$box -> $((Get-WmiObject Win32_ComputerSystem -computername $box).TotalPhysicalMemory)"
}
}

Related

foreach powershell i'm totally blind

I have issues with this PowerShell script, if i execute the line without the foreach works great but with him don't show up nothing, can someone tell me why?
The foreach works fantastic by himselft he read all the data from the CSV but for some reason don't work, the CSV contain PC names like PC1, Pc-RRHH, JosePc from my network, like i say without the foreach is fine.
$computers = Import-Csv “C:\PowerShell\Pc.csv”
$array = #()
foreach($pc in $computers)
{
Get-WmiObject -Namespace ROOT\CIMV2 -Class Win32_Product -Computer $pc.computername
Select-Object Name, Version, PSComputerName
Where-Object -FilterScript {$_.Name -like “Adobe*”}
}
Best regards
Assuming your CSV file indeed has a header with column 'computername' in it, you can change your code to:
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
# because NameSpace 'root/CIMV2' is the default, you do not have to specify that
Get-CimInstance -ClassName Win32_Product -ComputerName $pc.computername |
# or use the old Get-WmiObject
# Get-WmiObject -Class Win32_Product -Computer $pc.computername |
Where-Object { $_.Name -like "Adobe*" } |
Select-Object Name, Version, PSComputerName
}
Instead of piping to a Where-Object {..} clause, you can also use the -Filter parameter.
Beware though that this filter requires WQL syntax, which is different from PowerShell syntax.
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
# because NameSpace 'root/CIMV2' is the default, you do not have to specify that
Get-CimInstance -ClassName Win32_Product -ComputerName $pc.computername -Filter "Name like 'Adobe%'" |
Select-Object Name, Version, PSComputerName
}
Or use the -Query parameter:
$computers = Import-Csv "C:\PowerShell\Pc.csv"
# the query string to filter on. Also WQL syntax
$query = "Select * from Win32_Product where Name LIKE 'Adobe%'"
# let PowerShell collect the data for you in an array
$array = foreach($pc in $computers) {
Get-CimInstance Get-CimInstance -Query $query -ComputerName $pc.computername |
Select-Object Name, Version, PSComputerName
}
From your comment, I gather that your CSV file isn't a CSV at all, but just a text file with pc names each on a separate line and that there is not header 'computername'.
In that case, change $computers = Import-Csv "C:\PowerShell\Pc.csv" to $computers = Get-Content -Path "C:\PowerShell\Pc.csv" and in the loop use -ComputerName $pc instead if -ComputerName $pc.computername

Pull NT user ID from powershell

get-wmiobject -class win32_computersystem -computername c73118 | format-table username
Will output something similar to:
username
--------
GHS_NTDOMAIN\amacor
Is it possible to only output the amacor part only?
first, you don't really want FT for this I don't think. Use Select -Expand instead. So doing that we get back the string GHS_NTDOMAIN\amacor. Once you have that, you can do .Split("\") to split it into an array of strings, and [-1] to specify the last string in the array. So it would look like:
(get-wmiobject -class win32_computersystem -computername c73118 | Select -ExpandProperty username).Split("\")[-1]
That will result in:
amacor
Or if you wanted to be a bit more verbose about it, you can do:
$Data = get-wmiobject -class win32_computersystem -computername c73118
$DomainUser = $Data.Username
$UserName = $DomainUser.Split("\")[-1]
Then $UserName = "amacor"
Edit: Updated per Andy Arismendi's excellent suggestion.

Include computername parameter with Get-WmiObject data

Using PowerShell, I want to include the computer name with some of the returned data of the WMI query. I've studied custom columns - need something like that - but I do not know how to pass the computer name into the next loop to be included in the resulting table. For example:
Get-WmiObject -Class Win32_LogicalDisk -ComputerName MailServer01
Actually, I'm in another look where $_ is the computer name:
Get-WmiObject -Class Win32_LogicalDisk -ComputerName $_
This works great, but I want to include the ComputerName ($_) as part of the final output or report. Any ideas?
The computername is already there (as SystemName). It just isn't part of the default display properties.
Run
Get-WmiObject -Class Win32_LogicalDisk -ComputerName MailServer01 | format-list *
to see all of the properties of the returned objects.
The "__Server" property will always be available for the get-wmiobject objects
Also note:
"Beginning in Windows PowerShell 3.0, the __Server property of the object that Get-WmiObject returns has a PSComputerName alias. This makes it easier to include the source computer name in output and reports."
http://technet.microsoft.com/en-us/library/hh849824.aspx
Try this
Get-WMiObject -Class Win32_LogicalDisk -ComputerName $_ | Add-Member -MemberType NoteProperty -Name ComputerName -Value $_ -PassThru
Then you can output or manipulate your data anyway you see fit, and the properties you add via Add-Member will be available on that object as long as it exists.
Docs for the cmdlet are here
Yeah, I didn't realize there were more properties. Works great: __Server was the property I needed:
$myServers = #("server1", "server2", "server3")
"" > space.txt
$myServers | foreach-object {
write-host "Server: $_"
Get-WmiObject -Class Win32_LogicalDisk -ComputerName $_ | ? { $_.DeviceID -notmatch " [AR]"} | Select -Property __Server, DeviceID, #{Name=’FreeSpaceMB’;Expression={$_.FreeSpace/1MB} } | Format-Table -AutoSize >> c:\space.txt
}

Powershell's Invoke-Command won't take in a variable for -ComputerName parameter?

I'm pulling my hair out here, because I just can't seem to get this to work, and I can't figure out how to google this issue. I'm running Powershell 2.0. Here's my script:
$computer_names = "server1,server2"
Write-Output "Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}"
Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
The last command gives the error:
Invoke-Command : One or more computer names is not valid. If you are trying to
pass a Uri, use the -ConnectionUri parameter or pass Uri objects instead of
strings.
But when I copy the output of the Write-Output command to the shell and run that, it works just fine. How can I cast the string variable to something that Invoke-Command will accept? Thanks in advance!
Jamey and user983965 are correct, in that your declaration is wrong. However foreach here is not mandatory. If you just fix your array declaration like this, it will work:
$computer_names = "server1","server2"
Invoke-Command -ComputerName $computer_names -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
You declared your array incorrectly. Put a comma between strings and pipe it to for-each like:
$computer_names = "server1", "server2";
$computer_names | %{
Write-Output "Invoke-Command -ComputerName $_ -ScriptBlock {
...snip
If you're getting an array of computers from active directory too - like this:
$computers = Get-ADComputer -filter {whatever}
Make sure you remember to select/expand the results.. like this:
$Computers= Get-ADComputer -filter * | Select-Object -ExpandProperty Name
Then...
Invoke-Command -ComputerName $Computers -ScriptBlock {Do Stuff}
have you tried:
$computer_names = "server1" , "server2"
foreach ($computer in $computer_names)
{
Write-Output "Invoke-Command -ComputerName $computer -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}"
Invoke-Command -ComputerName $computer -ScriptBlock {
Get-WmiObject -Class Win32_LogicalDisk |
sort deviceid |
Format-Table -AutoSize deviceid, freespace
}
}

Powershell - filtering WMIObject processes by more than one name

I am trying to get a list of running processes and filter by two process names - can any one tell me how to get this working?
I've so far got it working and filtering out one process name:
$rn = Get-WMIObject Win32_Process -computer servername `
-credential mydomain\administrator -filter "Name='program1.exe'" |
select -expand path
$lst = Get-Content “C:\path\path2\List.txt”
Compare-Object $lst $rn
What I want it to do is filter two process names but nothing I've tried works. Any ideas?
Here's how to get a complete set of Process objects which match a list of process names you're interested in.
$ProcessNames = #( 'explorer.exe', 'notepad.exe' )
Get-WmiObject Win32_Process -Computer 'localhost' |
Where-Object { $ProcessNames -contains $_.Name } |
Select-Object ProcessID, Name, Path |
Format-Table -AutoSize
This example finds all processes, then filters that list by sending them to a pipeline filter that checks to see if the process name is contained in the list of interesting process names. The main benefit of using the pipeline this way is that you can easily access other attributes (such as ProcessID) of the returned processes.
ProcessID Name Path
--------- ---- ----
5832 explorer.exe C:\Windows\Explorer.EXE
4332 notepad.exe C:\Windows\system32\NOTEPAD.EXE
2732 notepad.exe C:\Windows\system32\notepad.exe
Use WQL operators like OR, AND, LIKE etc:
Get-WMIObject Win32_Process -computer servername -credential mydomain\administrator -filter "Name='program1.exe' OR Name='program2.exe'"
Create an array of the processes you're after:
$processes = #('winword.exe', 'notepad.exe', 'excel.exe') | `
% {
$rn = Get-WMIObject Win32_Process -computer servername -credential mydomain\admin -filter "Name='$_'" | select -expand path
#$lst = Get-Content “C:\path\path2\List.txt”
#Compare-Object $lst $rn
write-host $rn
}
I've commented out your compare so you can see how we are looping through the array clearly.
if I understood well try this:
$rn = Get-WMIObject Win32_Process -computer servername -credential mydomain\administrator -filter "Name='program1.exe OR Name='program2.exe'"
Compare-Object $rn[0].path $rn[1].path # if there are only one instance for process with name program1.exe and program2.exe