Disable multiple computer account from txt - powershell

$Computers = Get-Content c:\temp\computers.txt
foreach ($Computer in $Computers) {
$ADComputer = $null
$ADComputer = Get-ADComputer $Computer -Properties Description
if ($ADComputer) {
Add-Content C:\temp\computers.log -Value "Found $Computer, disabling"
Set-ADComputer $ADComputer -Description "Computer Disabled on $(Get-Date)" -Enabled $false
} else {
Add-Content C:\temp\computers.log -Value "$Computer not in Active Directory"
}
}
Can someone verify whether above code is correct?
Above code suppose to:
disable multiple computers, read from txt file.
Edit description of the disabled computers.
create log file for the result.
Customer don't have any testing environment that we can test. So I just don't want to risk anything.

The original code is working fine. So i am posting this as answer.
$Computers = Get-Content c:\temp\computers.txt
foreach ($Computer in $Computers) {
$ADComputer = $null
$ADComputer = Get-ADComputer $Computer -Properties Description
if ($ADComputer) {
Add-Content C:\temp\computers.log -Value "Found $Computer, disabling"
Set-ADComputer $ADComputer -Description "Computer Disabled on $(Get-Date)" -Enabled $false
} else {
Add-Content C:\temp\computers.log -Value "$Computer not in Active Directory"
}
}

Related

PowerShell - get-hotfix on multiple servers - error handling

I have a problem with my script to check multiple hotfixes on multiple servers. Sometimes I don't have a rpc connection to a server, in this case I want to log this information to the same output file. Can someone please help me? thanks
$computers = Get-Content -path C:\00-Scripts\printer\server.txt
$Patch = Get-Content -path C:\00-Scripts\printer\kb.txt
foreach ($computer in $computers) {
foreach ($patch1 in $patch) {
Try {
if (get-hotfix -id $patch1 -ComputerName $computer -ErrorAction stop) {
Add-content "$patch1 is Present in $computer" -path C:\00-Scripts\printer\Hotfix.txt
}
Else {
Add-content "$patch1 is not Present in $computer" -path C:\00-Scripts\printer\Hotfix.txt
}
}
catch {
Add-content "can not check $computer" -path C:\00-Scripts\printer\Hotfix.txt
}
}
}
In this case, you need to first check if the computer can be reached. If so, loop over the patches to report if they can be found or not. In you cannot reach the machine, write just one failure line in the log and proceed with the next computer.
$computers = Get-Content -path 'C:\00-Scripts\printer\server.txt'
$Patch = Get-Content -path 'C:\00-Scripts\printer\kb.txt'
$logFile = 'C:\00-Scripts\printer\Hotfix.txt'
foreach ($computer in $computers) {
if (Test-Connection -ComputerName $computer -Count 1 -Quiet) {
foreach ($patch1 in $patch) {
# use -ErrorAction SilentlyContinue here so $hotfix will either become $null or an object
$hotfix = Get-HotFix -Id $patch1 -ComputerName $computer -ErrorAction SilentlyContinue
if ($hotfix) {
"$patch1 is Present in $computer" | Add-Content -Path $logFile
}
else {
"$patch1 is not Present in $computer" | Add-Content -Path $logFile
}
}
}
else {
"Can not check $computer" | Add-Content -Path $logFile
}
}
With the above answer, script is not scanning the next computer and the results are not getting generated for the rest of computers
for example
Get-HotFix -ComputerName PC1,PC2 -ErrorAction SilentlyContinue
In above command if PC1 is not available or access denied. The command stops wihtout checking PC2 and generating output

PowerShell get output in CSV format

