Converting Process List to HTML Shows Only Single Process - windows

I have an PowerShell script which contains two variables:
$d: Array: Get TCP Connection, Just (ID) of each Process.
$gns: get name of each process in variable $d.
$d = #(Get-NetTCPConnection | Select -Expand OwningProcess)
foreach ($s in $d) {
$gns = Get-Process | Where-Object {$_.Id -eq $s} | Select -Expand Name
}
ConvertTo-HTML -PostContent $gns | Out-File c:\temp\TableHTML.html
Invoke-Item c:\temp\TableHTML.html
Result:
As you can see, the result shows just one process name, which is wrong!
I want to show all process names in the result.

Related

How to select the file with the maximum number of the specified file

I want to keep only the file with the largest version of the specified zip file in the folder using powershell. I wrote a shell script but it returns all the files. How can I modify the script to select only the file with the largest version?
$files = Get-ChildItem -Filter "*.zip"
$max = $files |Measure-Object -Maximum| ForEach-Object {[int]($_.Split("_")[-1].Split(".")[0])}
$largestFiles = $files | Where-Object {[int]($_.Split("_")[-1].Split(".")[0]) -eq $max}
Write-Output $largestFiles
Expectation:
A1_Fantasic_World_20.zip
A1_Fantasic_World_21.zip
B1_Mythical_Realms_11.zip
B1_Mythical_Realms_12.zip
C1_Eternal_Frame_Corporation_2.zip
C1_Eternal_Frame_Corporation_3.zip
↓
A1_Fantasic_World_21.zip
B1_Mythical_Realms_12.zip
C1_Eternal_Frame_Corporation_3.zip
A1_Fantasic_World's biggest number is 21.B1_Mythical_Realms's is 12.C1_Eternal_Frame_Corporation's is 3. So I want to choose the biggest version of zip.
First you add the calculated properties to your file system objects you use for filtering. Then with a combination of Group-Object, Sort-Object and Select.Object you can filter the desired files.
$FileList =
Get-ChildItem -Filter *.zip |
Select-Object -Property *,
#{
Name = 'Title'
Expression = {($_.BaseName -split '_')[0..$(($_.BaseName -split '_').count - 2)] -join '_' }
},
#{
Name = 'Counter'
Expression = {[INT]($_.BaseName -split '_')[-1]}
}
$LastOnesList =
$FileList |
Group-Object -Property Title |
ForEach-Object {
$_.Group | Sort-Object -Property Counter | Select-Object -Last 1
}
$LastOnesList |
Select-Object -Property Name

CSV comparison of Windows Services

