Powershell Return only value from PSObject - powershell

I am using the following to get the status of tracert
Currently it stores it in a New-Object psobject but the problem I am running into is that when I try and filter on Status wanting just to return Success I get the following returned instead #{Status=Success}, how can I remove the #{Status=} from around the results?
function Invoke-Trace() {
param(
[string[]]$targetIP,
$BeginHop = 1,
$EndHop = 30,
$timeout = 1000,
[switch]$GetHostname
)
$addrtype = [System.Net.Sockets.AddressFamily]::InterNetwork;
if($v6.ispresent) {
$addrtype = [System.Net.Sockets.AddressFamily]::InterNetworkV6;
}
$targetIPActual = $null;
if(![net.ipaddress]::TryParse($targetIP, [ref]$targetIPActual)) {
$target = [net.dns]::GetHostEntry($targetIP);
$targetIPActual = $target.addresslist | where {$_.addressfamily -eq $addrtype} | select -First 1
} else {
$target = New-Object psobject -Property #{"HostName" = $targetIP.tostring()}
}
for($i = $BeginHop; $i -lt $EndHop; $i++) {
$ping = new-object System.Net.NetworkInformation.ping;
$pingo = new-object System.Net.NetworkInformation.PingOptions $i, $true;
$sendbytes = #([byte][char]'a'..[byte][char]'z');
$pr = $ping.Send($targetIPActual, $timeout, $sendbytes, $pingo);
try {
$rtn = New-Object psobject -Property #{
"IP" = $pr.Address;
"RoundtripTime" = $pr.RoundtripTime;
"Status" = $pr.Status;
}
} catch {
$rtn = New-Object psobject -Property #{
"IP" = "*";
"RoundtripTime" = $pr.RoundtripTime;
"Status" = $pr.Status;
}
}
try {
if($GetHostname.ispresent) {
Add-Member -InputObject $rtn -MemberType NoteProperty -Name Hostname -Value ([net.dns]::GetHostEntry($pr.Address).hostname)
}
} catch{}
$rtn;
#$pr
try {
if($pr.Address.tostring() -eq $targetIPActual) { break; }
} catch{}
}
}

If your $rtn is a PSObject and you want to just return one property of it, then don't return the whole object. The line above #$pr is where your object is being returned, so you could do this instead:
$rtn.Status
It's a bit unclear to me why you're putting it in that object in the first place since you don't seem to want to use it, but I'm just going to assume you have a reason and give you this quick answer. Feel free to edit your question and clarify if there's something that might be missing.

Related

Writing the output of Get-NetTCPConnection to an array - no output

I am trying to write the values of the PowerShell cmdlet Get-NetTCPConnection to an array but nothing is being written to the list.
$list= #()
$outputs = Get-NetTCPConnection
foreach ($output in $outputs) {
$obj = New-Object PSObject -Property #{
TheLocalAddress = "EMPTY"
TheLocalPort = "EMPTY"
TheRemoteAddress = "EMPTY"
TheRemotePort = "EMPTY"
}
$obj.TheLocalAddress = $output.LocalAddress
$obj.TheLocalPort = $output.LocalPort
$obj.TheRemoteAddress = $output.RemoteAddress
$obj.TheRemotePort = $output.RemotePort
$list += $obj
}
$list
If the prefix The isn't required for the properties, why not use
$list = Get-NetTCPConnection | Select-Object LocalAddress,LocalPort,RemoteAddress,RemotePort
Or a more efficient [PSCustomObject] ?
$list = foreach ($Conn in Get-NetTCPConnection) {
[PSCustomObject]#{
TheLocalAddress = $Conn.LocalAddress
TheLocalPort = $Conn.LocalPort
TheRemoteAddress = $Conn.RemoteAddress
TheRemotePort = $Conn.RemotePort
}
}
$list

Powershell: Property stored in a variable

