Powershell add-member calculated value - arrays

I'm writing a script that takes unstructured input, reformats it and spits out a CSV.
In one of the members, I want to do an NSLOOKUP of another member to get the DNS entry associated with the IP. However, a number of the entries have an IP of 0.0.0.0 e.g. it's a listening port, there's no client yet connected.
These throw up errors from NSLOOKUP, quite rightly, because there's no DNS entry for it.
So, I amended my code to only do the NSLOOKUP if the IP was not 0.0.0.0, otherwise return an empty string.
But I can't make it work.
The following throws up no errors:
$srcdata -split "`r`n"|foreach {
$obj = New-Object System.Object
$obj|Add-Member -MemberType NoteProperty -Name Connection_ID -Value $_.Split(",")[0]
$obj|Add-Member -MemberType NoteProperty -Name Filename -Value $_.Split(",")[1]
$obj|Add-Member -MemberType NoteProperty -Name MCP_Port -Value $_.Split(",")[2]
$obj|Add-Member -MemberType NoteProperty -Name Client_Port -Value $_.Split(",")[3]
$obj|Add-Member -MemberType NoteProperty -Name Port_State -Value $_.Split(",")[4]
$obj|Add-Member -MemberType NoteProperty -Name Client_IP -Value $_.Split(",")[5]
$obj|Add-Member -MemberType NoteProperty -Name Client_DNS -value {If ($obj.Client_IP -ne "0.0.0.0") {(NSLOOKUP $obj.Client_IP|Select-String Name).Line.ToString().Replace(" ","").Split(":")[1]} else {""}}
$obj|Add-Member -MemberType NoteProperty -Name Protocol_Stack -Value $_.Split(",")[6]
$outfile += $obj
}
But then if I inspect one of the objects in the array I see:
Connection_ID : 1
Filename : CCF_MARC1
MCP_Port : 2001
Client_Port : 0
Port_State : LISTEN
Client_IP : 0.0.0.0
Client_DNS : If ($obj.Client_IP -ne "0.0.0.0") {(NSLOOKUP $obj.Client_IP|Select-String Name).Line.ToString().Replace(" ","").Split(":")[1]} else {""}
Protocol_Stack : LEGACY
If I wrap in parentheses instead of in a scriptblock, so the line setting up the Client_DNS is as follows:
$obj|Add-Member -MemberType NoteProperty -Name Client_DNS -value (If ($obj.Client_IP -ne "0.0.0.0") {(NSLOOKUP $obj.Client_IP|Select-String Name).Line.ToString().Replace(" ","").Split(":")[1]} else {""})
I get:
If : The term 'If' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
At K:\CodeSnippets\PowerShell\NW_CONN_TO_CSV.ps1:21 char:91
+ ... NS -value (If ($obj.Client_IP -ne "0.0.0.0") {(NSLOOKUP $obj.Client_IP|Selec ...
+ ~~
+ CategoryInfo : ObjectNotFound: (If:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
I'm sure I could get it to work as two separate lines of code, so do the If statement and put the result in a variable, then use that variable as the value in the add-member command, but I'm sure what I'm trying to do is eminently possible, I'm just missing something!
Any ideas?

You're interested in a ScriptProperty rather than a NoteProperty:
$obj |Add-Member -MemberType ScriptProperty -Name Client_DNS -Value {
nslookup $this.Client_IP |Select-String Name
}

You could use a regex to extract the name, something like this:
$outfile = $srcdata -split "[\r\n]" | % {
$v = $_.Split(",")
$re = [regex]::match((NSLOOKUP $v[5]), '(?<=Name:\s+)[^\s]+')
New-Object psobject -Property #{
Client_DNS = #('', $re.value)[$re.success]
Connection_ID = $v[0]
Filename = $v[1]
MCP_Port = $v[2]
Client_Port = $v[3]
Port_State = $v[4]
Client_IP = $v[5]
Protocol_Stack = $v[6]
}
}

Related

Powershell 2.0 random $null addition from Add-Member

My goal is to save some info into a variable that later will be written out ($Server).
I have created a cmdlet that gets some info from the CPU, which gives me the result i want to add into my server variable.
When i add it i get a $null value.
PS C:\> $CPU = Get-CPUInfo -Computername .
PS C:\> $CPU
CPUSpecification CPUCurrentClockSpeed CPUMaxClockSpeed Socket
---------------- -------------------- ---------------- ------
Intel(R) Core(TM) i5-6200U CPU # 2.30GHz 2300 2400 {#{SocketDesignation=U3E1; NumberOfCores=2; NumberOfLogicalProcessors=4}}
PS C:\> $Server = New-Object PSObject
PS C:\> Add-Member -InputObject $Server -MemberType NoteProperty -Name "CPU" -Value $CPU
PS C:\> $Server
CPU
---
{$null, #{CPUSpecification=Intel(R) Core(TM) i5-6200U CPU # 2.30GHz; CPUCurrentClockSpeed=2300; CPUMaxClockSpeed=2400; Socket=System.Object[]}}
PS C:\>
I would like to know why i get this $null inside, and how do i change it if it is some usefull information?
Later on i will create a .json file that stores my $Server variable, and it also saves the null value inside there.
I really do not like the idea of my users recieving null values where none are expected.
EDIT:
I have made this custom Get-CPUInfo cmdlet that i use, however it gives me what i need and no $null value:
function Get-CPUInfo
{
[CmdletBinding()]
Param
(
# Name of the computer to get version from
[Parameter(Mandatory=$true,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
[ValidateNotNull()]
[ValidateNotNullOrEmpty()]
[Alias("CN", "Host", "HostName")]
[string]$Computername
)
$MySocket = Get-WmiObject -Class Win32_Processor -ComputerName $ComputerName
$IsSocketArray = $MySocket -is [system.array]
$SocketInfo
$SocketInfoArray = #()
if(-not $IsSocketarray)
{
$SocketInfo = New-Object PSObject
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "SocketDesignation" -Value $MySocket.SocketDesignation
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "NumberOfCores" -Value $MySocket.NumberOfCores
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "NumberOfLogicalProcessors" -Value $MySocket.NumberOfLogicalProcessors
$SocketInfoArray += $SocketInfo
}
else
{
foreach ($s in $MySocket)
{
$SocketInfo = New-Object PSObject
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "SocketDesignation" -Value $s.SocketDesignation
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "NumberOfCores" -Value $s.NumberOfCores
Add-Member -InputObject $SocketInfo -MemberType NoteProperty -Name "NumberOfLogicalProcessors" -Value $s.NumberOfLogicalProcessors
$SocketInfoArray += $SocketInfo
}
}
$CPUSpecification = if($IsSocketarray){ $MySocket[0].Name} else{ $MySocket.Name}
$CPUCurrentClockSpeed = if($IsSocketarray){ $MySocket[0].CurrentClockSpeed} else{ $MySocket.CurrentClockSpeed}
$CPUMaxClockSpeed = if($IsSocketarray){ $MySocket[0].MaxClockSpeed} else{ $MySocket.MaxClockSpeed}
$CPUInfo = New-Object PSObject
Add-Member -InputObject $CPUInfo -MemberType NoteProperty -Name "CPUSpecification" -Value $CPUSpecification
Add-Member -InputObject $CPUInfo -MemberType NoteProperty -Name "CPUCurrentClockSpeed" -Value $CPUCurrentClockSpeed
Add-Member -InputObject $CPUInfo -MemberType NoteProperty -Name "CPUMaxClockSpeed" -Value $CPUMaxClockSpeed
Add-Member -InputObject $CPUInfo -MemberType NoteProperty -Name "Socket" -Value $SocketInfoArray
return $CPUInfo
}
PowerShell doesn't print null elements of an array when you display it directly, but it'll be printed in a compact representation of properties.
Let's check:
(Get-CPUInfo -Computername .).GetType()
Object[] System.Array
(Get-CPUInfo -Computername .).Count
2
(Get-CPUInfo -Computername .)[0] -eq $null
True
Something outputs a null value in the Get-CPUInfo function:
$SocketInfo
Remove it.

"Counting" in an arrays using powershell

Hi I'm trying to count number of arrow where two value are matched.
Here is how i put value in my array :
$obj | add-member -name "Site" -membertype Noteproperty -value $sitecode
$obj | add-member -name "Location" -membertype Noteproperty -value $location
$obj | add-member -name "SwitchName" -membertype Noteproperty -value $swname
$obj | add-member -name "MacAddress" -membertype Noteproperty -value $mac
$obj | add-member -name "Interface" -membertype Noteproperty -value $eth
$obj | add-member -name "Macvendor" -membertype Noteproperty -value ""
$obj | add-member -name "IP" -membertype Noteproperty -value ""
$tab += $obj
Now i would like to count each combibation of SwitchName / Interface.
Exemple my arrays can contains the following amongt other value :
Switchname=foo,portX
Switchname=foo,portY
Switchname=foo,portX
Switchname=foo,portZ
Switchname=bar,portX
Switchname=bar,portZ
Switchname=bar,portT
I want to be able to get :
Switchname=foo,portX,2
Switchname=foo,portY,1
Switchname=foo,portZ,1
Switchname=bar,portX,1
Switchname=bar,portZ,1
Switchname=bar,portT,1
I'm currently thinking about using another table to count all of this. Any easier way to do that?
Thanks.
Use the Group-Object cmdlet:
PS C:\> $tab |Group-Object -Property SwitchName,Interface -NoElement
Count Name
----- ----
2 foo, portX
1 foo, portY
1 foo, portZ
1 bar, portX
1 bar, portZ
1 bar, portT
try Something like this:
$tab | select SwitchName, Interface , #{N="Number";E={$switchname=$_.SwitchName;$interface=$_.Interface; ($tab | where {$_.SwitchName -eq $switchname -and $_.Interface -eq $interface }).Count}}

Creating and populating a hash table

I am looking to create either a non-jagged array or a hash table (I am not sure the difference nor what I need to get the job done). Here is what I am trying to do.
I would like to query a list of servers for several values and then store those values for output to a CSV file. Here is the code.
$allServers = "svr1","svr2","svr3"
$a = #{}
$outData = New-Object PSObject
$allServers | ForEach-Object {
$cpu = (Get-WmiObject win32_processor -ComputerName $_).length
$mem = (Get-WmiObject win32_physicalmemory -ComputerName $_).Capacity /1GB
$outData | Add-Member -Type NoteProperty -Name "SERVERNAME" -Value $_
$outData | Add-Member -Type NoteProperty -Name "#CPU" -Value $cpu
$outData | Add-Member -Type NoteProperty -Name "#GBRAM" -Value $mem
}
Write-Host $outData
I am getting errors because it seems like it is trying to create the same entries repeatedly. Is it possible to make an empty hash table (or non-jagged array) with column names and then just populate values?
Create the object inside the loop, output it, and assign the value of the whole pipeline to your array variable:
$allServers = "svr1","svr2","svr3"
$a = $allServers | ForEach-Object {
$cpu = (Get-WmiObject win32_processor -ComputerName $_).length
$mem = (Get-WmiObject win32_physicalmemory -ComputerName $_).Capacity /1GB
$outData = New-Object PSObject
$outData | Add-Member -Type NoteProperty -Name "SERVERNAME" -Value $_
$outData | Add-Member -Type NoteProperty -Name "#CPU" -Value $cpu
$outData | Add-Member -Type NoteProperty -Name "#GBRAM" -Value $mem
$outData
}
$a | Export-Csv $path -NoTypeInformation

Export-CSV powershell loop

What is the correct practice on outputting to a CSV file from a loop. My goal is to check the attributes of all files matching a series of extensions that have not been accessed in over a month and output to a csv file for reading later.
it only outputs the information for the first file. and errors the following:
Add-Member : Cannot add a member with the name "FileName" because a member with that name already exists. If you want to overwrite the member a
nyway, use the Force parameter to overwrite it.
At C:\Users\claw\Desktop\checkFileAge.ps1:10 char:25
+ $out2csv | add-member <<<< -MemberType NoteProperty -Name FileName -Value $i.fullname
+ CategoryInfo : InvalidOperation: (#{FileName=C:\u...012 9:33:46 AM}:PSObject) [Add-Member], InvalidOperationException
+ FullyQualifiedErrorId : MemberAlreadyExists,Microsoft.PowerShell.Commands.AddMemberCommand
Here is my example:
$out2csv = New-Object PSObject;
foreach ($i in get-childitem c:\users -recurse -include *.doc, *.xls, *.ppt, *.mdb, *.docx, *.xlsx, *.pptx, *.mdbx, *.jpeg, *.jpg, *.mov, *.avi, *.mp3, *.mp4, *.ogg)
{if ($i.lastaccesstime -lt ($(Get-Date).AddMonths(-1)))
{
$out2csv | add-member -MemberType NoteProperty -Name FileName -Value $i.fullname
$out2csv | add-member -MemberType NoteProperty -Name LastAccess -Value $i.LastAccessTime
}
} $out2csv | Export-Csv "C:\FileAccessInformation.csv" -NoTypeInformation -Force
Try something like this. It is a bit more canonical PowerShell.
$ext = '*.doc', '*.xls',...
Get-ChildItem C:\Users -r -inc $ext |
Where {$_.LastAccessTime -lt [DateTime]::Now.AddMonths(-1)} |
Select FullName, LastAccessTime |
Export-Csv -NoTypeInformation -Force C:\FileAccessInformation.csv

Add Member to get NIC Info Gives Error for Servers with More than One Nic ( powershell.)

Im trying to genreate a report for NIc Card info using powershell, & use add member to append the properties, but if a server is having more than 1 NIC, add members return an error "Do you want to owerwrite property" Use -force, could any one please help me to sort out the issue, also im having an array $output=#() into which im appending all these inputs,i Tried adding a for loop to get the no of NICS & iterate thru them one by one as an array, i see no output, can some one help me.
<#NIC card info Check#>
$colItems1 = get-wmiobject -class "Win32_NetworkAdapter" -namespace "root\CIMV2" -computername $compname
$colItems = get-wmiobject -class "Win32_NetworkAdapterconfiguration" -namespace "root\CIMV2" -computername $compname
$lengthcol=($colItems1).length
for ($i=0;$i-lt$length;$i++){
foreach ($objitem in $colItems)
{
# Match the current $objItem with the correct $ColItems1 element.
$objItem1 = $colItems1| where-object{$_.Caption -eq $objItem.Caption}
# A test is needed here as the loop will find a number of virtual network configurations with no "Hostname"
# So if the "Hostname" does not exist, do NOT display it!
if ($objItem.ipenabled -eq "true" -and $objitem1.netconnectionid) {
# Write to screen
#write-host "Caption: " $objItem.Caption
$nicname[$i]=$objitem1.netconnectionid
$dhcpenabled[$i]=$objItem.DHCPEnabled
$ipaddress[$i]=$objItem.IPAddress
$ipsubnet[$i]=$objItem.IPSubnet
$gateway[$i]=$objItem.DefaultIPGateway
$dhcpserver[$i]=$objItem.DHCPServer
$DNSDomain[$i]=$objItem.DNSDomain
$DNSDomainSearchOrder[$i]=$objItem.DNSDomainSuffixSearchOrder
$DNSServerSearchOrder[$i]=$objItem.DNSServerSearchOrder
$output | Add-Member -MemberType Noteproperty -Name NICCardName[$i] -Value $nicname[$i]
$output | Add-Member -MemberType Noteproperty -Name DHCPEnabled[$i] -Value $dhcpenabled[$i]
$output | Add-Member -MemberType Noteproperty -Name IPAddress[$i] -Value $ipaddress[$i]
$output | Add-Member -MemberType Noteproperty -Name SubnetMask[$i] -Value $ipsubnet[$i]
$output | Add-Member -MemberType Noteproperty -Name Gateway[$i] -Value $gateway[$i]
$output | Add-Member -MemberType Noteproperty -Name DHCPServer[$i] -Value $dhcpserver[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSDomain[$i] -Value $DNSDomain[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSDomainSuffixSearchOrder[$i] -Value $DNSDomainSearchOrder[$i]
$output | Add-Member -MemberType Noteproperty -Name DNSServerSearchOrder[$i] -Value $DNSServerSearchOrder[$i]
}
}
}
$outputs+=$output
Try this:
Get-WmiObject Win32_NetworkAdapter -ComputerName $computer| ForEach-Object {
$NetConnectionId = $_.NetConnectionId
$nac = $_.GetRelated('Win32_NetworkAdapterconfiguration') | Select-Object IPEnabled,DHCPEnabled,IPAddress,IPSubnet,DefaultIPGateway,DHCPServer,DNSDomain,DNSDomainSuffixSearchOrder,DNSServerSearchOrder
$nac | Select-Object *,#{Name='NetConnectionId';Expression={$NetConnectionId}}
}
UPDATE (per poster request):
$compname='.'
$colItems1 = get-wmiobject -class Win32_NetworkAdapter -computername $compname
$colItems = get-wmiobject -class Win32_NetworkAdapterconfiguration -computername $compname
foreach ($objitem in $colItems)
{
$objItem1 = $colItems1 | where-object{$_.Caption -eq $objItem.Caption}
if ($objItem.ipenabled -eq $true -and $objitem1.netconnectionid)
{
$output = new-object -typename psobject
$output | Add-Member -MemberType Noteproperty -Name NICCardName -Value $objitem1.netconnectionid
$output | Add-Member -MemberType Noteproperty -Name DHCPEnabled -Value $objItem.DHCPEnabled
$output | Add-Member -MemberType Noteproperty -Name IPAddress -Value $objItem.IPAddress
$output | Add-Member -MemberType Noteproperty -Name SubnetMask -Value $objItem.IPSubnet
$output | Add-Member -MemberType Noteproperty -Name Gateway -Value $objItem.DefaultIPGateway
$output | Add-Member -MemberType Noteproperty -Name DHCPServer -Value $objItem.DHCPServer
$output | Add-Member -MemberType Noteproperty -Name DNSDomain -Value $objItem.DNSDomain
$output | Add-Member -MemberType Noteproperty -Name DNSDomainSuffixSearchOrder -Value $objItem.DNSDomainSuffixSearchOrder
$output | Add-Member -MemberType Noteproperty -Name DNSServerSearchOrder -Value $objItem.DNSServerSearchOrder -PassThru
}
}

Resources