I have a script which get a tcp connections Get-NetTCPConnection.
The $flam variable can get last record for each object, and the $rfrt variable can get all output objects without the last one.
As I show the $CntTableBodyr variable is my mistake, I want to add $flam and $rfrt variable as HTML table with the following details :
Each tr of the $flam which has recognized by Id=111, to the first row then the $rfrt which has recognized by Id=222 to those rows which contain by the first above rows digitalis!
Can't understand? Here what I mean :
Screenshot :
Explanation :
For example, in my $GetCon variable which includes all tcp-connections [as you know]. my complete output count is [7 Count] as I show in above image, for example the [OwningProcess for 1177] has 3 count result, and so on, I want to get last object of 1177 as the first row with id=111 then second and all connections about 1177 to bottom. Other connections are same as 1177 and [LocalAddress].
Example:
$GetCon = Get-NetTCPConnection
$ss = $GetCon | select OwningProcess | Group-Object -Property OwningProcess | select Count, Name
$cccs = $ss | Select -ExpandProperty Name
$flam = ForEach ($oio in $cccs) {
$GetCon | Where-Object {$_.OwningProcess -eq $oio} | select -Last 1
}
$yyoiu = $GetCon | Group-Object -Property OwningProcess
for ($irt = 0; $irt -lt $yyoiu.Count; $irt++)
{
$rfrt = foreach($grpop in $yyoiu[0..$irt]){
$jrtgrpcnt = [int]($grpop.Group.Count - 1)
$grpop.Group | select -First (0+$jrtgrpcnt)
}
}
$CntTableBodyr=""
#$frcntArrr = $flam | select -ExpandProperty OwningProcess #$frcntr.GetEnumerator() |%{$_}
ForEach ($Rowr in $flam) {
$CntTableBodyr+="<tr id='111' style='background-color: lightblue;'><td>$($Rowr.OwningProcess)</td><td>$($Rowr.LocalAddress)</td></tr>
<tr id='222' style='background-color: lightgray;'><td>$($rfrt.OwningProcess)</td><td>$($rfrt.LocalAddress)</td></tr>"
}
$html=#"
<table id='tblId'>
$CntTableBodyr
</table>
"#
ConvertTo-Html -Body $html | Out-File c:\out.html
Invoke-Item c:\out.html
Just taking the essential part (as I do not have access to the same resources):
$flam = ConvertFrom-CSV #"
OwningProcess,LocalAddress
1177,127.0.0.1
1177,192.168.1.2
1177,192.168.1.1
2211,192.168.1.1
2211,127.0.0.1
3122,192.168.1.1
3122,192.168.1.1
"#
$OwningProcesses = #()
$flam | ForEach {
$id = If ($OwningProcesses -Contains $_.OwningProcess) {"222"} Else {$OwningProcesses += $_.OwningProcess; "111"}
$_ | Add-Member -Force id $id
}
Result:
PS C:\> $flam
OwningProcess LocalAddress id
------------- ------------ --
1177 127.0.0.1 111
1177 192.168.1.2 222
1177 192.168.1.1 222
2211 192.168.1.1 111
2211 127.0.0.1 222
3122 192.168.1.1 111
3122 192.168.1.1 222
Including this in the HTML file:
$CntTableBodyr=""
#$frcntArrr = $flam | select -ExpandProperty OwningProcess #$frcntr.GetEnumerator() |%{$_}
$flam | {
$CntTableBodyr+="<tr id='$($_.id)' style='background-color: lightblue;'><td>$($_.OwningProcess)</td><td>$($_.LocalAddress)</td></tr>"
}
$html=#"
<table id='tblId'>
$CntTableBodyr
</table>
"#
ConvertTo-Html -Body $html | Out-File c:\out.html
Related
I wrote a code for Azure subscription cost calculation based on two Tags (In this case Application tag and Owner tag), that are used in our environment.
$ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
$ApplicationTagLoop = #(Foreach ($ApplicationTag in $ApplicationTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate
(Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag}
$SumForApplicationTag = 0
$TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur"
$OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
ForEach ($OwnerTag in $OwnerTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -
EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
$SumForOwner = 0
$TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
ConvertTo-HTML -Body "Application tag: $ApplicationTag 'Owner: $OwnerTag Cost:
$([int]$SumForOwner) Eu." -Title "Cost of subscriptions" | Out-File c:\example.html
Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
}
})
Output of this PS code is:
Application tag is Testing. Sum for the tag is: 25 Eur
Owner is - john.johnson#contoso.com Sum for the owner is: 15 Eur
Owner is - tom.thompson#contoso.com Sum for the owner is: 10 Eur
Application tag is Testing 2. Sum for the tag is: 100 Eur
Owner is - jim.jameson#contoso.com Sum for the owner is: 40 Eur
Owner is - eve.evens#contoso.com Sum for the owner is: 40 Eur
Owner is - charles.mcgill#contoso.com Sum for the owner is: 20Eur
...and so on...
Now I need to stream this output to an HTML table somehow, I tried doing that with ConvertTo-HTML command but it keeps rewriting itself with the last output and does not populate the table in any way.
I also tried to make ForEach loops into arrays like so:
$ApplicationTagLoop = #(foreach ($i in $ApplicationTag)
And using that with Convert-To-HTML, but doing it this way $ApplicationTagLoop does not provide any results at all, so nothing is converted to HTML.
How could I rewrite the ConvertTo-HTML part so that every output of the loop would be saved into a new line of the HTML file?
Desired output format should be:
https://i.stack.imgur.com/z13SM.png
Viewing the code, i guess the expected oputput.
Use object collection build to get proper HTML :
$ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
$html = [System.Collections.ArrayList]#()
Foreach ($ApplicationTag in $ApplicationTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate
(Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag}
$SumForApplicationTag = 0
$TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur"
$OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
ForEach ($OwnerTag in $OwnerTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -
EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
$SumForOwner = 0
$TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
#ConvertTo-HTML -Body "Application tag: $ApplicationTag 'Owner: $OwnerTag Cost:
#$([int]$SumForOwner) Eu." -Title "Cost of subscriptions" | Out-File c:\example.html
$html.Add((Select-Object #{n='Application tag';e={$ApplicationTag}},#{n='Owner';e={$OwnerTag}},#{n='Cost';e={[string]$([int]$SumForOwner)+" Eu."}} -InputObject ''))
Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
}
}; $html | ConvertTo-Html -As Table -Title "Cost of subscriptions" | Out-File c:\example.html
Which should render the following HTML :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Cost of subscriptions</title>
</head><body>
<table>
<colgroup><col/><col/><col/></colgroup>
<tr><th>Application tag</th><th>Owner</th><th>Cost</th></tr>
<tr><td>Testing</td><td>john.johnson#contoso.com</td><td>15 Eu</td></tr>
<tr><td>Testing</td><td>tom.thompson#contoso.com</td><td>10 Eu</td></tr>
<tr><td>Testing 2</td><td>jim.jameson#contoso.com</td><td>40 Eu</td></tr>
<tr><td>Testing 2</td><td>eve.evens#contoso.com</td><td>40 Eu</td></tr>
<tr><td>Testing 2</td><td>charles.mcgill#contoso.com</td><td>20 Eu</td></tr>
</table>
</body></html>
Second edit as OP required a new formatted output, we're using a hash to break by application tag and format the output accordingly.
$ApplicationTags = ((Get-AzResource).Tags).Application | select -Unique
$html = [System.Collections.ArrayList]#()
$hash = #{}
Foreach ($ApplicationTag in $ApplicationTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -EndDate
(Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag}
$SumForApplicationTag = 0
$TotalCostPerApplicationTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerApplicationTag | ForEach {$SumForApplicationTag += $_}
Write-Host "Application tag is"$ApplicationTag". Sum for the tag is:" $([int]$SumForApplicationTag) "Eur"
$OwnerTags = ((Get-AzResource -TagValue $ApplicationTag).Tags).Owner | select -Unique
ForEach ($OwnerTag in $OwnerTags) {
$ConsumptionUsageDetail = (Get-AzConsumptionUsageDetail -StartDate (Get-Date).addmonths(-1) -
EndDate (Get-Date)) | Where-Object {$_.Tags -ne $null} | Where-Object {$_.Tags['Application'] -eq
$ApplicationTag} | Where-Object {$_.Tags['Owner'] -eq $OwnerTag}
$SumForOwner = 0
$TotalCostPerOwnerTag = $ConsumptionUsageDetail.PretaxCost
$TotalCostPerOwnerTag | Foreach {$sumforowner += $_}
# We use the hash to check for break by ApplicationTag
if (!$hash[ApplicationTag]) {
$hash[$ApplicationTag]=$True
$html.Add((Select-Object #{n="Application tag";e={$ApplicationTag}},#{n="Owner";e={""}},#{n="Cost";e={[string]$([int]$SumForApplicationTag)+" Eu."}} -InputObject ''))
}
# Adding the owners
$html.Add((Select-Object #{n="Application tag";e={""}},#{n='Owner';e={$OwnerTag}},#{n='Cost';e={[string]$([int]$SumForOwner)+" Eu."}} -InputObject ''))
Write-Host Owner is - $OwnerTag" Sum for the owner is:" $([int]$SumForOwner) "Eur"
}
}; $html | ConvertTo-Html -As Table -Title "Cost of subscriptions" | Out-File c:\example.html
Which should render the following HTML :
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Cost of subscriptions</title>
</head><body>
<table>
<colgroup><col/><col/><col/></colgroup>
<tr><th>ApplicationTag</th><th>Owner</th><th>Cost</th></tr>
<tr><td>Testing</td><td></td><td>25 Eu</td></tr>
<tr><td></td><td>john.johnson#contoso.com</td><td>15 Eu</td></tr>
<tr><td></td><td>tom.thompson#contoso.com</td><td>10 Eu</td></tr>
<tr><td>Testing 2</td><td></td><td>100 Eu</td></tr>
<tr><td></td><td>jim.jameson#contoso.com</td><td>40 Eu</td></tr>
<tr><td></td><td>eve.evens#contoso.com</td><td>40 Eu</td></tr>
<tr><td></td><td>charles.mcgill#contoso.com</td><td>20 Eu</td></tr>
</table>
</body></html>
Wich should render as :
I am trying to retrieve the running applications, the computers' username and its IP address. Now, every time that the results are saved on the text file, the IP address part would always give me this result:
"Length"
"11"
Is there any way to get the IP address?
$savepath = "C:\Users\$([Environment]::UserName)\Desktop\apps\runningapps.txt"
Get-Process | where {$_.mainwindowtitle.length -ne 0} |
select name, mainwindowtitle| ConvertTo-Csv -NoType |
Set-Content $savepath
Get-WmiObject -Class Win32_ComputerSystem | select username |
ConvertTo-Csv -NoType | Add-Content $savepath
Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" } | ConvertTo-Csv -NoType | Add-Content $savepath
The IP addresses are a list of strings, so you can write them directly to the output file if you want them one address per line:
Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" } | Add-Content $savepath
If you want the addresses as a comma separated list in one line you need to join them first:
(Get-WmiObject Win32_NetworkAdapterConfiguration |
Where { $_.IPAddress } |
Select -Expand IPAddress |
Where { $_ -notlike "*:*" }) -join ',' | Add-Content $savepath
ConvertTo-Csv won't help you here, because it takes an object as input and outputs a comma-separated list of the object's properties. If your input objects are strings (which have only the property Length) then the output becomes a list of the lengths of the input strings.
As a side note: a simpler way of building the output file path is to use the USERPROFILE environment variable:
$savepath = "$env:USERPROFILE\Desktop\apps\runningapps.txt"
I am trying to replace null values in a certain column to 0 using PowerShell.
I have the CSV in this format:
test test2 test3 test4
---- ----- ----- -----
blah fsds 4 45645
bla1 fsds1 45645
blah2 fsds2 4 34322
blah3 fsds3 4 67544
blah4 fsds4 3432432
so I want to go through the null values in "test3" and replace to 0.
I have this, but it doesn't work:
$inFilePath = "G:\powershell\excel\test.csv"
$csvColumnNames = (Get-Content $inFilePath | Select-Object -First 1).Split(",")
foreach ($row in $inFilePath) {
if ($row.test3 -eq $null) {
$row.test3 = 0
Write-Host "updating value in excel"
}
}
$csvColumnNames | Export-Csv "G:\powershell\excel\replaced2.csv" -NoTypeInformation
you are on the right track with foreach and if.Try this:
foreach($row in $inFilePath)
{
if (-not $row.test3)
{
$row.test3= 0
}
}
to get the column headers:
$inFilePath | Get-Member -MemberType NoteProperty | Select-Object -ExpandProperty Name
Use Import-Csv for reading and Export-Csv for writing CSV files.
$inFilePath = "G:\powershell\excel\test.csv"
$outFilePath = "G:\powershell\excel\replaced2.csv"
Import-Csv $inFilePath | % {
if (-not $_.test3) { $_.test3 = 0 }
$_ # echo all records, so they can be exported back to a file
} | Export-Csv $outFilePath -NoType
Powershell Script to Delete Blank Columns from CSV
I have a spread sheet which I'm importing into a MySQL database, the import fails because of blank columns in the spread sheet.
Is there a powershell script I can run / create that will check any given CSV file and remove blank columns?
Col1,Col2,Col3,Col4,,,,
Val1,Val2,Val3,Val4
How about something like this:
$x = Import-Csv YourFile.csv
$f = $x[0] | Get-Member -MemberType NoteProperty | Select name
$f | Add-Member -Name count -Type NoteProperty -Value 0
$f | %{
$n = $_.Name
$_.Count = #($x | Select $n -ExpandProperty $n | ? {$_ -ne ''}).count
}
$f = #($f | ? {$_.count -gt 0} | Select Name -expandproperty Name)
$x | Select $f | Export-Csv NewFile.csv -NoTypeInformation
It uses Get-Member to get the column names, cycles though each one to check how many are not blank and then uses the results in a select.
When I run Dave Sexton's code, I get:
Select-Object : Cannot convert System.Management.Automation.PSObject to one of the following
types {System.String, System.Management.Automation.ScriptBlock}.
At line:15 char:12
+ $x | Select <<<< $f | Export-Csv ColsRem.test.$time.csv -NoTypeInformation
+ CategoryInfo : InvalidArgument: (:) [Select-Object], NotSupportedException
+ FullyQualifiedErrorId :
DictionaryKeyUnknownType,Microsoft.PowerShell.Commands.SelectObjectCommand
I corrected this issue by adding one more line, to force each array element to be a string.
$x = Import-Csv YourFile.csv
$f = $x[0] | Get-Member -MemberType NoteProperty | Select name
$f | Add-Member -Name count -Type NoteProperty -Value 0
$f | %{
$n = $_.Name
$_.Count = #($x | Select $n -ExpandProperty $n | ? {$_ -ne ''}).count
}
$f = #($f | ? {$_.count -gt 0} | Select Name -expandproperty Name)
# I could get the select to work with strings separated by commas, but the array would
# always produce the error until I added the following line, explicitly changing the
#values to strings.
$f = $f | Foreach-Object { "$_" }
$x | Select $f | Export-Csv NewFile.csv -NoTypeInformation
My import CSV contains a few hundred columns and about half likely won't be populated, so getting rid of the extra columns was necessary. Now I just need to figure out how to counteract the unintended re-ordering of the columns into alphabetical order by name, without changing the names.
In my script I've collected all the data I want to report in different variables. Now I'm trying to generate an HTML-table so I can send this by mail.
What I would like to achieve is HTML-code that generates this:
OU | Logon scripts incorrect | Name incorrect | No description
\\Domain\NLD Users | 2 | 6 | 2
\\Domain\FRA users | 5 | 7 | 0
\\Domain\BEL users | 6 | 1 | 1
TOTAL USERS: 2048 | 13 | 14 | 3
I'm a bit confused on what would be the best approach for this (array, psobject, hashtable, ..). Because I'm not going to work with a foreach loop, the data would be static.
What I tried so far but isn't quite giving the desired result:
$Table = #( ('OU', 'Logon scripts incorrect', 'Name incorrect', 'No description'),
('\\Domain\NLD Users','2','6','2' ),
('\\Domain\FRA Users','5','7','0' ),
('\\Domain\BEL Users','6','1','1' ),
('TOTAL USERS: 2048','13','14','3' )
)
$Table | ConvertTo-Html -As Table -Fragment
It feels like I'm over-complicating things.
convertto-html is waiting for a psobject as its input.
What you can do is pass your data as csv then use convertfrom-csv to tansform it to psobject the run convertto-html :
$Table = #"
'\\Domain\NLD Users','2','6','2'
'\\Domain\FRA Users','5','7','0'
"#
$Table | ConvertFrom-Csv -Header 'OU', 'Logon scripts incorrect', 'Name incorrect', 'No description' | ConvertTo-Html -Fragment -As Table
#( ('OU', 'Logon scripts incorrect', 'Name incorrect', 'No description'),
('\\Domain\NLD Users','2','6','2' ),
('\\Domain\FRA Users','5','7','0' ),
('\\Domain\BEL Users','6','1','1' ),
('TOTAL USERS: 2048','13','14','3' )
) | Select-Object -Skip 1 | ForEach-Object{
[PSCustomObject]#{
OU = $_[0]
"Logon scripts incorrect" = $_[1]
"Name incorrect" = $_[2]
"No Description" = $_[3]
}
} | ConvertTo-Html -As Table -Fragment
From what i have read ConvertTo-Html takes .Net Objects and not arrays to convert to html. I converted your static table to a custom object which then was exported. This might look more to your liking.
You're creating an array of arrays with your statement, which looks neat, but isn't something ConvertTo-Html can handle. Create new objects instead (this is for v3):
$x = #(
([pscustomobject] #{
"OU" = "\\Domain\NLD Users";
"Logon scripts incorrect" = 2;
"Name incorrect" = 6;
"No description" = 2;
}),
([pscustomobject] #{
"OU" = "\\Domain\FRA Users";
"Logon scripts incorrect" = 5;
"Name incorrect" = 7;
"No description" = 0;
})
# ...and so on, or more realistically, constructed using Foreach-Object
)
$x | convertto-html -fragment
If you're confined to PowerShell v2, you can use new-object -type psobject -prop instead, but then the properties are not ordered so you will need an explicit Select.