I am trying to identify some orphan server's, these are windows servers in active directory I have a domain list of about 100 domain, I'm try to write a script where I can input a server name and it searches the domain names which I have stored in a text file, any assistance would be appriciated.
You can do the following
Get the content of the file with - Get-Content C:\temp\file.txt
Do foreach loop for every server
Try to ping the server using Test-Connection
Use Get-ADComputer to pull computer object from AD and check when is the last time it updated it's password
If password is not changed in the last 30 days, append the computer name and Password Last Set date in orphan.csv file.
$serverlist = Get-Content C:\temp\file.txt
foreach ($server in $serverlist)
{
if (-not (Test-Connection -Ping $server -Count 1 -Quiet))
{
Get-ADComputer $server -Properties PasswordLastSet |
Where {$_.Passwordlastset -le (Get-date).AddDays(-30)} |
Select-Object Name,PasswordLastSet |
Export-CSV C:\temp\orphan.csv -append -force -NoTypeInformation
}
}
Related
Beginner question. We only grant access to servers by AD group. We need to report who has admin access to a list of Windows servers. My auditor likes my Server Admins script however she also wants to know the group members first, last name. I don't need to use the ADGroupMember script, if there is a better way.
If someone could point me in the right direction that will be great. It's important I understand so I can do it myself next time : )
Thanks in advance
$computers = Get-content "c:\scripts\servers.txt"
ForEach ($Line In $computers)
{
#write-host $Line
Invoke-command -ComputerName $line -ScriptBlock { net localgroup administrators} | Get-ADGroupMember -Identity "$_????what goes here????" |%{get-aduser $_.SamAccountName | select userPrincipalName } | out-file "c:\scripts\'$line'LocalAdmin.txt"
}
This script works great but does not list out group members first, lastname
$computers = Get-content "c:\scripts\servers.txt"
ForEach ($Line In $computers)
{
#write-host $Line
Invoke-command -ComputerName $line -ScriptBlock { net localgroup administrators} | out-file "c:\scripts\'$line'LocalAdmin.txt"
}
If you really need information about the users in the local Administrators group, you can use the cmdlets from the PSv5.1+ Microsoft.PowerShell.LocalAccounts module.
However, note that local accounts just have a single .FullName property, not separate first and last name ones. Also, this property may or may not be filled in:
Invoke-Command -ComputerName (Get-Content c:\scripts\servers.txt) -ScriptBlock {
Get-LocalGroupMember -Group Administrators |
Where-Object ObjectClass -eq User |
Select-Object Sid |
Get-LocalUser
} |
Sort-Object PSComputerName |
Select-Object PSComputerName, Name, FullName
If domain users are among the group's members and you do need separate first and last name information, pipe to Get-ADUser instead of to Get-LocalUser - you can distinguish users by their source (where they are defined) via the .PrincipalSource property, available on the output objects from Get-LocalGroupMember from Window 10 / Windows Server 2016.
An alternative to mklement0's helpful answer, somewhat old school, using [adsi]:
$servers = Get-Content c:\scripts\servers.txt
Invoke-Command -ComputerName $servers -ScriptBlock {
$adsi = [adsi]"WinNT://$env:COMPUTERNAME,computer"
$adsi.PSBase.Children.Find('Administrators').PSBase.Invoke('members') |
ForEach-Object {
$Name = $_.GetType().InvokeMember('Name','GetProperty',$null,$_,$null)
$class = $_.GetType().InvokeMember('Class','GetProperty',$null,$_,$null)
$adspath = $_.GetType().InvokeMember('ADSPath','GetProperty',$null,$_,$null)
$sid = [System.Security.Principal.SecurityIdentifier]::new(
$_.GetType().InvokeMember('objectsid','GetProperty',$null,$_,$null),0
).Value
[pscustomobject]#{
Name = $Name
Class = $Class
Path = $adspath -replace '^WinNT://'
SecurityIdentifier = $sid
}
} | Sort-Object Class -Descending
} | Where-Object Class -EQ User
I currently use the following powershell script to export the list of all VMs on our network with their information and export into an excel file:
#// Set CSV file name
$uDateTime = Get-Date -f "yyyy-MM"
$uCSVFile = "C:\Servers"+$uDateTime+".csv"
#//Export out to csv file.
Get-ADComputer -filter * -Properties ipv4Address, OperatingSystem,DistinguishedName |
select-object Name, ipv4Address, OperatingSystem, #{label='OU';expression=
{$_.DistinguishedName.Split(',')[1].Split('=')[1]}} |
export-csv -path $uCSVFile
The excel content would look something like this:
I want to add another column to indicate if specific application exists on each server or not like this one
Upon googling around I see that I can utilize the Get-ItemProperty to read the registry in order to check if certain program is installed on individual VM, but I am having problem tying the code to my existing one. It gives me the same result based on the machine where this PowerShell scripts runs on instead of each VM registry individually ...
Can you help me making this script read each VM's registry
#// Set CSV file name
$uDateTime = Get-Date -f "yyyy-MM"
$uCSVFile = "C:\Servers"+$uDateTime+".csv"
#//Export out to csv file.
Get-ADComputer -filter * -Properties ipv4Address, OperatingSystem,DistinguishedName |
select-object Name, ipv4Address, OperatingSystem, #{label='OU';expression=
{$_.DistinguishedName.Split(',')[1].Split('=')[1]}},
#{label='HelloKitty Installed';expression={(Get-ItemProperty "HKLM:\Software\HelloKitty\*" | Where {
$_.Version -ne $null }) -ne $null}}|
export-csv -path $uCSVFile
To read a registry key from the computer you are targetting instead of the computer the script is currently running from, you should use the Invoke-Command cmdlet.
However, keep in mind that Get-ADComputer can also list computers that are currently off-line, so I would suggest using a ForEach-Object loop which will give you a chance to test for that first.
Something like this:
#// Set CSV file name
$uCSVFile = 'C:\Servers{0:yyyy-MM}.csv' -f (Get-Date)
#//Export out to csv file.
$result = Get-ADComputer -Filter * -Properties ipv4Address, OperatingSystem,DistinguishedName |
ForEach-Object {
if (Test-Connection -ComputerName $_.Name -Count 1 -Quiet) {
# computer is on line. If need be, add -Credential to the Invoke-Command cmdlet
# because reading the HKEY_LOCAL_MACHINE hive needs Administrator permissions.
# Also, the targetted machines must have the 'Remote Registry' service enabled.
try {
$installed = Invoke-Command -ComputerName $_.Name -ScriptBlock {
$null -ne (Get-ItemProperty "HKLM:\SOFTWARE\HelloKitty\*" |
Where-Object { $null -ne $_.Version }).Version
} -ErrorAction Stop
}
catch { $installed = "ERROR" }
}
else { $installed = "OFF-LINE" }
# output an object
$_ | Select-Object Name, ipv4Address, OperatingSystem,
#{Name = 'HelloKitty Installed'; Expression = { $installed }}
}
# now export to CSV
$result | Export-Csv -Path $uCSVFile -UseCulture -NoTypeInformation
I have added switch -UseCulture to the Export-Csv cmdlet so the delimiter character used in the csv file will be the same as your local Excel expects
$Inventory = Get-Content -Path "C:\Temp\computer list.txt"
foreach ($Computer in $Inventory) {
(Get-WmiObject -Class win32_process -ComputerName $Computer | Where-Object name -Match explorer).getowner().user
}
I'm trying to run a script that will get me the username and timestamp of lastlogon through a list of computer names in a text file associated with AD.
I can manage to get the names but I run into null-valued errors as it goes through the list and takes longer than expected to finish.
How would I go about fixing that and adding a timestamp for users who last logged on/off?
A better method would be to parse through event logs to find their log on log off times
this script looks like it fits the bill
https://gallery.technet.microsoft.com/scriptcenter/Find-user-logon-duration-667b8c48
you could then use it like this
$Inventory = Get-Content -Path 'C:\Temp\computerlist.txt'
ForEach ($Computer in $Inventory) {
Get-OSCUserLogonDuration -ComputerName $Computer -IncludeRemoteInteractive -
Verbose | FT -AutoSize
}
I'm writing a script to get the Username of any user logged on to any computer. It works fine with 2 Exceptions.
Here is the code:
$computername = Get-Content 'I:\NodeList\SWSL.txt'
Remove-item "I:\NodeList\UsersPC.txt"
foreach ($computer in $computername)
{
if(Test-Connection -Computername $Computer -BufferSize 16 -Count 1 -ea 0)
{
$Uinfo = gwmi win32_computersystem -comp $computer | select Username,Caption #,Manufacturer
$Uinfo | Out-File -Filepath "I:\NodeList\UsersPC.txt" -Append
Write-Host $Uinfo
}else{
Write-Host $computer " Is offline, not responing to ping"
$computer + " Is offline!" | Out-File -Filepath "I:\NodeList\UsersPC.txt" -Append
}
}
First the Output is:
USername Caption
-------- -------
BINYAN\Charlie SYD-WS04
But I would only like to have:
Charlie SYD-WS04
The domain is always the same, so I just need the username and the computer name, and NOT the headings or the "---"
2nd Problem is, we are a render farm and all renders are processed on a user account Called "Render".
For those computers I only get the computer name, Username is Blank.
This user account is a Domain user, but not in an OU like the others (Sydney, Melbourne, Brisbane).
It resides in the default "Users" folder in AD.
You could remove the domain name using a regex that replaces everything until and including a \: '.*?\\'
You get rid of the heading using select -expand or using a foreach loop where you select the properties using $_.PROPERTY
So your statement could look like this:
$Uinfo = gwmi win32_computersystem -comp $computer |
foreach { '{0} {1}' -f ($_.Username -replace '.*?\\'), $_.Caption }
I have no answer for / I dont understand your second question.
I'm new to PowerShell and I'm attempting to write a script that will query AD for machine names, check which ones are responding and write the output into a file. So far I have this:
$computers = Get-ADComputer -filter {(Name -like "PC*")} | Select-Object -Property Name
foreach ($computer in $computers) {
if((Test-Connection -Cn $computer -BufferSize 16 -Count 1 -Ea 0 -Quiet)) {
"Machine $computer connected." | Out-File "out.txt" -Append
} else {
"Machine $computer not connected." | Out-File "out.txt" -Append
} #end if
} #end foreach
What I get in the output text file looks like the following:
...
Machine #{Name=PC-0649} not connected.
Machine #{Name=PC-1541} not connected.
Machine #{Name=PC-1574} not connected.
...
I think my problem lies with the Select-Object -Property Name part of the first line. Running the debugger, it looks like PowerShell is formatting each iteration of $computer to include the header line.
[DBG]: PS Y:\>> $computer
Name
----
PC-0649
What's the best way for me to strip out everything except the PC-#### part in this situation?
I think your problem is that you still have a list of (truncated) computer objects in $computers. Verify this by doing $computers[0].GetType(). If you don't see String, it's not a string. :) Try this instead:
$computers = Get-ADComputer -filter {(Name -like "PC*")} |
Select-Object -ExpandProperty Name