Gathering System Process IO details - powershell

I am trying to prepare a report wherein I need to collect the I/O read,write and other bytes of all the process running on the system. Below is the script which I currently use.
Get-Process|select name,cpu,#{name="WorkingSet";Expression={$_.WorkingSet/1kb}},BasePriority,path|where {$_.Name -in 'dllhost','firefox','dsapi'}
Below is output that we obtain after a few processing and measure object.
The issue which I am facing is that for most of the system processes or where the username is system, the value for those returns mostly in the form zero. Kindly provide some directions on how to fix this issue and obtain the actual value for the system process as well.
<>
From what I read on the I/O values will not be extracted from the get-process cmdlet which is why I have used the below cmdlet and it works fine for user created process however for the system created process the script returns a zero value as show in the above image.
$gc = get-counter '\Process(dllhost)\IO Read Bytes/sec'
$gc.countersamples | sort cookedvalue

Ensure you're running powershell as administrator.
There is no ReadByteSec or WriteBytpeSec from what I can see.
You're also using a select statement which doesn't contain those properties.
Type this to see all the available properties for dllhost:
$processes = Get-Process | where {$_.Name -in 'dllhost'}
Get-Member -InputObject $processes[0]
And then add those to your statement:
Get-Process|select name,cpu,#{name="WorkingSet";Expression={$.WorkingSet/1kb}},BasePriority,path, *BytesField1, BytesField2, etc* |where {$.Name -in 'dllhost','firefox','dsapi'}

Related

Get serialnumber from asset list

Started in recent weeks in a Junior infrastructure role, and begun playing around with powershell to help save some time here and there.
I am trying to do the following:
1- I'm port a CSV file with a single column names asset
2- Perform a "ForEach" check on each line to find the device's serial number
3- Output results to a CSV with two column "asset" and "serialnumber"
I have dabbled in a few areas, and am currently sitting at something like this:
$file1 = Import-Csv -path "c:\temp\assets.csv" | ForEach-Object {
$asset = $_.asset
}
wmic /node:$asset bios get serialnumber
Export-Csv -Path "c:\temp\assetandserial.csv" -NoTypeInformation
As you may or may not see, I tried to set the column labelled "asset" as the variable, however, not sure if I placed it correctly.
I have tried a few other things, but honestly it's all new to me, so I haven't the foggiest idea where to go from here.
wmic is deprecated, and, for rich type support (OO processing), using PowerShell-native cmdlets is preferable in general.
wmic's immediate PowerShell counterpart is Get-WmiObject, which, however, is equally deprecated, in favor of Get-CimInstance.
Important: The command below uses Get-CimInstance, but note that the CIM cmdlets use a different remoting protocol than the obsolete WMI cmdlets. In short: To use the CIM cmdlets with remote computers, those computers must be set up in the same way that PowerShell remoting requires - see this answer for details.
Get-CimInstance Win32_BIOS -ComputerName (Import-Csv c:\temp\assets.csv).asset |
Select-Object #{ n='Asset'; e='PSComputerName' }, SerialNumber |
Sort-Object Asset |
Export-Csv c:\temp\assetandserial.csv -NoTypeInformation
Note the use of member-access enumeration to extract all .asset values directly from the collection of objects returned from Import-Csv.
All computer (asset) names are passed at once to Get-CimInstance, which queries them in parallel. Since the ordering of the responses from the targeted remote machines isn't guaranteed, Sort-Object is used to sort the results.
A calculated property is used with Select-Object to rename the automatically added .PSComputerName property to Asset.

Unable to retrieve accessed folders from Event Logs using PowerShell

I am trying to control accesses to specific folder, so I have Audit Object Access policy enable and I've also enabled Auditing on the folder I want. Now I plan to see these accesses on a CSV file.
I have the following script that is supposed to achieve this
$OutputFileName = "EventsFrom-{0}.csv" -f (Get-Date -Format "MMddyyyy-HHmm")
Get-EventLog -LogName Security | Where-Object {$_.EventID -eq 4656} | Select-Object -Property TimeGenerated, MachineName, #{n='AccountName';e={$_.ReplacementStrings[1]}} | Export-CSV c:\scripts\$OutputFileName -NoTypeInformation
but the condition
Where-Object {$_.EventID -eq 4656}
causes the resulting CSV file to come out completely empty (even with no table headers). But when I change the Event ID (from 4656 to something like 4673) or remove the condition altoghether, I do get results on the resulting CSV.
Also, from the event viewer when I filter the results with the ID 4656, results do show up. Right now I genuinely don't know what to do. Thanks in advance for any help.
I appreciate if anyone could help me track down the cause for this. I don't really have much experience with PS scripting so a detailed expanation as to why this is happening (or the actual solution for my problem) would be very helpful.

Script has two variables when done, but when I pipe to SELECT-object only first one returns data to console

