Script to test RDP connection to Multiple Servers - python-3.x

I am New to scripting world.
I have a requirement to test RDP access to our Servers in two datacenter as a part of a Leased Line Migration. I have a little over 2000+ servers and I cannot manually test RDP connection to all of them. I was hoping if any of you can help me prepare a script where I give the IP addresses of all my servers in the script and it tests RDP connections to all those servers and gives me a result if the RDP connection is successful or not.
Thanks in advance
Ravi

Create a text file of the server names or read directly from ADDS.
Pass that computername in a pipeline to the Test-NetConnection cmdlet using the CommonTCPPort switch for the RDP protocol in a ForLoop.
# Get specifics for a module, cmdlet, or function
(Get-Command -Name Get-Content).Parameters
(Get-Command -Name Get-Content).Parameters.Keys
Get-help -Name Get-Content -Examples
Get-help -Name Get-Content -Full
Get-help -Name Get-Content -Online
(Get-Command -Name Get-ADComputer).Parameters
(Get-Command -Name Get-ADComputer).Parameters.Keys
Get-help -Name Get-ADComputer -Examples
Get-help -Name Get-ADComputer -Full
Get-help -Name Get-ADComputer -Online
(Get-Command -Name Test-NetConnection).Parameters
(Get-Command -Name Test-NetConnection).Parameters.Keys
Get-help -Name Test-NetConnection -Examples
Get-help -Name Test-NetConnection -Full
Get-help -Name Test-NetConnection -Online
About_loops
Youtube
Update
As per my comment, you should only really need something like this.
(Get-ADComputer).Name |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
Or
Get-Content -Path 'D:\ServerNames.txt' |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
Update
A follow-up to your Out-File comment that you put as an answer. Again, step back take the time to learn PowerShell (the built-in help files, Youtube, articles, books, blogs, etc...) to limit/avoid confusion, mistakes, bad coding habits, frustrations as well as possible serious harm to your computer or your environment when create, update, deletes may be a later use case.
So, your file use case is one of these:
$env:COMPUTERNAME |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort RDP}
<#
# Results
ComputerName : Labhost001
RemoteAddress : ...
RemotePort : 3389
InterfaceAlias : ...
SourceAddress : ...
PingSucceeded : True
PingReplyDetails (RTT) : ...
TcpTestSucceeded : False
#>
You should only need these ....
ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded
... that last property says whether the connection worked.
$env:COMPUTERNAME |
ForEach {Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB}
<#
# Results
ComputerName : Labhost001
RemoteAddress : ...
RemotePort : 445
InterfaceAlias : ...
SourceAddress : ...
TcpTestSucceeded : True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded
}
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded |
Out-File -FilePath 'D:\Temp\TNCResults.txt' -Append
}
Get-Content -Path 'D:\Temp\TNCResults.txt'
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>
$env:COMPUTERNAME |
ForEach {
Test-NetConnection -ComputerName $PSItem -CommonTCPPort SMB |
Select-Object -Property ComputerName, RemotePort, PingSucceeded, TcpTestSucceeded |
Export-Csv -Path 'D:\Temp\TNCResults.csv' -NoTypeInformation -Append
}
Get-Content -Path 'D:\Temp\TNCResults.csv'
<#
# Results
"ComputerName","RemotePort","PingSucceeded","TcpTestSucceeded"
"Labhost001","445","False","True"
#>
Import-Csv -Path 'D:\Temp\TNCResults.csv'
<#
# Results
ComputerName RemotePort PingSucceeded TcpTestSucceeded
------------ ---------- ------------- ----------------
Labhost001 445 False True
#>