I am seeking help to get output in csv format. I have written powershell code and would want to tweak the output to get in csv format as shown in below pic.
$servers = Get-Content 'C:\Temp\listofservers.txt'
foreach ($server in $servers)
{
#DHCP
if (((Get-Service -ComputerName $server -ServiceName 'DHCPServer' -ErrorAction SilentlyContinue).Status) -eq 'Running')
{
if ((((Get-DhcpServerv4Scope -ComputerName $server | Get-DhcpServerv4Lease -ComputerName $server) | Measure-Object).Count) -ge 1)
{
Write-Host "DHCP present on $server and in use"
}
else
{
Write-Host "DHCP present on $server and not in use"
}
}
else
{
Write-Host("DHCP is not present on $server")
}
#Certificate authority
if (((Get-Service -ComputerName $server -ServiceName 'CertSvc' -ErrorAction SilentlyContinue).Status) -eq 'Running')
{
Write-Host "Certificate Authority is present on $server"
}
else
{
Write-Host "Certificate Authority is not present on $server"
}
}
Send all outputs to a custom object then export them:
$servers = get-content "C:\Temp\listofservers.txt"
$ExportPath = 'c:\temp\results.csv'
$Servers | ForEach-Object {
Write-Host "Checking $_"
# DHCP status
# Use Try....Catch to trap the errors - it's more robust than
# If...Then and prevents a wall of red text if something goes wrong
Try {
$DHCPStatus = Get-Service -ComputerName $_ -Name 'DHCPServer' -ErrorAction Stop
If ($DHCPStatus.Status -eq "Running") {
Try {
If ((((Get-DhcpServerv4Scope -ComputerName $_ -ErrorAction Stop | Get-DhcpServerv4Lease -ComputerName $_ -ErrorAction Stop) | Measure-Object).Count) -ge 1) {
$DHCPResult = "DHCP present on, in use"
}
Else {
$DHCPResult = "DHCP present, not in use"
}
}
Catch {
$DHCPResult = "DHCP present - error obtaining details: $_"
}
}
}
Catch {
$DHCPResult = "DHCP is not present"
}
#Certificate authority
Try {
If (((Get-Service -ComputerName $_ -ServiceName 'CertSvc' -ErrorAction Stop).Status) -eq "Running") {
$CAResult = "Certificate Authority is present"
}
}
Catch {
$CAResult = "Certificate Authority is not present"
}
[pscustomobject]#{ComputerName = $_;DHCP = $DHCPResult;CA=$CAResult}
} | Export-Csv -Path $ExportPath -NoTypeInformation
Use a hashtable to build your object, adding key/values for each property along the way. Then convert the hashtable to a [PSCustomObject] and output it capturing in a variable ($results). Finally, export it to csv using Export-Csv
$servers = Get-Content 'C:\Temp\listofservers.txt'
$results = foreach ($server in $servers) {
# Create hashtable to build object and add ComputerName property
$output = [ordered]#{ComputerName = $server }
#DHCP
if (((Get-Service -ComputerName $server -ServiceName 'DHCPServer' -ErrorAction SilentlyContinue).Status) -eq 'Running') {
if ((((Get-DhcpServerv4Scope -ComputerName $server |
Get-DhcpServerv4Lease -ComputerName $server) |
Measure-Object).Count) -ge 1) {
# add Dhcp property if present, in use
$output.Add('Dhcp', 'Present, in use')
}
else {
# add Dhcp property if present, not in use
$output.Add('Dhcp', 'Present, not in use')
}
}
else {
# add Dhcp property if not present
$output.Add('Dhcp', 'Not present')
}
#Certificate authority
if (((Get-Service -ComputerName $server -ServiceName 'CertSvc' -ErrorAction SilentlyContinue).Status) -eq 'Running') {
# add CA property if present
$output.Add('CA', 'Present')
}
else {
# add CA property if not present
$output.Add('CA', 'Not present')
}
# Convert hashtable to pscustomobject and output it
[PSCustomObject]$output
}
# output results to screen
$results
# export results to csv file
$results | Export-Csv -Path c:\temp\server_dhcp_ca_check.csv -NoTypeInformation

Script to disable RDP