I am trying to query multiple servers with WMI, but I don't always have access to the servers.
The code is below. Alas, it returns "access is denied" to the console, but I can't seem to get rid of it. Oh well.
However, I am trapping the servers that I can't connect to, so that I can tell someone else to look at them, or request access.
But when I run the code, it only returns the first list of servers; even if $failed_servers has values, nothing is returned. If I tell both to pipe to ogv, then two windows pop up.
Why won't both "$variable|select" work? If I remove the select on $failed_servers, then it shows up, albeit just sitting immediately underneath the successful ones. Which is okay-but-not-great.
$list = ("servera","serverb","serverc")
$failed_servers = #()
$final = foreach ($server_instance in $list)
{
$errors=#()
gwmi -query "select * from win32_service where name like '%SQLSERVER%'" -cn $server_instance -ErrorVariable +errors -ErrorAction SilentlyContinue
if ($errors.Count -gt 0) {$failed_servers += $server_instance
}
}
$final|select pscomputername, name, startmode, state |where {$_.pscomputername -ne $null}
$failed_servers |select #{N='Failed Servers'; E={$_}}
What you're experiencing is merely a display problem:
Both your Select-Object calls produce output objects with 4 or fewer properties whose types do not have explicit formatting data associated with them (as reported by Get-FormatData).
This causes PowerShell's for-display output formatting system to implicitly render them via the Format-Table cmdlet.
The display columns that Format-Table uses are locked in based on the properties of the very first object that Format-Table receives.
Therefore, your second Select-Object call, whose output objects share no properties with the objects output by the first one, effectively produces no visible output - however, the objects are sent to the success output stream and are available for programmatic processing.
A simple demonstration:
& {
# This locks in Month and Year as the display columns of the output table.
Get-Date | Select-Object Month, Year
# This command's output will effectively be invisible,
# because the property set Name, Attributes does not overlap with
# Month, Year
Get-Item \ | Select-Object Name, Attributes
}
The output will look something like this - note how the second statement's output is effectively invisible (save for an extra blank line):
Month Year
----- ----
9 2021
Note the problem can even affect a single statement that outputs objects of disparate types (whose types don't have associated formatting data); e.g.:
(Get-Date | Select-Object Year), (Get-Item \ | Select-Object Name)
Workarounds:
Applying | Format-List to the command above makes all objects visible, though obviously changes the display format.
Intra-script you could pipe each Select-Object pipeline to Out-Host to force instant, pipeline-specific formatting, but - given that the results are sent directly to the host rather than to the success output stream - this technique precludes further programmatic processing.
Potential future improvements:
GitHub issue #7871 proposes at least issuing a warning if output objects effectively become invisible.

Passing previous Powershell command properties into a piped command

Can someone show how to pass a property from one Powershell command into the next piped command (in order to pull properties from both levels of the request)?
I need to get archive mailbox sizes for users in Exchange Online. An example of this is here:
Get-EXOMailbox | get-MailboxStatistics -archive | select displayname,totalitemsize
When you run this, obviously you are grabbing properties from the second command. I need to also grab the identity property tied to Get-EXOMAilbox, the first command (which shows the user's active mailbox and is useful for subsequent actions.
Thanks!
As Doug Maurer suggests, you might want to take advantage of the -PipelineVariable common parameter:
Get-EXOMailbox -PipelineVariable mailbox |Get-MailboxStatistics -Archive |Select #{Name='DisplayName';Expression={ $mailbox.DisplayName }},TotalItemSize

pipelined Powershell cmdlet showing partial result?

I am writing some C# program that executes PowerShell script.
I have the following line
Get-Mailbox -ResultSize:unlimited |
Get-MailboxPermission |
Where {($_.IsInherited -eq $false) -and !($_.user -like "S-1*") -and !($_.user -like "NT A*") } |
select identity,user,#{n="objectid";e={(get-recipient -identity $_.user).ExternalDirectoryObjectId}}
basically it finds all mailbox permissions and retrieves corresponding ExternalDirectoryObjectId (which is same as Azure ObjectID)
The issue here is that the result returned is different from different machines. I would get all identity, user values, but for expression values that are in bold above, will only start to show up half way through the execution.
for example on computer x
Identity|User|objectid
user1 |userA|
user2 |userA|
user2 |userB|
... |... |
user10|userC|
user11|userC|<objectID1>
user11|userD|<objectID2>
I noticed that on fast computer the objectIDs start showing up late, on slower computers it starts showing up early, however execution times are different.
How do I modify this so that objectGuid is retrieved for all entries? Why is pipelining not waiting until the calculated property objectID is properly retrieved?
If I write a short PowerShell script and use for loops for each mboxpermissions and retrieve them one by one, all of those objectGuids are retrievable. But it's slow.
Thanks for help and Please give me any suggestions!