I just worked on this similar task today and got it working successfully.
You will need to create a text file contains the list of servers names or IPs.
In my case, I used two text files:
One file for Windows servers "rdp.txt"
The second file for Linux servers "ssh.txt"
Then in PowerShell run the following script:
Don't forget to update the files paths in lines (2 & 3) according to the directory you place the files in
#Read the text files contents
$RDPServers = Get-content 'C:\scripts\rdp.txt'
$SSHServers = Get-content 'C:\scripts\ssh.txt'
#Define two containers variables to hold the list of reachable and unreachable servers.
$LiveServer = #()
$DeadServer = #()
#Loop over the windows servers list to test each server connectivity
foreach($Server in $RDPServers){
#Test the connectivity to windows server and store the response "True" or "False" in $nettest Variable
$netest = Test-NetConnection -ComputerName $Server -Port 3389 | Select-Object -ExpandProperty TcpTestSucceeded
Write-Output "RDP $($Server) is : $($netest)"
if($netest -eq "True")
#Add to the $Lifeserers list
{ $LiveServer += "$Server"}
else
#Add to the $DeadServers list
{$DeadServer += "$Server" }
}
echo "..."
echo "..."
#Loop over the Linux servers list to test each server connectivity
foreach($Server in $SSHServers)
{
#Test the connectivity to Linux server and store the response "True" or "False" in $nettest Variable
$netest = Test-NetConnection -ComputerName $Server -Port 22 | Select-Object -ExpandProperty TcpTestSucceeded
Write-Output "SSH $($Server) is : $($netest)"
if($netest -eq "True") { $LiveServer += "$Server"}
else {$DeadServer += "$Server" }
}
echo "Test Completed."
Write-Host "Reachable Computer as below"
$LiveServer
Write-Host "Not Reachable Computer as below"
$DeadServer
Run the script and check the output.

Related

How to split different values in powershell by a line

With this script i am able to fetch all the Tags that a VM has but i want that in output the each key and its value should be separated by a line in the way that each key and its value appears on different lines like this
reference image
# Sign into Azure Portal
connect-azaccount
# Fetch the Virtual Machines from the subscription
$azureVMDetails = get-azvm
# Fetch the NIC details from the subscription
$azureNICDetails = Get-AzNetworkInterface | ?{ $_.VirtualMachine -NE $null}
#Fetching Virtual Machine Details
$virtual_machine_object = $null
$virtual_machine_object = #()
#Iterating over the NIC Interfaces under the subscription
foreach($azureNICDetail in $azureNICDetails){
#Fetching the VM Name
$azureVMDetail = $azureVMDetails | ? -Property Id -eq $azureNICDetail.VirtualMachine.id
#Fetching the VM Tags
foreach($azureDetail in $azureVMDetails) {
$vm_tags = $azureVMDetail| Select-Object -Property (
#{name='Tags'; expression = {($_.tags.GetEnumerator().ForEach({ '{0} : {1}' -f $_.key, $_.value }) -join ';')}}
)
}
#VM Details export
$virtual_machine_object_temp = new-object PSObject
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "name" -Value $azureVMDetail.Name
$virtual_machine_object_temp | add-member -membertype NoteProperty -name "comments" -Value ($vm_tags.Tags -join ';')
$virtual_machine_object += $virtual_machine_object_temp
}
#Report format and path
$virtual_machine_object | Export-Csv "C:\Users\JOHN\Desktop\Inventory\Final Scripts\VM_details_$(get-date -f dd.MM.yyyy).csv" -NoTypeInformation -Force
I tried to reproduce the same in my environment and got the results successfully by using the below PowerShell script:
$vmdeatil = Get-AzVm -Name testvm | Select -ExpandProperty Tags
$value = $vmdeatil
foreach($i in 0..($value.Count -1))
{
$ErrorActionPreference = ‘SilentlyContinue’
[array]$report += [pscustomobject] #{
key = $key[$i]
name = $value[$i]
}
}
$report | Export-Csv -Path "C:\Users\ruk1.csv" -NoTypeInformation
Response:
The output is successfully exported in the csv file like below:

Display Data on Two Columns Within Excel

