Adding custom property or replacing read-only property - powershell

I'm attempting to automate a loop that goes through our servers collecting logs from eventviewer to later export into a webpage which works just fine, BUT, I would like to add a property to this list or possible modify an existing read-only property.
Here is the scriptlines I'm using:
$eventlog = (Get-EventLog -LogName system -Newest 5 -EntryType Error)
$eventlog | Select-Object Source,Message,MachineName | ConvertTo-Html -Head $a | Out-File C:\logs.htm
The only real issue here is that the property "MachineName" list "name.domain.com" instead of just "name", so I went ahead and added the following:
$eventlog | ForEach-Object {
$_.MachineName=$env:COMPUTERNAME
}
This was stopped because the property is read-only so I thought I could perhaps add a property to my object and just populate it with a variable which I still believe should work but I'm not getting the hang of how Add-Memberworks fully.
Here is how I went about it:
$eventlog | Add-Member -Name Hostname -Value $env:COMPUTERNAME
or
Add-Member -InputObject $eventlog -Name Hostname -Value $env:COMPUTERNAME
Obviously this alone doesn't work but I can't get my head around how the rest of the parameters are supposed to look. I'm also fairly certain the line above isn't even right but it's enough to make you understand what I'm trying to achieve and perhaps know of a better solution!

You could use a calculated property. This way you can modify read only properties or add new....
$eventlog = (Get-EventLog -LogName system -Newest 5 -EntryType Error)
$eventlog | Select-Object Source,Message, #{l='MachineName'; e={$env:COMPUTERNAME}} |
ConvertTo-Html -Head $a |
Out-File C:\logs.htm

$eventlog | Add-Member -Name 'Hostname' -Value $env:COMPUTERNAME -MemberType NoteProperty
$eventlog | Select ...,hostname | ConvertTo-Html -Head $a | Out-File C:\logs.htm

Related

Powershell How to include username along with processname, etc.,?

Get-NetTCPConnection | Select-Object -Property LocalAddress,LocalPort,RemoteAddress,RemotePort,State,#{name='NameofApp';expression={(Get-Process -id $_.OwningProcess).MainModule.FileVersionInfo.FileDescription}} | Format-Table -AutoSize
The above one works perfectly, Here I want to include the Username as well:
I know that Get-Process -IncludeUserName will return the UserName but I don't know how to join this in the above working command.
Using your current query, here is a simple modified approach that will solve your problem:
Get-NetTCPConnection | ForEach-Object {
$process = Get-Process -Id $_.OwningProcess -IncludeUserName
$description = $process.MainModule.FileVersionInfo.FileDescription
$username = $process.UserName
$properties = $_ | Select-Object -Property LocalAddress,LocalPort,RemoteAddress,RemotePort,State
$properties | Add-Member -Name "NameOfApp" -Type NoteProperty -Value $description
$properties | Add-Member -Name "UserName" -Type NoteProperty -Value $username
$properties
} | Format-Table -AutoSize
Explanation:
Pipe Get-NetTCPConnection through to Foreach-Object.
Get the process object with Get-Process, making sure to include User Names with the -IncludeUserName switch.
Store the descriptions and usernames in separate variables. Not necessary, but I split them up for clarity.
Get all the TCP connection properties that can be selected immediately with Select-Object into a System.Management.Automation.PSCustomObject. This uses the default pipeline variable $_ from Foreach-Object, which is basically the current item from GetNetTCPConnection. You can run Get-Help -Name about_Automatic_Variables to find out more about pipeline variables, and Get-Help -Name about_pipelines for finding out more about pipelines. Unfortunately, these Help files don't contain online versions.
Add the NameOfApp and UserName members to the object with Add-Member.
Format into a table with Format-Table and auto size columns with the -AutoSize switch.
You could also use regular foreach enumeration as well:
& {
foreach ($connection in Get-NetTCPConnection) {
$process = Get-Process -Id $connection.OwningProcess -IncludeUserName
$description = $process.MainModule.FileVersionInfo.FileDescription
$username = $process.UserName
$properties = $connection | Select-Object -Property LocalAddress,LocalPort,RemoteAddress,RemotePort,State
$properties | Add-Member -Name "NameOfApp" -Type NoteProperty -Value $description
$properties | Add-Member -Name "UserName" -Type NoteProperty -Value $username
$properties
}
} | Format-Table -AutoSize
The above is wrapping the foreach loop inside a script block, so you need to use the call operator & to run it. You can read more About Operators and About Script Blocks.

Unable to copy contents from `Out-GridView` window