I would like to find all cells in a range based on a property value using EPPlus. Let's say I need to find all cells with bold text in an existing spreadsheet. I need to create a function that will accept a configurable properties parameter but I'm having trouble using a property stored in a variable:
$cellobject = $ws.cells[1,1,10,10]
$properties = 'Style.Font.Bold'
$cellobject.$properties
$cellobject.{$properties}
$cellobject.($properties)
$cellobject."$properties"
None of these work and cause a call depth overflow.
If this way wont work, is there something in the library I can use?
Edited: To show the final solution I updated the function with concepts provided by HanShotFirst...
function Get-CellObject($ExcelSheet,[string]$PropertyString,[regex]$Value){
#First you have to get the last row with text,
#solution for that is not provided here...
$Row = Get-LastUsedRow -ExcelSheet $ExcelSheet -Dimension $true
while($Row -gt 0){
$range = $ExcelSheet.Cells[$Row, 1, $Row, $ExcelSheet.Dimension.End.Column]
foreach($cellObject in $range){
if($PropertyString -like '*.*'){
$PropertyArr = $PropertyString.Split('.')
$thisObject = $cellObject
foreach($Property in $PropertyArr){
$thisObject = $thisObject.$Property
if($thisObject -match $Value){
$cellObject
}
}
}
else{
if($cellObject.$PropertyString -match $Value){
$cellObject
}
}
}
$Row--
}
}
#The ExcelSheet parameter takes a worksheet object
Get-CellObject -ExcelSheet $ws -Property 'Style.Font.Bold' -Value 'True'
Dot walking into properties does not really work with a string. You need to separate the layers of properties. Here is an example for an object with three layers of properties.
# create object
$props = #{
first = #{
second = #{
third = 'test'
}
}
}
$obj = New-Object -TypeName psobject -Property $props
# outputs "test"
$obj.first.second.third
# does not work
$obj.'first.second.third'
# outputs "test"
$a = 'first'
$b = 'second'
$c = 'third'
$obj.$a.$b.$c
In your example this would be something like this:
$cellobject = $ws.cells[1,1,10,10]
$p1 = 'Style'
$p2 = 'Font'
$p3 = 'Bold'
$cellobject.$p1.$p2.$p3
Or you can do it a bit dynamic. This should produce the same result:
$cellobject = $ws.cells[1,1,10,10]
$props = 'Style.Font.Bold'.Split('.')
$result = $cellobject
foreach ($prop in $props) {
$result = $result.$prop
}
$result
And since its Friday, here is a function for it :)
function GetValue {
param (
[psobject]$InputObject,
[string]$PropertyString
)
if ($PropertyString -like '*.*') {
$props = $PropertyString.Split('.')
$result = $InputObject
foreach ($prop in $props) {
$result = $result.$prop
}
} else {
$result = $InputObject.$PropertyString
}
$result
}
# then call the function
GetValue -InputObject $cellobject -PropertyString 'Style.Font.Bold'

Is There A Simple Powershell Command to tell if COM+ Application is Paused?

