I am trying to add some simple helper methods to an existing PSCustomObject.
My goal is to replace something like this:
$Persons.Where{$_.FirstName -like "*Test*"}
With this:
$Persons.GetFirstName("Test")
I am having a lot of trouble figuring out a working ScriptMethod to use with add-member.
Here is my example code, along with all of the variations I have tried so far:
$Persons = [PSCustomObject]#()
$Person1 = [PSCustomObject]#{
FirstName = 'John';
LastName = 'Doe';
Age = 27
}
$Person2 = [PSCustomObject]#{
FirstName = 'Test';
LastName = 'Dummy';
Age = 27
}
$Persons += $Person1
$Persons += $Person2
$Persons
#FirstName LastName Age
#--------- -------- ---
#John Doe 27
#Test Dummy 27
#Get using a regular where method to confirm
$Persons.Where{$_.FirstName -like "*Test*"}
#FirstName LastName Age
#--------- -------- ---
#Test Dummy 27
#Add the Helper Method GetFirstName
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where{$_.FirstName -like "$Args[0]"}}
#Check if the Test record is returned
$Persons.GetFullName("Test")
#Use this to remove the method for the next try
$Persons.PSObject.properties.remove('GetFirstName')
#Other Permutations I have tried
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where($this.FirstName -like "$($Args[0])")}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({FirstName -like $Args[0]})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({FirstName -like $args(0)})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({FirstName -like "$Args[0]"})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({FirstName -like "$($Args[0])"})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({$this.FirstName -like $Args[0]})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({$this.FirstName -like "*$($Args[0])*"})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({$this.FirstName -eq $Args[0]})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({$_.FirstName -like $Args[0]})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where({$_.FirstName -like "$($Args[0])"})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where("FirstName -like ""$($Args[0])""")}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.where("$($_.FirstName) -like ""$($Args[0])""")}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.GetEnumerator().where{FirstName -like $Args[0]}}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.GetEnumerator().where{$this.FirstName -like $Args[0]}}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this.GetEnumerator().where{$_.FirstName -like $Args[0]}}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this | ?{$_.FirstName -like $Args[0]}}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this | ?({$_.FirstName -like $Args[0]})}
add-member -inputobject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {$this | ?({$_.FirstName -like "$($Args[0])"})}
There's one $Args per scope, so $Args inside .Where{ <in here> } does not actually contain the input arguments to the script method - declare a named parameter instead and it'll work:
Add-Member -InputObject $Persons -MemberType ScriptMethod -Name GetFirstName -Value {
param([string]$fnArg)
$this.Where{$_.FirstName -like $fnArg}
} -Force
Related
I have a situation regarding PSObject. Thing is when I write only the same PSObject in different script it returns what it should.
$returnobject = New-Object -TypeName psobject
$returnobject | Add-Member -MemberType NoteProperty -Name LocalITMail -Value "what"
$returnobject | Add-Member -MemberType NoteProperty -Name LocationSufix -Value "wont you "
$returnobject | Add-Member -MemberType NoteProperty -Name Webproxy -Value "work"
return $returnobject
I get this
which is good.
But when I call the function from bigger script the return type is not as the form above and I cannot access its properties.
Example:
What am I doing wrong, is there a way on how to return the PSObject type so I don't get this #{...} output? Thanks.
When working with Class in powershell and calling a function/method the PSObject is not a String. This was my problem here.
#codaamok comment helped me here
Didnt know that powershell mehtod/function allows the return of PSObject
[PSobject] GetLocation($User, $LocationList) {
#create return object since we are returning more values.
$returnobject = New-Object -TypeName psobject
foreach ($item in $LocationList) {
if ($item.zzlocat -eq $user.l -or $item.l -eq $user.l) {
$returnobject | Add-Member -MemberType NoteProperty -Name LocalITMail -Value $item.Mail
$returnobject | Add-Member -MemberType NoteProperty -Name LocationSufix -Value $item.'sAMAccount Abbrevations (5th and 6th characters)'
$returnobject | Add-Member -MemberType NoteProperty -Name Webproxy -Value $item.sec_WWGG_WebSecurity_Office
}
}
return $returnobject
Write-output "$($this.TimeSTAMP)[Helper]::GetLocation -> Found Location from User" | Out-File $this.Workflow -Append
}
For some reason when I wrote this Powershell object, the last member does not get displayed in my result:
$resultObject = New-Object -TypeName psobject
$resultObject | Add-Member -MemberType NoteProperty -Name Date -Value $date
$resultObject | Add-Member -MemberType NoteProperty -Name TotalPCs -Value $ad
$resultObject | Add-Member -MemberType NoteProperty -Name UnmanagedTotal -Value $total
$resultObject | Add-Member -MemberType NoteProperty -Name TotalEMEA -Value $adEMEA
$resultObject | Add-Member -MemberType NoteProperty -Name UnmanagedEMEA -Value $totalEMEA
$resultObject | Add-Member -MemberType NoteProperty -Name TotalAFRICA -Value $adAFRICA
$resultObject | Add-Member -MemberType NoteProperty -Name UnmanagedAFRICA -Value $totalAFRICA
$resultObject | Add-Member -MemberType NoteProperty -Name TotalAMERICAS -Value $adAMERICAS
$resultObject | Add-Member -MemberType NoteProperty -Name UnmanagedAMERICAS -Value $totalAMERICAS
$resultObject | Add-Member -MemberType NoteProperty -Name TotalAPAC -Value $adAPAC
$resultObject | Add-Member -MemberType NoteProperty -Name UnmanagedAPAC -Value $totalAPAC
$resultObject | ft -AutoSize | out-file -FilePath "C:\BAC\WSUSScripts\KPI\ManagedComputers.txt" -Append
I have no clue why since every info is retrieved the same way and for the other member it all works. The last member just falls off.
I'm attempting to output an object array (of event logs) to a DataTable with the expectation to pipe into SQL.
The basics are:
Get some forwarded events
Process them to pull some required info out
Output to a data table
function Get-Type
{
param($type)
$types = #(
'System.Boolean',
'System.Byte[]',
'System.Byte',
'System.Char',
'System.Datetime',
'System.Decimal',
'System.Double',
'System.Guid',
'System.Int16',
'System.Int32',
'System.Int64',
'System.Single',
'System.UInt16',
'System.UInt32',
'System.UInt64')
if ( $types -contains $type ) {
Write-Output "$type"
}
else {
Write-Output 'System.String'
}
} #Get-Type
function Out-DataTable
{
[CmdletBinding()]
param([Parameter(Position=0, Mandatory=$true, ValueFromPipeline = $true)] [PSObject[]]$InputObject)
Begin
{
$dt = new-object Data.datatable
$First = $true
}
Process
{
Write-Output "test"
foreach ($object in $InputObject)
{
$DR = $DT.NewRow()
foreach($property in $object.PsObject.get_properties())
{
if ($first)
{
$Col = new-object Data.DataColumn
$Col.ColumnName = $property.Name.ToString()
if ($property.value)
{
if ($property.value -isnot [System.DBNull]) {
$Col.DataType = [System.Type]::GetType("$(Get-Type $property.TypeNameOfValue)")
}
}
$DT.Columns.Add($Col)
}
if ($property.Gettype().IsArray) {
$DR.Item($property.Name) =$property.value | ConvertTo-XML -AS String -NoTypeInformation -Depth 1
}
else {
$DR.Item($property.Name) = $property.value
}
}
$DT.Rows.Add($DR)
$First = $false
}
}
End
{
Write-Output #(,($dt))
}
} #Out-DataTable
$allEvents = Get-WinEvent -LogName ForwardedEvents | Where-Object{$_.Id -ne 111}
$outEvents = #()
$dt = $null
foreach ($curEvent in $allEvents){
$curObj = $null
switch ($curEvent.ID) {
4624 {
$curObj = New-Object -TypeName PSObject
Add-Member -InputObject $curObj -MemberType NoteProperty -Name TimeCreated -Value ([datetime]$curEvent.TimeCreated)
Add-Member -InputObject $curObj -MemberType NoteProperty -Name Action -Value $curEvent.TaskDisplayName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name MachineName -Value $curEvent.MachineName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name UserName -Value ((($curEvent.Message).Split([Environment]::NewLine)[36]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name LoginID -Value ((($curEvent.Message).Split([Environment]::NewLine)[40]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name SourceIP -Value ((($curEvent.Message).Split([Environment]::NewLine)[64]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name ID -Value $curEvent.Id
Add-Member -InputObject $curObj -MemberType NoteProperty -Name RecordID -Value $curEvent.RecordID
}
4647 {
$curObj = New-Object -TypeName PSObject
Add-Member -InputObject $curObj -MemberType NoteProperty -Name TimeCreated -Value ([datetime]$curEvent.TimeCreated)
Add-Member -InputObject $curObj -MemberType NoteProperty -Name Action -Value $curEvent.TaskDisplayName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name MachineName -Value $curEvent.MachineName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name UserName -Value ((($curEvent.Message).Split([Environment]::NewLine)[8]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name LoginID -Value ((($curEvent.Message).Split([Environment]::NewLine)[12]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name SourceIP -Value "Not Available"
Add-Member -InputObject $curObj -MemberType NoteProperty -Name ID -Value $curEvent.Id
Add-Member -InputObject $curObj -MemberType NoteProperty -Name RecordID -Value $curEvent.RecordID
}
4778 {
$curObj = New-Object -TypeName PSObject
Add-Member -InputObject $curObj -MemberType NoteProperty -Name TimeCreated -Value ([datetime]$curEvent.TimeCreated)
Add-Member -InputObject $curObj -MemberType NoteProperty -Name Action -Value "Reconnect"
Add-Member -InputObject $curObj -MemberType NoteProperty -Name MachineName -Value $curEvent.MachineName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name UserName -Value ((($curEvent.Message).Split([Environment]::NewLine)[6]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name LoginID -Value ((($curEvent.Message).Split([Environment]::NewLine)[10]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name SourceIP -Value ((($curEvent.Message).Split([Environment]::NewLine)[24]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name ID -Value $curEvent.Id
Add-Member -InputObject $curObj -MemberType NoteProperty -Name RecordID -Value $curEvent.RecordID
}
4800 {
$curObj = New-Object -TypeName PSObject
Add-Member -InputObject $curObj -MemberType NoteProperty -Name TimeCreated -Value ([datetime]$curEvent.TimeCreated)
Add-Member -InputObject $curObj -MemberType NoteProperty -Name Action -Value "Locked"
Add-Member -InputObject $curObj -MemberType NoteProperty -Name MachineName -Value $curEvent.MachineName
Add-Member -InputObject $curObj -MemberType NoteProperty -Name UserName -Value ((($curEvent.Message).Split([Environment]::NewLine)[8]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name LoginID -Value ((($curEvent.Message).Split([Environment]::NewLine)[12]).split(":")[1]).Trim()
Add-Member -InputObject $curObj -MemberType NoteProperty -Name SourceIP -Value "Not Available"
Add-Member -InputObject $curObj -MemberType NoteProperty -Name ID -Value $curEvent.Id
Add-Member -InputObject $curObj -MemberType NoteProperty -Name RecordID -Value $curEvent.RecordID
}
Default { }
}
$outEvents += $curObj
}
$outEvents
$dt = Out-DataTable -InputObject $outEvents
When I run this, the last output of $outEvents lists all of the event objects with the correct details however trying to pipt it into Out-DataTable returns:
Out-DataTable : Cannot bind argument to parameter 'InputObject' because it is null.
At \\server\scripts\Repository\Write-UserLoginEvent\Write-UserLoginEvent.ps1:140 char:38
+ $dt = Out-DataTable -InputObject $outEvents
+ ~~~~~~~
+ CategoryInfo : InvalidData: (:) [Out-DataTable], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Out-DataTable
I've tried all different methods of formatting the data etc and I can't seem to get this function to accept my custom object array.
If I use a built in function like 'Get-Process' the function works correctly and returns the DataTable so I'm thinking it is something specific to the object I'm returning.
EDIT: Before I posted this, I also moved the DataTable segment into the loop, to attempt to print each event object as an individual DataTable. Hoping to identify where the issue was. It failed immediately on the first object.
So the issue was that I had an un-captured event type that had slipped through.
Because this event was not being formatted correctly there was a single event in the output that would not fit into the DataTable structure, causing the NULL error.
To identify the issue I put an Out-DataTable step inside the loop to process each object individually and in the output I could see that all objects succeeded except one. Tracking down that one I could see that I hadn't catered for that Event ID (8001).
$thisplan = New-Object PSObject
Add-Member -InputObject $thisplan -MemberType NoteProperty -Name PlanID -Value $planid
Add-Member -InputObject $thisplan -MemberType NoteProperty -Name PlanName -Value $plan.name
Add-Member -InputObject $thisplan -MemberType NoteProperty -Name SessionPassword -Value $sessionpass
$schedule = $plan.backupConfiguration.advanceSchedule.periodSchedule
#DAY
add-Member -InputObject $thisplan -MemberType NoteProperty -Name DayRetention -Value $schedule.daySchedule.retentionCount
if ($schedule.daySchedule.retentionCount -gt 0)
{
$dstart = udptime($schedule.daySchedule.dayTime)
}
else
{
$dstart = ""
}
Add-Member -InputObject $thisplan -MemberType NoteProperty -Name DayStart -Value $dstart
########################
is there a way to make a function from the #day section?
This is a small part from my script.
I have a problem :(
I have many errors when I add New object with the same name of property which previously Object .
"Add-Member : Cannot add a member with the name "ServerName" because a
member with that name already exists. To overwrite the member anyway,
add the Force par ameter to your command."
it works but with errors;)
Have someone a solution for me ??
Below example code :
$OutputObj = #()
$OutputObj += New-Object -TypeName PSobject
$OutputObj | Add-Member -MemberType NoteProperty -Name ServerName -Value "server1"
$OutputObj | Add-Member -MemberType NoteProperty -Name Status -Value "online"
$OutputObj | Add-Member -MemberType NoteProperty -Name Uptime -Value "01:20"
$OutputObj += New-Object -TypeName PSobject
$OutputObj | Add-Member -MemberType NoteProperty -Name ServerName -Value "server2"
$OutputObj | Add-Member -MemberType NoteProperty -Name Status -Value "online"
$OutputObj | Add-Member -MemberType NoteProperty -Name Uptime -Value "01340"
You are adding the member on the array, not on the object. Try the following:
$OutputObj = #()
$NewObj = New-Object -TypeName PSobject
$NewObj | Add-Member -MemberType NoteProperty -Name ServerName -Value "server1"
$NewObj | Add-Member -MemberType NoteProperty -Name Status -Value "online"
$NewObj | Add-Member -MemberType NoteProperty -Name Uptime -Value "01:20"
$OutputObj += $NewObj
$NewObj = New-Object -TypeName PSobject
$NewObj | Add-Member -MemberType NoteProperty -Name ServerName -Value "server2"
$NewObj | Add-Member -MemberType NoteProperty -Name Status -Value "online"
$NewObj | Add-Member -MemberType NoteProperty -Name Uptime -Value "01340"
$OutputObj += $NewObj
Alernatively, I would do the following:
$OutputObj = #()
$OutputObj += New-Object -TypeName PSobject -Property #{
ServerName = "server1"
Status = "Online"
Uptime = "01:20"
}
$OutputObj += New-Object -TypeName PSobject -Property #{
ServerName = "server2"
Status = "Online"
Uptime = "01340"
}
Since Add-Member destroys and generates a new object each time it is used.