I'm trying to disable RDP using powershell.
I've tried the following code, but the values on the machine name I'm listing aren't changing.
$file = Get-Content c:\PSscripts\regchange\computers.txt
foreach ($computername in $file){
$PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$computername'" | Select-Object StatusCode
If ($PingStatus.StatusCode -eq 0){
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername )
$regKey= $reg.OpenSubKey("System\\CurrentControlSet\\Control\\Terminal Server" ,$true)
$regKey.SetValue("fDenyTSConnections","1",[Microsoft.Win32.RegistryValueKind]::dword)
}
else {
Write-Host "$computername unreachable"
}
}
I suspect there's something wrong with the way I entered the registry path name. any help would be appreciated.
The issue must be either permissions (which I assume you have as there are no obvious error messages), refreshing issue or in Get-Content and the structure of your file.
In order for Get-Content to work in this manner, each computer on a separate line. e.g.:
MyComputer1
MyComputer2
Another troubleshooting step is to try adding in Write-Host $computername entries to verify that you are looping through properly.:
$file = Get-Content c:\PSscripts\regchange\computers.txt
foreach ($computername in $file){
$PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$computername'" | Select-Object StatusCode
If ($PingStatus.StatusCode -eq 0){
Write-Host "$computername set"
}
else {
Write-Host "$computername unreachable"
}
}
You can also confirm by adding in a $regKey.GetValue after setting:
$file = Get-Content c:\PSscripts\regchange\computers.txt
foreach ($computername in $file){
$PingStatus = Gwmi Win32_PingStatus -Filter "Address = '$computername'" | Select-Object StatusCode
If ($PingStatus.StatusCode -eq 0){
$reg = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey('LocalMachine', $computername )
$regKey= $reg.OpenSubKey("System\\CurrentControlSet\\Control\\Terminal Server" ,$true)
$regKey.SetValue("fDenyTSConnections","1",[Microsoft.Win32.RegistryValueKind]::dword)
Write-Host "$computername set to: $($regKey.GetValue("fDenyTSConnections"))"
}
else {
Write-Host "$computername unreachable"
}
}
Manually setting $computername = "MyComputer" and running the code, I can confirm that the code for setting the registry works... I can also confirm that remotely killing your RDP access to your remote virtual workstation also works.. and... is as terrible as it sounds ;-)
If PSRemoting is enabled, try something like this …
(This needs to be executed in a PowerShell elevated admin session.)
Get-Content -Path 'c:\PSscripts\regchange\computers.txt' |
ForEach{
If (Test-Connection -$PSItem -Count 1 -Quiet)
{
$paramblock = #{
Path = 'HKLM:\System\CurrentControlSet\Control\Terminal Server'
Name = 'fDenyTSConnections'
Value = '1'
}
Invoke-Command –Computername $PSItem –ScriptBlock {Set-ItemProperty #paramblock}
}
Else
{Write-Warning -Message "Either the host $PSItem is offline or not reachable."}
}

Powershell script to compare AD computers to text file and change registry service on those computer and then write the computers that were offline

I'm trying to filter out computers that have already ran the script (that enables remote registry service) within AD from a list in a text file
$NamesFromFile = Get-Content
C:\scripts\Inventory\offlineRemoteRegStartupWorkstations.txt
$computers = get-adcomputer -Filter * | Where-Object {
$_.Name.SubString(1) -in $NamesFromFile }
foreach ($computer in $computers)
{
if (Test-Connection -count 1 -computer $computer.Name -quiet){
Write-Host "Updating system" $computer.Name "....." -ForegroundColor
Green
Set-Service –Name remoteregistry –Computer $computer.Name -StartupType
Automatic
Get-Service remoteregistry -ComputerName $computer.Name | start-service
}
else
{
Write-Host "System Offline " $computer.Name "....." -ForegroundColor Red
echo $computer.Name >> C:\scripts\Inventory\offlineRemoteRegStartup.txt}
}
no errors just blank
Below a re-write of your script.
Because you test if only the first character of the computer name is in the list of computers, your $computers variable will remain empty, so nothing happens.
Also, I think it would be wise to add a check if the startup type of the RemoteRegistry service is not already set to Automatic, because after all.. the computernames you read in from the file may not be accurate.
To avoid having to use $computer.Name all the time, I use a Select-Object -ExpandProperty Name, so we only have to run through a list of strings.
$NamesFromFile = Get-Content -Path 'C:\scripts\Inventory\offlineRemoteRegStartupWorkstations.txt' | Sort-Object -Unique
Get-ADComputer -Filter * |
Where-Object { $NamesFromFile -contains $_.Name } | # if the computer name is in the list
Select-Object -ExpandProperty Name | # we're only interested in the Name property
ForEach-Object {
# the automatic variable '$_' represents a single computername from the list
if (Test-Connection -Count 1 -ComputerName $_ -Quiet) {
# test if the RemoteRegistry service startup type is not already Automatic
# you can do the same with (Get-WmiObject -Class Win32_Service -Filter "Name='RemoteRegistry'" -ComputerName $_)
# only slower..
if ((Get-CimInstance -Class Win32_Service -Filter "Name='RemoteRegistry'" -ComputerName $_).StartMode -ne 'Auto') {
Write-Host "Updating system '$_'....." -ForegroundColor Green
Set-Service –Name RemoteRegistry –Computer $_ -StartupType Automatic
Get-Service -Name RemoteRegistry –Computer $_ | Start-Service
}
else {
Write-Host "RemoteRegistry service startup type already Automatic on computer '$_'....." -ForegroundColor Yellow
}
}
else {
Write-Host "System Offline '$_'....." -ForegroundColor Red
Add-Content -Path 'C:\scripts\Inventory\offlineRemoteRegStartup.txt' -Value $_
}
}