I can't copy the data from the grid window when using CTRL+C. It just closes the window.
My code:
Get-ADUser -Filter * | ForEach-Object -Process {
Add-Member -InputObject $_ -Name TerminalServicesProfilePath -Force -Membertype NoteProperty -Value (([ADSI]"LDAP://$($_.DistinguishedName)").TerminalServicesProfilePath) -PassThru
} | Select-Object -Property SamAccountName, TerminalServicesProfilePath | Out-GridView
This may or may not solve your problem, but instead of using Add-Member (which is of limited use in this case), try using a calculated property in your pipeline:
Get-ADUser -Filter * | Select-Object -Property #(
'SamAccountName'
#{
Label = 'TerminalServicesProfilePath'
Expression = { ([adsi]"LDAP://$($_.DistinguishedName)").TerminalServicesProfilePath }
}
) | Out-GridView
If you're using this in a script, or something of that nature, then your problem is not using the Wait switch on Out-GridView. See the documentation here.

Custom PowerShell Object Property Issue

I'm attempting to create a custom PowerShell object using data from the WebAdministration module for IIS7. The object should capture the ClientIPAddress and SiteID from the GetExecuteRequest WmiMethod for Worker Processes in IIS.
$p = Get-WmiObject WorkerProcess -Namespace root\WebAdministration -ComputerName . | Invoke-WmiMethod -Name GetExecutingRequests | Select-Object -ExpandProperty OutputElement
$wpob = #()
foreach($w in $p)
{
$webrequests = New-Object PSObject
$webrequests | Add-Member -Type NoteProperty -Name ClientIP -Value ($w | select -ExpandProperty ClientIPAddress)
$webrequests | Add-Member -Type NoteProperty -Name SiteID -Value ($W | select -ExpandProperty SiteID)
$wpobj += $webrequests
}
The Problem:
Object ($wpobj) contains the 'ClientIP' and 'SiteID' under get-member, but you cannot get those values by using $wpobj.clientip or $wpobj.siteid. Only way I could retrieve those values were to use $wpobj | select clientip or $wpobj | select siteid
Not being able to get the values for the properties in the above mentioned way makes it more difficult to sort/group the data as I can't select the values later on down the pipeline.
Anyone know what I may be missing? I have not seen this before. Only in this particular case
Solution was to upgrade Powershell to V4.0. IE.invoke won't work on earlier versions of Powershell.

Formatting the results of a powershell script

How can i add the server name at the left of each line result on this script?. Thank you!
$servers = Get-Content -path .\Machines.txt
[pscustomobject]$result = #()
$subresult =
ForEach ($server in $servers)
{
Set-Service -computername $servers -Name sacsvr -StartupType Disabled -PassThru
}
$result = $subresult
$result | Out-File local_group_members.csv
This is an example result:
Status Name DisplayName
------ ---- -----------
Stopped sacsvr Special Administration Console Helper
Stopped sacsvr Special Administration Console Helper
Stopped sacsvr Special Administration Console Helper
Alternatively you can just add a property to the objects you're outputting right now. Pipe your Set-Service to Add-Member like this:
Set-Service -computername $servers -Name sacsvr -StartupType Disabled -PassThru | Add-Member -MemberType NoteProperty -Name 'Server' -Value $Server -PassThru
Now each object that you pass to $subresult has a new property Server that is the name of the server it was run on. You'll probably want to pipe through Select when outputting to have the order you want.
$SubResult | Select Server, Status, Name, DisplayName | Export-CSV 'local_group_members.csv' -NoType
You can arbitrarily re-order or add to your output with Select-Object. You can use hash tables to include calculated properties such as your desired ServerName.
So for each server, you can set the services and tag the output with that server name:
ForEach ($server in $servers)
{
Set-Service -computername $server -Name sacsvr -StartupType Disabled -PassThru |
Select #{Name = 'ServerName'; Expression = {$server}}, Name, DisplayName, Status
}
The above is shorthand for:
Select-Object -Property (properties)
The -Property parameter allows you to select any arbitrary grouping of properties on the type of object being piped in. Another parameter, -InputObject allows us to pipe in objects by value.

Showing LogName in table when querying multiple logs with PowerShell get-eventlog

I'm new to PowerShell and I am trying to get recent events for a group of logs (right now application and system for testing purposes).
What's missing is a column in the final output showing the log the event came from.
I tried piping the output before the format-table to get member to see if there was a property that contained the logname and there doesn't seem to be one.
Is there a workaround to get this?
What I have right now is:
"application", "system" | foreach { Get-EventLog -LogName $_ -Newest 10 } | sort time -Descending | ft timegenerated, LogName, source, message -wrap -AutoSize
This is what I want, but the LogName column is blank because there's no such property.
Someone may be able to clean this up a little, but you could try this:
"application", "system" | foreach { $events = Get-EventLog -LogName $_ -Newest 10; $events | Add-Member -MemberType NoteProperty -Name LogName -Value (Get-Culture).TextInfo.ToTitleCase($_); $events } | sort timegenerated -Descending | ft timegenerated, LogName, source, message -wrap -AutoSize
I fixed the sort command(typo) and format the logname as proper(uppercase first letter) to clean it up.