This Powershell code will start/shutdown a COM+, I'm thinking.
$comAdmin= New-Object -com ("COMAdmin.COMAdminCatalog.1")
$comAdmin.ShutdownApplication("pkgAdap2")
$comAdmin.StartApplication("pkgAdap2")
Powershell doesn't complain. But how do I look and see if the Application is shutdown/started? I can see it in the Component Services window, but not sure how to tell if it is running.
Is there an easy way to use Powershell to tell me this?
I have found that there is a COMAdminCatalogObject called "IsPaused" which returns a true or false. However, I don't know how to reference it. All examples and solutions I have found are multiline loops through all Applications in the Component Services.
I was thinking something like this would work:
$comAdmin.IsPaused("pkgAdap2")
COM List
$comAdmin = New-Object -com ("COMAdmin.COMAdminCatalog.1")
$applications = $comAdmin.GetCollection("Applications")
$applications.Populate()
foreach ($application in $applications)
{
$components = $applications.GetCollection("Components",$application.key)
$components.Populate()
foreach ($component in $components)
{
$dllName = $component.Value("DLL")
$componentName = $component.Name
"Component Name:$componentName"
"DllName: $dllName`n"
}
}
You can Start or Stop Using:
$comAdmin.StartApplication("appName")
$comAdmin.ShutdownApplication("appName")
For Installation :
Refer to: Microsoft Link
$comAdmin.InstallApplication("fileName")
For Shutting down all COM:
$sb = {
$admin = New-Object -Com ("COMAdmin.COMAdminCatalog")
$apps = $admin.GetCollection("Applications")
$apps.Populate()
$apps | % {
$component = $apps.GetCollection("Components", $_.Key)
$component.Populate()
$component | % {
$admin.ShutdownApplication("$_.Name")
}
}
}
$servers | % {Invoke-Command -ComputerName $_ -ScriptBlock $sb}
Hope it helps.
There:
$catalog = New-Object -ComObject "COMAdmin.COMAdminCatalog"
$appCollection = $catalog.GetCollection("Applications")
$appCollection.Populate()
$appList = #{}
$appCollection | ForEach-Object {
$appList.Add($_.Value("ID"), $_.Name)
}
$appInstances = $catalog.GetCollection("ApplicationInstances")
$appInstances.Populate()
$appInstanceList = #{}
$appInstances | ForEach-Object {
$appValue = $_.Value("Application")
$appInstanceList.Add($appValue, $appList[$appValue])
}
$appList.Keys | ForEach-Object {
New-Object PSObject -Property #{
"Name" = $appList[$_]
"ID" = $_
"Running" = $appInstanceList.ContainsKey($_)
}
}

Is there a PowerShell equivalent tracert that works in version 2?