I'm fairly new to Powershell and I'm stuck with this portion of a much larger script. I need to pull all Windows Services and compare them to see if their Startup Type of Status has changed. If there were any changes, I need to count them so I can put that value in the body of an e-mail. Also, I need to attach an HTML report showing the previous and current state of the Windows services that changed.
What I've done is the following:
That piece of code generates a CSV file showing the current state of the services.
Get-Service | Select-Object -Property Name,DisplayName,StartType,ServiceType,Status | Export-Csv -Path "C:\logs\after.csv"
Then i declare two variables, one for the current state, another one for the "template", the desired state of all Windows Services.
$before = Import-Csv -Path "C:\logs\before.csv"
$after = Import-Csv -Path "C:\logs\after.csv"
Then, i compare both of them, parsing only those service that've changed and generate a CSS styled HTML report based on that
Compare-Object $before $after -Property Name,DisplayName,StartType,ServiceType,Status | ConvertTo-html -Head $css | Set-Content "C:\logs\comparison.html"
This is what i get:
This is what it should look like:
Basically, i want to show the status of the latter CSV report in a new column after the Status column of the original CSV report. And I would also like to make a row count after that, so I can send an e-mail reporting HOW MANY services suffered any changes.
Any help will be deeply appreciated.
You could use Group-Object after Compare-Object and parse out the columns you need from that.
$before = Import-Csv -Path "C:\logs\before.csv"
$after = Import-Csv -Path "C:\logs\after.csv"
# find the differences in the StartType and Status columns. Use -PassThru to be able to process further
$groups = Compare-Object -DifferenceObject $before -ReferenceObject $after -Property StartType, Status -PassThru |
Sort-Object Name | Group-Object Name
$result = foreach ($group in $groups) {
$refGroup = $after | Where-Object { $_.Name -eq $group.Name }
# output an object with new StartType_* and Status_* columns and capture that in variable $result
$group.Group[0] |
Select-Object *, #{Name = 'StartType_Before'; Expression = {$_.StartType}},
#{Name = 'StartType_After'; Expression = {$refGroup.StartType}},
#{Name = 'Status_Before'; Expression = {$_.Status}},
#{Name = 'Status_After'; Expression = {$refGroup.Status}} -ExcludeProperty StartType,Status, SideIndicator
}
# now convert the $result to HTML and add a summary line with the number of services that have changed
$result | ConvertTo-Html -Head $css -PostContent "<br />Services affected: $($result.Count)" |
Set-Content "C:\logs\comparison.html"
If you also want output in the console do:
$result | Format-Table -AutoSize
Of course it is also possible to not use Compare-Object and do like below (will be slower, but easier to understand I guess):
$before = Import-Csv -Path "C:\logs\before.csv"
$after = Import-Csv -Path "C:\logs\after.csv"
$result = foreach ($item in $before) {
$diff = $after | Where-Object { $_.Name -eq $item.Name -and
($_.StartType -ne $item.StartType -or $_.Status -ne $item.Status) }
if ($diff) {
$item | Select-Object *, #{Name = 'StartType_Before'; Expression = {$item.StartType}},
#{Name = 'StartType_After'; Expression = {$diff.StartType}},
#{Name = 'Status_Before'; Expression = {$item.Status}},
#{Name = 'Status_After'; Expression = {$diff.Status}} -ExcludeProperty StartType,Status
}
}
# output to console
$result | Format-Table -AutoSize
# convert to HTML
$result | ConvertTo-Html -Head $css -PostContent "<br />Services affected: $($result.Count)" |
Set-Content "C:\logs\comparison.html"
Output on screen will look something like
Name DisplayName ServiceType StartType_Before StartType_After Status_Before Status_After
---- ----------- ----------- ---------------- --------------- ------------- ------------
AarSvc_8246b1 Agent Activation Runtime_8246b1 224 Manual Automatic Stopped Stopped
AdobeARMservice Adobe Acrobat Update Service Win32OwnProcess Automatic Automatic Running Stopped
ALG Application Layer Gateway Service Win32OwnProcess Manual Automatic Stopped Stopped
WdNisSvc Microsoft Defender Antivirus Network Inspection Service Win32OwnProcess Manual Manual Running Stopped

PS - Get All SMB shares with permissions

I'm trying to get all smb shares on my windows server with all user permissions on them for inventory check.
This is what i have:
$Shares = Get-SmbShare
foreach($Share in $Shares)
{
Get-SmbShareAccess -Name $Share.Name | Where-Object {$_.AccountName -Match "DOMAINNAME"}
}
Which gets me all domain users with their shares and which access they have.
But it only shows name of folder. I would like its gonna show full path on the server (Not UNC)
And it would be exportable in csv format.
When i do:
$Shares = Get-SmbShare
foreach($Share in $Shares)
{
Get-SmbShareAccess -Name $Share.Name | Where-Object {$_.AccountName -Match "PRAGUELOFTS"} | Export-Csv -Path C:\perms.csv
}
It only exports the last user.
You can define your output columns very precisely when you pass to Select-Object an array of hashes in this format: #{name="xyz"; expr={ calculated value }}.
This way you can unify values from multiple sources, such as "share" and "share access", and manually calculated values, into one custom result.
Get-SmbShare | Where-Object Special -eq $false | ForEach-Object {
$share = $_
$share | Get-SmbShareAccess | Where-Object AccountName -Match "DOMAINNAME" | Select-Object #(
#{name="UncPath"; expr={ "\\" + $env:COMPUTERNAME + "\" + $share.Name }}
#{name="LocalPath"; expr={ $share.Path }}
#{name="Account"; expr={ $_.AccountName }}
#{name="Type"; expr={ $_.AccessControlType }}
#{name="Right"; expr={ $_.AccessRight }}
)
}
You can then go on and pipe this into Export-Csv -Path C:\perms.csv.
As for your second question - this
foreach ($Share in $Shares)
{
Get-SmbShareAccess -Name $Share.Name | Export-Csv -Path C:\perms.csv
}
only gives you the last result in the CSV file because it literally says "for each share, write a CSV file". You keep overwriting the same file in every loop iteration.
Collect all the results into a variable first
$results = foreach ($Share in $Shares) {
# ...
}
and then create the output file
$results | Export-Csv -Path C:\perms.csv