I am trying to display data within an Excel document where Column A displays the server name and column B displays the .NET version. I'm running into an issue exporting to a .csv because it says that the file path does not exist. I would like some guidance on how I can resolve that issue and how I can display data on the two columns within Excel.
$Servers =
(
"test"
)
foreach ($Server in $Servers)
{
Invoke-Command -ComputerName $Server -ScriptBlock {
Write-Output "$(hostname)"
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse | Get-ItemProperty -Name Version,Release -EA 0 | where { $_.PSChildName -match '^(?!S)\p{L}'} | select PSChildName, Version, Release | Select -ExpandProperty Version | Sort-Object Version | Export-Csv -Path C:\Users\User\Desktop\example.csv
}
The main issue is that you're using Export-Csv on the remote hosts since it is inside the Invoke-Command script block, and the likeable error is because the path you are using as export doesn't exist on those hosts.
It's also worth noting that Invoke-Command can run in parallel, -ComputerName as well as -Session can take an array, this removes the need for the foreach loop as well as it is much faster / efficient.
Invoke-Command -ComputerName $servers -ScriptBlock {
Write-Host "Working on $($env:COMPUTERNAME)..."
Get-ChildItem 'HKLM:\SOFTWARE\Microsoft\NET Framework Setup\NDP' -Recurse |
Get-ItemProperty -Name Version, Release -EA 0 |
ForEach-Object {
if($_.PSChildName -notmatch '^(?!S)\p{L}') {
return # skip this
}
[pscustomobject]#{
HostName = $env:COMPUTERNAME
Version = $_.Version
}
} | Sort-Object Version
} -HideComputerName | Select-Object * -ExcludeProperty RunspaceID |
Export-Csv -Path C:\Users\User\Desktop\example.csv -NoTypeInformation

Powershell export CSV looks weird

