I have a Powershell script to find specific servers and their corresponding service accounts. If I modify the script to use a single server and a single service account, the results are what I expect. If I loop thru the servers and accounts, I receive the following error:
#################################################################
# Find Service Account(s) used to start Services on a Server(s) #
#################################################################
$accounts = (Get-Content C:\Users\location\Scripts\Service_Accounts.txt)
Remove-Item -path C:\Users\location\Scripts\ServiceAccountFnd.txt -force -erroraction silentlycontinue
Import-Module ActiveDirectory # Imports the Active Directory PowerShell module #
## Retrieves servers in the domain based on the search criteria ##
$servers=Get-ADComputer -Filter {Name -Like "namehere*"} -property *
## For Each Server, find the services running under the user specified in $account ##
ForEach ($server in $servers) {
Write-Host $server
ForEach ($account in $accounts) {
Write-Host $account
Get-WmiObject Win32_Service -ComputerName $server | Where-Object {$_.StartName -like "*$account*"} | Format-Table -HideTableHeaders -property #{n='ServerName';e={$_.__SERVER}}, StartName, Name -AutoSize | Out-File -FilePath C:\Users\location\Scripts\ServiceAccountFnd.txt -append -Width 150
}
}
Your $server variable does not only contain the hostname, but also all attributes of the AD computer object.
Try to change the ComputerName value to $server.name.
If that doesn't help: Can you confirm, that you used the very same computer in the loop as without the loop, as you described? I'd assume that you try to access another computer, which is not configured as expected.
Besided that, I'd recommend you to use Get-CimInstance rather than Get-WmiObject, as it doesn't use RPC, but WinRM by default. WinRM is more firewall friendly, secure and faster.
Related
I'm wanting to improve on my script to be able to accomplish the following:
Scan servers based on get-adcomputer on specific OUs.
Scan each server based on whatever drive letter it has.
Scan each server for log4j.
Export all results to a CSV that identifies the folder path, name of file, and the server that the file was found on.
I have been using the following code to start with:
$Servers = Get-ADComputer -Filter * -SearchBase "OU=..." | Select -ExpandProperty Name
foreach ($server in $Servers){
Invoke-Command -ComputerName $Server -ScriptBlock {
$Drives = (Get-PSDrive -PSProvider FileSystem).Root
foreach ($drive in $Drives){
Get-ChildItem -Path $drive -Force -Filter *log4j* -ErrorAction SilentlyContinue | '
foreach{
$Item = $_
$Type = $_.Extension
$Path = $_.FullName
$Folder = $_.PSIsContainer
$Age = $_.CreationTime
$Path | Select-Object `
#{n="Name";e={$Item}}, `
#{n="Created";e={$Age}},`
#{n="FilePath";e={$Path}},`
#{n="Extension";e={if($Folder){"Folder"}else{$Type}}}`
} | Export-Csv C:\Results.csv -NoType
}
}
I am having the following issues and would like to address them to learn.
How would I be able to get the CSV to appear the way I want, but have it collect the information and store it on my machine instead of having it on each local server?
I have noticed extreme performance issues on the remote hosts when running this. WinRM takes 100% of the processor while it is running. I have tried -Include first, then -Filter, but to no avail. How can this be improved so that at worst, it's solely my workstation that's eating the performance hit?
What exactly do the ` marks do?
I agree with #SantiagoSquarzon - that's going to be a performance hit.
Consider using writing a function to run Get-ChildItem recursively with the -MaxDepth parameter, including a Start-Sleep command to pause occasionally. Also, you may want to note this link
You'd also want to Export-CSV to a shared network drive to collect all the machines' results.
The backticks indicate a continuation of the line, like \ in bash.
Finally, consider using a Scheduled Task or start a powershell sub-process with a lowered process priority, maybe that will help?
Trying to get list of all machines in a Domain with a certain service
tried via all posts in here, helped per one machine, but if i use a text file with multiple machines, it failes
$computers = Get-Content c:\script\computers.txt
$service = "*crystal*"
foreach ($computer in $computers) {
$servicestatus = Get-Service -ComputerName $computer -Name $service
}
$Data = $servicestatus | Select-Object Name,Machinename | Format-Table -AutoSize
Write($Data) | Out-File c:\script\output.txt -Append
Expected list of machines with service in table, instead got error:
This operation might require other privileges
same script, but with a direct machine name, works like a charm.
Any clue what is wrong?
Why not use:
Invoke-Command -ComputerName $computers -ScriptBlock {Get-Service -Name *crystal*}
Eventually you may store the result from invoke into a variable and work with it.
The benefit of using Invoke-Command, insted of foreach is that Invoke works in parallel, while foreach is serial ...
Hope it helps!
Best regards,
Ivan
I am trying to collect a list of the viewers installed on a set of servers. I am trying to loop through that list and run a wmi query and store the results and export a table with with the wmi result and server name next to it.
I am running this on server 2012
$computers = Get-Content C:\computers.txt
$WMIQuery = foreach ($computer in $computers){Get-WmiObject -Class
Win32_Product | where-object {$_.name -match "Microsoft Viewer*"}}
$WMIQuery
$WMIQuery | Out-File c:\Viewers.txt
Desired Results
Server Name Object1 Object2
Server1 Microsoft Excel Viewer Microsoft Visio Viewer
I output the file and get a blank txt file.
foreach ($computer in (Get-Content -Path "C:\computers.txt")) {
Get-WMIObject -ComputerName $computer -Class Win32_Product |
Where-Object {$_.name -match "Microsoft Viewer" } |
Out-File -Append -Path "C:\viewers.txt"
}
Your original code wasn't identifying the computer to perform Get-WMIObject against, so it was looking at only the computer that you were running the script on.
If there are many products on the remote computer, you may want to consider filtering on the remote computer instead of locally, so as to avoid transferring large amounts of data over what may be a slower-than-ideal network:
foreach ($computer in (Get-Content -Path "C:\computers.txt")) {
Get-WMIObject -ComputerName $computer -Class Win32_Product -Filter "Name LIKE '*Microsoft Viewer*'"|
Out-File -Append -Path "C:\viewers.txt"
}
(I think I have the filter syntax correct; I seem to have to hack at it every time I write a new filter...)
I don't have enough rep to add a comment, but Jeff is correct. However, there are still issues with the original poster's query. The following piece of code will yield no results based on the examples provided by the poster:
{$_.name -match "Microsoft Viewer*"}
That needs to either be changed to
{$_.name -like "*Microsoft*Viewer*"}
or
{$_.name -match "Microsoft.*?Viewer"}
Getting an ambiguous identity error. I can search successfully to return the group that a user account is a member of, but when I try to search for the groups that a computer account is a member of there is the ambiguous identity error. I tried to use a -type or -identity switch, but either I did not have the syntax correct or it was just not applicable.
Where my targeted computer account is called SNA00760856, I have been working on using...
Get-QADGroup -Containsindirectmember SNA00760856
Any massaging that I can do to the command to get the groups that the computer SNA00760856 is a member of? Dropping in a user account in place of the computer account works like a charm.
I have also tried to qualify the computer name with the domain info.
Ie SNA00760856.mydivision.mydomain.com or mydivision\SNA00760856
Also tried to collect the membership of the computer using which I know is wrong after a closer reading of the switch info....
Get-QADobject -IndirectMemberOf SNA00760856
Results in ambiguous identity as well.
You can get the group memberships of a computer in AD through the ActiveDirectory module with Get-ADPrincipalGroupMembership. You'll need to search via the computers DistinguishedName, which can be achieved by leveraging Get-ADComputer:
Get-ADPrincipalGroupMembership (Get-ADComputer SNA00760856).DistinguishedName
That'll return all of the group objects SNA00760856 is a member of.
If you want to clean up the output, use this
Get-ADPrincipalGroupMembership (Get-ADComputer ComputerName) | select-object name
If you export to a list use
Get-AdPrincipalGroupMembership ( Get-ADComputer XXXXXXX ) | Out-File C:\XXX\XXX
I used something to pull down the AD Computer information and the Computer membership into one Text file.
This is using $Env:computerName to get the name of computer script is run on. If you want to select a different computer, change out the variable $HostName = to a computer name of your choice. Example $HostName = "Janes-Laptop01" .
The computer you run this script on must have the Active Directory module installed for this to work.
Import-module -Name ActiveDirectory
$HostName = $Env:computerName
$path = "c:\temp\Computer_AD_Membership_Info_$($HostName)_$(get-date -f yyyyMMdd-hhmm).txt"
Echo "`r`n ******* Computer OU Information. ******* `r`n" | Out-File -FilePath $path -Encoding utf8 -Force ;
Get-AdComputer -Identity $($HostName) -Properties * | Out-File -FilePath $path -Encoding utf8 -Append -Force ;
Echo "`r`n ******* AD Groups Computer Member of. ******* `r`n" | Out-File -FilePath $path -Encoding utf8 -Append -Force ;
Get-ADPrincipalGroupMembership (Get-ADComputer $($HostName)).DistinguishedName | Out-File -FilePath $path -Encoding utf8 -Append -Force ;
I have what should be a simple script that will connect to all the servers in a domain and build a table of all the services running on each server. However, when I try to automate the script to grab all the servers in a foreach loop I get an RPC error. If the $name variable is replaced with the server DNS name everything works as expected. I've checked the firewall and DCOM services on my system (win7) and the servers (2000 - 2008R2) and these are all enabled or disabled appropriately. So, I'm thinking something in the script is broke. I'm still learning powershell, so any tips are appreciated.
Here is the script so far.
$servernames = get-adobject -Filter 'ObjectClass -eq "Computer" ' -Searchbase "OU=Servers,DC=E,DC=BENEFIS,DC=ORG"
foreach ($name in $servernames) {
Get-WMIObject win32_service -computername $name -Property SystemName,Name,StartName,StartMode |
Format-table SystemName, Name, Startname >c:\serverservices.txt }
Each object you get back have a name property so you need to pass its value to the ComputerName parameter. In addition, to get computer object use the Get-ADComputer cmdlet, you also need to specify the Append switch when you export to the file otherwise content will be overwritten and what you'll see finally is the output of the last computer only.
$servernames = Get-ADComputer -SearchBase "OU=Servers,DC=E,DC=BENEFIS,DC=ORG" -Filter *
foreach ($name in $servernames)
{
Get-WMIObject win32_service -computername $name.Name -Property SystemName,Name,StartName,StartMode |
Format-table SystemName, Name, Startname | Out-File c:\serverservices.txt -Append
}