powershellv2 - how to sort a list after splitting the string

I have a file containing a list of email addresses:
e.g.
personB#placeB.com
nameA#location2.com
nameB#location2.com
I want to order them, but by the domain, and then by the local, and then output the ordered list. so I end up with:
nameA#location2.com
nameB#location2.com
personB#placeB.com
I can use sort-object to order them, but this is by the whole string.
So far I have got this far:
SELECT-STRING -path path_To_My_File |
FOREACH{
$a = $_.split"(#)"
$local = $a[0]
$domain = $a[1]
}
but can't see how to incorporate the sort-object.
Similar to Matt's answer, but will give you the sorted email addresses as a list:
$addresses = #()
Get-Content .\path\to\file | % {
$n = $($_ -split '#')[0]
$d = $($_ -split '#')[1]
$o = New-Object PSObject -property #{name=$n;domain=$d;email=$_}
$addresses += ,$o
}
$addresses | sort domain,name | select -ExpandProperty email
The $addresses array can be sorted by the object you created on the fly in the Foreach-Object or % loop, and then you can just select the email property to give you the sorted list
Sort-Object obviously needs an object to sort on. So we can create an object like this. ( There are other ways as well). Also we dont need to use select-string since you are applying no patterns
Get-Content -path "path_To_My_File" |
Select-Object #{Name="Local";Expression={($_.split("#"))[0]}},#{Name="Domain";Expression={($_.split("#"))[1]}} |
Sort-Object domain,local
Create properties using Select-Object for Local and Domain using the same split that you had. The select on its own would output this:
Local Domain
----- ------
personB placeB.com
nameA location2.com
nameB location2.com
Then we can sort to get this:
Local Domain
----- ------
nameA location2.com
nameB location2.com
personB placeB.com
If you need the full address as well we can shorten the code and add that variable.
Get-Content -path "path_To_My_File" |
Select #{N="Address";E={$_}},
#{N="Local";E={($_.split("#"))[0]}},
#{N="Domain";E={($_.split("#"))[1]}} |
Sort domain,local

How to sort the output in powershell

I am trying to list the content of a directory and try to sort them out the most recently created folders of file. I am using the following script but it is only giving me 1 item which is most recently created. All I would like to do is list all the folders in asc or desc order
$content = get-childitem 'C:\Users\tim\Desktop\tim_test'
write-output $content | Sort-Object LastWriteTime -Descending | Select-Object -First 1
Your "Select-Object -First 1" gives you only the first file, to get all files, remove that. Like so:
$newPath = 'C:\Users\tim\Desktop\tim_test2'
$content = get-childitem 'C:\Users\tim\Desktop\tim_test' | Sort-Object LastWriteTime -Descending
Write-Host $content
# Part 2
$oldFile = $content | Select-Object -first 1
$prefix = Read-Host "Enter prefix"
$newFile = "$newPath\$prefix$oldFile"
Copy $file $newFile
Something like that should work :)

Resources