I have an issue with my CSV export to Excel with powershell. When I import it looks like pretty bad and I can't find any information that helps me to solve it.
Here I attach an image of the import and the code. I see other CSV imports and it looks normal with its categories spaced by rows in Excel, but I don't know how to do it.
Image of my workbook
$Computers = Get-ADComputer -Filter {OperatingSystem -like "*Server*"} -Properties OperatingSystem | Select-Object -ExpandProperty Name
Foreach($computer in $computers){
if(!(Test-Connection -Cn $computer -BufferSize 16 -Count 1 -ea 0 -quiet))
{write-host "cannot reach $computer offline" -f red}
else {
$outtbl = #()
Try{
$sr=Get-WmiObject win32_bios -ComputerName $Computer -ErrorAction Stop
$Xr=Get-WmiObject –class Win32_processor -ComputerName $computer -ErrorAction Stop
$ld=get-adcomputer $computer -properties Name,Lastlogondate,operatingsystem,ipv4Address,enabled,description,DistinguishedName -ErrorAction Stop
$r="{0} GB" -f ((Get-WmiObject Win32_PhysicalMemory -ComputerName $computer |Measure-Object Capacity -Sum).Sum / 1GB)
$x = gwmi win32_computersystem -ComputerName $computer |select #{Name = "Type";Expression = {if (($_.pcsystemtype -eq '2') )
{'Laptop'} Else {'Desktop Or Other something else'}}},Manufacturer,#{Name = "Model";Expression = {if (($_.model -eq "$null") ) {'Virtual'} Else {$_.model}}},username -ErrorAction Stop
$t= New-Object PSObject -Property #{
serialnumber = $sr.serialnumber
computername = $ld.name
Ipaddress=$ld.ipv4Address
Enabled=$ld.Enabled
Description=$ld.description
Ou=$ld.DistinguishedName.split(',')[1].split('=')[1]
Type = $x.type
Manufacturer=$x.Manufacturer
Model=$x.Model
Ram=$R
ProcessorName=($xr.name | Out-String).Trim()
NumberOfCores=($xr.NumberOfCores | Out-String).Trim()
NumberOfLogicalProcessors=($xr.NumberOfLogicalProcessors | Out-String).Trim()
Addresswidth=($xr.Addresswidth | Out-String).Trim()
Operatingsystem=$ld.operatingsystem
Lastlogondate=$ld.lastlogondate
LoggedinUser=$x.username
}
$outtbl += $t
}
catch [Exception]
{
"Error communicating with $computer, skipping to next"
}
$outtbl | select Computername,enabled,description,ipAddress,Ou,Type,Serialnumber,Manufacturer,Model,Ram,ProcessorName,NumberOfCores,NumberOfLogicalProcessors,Addresswidth,Operatingsystem,loggedinuser,Lastlogondate |export-csv -Append C:\temp\VerynewAdinventory.csv -nti
}
}
As commented, your locale computer uses a different delimiter character that Export-Csv by default uses (that is the comma).
You can check what character your computer (and thus your Excel) uses like this:
[cultureinfo]::CurrentCulture.TextInfo.ListSeparator
To use Export-Csv in a way that you can simply double-click the output csv file to open in Excel, you need to either append switch -UseCulture to it, OR tell it what the delimiter should be if not a comma by appending parameter -Delimiter followed by the character you got from the above code line.
That said, your code does not produce the full table, because the export to the csv file is in the wrong place. As Palle Due commented, you could have seen that if you would indent your code properly.
Also, I would advise to use more self-describing variable names, so not $r or $x, but $memory and $machine for instance.
Nowadays, you should use Get-CimInstance rather than Get-WmiObject
AND adding to an array with += should be avoided as it is both time and memory consuming. (on every addition to an array, which is of fixed size, the entire array has to be rebuilt in memory).
Your code revised:
# set the $ErrorActionPreference to Stop, so you don't have to add -ErrorAction Stop everywhere in the script
# remember the currens value, so you can restore that afterwards.
$oldErrorPref = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
# get an array of computers, gathering all properties you need
$computers = Get-ADComputer -Filter "OperatingSystem -like '*Server*'" -Properties OperatingSystem, LastLogonDate, IPv4Address, Description
$result = foreach ($computer in $computers) {
$serverName = $computer.Name
if(!(Test-Connection -ComputerName $serverName -BufferSize 16 -Count 1 -ErrorAction SilentlyContinue -Quiet)) {
Write-Host "cannot reach $serverName offline" -ForegroundColor Red
continue # skip this computer and proceed with the next one
}
try {
# instead of Get-WmiObject, nowadays you should use Get-CimInstance
$bios = Get-WmiObject -Class Win32_bios -ComputerName $serverName
$processor = Get-WmiObject -Class Win32_Processor -ComputerName $serverName
$memory = Get-WmiObject -Class Win32_PhysicalMemory -ComputerName $serverName
$disks = Get-WmiObject -Class Win32_LogicalDisk -ComputerName $serverName
$machine = Get-WmiObject -Class Win32_ComputerSystem -ComputerName $serverName |
Select-Object #{Name = "Type"; Expression = {
if ($_.pcsystemtype -eq '2') {'Laptop'} else {'Desktop Or Other something else'}}
},
Manufacturer,
#{Name = "Model"; Expression = {
if (!$_.model) {'Virtual'} else {$_.model}}
},
UserName
# output an object to be collected in variable $result
# put the properties in the order you would like in the output
[PsCustomObject] #{
ComputerName = $serverName
Enabled = $computer.Enabled
Description = $computer.description
IpAddress = $computer.IPv4Address
Ou = $computer.DistinguishedName.split(',')[1].split('=')[1]
Type = $machine.type
SerialNumber = $bios.serialnumber
Manufacturer = $machine.Manufacturer
Model = $machine.Model
Ram = '{0} GB' -f (($memory | Measure-Object Capacity -Sum).Sum / 1GB)
ProcessorName = $processor.Name
NumberOfCores = $processor.NumberOfCores
NumberOfLogicalProcessors = $processor.NumberOfLogicalProcessors
Addresswidth = $processor.Addresswidth
OperatingSystem = $computer.OperatingSystem
# {0:N2} returns the number formatted with two decimals
TotalFreeDiskSpace = '{0:N2} GB' -f (($disks | Measure-Object FreeSpace -Sum).Sum / 1GB)
LoggedInUser = $machine.UserName
Lastlogondate = $computer.LastLogonDate
}
}
catch {
Write-Warning "Error communicating with computer $serverName, skipping to next"
}
}
# restore the ErrorActionPreference to its former value
$ErrorActionPreference = $oldErrorPref
# output the completed array in a CSV file
# (using the delimiter characer your local machine has set as ListSeparator)
$result | Export-Csv -Path 'C:\temp\VerynewAdinventory.csv' -UseCulture -NoTypeInformation

Using Objects in Powershell to do command