I'm using PSVersion 2.0 and I was wondering is there a equivalent to the traceroute for it?
I'm aware that on PowerShell v4 there is Test-NetConnection cmdlet to do tracert but v2?! It can be done like:
Test-NetConnection "IPaddress/HOSTaname" -TraceRoute
Thanks
As mentioned in the comment, you can make your own "poor-mans-PowerShell-tracert" by parsing the output from tracert.exe:
function Invoke-Tracert {
param([string]$RemoteHost)
tracert $RemoteHost |ForEach-Object{
if($_.Trim() -match "Tracing route to .*") {
Write-Host $_ -ForegroundColor Green
} elseif ($_.Trim() -match "^\d{1,2}\s+") {
$n,$a1,$a2,$a3,$target,$null = $_.Trim()-split"\s{2,}"
$Properties = #{
Hop = $n;
First = $a1;
Second = $a2;
Third = $a3;
Node = $target
}
New-Object psobject -Property $Properties
}
}
}
By default, powershell formats objects with 5 or more properties in a list, but you can get a tracert-like output with Format-Table:
Fixed a few bugs in " Mid-Waged-Mans-Tracert" Version, modularized it, and added some customization pieces. #MrPaulch had a great PoC.
function Invoke-Traceroute{
[CmdletBinding()]
Param(
[Parameter(Mandatory=$true,Position=1)]
[string]$Destination,
[Parameter(Mandatory=$false)]
[int]$MaxTTL=16,
[Parameter(Mandatory=$false)]
[bool]$Fragmentation=$false,
[Parameter(Mandatory=$false)]
[bool]$VerboseOutput=$true,
[Parameter(Mandatory=$false)]
[int]$Timeout=5000
)
$ping = new-object System.Net.NetworkInformation.Ping
$success = [System.Net.NetworkInformation.IPStatus]::Success
$results = #()
if($VerboseOutput){Write-Host "Tracing to $Destination"}
for ($i=1; $i -le $MaxTTL; $i++) {
$popt = new-object System.Net.NetworkInformation.PingOptions($i, $Fragmentation)
$reply = $ping.Send($Destination, $Timeout, [System.Text.Encoding]::Default.GetBytes("MESSAGE"), $popt)
$addr = $reply.Address
try{$dns = [System.Net.Dns]::GetHostByAddress($addr)}
catch{$dns = "-"}
$name = $dns.HostName
$obj = New-Object -TypeName PSObject
$obj | Add-Member -MemberType NoteProperty -Name hop -Value $i
$obj | Add-Member -MemberType NoteProperty -Name address -Value $addr
$obj | Add-Member -MemberType NoteProperty -Name dns_name -Value $name
$obj | Add-Member -MemberType NoteProperty -Name latency -Value $reply.RoundTripTime
if($VerboseOutput){Write-Host "Hop: $i`t= $addr`t($name)"}
$results += $obj
if($reply.Status -eq $success){break}
}
Return $results
}
I must admit I wanted to see whether someone already did this.
You can use the .Net Framework to implement a not-so-poor-mans-traceroute as a Powershell Script
Here a primer, that works fast, but dangerous.
Also, no statistics.
#
# Mid-Waged-Mans-Tracert
#
$ping = new-object System.Net.NetworkInformation.Ping
$timeout = 5000
$maxttl = 64
$address = [string]$args
$message = [System.Text.Encoding]::Default.GetBytes("MESSAGE")
$dontfragment = false
$success = [System.Net.NetworkInformation.IPStatus]::Success
echo "Tracing $address"
for ($ttl=1;$i -le $maxttl; $ttl++) {
$popt = new-object System.Net.NetworkInformation.PingOptions($ttl, $dontfragment)
$reply = $ping.Send($address, $timeout, $message, $popt)
$addr = $reply.Address
$rtt = $reply.RoundtripTime
try {
$dns = [System.Net.Dns]::GetHostByAddress($addr)
} catch {
$dns = "-"
}
$name = $dns.HostName
echo "Hop: $ttl`t= $addr`t($name)"
if($reply.Status -eq $success) {break}
}
Edit:
Removed some of the danger by adding a catch statement.
The only danger that is still present is the fact that we only send a single request per hop, which could mean that we don't reach a hop due to a innocent package drop.
Resolving that issue remains a readers exercise.
Hint: (Think of loops within loops)
Bonus: We now attempt to get the dns entry of each hop!
With at least PS 5 you can
Test-Netconnection stackoverflow.com -TraceRoute

Format as Table an Array of Object

i want to format as table an Array of PSObject my code is:
$object = #()
Foreach ($Alarm in Get-AlarmDefinition) {
Foreach ($AlarmAction in Get-AlarmAction -AlarmDefinition $Alarm) {
$obj = New-Object PSObject -property #{Definition = $Alarm.Name; Action =""; GY=""; YR=""; RY=""; YG=""}
Foreach ($AlarmActionTrigger in Get-AlarmActionTrigger -AlarmAction $AlarmAction) {
$obj.Action = $AlarmAction.ActionType
If ($AlarmActionTrigger.StartStatus -eq "Green") {
$obj.GY = $AlarmActionTrigger.Repeat
} Else {
If($AlarmActionTrigger.StartStatus -eq "Red") {
$obj.RY = $AlarmActionTrigger.Repeat
} Else {
If ($AlarmActionTrigger.EndStatus -eq "Green") {
$obj.YG = $AlarmActionTrigger.Repeat
} Else {
$obj.YR = $AlarmActionTrigger.Repeat
}
}
}
}
$object += $obj
}
}
$object | Format-Table Definition, Action,GY,YR,RY,YG -auto
But returns this error:
ConsoleLineOutputOutOfSequencePacket,Microsoft.PowerShell.Commands.OutLineOutputCommand
Can some please Help?
TNX
You may want to try setting up the format for the table before you call the "Format-Table"
Like this:
$myformat = #{Expression={$_.*one*};Label="*name*";width=10},
#{Expression={$_.*two*};Label="*Two*";width=50},
$Result = $object | Format-Table $myformat -Wrap | Out-String
Write-Host $Result
Microsoft's Documentation