Output running services to csv with computer name - powershell

I need to generate a csv containing running services to csv with the corresponding computer name
I know there is a simple way to do this and I have been tinkering with creating a new psobject, but I am not sure how to pipe the results to the new-object...
Here is what I am using:
$Input = "SomePath"
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "$Input"
ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Export-csv -Path "$Output"
}
What I need in the CSV is:
ComputerName, ServiceName, DisplayName
basically, I need to add the computer name to the array.

If you want to be able to pipe the results, use a foreach-object.
$Output = "SomeOtherPath"
Get-Content -Path "SomePath" | ForEach-Object {
Get-Service -ComputerName $_ | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName
} | Export-csv -Path "$Output"
If you want to stick to a foreach statement, collect it all first then export it.
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "SomePath"
$results = ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName
}
$results | Export-csv -Path "$Output"

Try like this (Don't use $Input as variable name)
$InputX = "SomePath"
$Output = "SomeOtherPath"
$CompNames = Get-Content -Path "$Input"
ForEach ($CompName in $CompNames){
Get-Service -ComputerName $CompName | Where-Object {$_.Status -eq "Running"} | Select-Object ComputerName, ServiceName, DisplayName | Export-csv -Path "$Output"
}

Related

Filter file "yyyy-MM-dd_HH-mm-ss_Computername_Username_File.json" by Computername/Username

I have a folder containing text-files with a standardized naming-scheme like:
2021-03-16_21-25-55_Client1_Edward.Hall_ServerResponse.json
2021-03-16_21-25-33_Client2_Eloise.Glover_ServerResponse.json
2021-03-16_21-17-38_Client3_Millie.Walsh_ServerResponse.json
2021-03-16_21-17-30_Client4_Lilly.Morton_ServerResponse.json
2021-03-16_21-15-45_Client5_Tia.Curtis_ServerResponse.json
2021-03-16_21-15-23_Client1_Edward.Hall_ServerResponse.json
2021-03-16_21-15-10_Client1_Lilly.Morton_ServerResponse.json
2021-03-16_21-15-03_Client2_Eloise.Glover_ServerResponse.json
2021-03-16_21-12-14_Client2_Eloise.Glover_ServerResponse.json
2021-03-16_21-11-25_Client3_Administrator_ServerResponse.json
I want to filter the files and retrieve the latest file (LastWriteTime) of a specific Computername-/Username-combination. Therefore I want to use a code like this:
# $env:COMPUTERNAME = "Client1"
# $env:USERNAME = "Edward.Hall"
$MyFolder = "C:\MyFolder"
Get-ChildItem -Path $MyFolder -File -ErrorAction SilentlyContinue | Where-Object {
$_.Extension -eq ".json" -and $_.COMPUTERNAME -eq $env:COMPUTERNAME -and $_.USERNAME -eq $env:USERNAME
} | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1
Of course the part -and $_.COMPUTERNAME -eq $env:COMPUTERNAME -and $_.USERNAME -eq $env:USERNAME is NOT working and should only show up the direction to what I imagine.
In the example above the result should be the file "2021-03-16_21-25-55_Client1_Edward.Hall_ServerResponse.json".
I was thinking of using -match, but it should be a exact match -eq.
Could you please help me to find a solution for this?
Thank you very much!
As long as you can count on the name format always conforming to that standard you can just split up the name strings for your required sections:
# $env:COMPUTERNAME = "Client1"
# $env:USERNAME = "Edward.Hall"
$MyFolder = "C:\MyFolder"
Get-ChildItem -Path $MyFolder -File -ErrorAction SilentlyContinue | Where-Object {
($_.Extension -eq ".json") -and ($_.Name.Split('_')[2] -eq $env:COMPUTERNAME) -and ($_.Name.Split('_')[3] -match $env:USERNAME)
} | Sort-Object -Descending -Property LastWriteTime | Select-Object -First 1

Getting effective user Permissions for many directories

Usually $Plist would be an array but for example we take just one directory.
My problem is I can't use the $ids var. Somehow I cant read out the data and can't bypass it to:
Get-ADGroup -Identity $id -Properties member | Select-Object -ExpandProperty member
I need the usernames per directory with their group names.
Like : Path GroupName UserList
Can someone help? Maybe tweak my code or make something similar :)
$plist = "\\Server\Share"
$FList = foreach($dir in $Plist)
{
Resolve-Path -Path $dir
Get-Acl -Path $dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Select-Object IdentityReference
Get-Item $dir | select FullName
}
$Flist | ft FullName, IdentityReference
$identity = $Flist.IdentityReference | out-string
$ids = foreach($ident in $identity)
{
$ident = $ident.Replace("Domain\","")
$ident
}
foreach($id in $ids)
{
$id
Get-ADGroup -Identity $id -Properties member | Select-Object -ExpandProperty member
}
Do not use ft (Format-Table) or Out-String on values that you may ned later in your script.
$ids = foreach($ident in $Flist.IdentityReference){
"$ident".Replace('Domain\','')
}
You could also strip the domain prefix from all the user names in one go with the -replace operator:
foreach($id in $flist.IdentityReference.Value -replace 'Domain\\')
{
Get-ADGroup $id -Properties member | Select-Object -ExpandProperty member
}
The Final Script is this, for people who might need something similar. So you can read out the effective permissions and show the group member of permission granted groups.
$ErrorActionPreference = "SilentlyContinue"
$Path = "\\Server\Share\Logs\"
$Log = $Path + "Effective_Permissions" + ".log"
$PPath = Read-Host "Enter Path to scan"
$plist = Get-Childitem -Path $PPath -Recurse | ?{ $_.PSIsContainer } | Select-Object FullName
foreach($Dir in $PList)
{
$Dir = $Dir -replace "#{FullName=", "" -replace "}"
Resolve-Path -Path $Dir
Write-Output "`n" | Out-File $log -append
Write-Output "#######################################################################" | Out-File $Log -append
Get-Item $Dir | select FullName | Out-File $Log -append
$AclList = Get-Acl -Path $Dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Select-Object IdentityReference
Get-Acl -Path $dir -Filter Access | Select-Object -ExpandProperty Access | Where-Object {$_.IdentityReference -like "Domain\*"} | Out-File $Log -append
foreach($Id in $AclList.IdentityReference.Value -replace 'Domain\\')
{
$ADGroup = Get-ADGroup $Id -Properties member | Select-Object -ExpandProperty member
Write-Output "`n" | Out-File $Log -append
Write-Output "Member of $Id `n
---------------------------------" | Out-File $Log -append
foreach ($Object in $ADGroup)
{
$Group = Get-ADUser -filter * -SearchBase "$Object"
if($Group -ne $null)
{
$GrName = $Group.Name
Write-Output "$GrName" | Out-File $Log -append
}
}
}
Clear-Variable Object, Group, ADGroup, ACLList, GRName, Id
}

Copy result from powershell to another file

I made query:
gwmi Win32_networkadapterconfiguration | Where-Object {$_.ipaddress -like "*192.168.3*"} | Select-Object -Property SettingID | Format-Wide
As a result, I get for example:
{CD4FCC20-30E3-4E2E-8F8A-556833287B3C}
How to copy the string {CD4FCC20-30E3-4E2E-8F8A-556833287B3C} to an existing file in piece "\Device\" between \ and "
Solved:
$adapter = gwmi Win32_networkadapterconfiguration | Where-Object {$_.ipaddress -like "192.168.3"} | Select-Object -expandProperty SettingID
$path = "c:\ProgramData\Triangle MicroWorks\IEC 61850 Suite\Hammer\Hammer_Clients.cnfg"
$word = "{}"
$replacement = "$adapter"
$text = get-content $path
$newText = $text -replace $word,$replacement
$newText > $path

Cannot bind argument to parameter "FilePath" because it is null

Every time I run the script below I get
Cannot bind argument to parameter 'FilePath' because it is null.
It was working last night. No changes have been made and this morning it just fails. the funny thing is if i save the script and then run it, it works. However if I clear console then run it again it fails.
Am I missing something obvious?
New-Item -ItemType Directory -Force -Path C:\NonStandard_Services
set-location C:\NonStandard_Services
$Computers= Get-Content C:\computers.txt
$Report= $file
$file= $Computer
ForEach ($Computer in $Computers)
{
Get-WmiObject -ComputerName $Computer -class Win32_Service -ErrorAction SilentlyContinue |
Where-Object -FilterScript {$_.StartName -ne "LocalSystem"}|
Where-Object -FilterScript {$_.StartName -ne "NT AUTHORITY\NetworkService"} |
Where-Object -FilterScript {$_.StartName -ne "NT AUTHORITY\LocalService"} |
Select-Object -Property StartName,Name,DisplayName|
ConvertTo-Html -Property StartName,Name,DisplayName -head $HTML -body "<H2>Non- Standard Service Accounts on $Computer</H2>"| Out-File $Report -Append}
#Rename-Item c:\GP_Services\Report.htm $file
Get-ChildItem | Where-Object {$_.extension -ne ".htm"} | Rename-Item -newname { $_.name + '.htm' }
$Report= $file
$file= $Computer
ForEach ($Computer in $Computers)
{
...
}
You assign variables to other variables before they were assigned a value themselves. Change the above to this:
ForEach ($Computer in $Computers) {
$file = $Computer
$Report = $file
...
}
Or directly use $Computer in Out-File:
... | Out-File "$Computer.txt" -Append

Get group member names from Get-Acl and Append to CSV

I need to extract all the members of a group and then format that into Names, so I only get the Full Names like "Don Joe" is member of my-domain\UNCShareDrive
I need that to appear in my CSV after I have exported the ACL lists.
As an example:
Path FileSystemRights AccessControlType IdentityReference
---- ---------------- ----------------- -----------------
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\DK FullControl Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow BUILTIN\Administratorer
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow MY-DOMAIN\Drev Management
Microsoft.PowerShell.Core\FileSystem::\\fileshare\management\ FullControl Allow BUILTIN\Administratorer
**These persons has access to the drive:**
**Finding group: MY-DOMAIN\Administrators**
Name SamAccountName Mail
---- -------------- ----
Administrator Administrator Administrator#my-domain.dk
This is what I have so far done in Powershell:
$Searching = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local"
$mypath = "U:\mytest.csv"
if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
Remove-Item $mypath -Force
}
$ShareName = "\\\sharename\D$"
$shares = Get-Childitem -path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference |
export-csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
$foldertotal = 0
Add-Content $mypath ""
Add-Content $mypath ""
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath ""
Add-Content $mypath ""
$myLoop = ''
foreach ($testLoop in $myLoop) {
$Group = Get-ADGroup -Filter * -SearchBase "DC=my-domain,DC=local" -Properties IdentityReference |
Select-Object Name # Need only groups in $Shares - who are displayed
$myLoop += Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
$myLoop += ForEach ($Group in $share) {
Get-ADGroupMember -identity $($Group.name) -recursive |
Get-ADUser -Properties Name,SamAccountName,Mail |
Select-Object Name,SamAccountName,Mail
}
$testLoop | Out-File -filePath $mypath -append -encoding utf8
}
Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"
I have also a hard time to filter out only the share path:
$shares.Replace('Microsoft.PowerShell.Core\FileSystem::', ' ') |
Out-File -filePath $mypath -append -encoding utf8
How come that this thing Works when I use User Input and not just automatically loop through it without the console prompt:
$Searching = Get-ADGroup -Filter * -SearchBase "DC=MY-DOMAIN,DC=local"
$mypath = "U:\mytest.csv"
$networkPath = "\\ShareName\D$"
$acl = Get-acl -path $networkPath
if((Test-Path -Path "U:\mytest.csv" -pathtype Container) -eq $True){
Write-Host -ForegroundColor red "We found a file: $mypath --> REMOVING!`r`n"
Remove-Item $mypath -Force
}
Write-Host -ForegroundColor Yellow "Eksempel på share: "`r`n\\ShareName\D$`r`n\\ShareTwo\\E$`r`n\\ShareName\management`r`n""
$ShareName = Read-host "Hvilket sharenavn vil du finde Access Control List fra?"
if($ShareName -eq "1"){
$Sharename = "\\ShareName\D$"
}
if($ShareName -eq "2"){
$Sharename = "\\ShareTwo\\E$"
}
if($ShareName -eq "3"){
$Sharename = "\\ShareName\management"
}
Get-Childitem -path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference |
FT -AutoSize |
Out-File -Encoding utf8 $mypath
Add-Content $mypath ""
Add-Content $mypath ""
Add-Content $mypath "Disse personer har adgang til share navnet"
Add-Content $mypath ""
$users = get-aduser -Filter {Name -Like "*"} -Searchbase "dc=MY-DOMAIN,dc=local" -Properties MemberOf |
Where-Object { $_.Enabled -eq 'True' }
Write-Host -ForegroundColor red "Example: Drev Management`r`n"
$myGroups = Read-Host "Hvilken Gruppe vil du bruge?"
if($myGroups -eq "1"){
$myGroups = " Drev Management"
}
$Groups = Get-ADGroup -filter {Name -like $myGroups} | Select-Object Name
Add-Content $mypath "Finding group: $($group.name)"
Write-Host -ForegroundColor Yellow "Finding group: $($Group.name).....`n"
Add-Content -Path $mypath $result
ForEach ($Group in $Groups) {
Get-ADGroupMember -identity $($Group.name) -recursive |
Get-ADUser -Properties Name,SamAccountName,Mail |
Select-Object Name,SamAccountName,Mail |
FT -AutoSize |
Out-File -Append -encoding utf8 $mypath
}
Write-Host -ForegroundColor Cyan "$($Group.name) is now exported to: $mypath`n"
Your second code sample works, because it doesn't make the same mistakes as the first one.
$myLoop = ''
foreach ($testLoop in $myLoop) {
$Group = Get-ADGroup -Filter * ...
$myLoop += Write-Host ...
$myLoop += ForEach ($Group in $share) {
Get-ADGroupMember ...
}
$testLoop | Out-File -filePath $mypath -append -encoding utf8
}
You make $myLoop an empty string, then iterate over each element of $myLoop (one empty string), so you get a single loop cycle, no matter what you append to $myLoop inside the loop.
Instead of the group members you write the content of $testLoop (an empty string) to the output file.
You read AD groups into the variable $Group, and then overwrite its content when you use $Group as the loop variable in foreach ($Group in $share).
$share is emtpy, because it's never initialized anywhere. Even $shares is empty, because when you write the ACL information to the CSV, no output is left that could be assigned to the variable.
And as a side-note: you can't append Write-Host output to anything, because the cmdlet writes to the host process (i.e. the console), not a stream that could be captured or redirected.
You need to capture the ACL information in $shares before writing it to a file:
$shares = Get-Childitem -Path $ShareName |
Where-Object {$_.PSIsContainer} |
Get-ACL |
Select-Object Path -ExpandProperty Access |
Select Path, FileSystemRights,AccessControlType,IdentityReference
$shares | Export-Csv $mypath -Delimiter ';' -NoTypeInformation -Encoding UTF8
Then you can determine the members of the groups having access to shares like this:
$shares | Select-Object -Expand IdentityReference |
Select-Object -Expand Value |
ForEach-Object {
$name = $_ -replace '^DOMAIN\\' # <-- replace with actual domain name
Get-ADObject -Filter { Name -eq $name }
} |
Where-Object { $_.ObjectClass -eq 'group' } |
Get-ADGroupMember |
Get-ADUser -Properties * |
Select-Object Name, SamAccountName, Mail |
Out-File $mypath -Append -Encoding UTF8
Note that this will not resolve nested groups, and also won't distinguish between shares.
If you want to store both the group name and its members you need to add a loop to the pipeline:
$shares | Select-Object -Expand IdentityReference |
Select-Object -Expand Value |
ForEach-Object {
$name = $_ -replace '^DOMAIN\\' # <-- replace with actual domain name
Get-ADObject -Filter { Name -eq $name }
} |
Where-Object { $_.ObjectClass -eq 'group' } |
ForEach-Object {
$_
Get-ADGroupMember -Identity $_ |
Get-ADUser -Properties * |
Select-Object Name, SamAccountName, Mail
} |
Out-File $mypath -Append -Encoding UTF8