What im trying to do is the following:
Im getting a list of all VM`s that have some set values such as being in use and NOT having Azure Benefits turned on.
What i have is that i made a tiny script to get all machines within an subscription and select on the basis mentioned above.
What i want to do with that output is do the command Update-azureVM in bulk.
Could someone help me with this ? do i need to export the values to an excel and use that sheet to do a bulk update-AzureVM
here is the code that i have setup at the moment:
$returnObj = #()
$VMs=Get-AzVm -status
foreach ($VM in $VMs)
{
$obj = New-Object psobject -Property #{
"VmSize" = $VM.HardwareProfile.VmSize;
"VmName" = $vm.Name;
"PowerState" = $vm.PowerState;
"License_Type" = $vm.LicenseType;
}
$returnObj += $obj | select VmSize, VmName, PowerState, License_Type
}
$returnObj |
Where-Object{$_.PowerState -ne "VM deallocated"} |
Where-Object{$_.License_Type -ne "Windows_Server"} |
Where-Object{$_.License_Type -ne "Windows_Client"} |
Export-Csv C:\temp\freek.csv
Thank you all in advance!

How to export the Certificate details related to the particular IIS site using Powershell script

I wrote a script where in it will export all the SSL certificate details from my machine to an Excel sheet, but I need to export the Certificates which are mapped to the particular site in IIS and then I need to export those details with Site name and the Certificate details to an Excel sheet.
Code
#Clearing the Console host in PS
Clear-Host
#Installing the Excel module to the Powershell
Install-Module -Name ImportExcel
#List of Servers
$computers = Get-Content "C:\TEMP\servers.txt"
#Number of days to look for expiring certificates
$threshold = 300
#Set deadline date
$deadline = (Get-Date).AddDays($threshold)
Invoke-Command -ComputerName $computers {
Get-ChildItem -Path 'Cert:\LocalMachine\My' -Recurse |
Select-Object -Property #{n='ServerName';e={$env:COMPUTERNAME}},Issuer, Subject, NotAfter,
##{Label = 'ServerName';Expression = {$env:COMPUTERNAME}}
#{Label='Expires In (Days)';Expression = {(New-TimeSpan -Start (Get-Date) -End $PSitem.NotAfter).Days}}
} | Export-Excel -Path C:\users\$env:username\documents\MultipleServer_Certificate_Expiry_Details.xlsx`
This is a very common thing, with many articles and samples all over the web on this IIS use case. This is what the web administration module is used for.
<#
Get all IIS bindings and SSL certificates
On a local or remote IIS PowerShell Session
#>
Import-Module -Name WebAdministration
Get-ChildItem -Path IIS:SSLBindings |
ForEach-Object -Process {
if ($_.Sites)
{
$certificate = Get-ChildItem -Path CERT:LocalMachine/My |
Where-Object -Property Thumbprint -EQ -Value $_.Thumbprint
[PsCustomObject]#{
Sites = $_.Sites.Value
CertificateFriendlyName = $certificate.FriendlyName
CertificateDnsNameList = $certificate.DnsNameList
CertificateNotAfter = $certificate.NotAfter
CertificateIssuer = $certificate.Issuer
}
}
}
Customize the above to fit your output needs.
Note if you happen to be on a legacy version of PowerShell:
[PsCustomObject]#{} will not work in PS 2.0 but you may replace it by New-Object -TypeName PSObject
Update
You've asked for a sample script to run on multiple servers. However, you already have the code in your post. Just put that Invoke-Command inside a ForEach loop and pass in a list of computers.
$Computers |
ForEach {
Invoke-Command -ComputerName $PSItem -ScriptBlock {
Get-ChildItem -Path 'Cert:\LocalMachine\My' -Recurse |
Select-Object -Property #{n='ServerName';e={$env:COMPUTERNAME}},Issuer, Subject, NotAfter,
#{Label='Expires In (Days)';Expression = {(New-TimeSpan -Start (Get-Date) -End $PSitem.NotAfter).Days}}
} | Export-Excel -Path "C:\users\$env:username\documents\MultipleServer_Certificate_Expiry_Details.xlsx"
}
Of course, you'll need to add in that sample for the Web Admin block to your cert data points

Resources