Function within a Function - Powershell

OK I am going to try to explain this as best as I can. What started out as a simple script has turned into a huge mess and now I cannot figure out how to get it working. I have been coming here for answers for some time so maybe you guys can help.
What I am trying to do is a import a list of systems and check to see if they are online. If they are online they go in one list and if not they go in another.
foreach ($server in $servers) {
if (Test-Connection $server -Count 1 -ea 0 -Quiet) {
Write-Host "$server Is Up" -ForegroundColor Green
$server | out-file -Append $liveSystems -ErrorAction SilentlyContinue
} else {
Write-Host "$server Is Down" -ForegroundColor Red
$server | out-file -Append $inactive -ErrorAction SilentlyContinue
}
}
From there I check to see if the application I need installed is on the systems. That is where things start to go off-track. When I run the function to process the $liveSystems file all I get is the last line of the file (or the same system over and over) and not each system as it should be.
function Is-Installed( $program ) {
$x86 = ((Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall") |
Where-Object { $_.GetValue( "DisplayName" ) -like "*$program*" } ).Length -gt 0;
$x64 = ((Get-ChildItem "HKLM:\Software\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall") |
Where-Object { $_.GetValue( "DisplayName" ) -like "*$program*" } ).Length -gt 0;
}
$program
function process-file1 {
param($filename)
Get-Content $filename -PipelineVariable line | ForEach-Object {
Is-Installed -program "My_Service"
if (Is-Installed -eq "True") {
Write-Host "$server has agent installed" -ForegroundColor Green
$server | Out-File $installed -ErrorAction SilentlyContinue
}
else
{
Write-Host "$server does not have agent installed" -ForegroundColor Red
$server | Out-File -Append $notInstalled -ErrorAction SilentlyContinue
}
}
}
process-file1 -filename $liveSystems
Once I can get the systems to process through the list of installed and not installed I am trying to take the list of installed systems and check which ones have the service running and which ones do not.
$array = #()
foreach($i in (gc $installed)) {
$svc = Get-Service my_service -ComputerName $i -ea "0"
$obj = New-Object psobject -Property #{
Name = $svc.name
Status = $svc.status
Computer = $i
}
$array += $obj
}
$array | Select Computer,Name,Status | Export-Csv -Path $resultsFile -
NoTypeInformation
Last but not least I run through that list of running and not running and attempt to start the service on systems that are not running.
function process-CSVfile2 {
param($filename)
Import-Csv $filename |
ForEach-Object -PipelineVariable object {
if($_.Status -eq "Running") {
Write-Host "Your Service is currently Running on" $_.Computer
}
if($_.Status -eq "Stopped") {
$serviceName = 'my_service'
$service = Get-CimInstance Win32_Service -ComputerName $_.Computer -Filter "Name=$serviceName"
$service.Start()
$service.WaitForStatus("Started",'00:00:30')
Start-Sleep 10
}
}
}
Several of these blocks run separately but when put together they will not run. I can't seem to get past the second block where it just looks at the same line over and over.
In addition there is a piece I have been trying to get working that would install the application on systems that do not have the service installed but that is not working either but I will save that for a different time.
If anyone can help me with this I would really appreciate it. After 3 days of trying to get it running I am at my wits end.
I'd create objects and properties instead of files with computers online etc...
Something like:
$Computers=New-Object -TypeName System.Collections.ArrayList
$Servers = #(Get-Content -path c:\servers.txt)
$Servers = $Servers | ? {$_} | select-object -uniqe |ForEach-Object {$_.TrimEnd()}
$Servers|ForEach-Object {
$tempobj=New-Object -TypeName PSObject
$tempobj | Add-Member -type NoteProperty -name Name -value $_
$tempobj | Add-Member -type NoteProperty -name isOnline -value $FALSE
$tempobj | Add-Member -type NoteProperty -name Installed -value $FALSE
$tempobj | Add-Member -type NoteProperty -name serviceRunning -value $FALSE
[void]$Computers.Add($tempobj)
then You could work on array (no need for additional files)
$Computers|Where-Object {$_.isOnline -eq $TRUE}
etc