Invoke-Command to multiple servers, what is the current server? - powershell

Below is my striped down code.
How can I determine what the current server is when parsing to Write-Host? With other words, what can I use instead of "$CURRENTSERVER"?
$servers = SERVER1,SERVER2,SERVER3
Try
{
Invoke-Command -ComputerName $servers -ErrorAction Stop -ScriptBlock{CODE}
}
Catch
{
Write-Host -ForegroundColor Yellow "[WARNING] Cannot connect to $CURRENTSERVER"
}
The information is there somewhere, if I run the command without try-catch I get
[SERVER3] Connecting to remote server SERVER3 failed with the following error message : WinRM cannot process the request.

I found the parameter for the information:
$_.TargetObject

Related

Unable to restart server after it joins the domain

Morning guys,
I'm running into an issue where I have a script that joins a Server to a Domain and restarts, intalls it's roles/features, etc and then restarts it again. I don't have an issue with the first restart:
Restart-Computer -ComputerName $IP -Credential $AdminCred -Wait -For PowerShell
but when I try to do the second restart at the end of the script it get the following error
Restart-Computer : The computer is skipped. Fail to retrieve its LastBootUpTime via the WMI service with the
following error message: Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED)).
The following is the original code I tried
Restart-Computer -ComputerName $HostName -Wait -For PowerShell
Without credentials, as I expect Kerberos to work as the account from the laptop has proper permissions
but I also ran it with -Credential and same error. Then I tried changing $HostName to $IP and still no luck.
I can get around the error, by enclosing the Restart-Computer command into an invoke-command session but then I can't "wait for powershell" unless I set an arbitrary sleep timer for a couple minutes.
Any Ideas are appreciated!
I figured it out. I had to add the -WsmanAuthentication param and specify Kerberos. Final code
Restart-Computer -ComputerName $HostName -WsmanAuthentication Kerberos -Wait -For PowerShell

WINRM credentials in remote script block not working as expected

I am trying to use WINRM to connect to one host (in the internal domain) and then from there WINRM into another server in another domain (the DMZ). Below is an example:
$domainServer = 'DOMAINSERVER'
$dmzServer = 'DMZSERVER'
$domainCred = Get-Credential -Message "Enter domain creds"
$dmzCred = Get-Credential -Message "Enter dmz creds"
Invoke-Command -ComputerName $domainServer -ArgumentList $dmzServer,$dmzCred -ScriptBlock {
Write-Host "connected to $domainServer"
Invoke-Command -ComputerName $args[0] -ScriptBlock {
Write-Host "connected to $args[0]"
} -Credential $args[1]
} -Credential $domainCred
However when I try this I am getting this error:
[DMZSERVER] Connecting to remote server DMZSERVER failed with the following error message : WinRM cannot process the request. The
following error with errorcode 0x80090311 occurred while using Kerberos authentication: There are currently no logon servers available to service the
logon request.
I am able to open a WINRM session from DOMAINSERVER to DMZSERVER if I log on to DOMAINSERVER and open a console and try there, so the problem is something with my nested "invoke-command"

New-PSSession - WinRM cannot process the request

I am trying to list all the websites in IIS on a remote server using PowerShell scripting. Below is how I am trying to connect to the server:
$s = New-PSSession -ComputerName $Server
But when I run the script I am getting the following error:
New-PSSession : [Server] Connecting to remote server Server failed with the
following error message : WinRM cannot process the request. The following error
occurred while using Kerberos authentication: Cannot find the computer Server.
Verify that the computer exists on the network and that the name provided is
spelled correctly. For more information, see the about_Remote_Troubleshooting
Help topic.
At C:\AppServers\Application.ps1:8 char:8
+ $s = New-PSSession -ComputerName Server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTransportException
+ FullyQualifiedErrorId : NetworkPathNotFound,PSSessionOpenFailed
The server is already enabled to receive remote requests.
Update:
Below is the full function that i am trying to run:
function audit-servers {
if (Test-path "ApplicationsOnTheServer.txt") {Remove-Item "ApplicationsOnTheServer.txt"}
if (Test-Path "ServersList.txt") {
foreach ($server in Get-Content .\ServersList.txt) {
"Application Server : $server`n" | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
"Applications list:" | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
$s = New-PSSession -ComputerName $server -Credential domainabc\myname
Invoke-Command -Session $s -ScriptBlock {Import-Module WebAdministration;Get-iissite} | out-file -FilePath "ApplicationsOnTheServer.txt" -Append
}
} else {
"ServersList.txt file is missing"
break;
}
"`nAll Done!`n"}
The ServersList.txt has atstappvmabc.tsteag.com
The error message clearly states that you wanted to connect to the server named Server not to the server which name is stored in $Server variable (text in bold is actually the name of the server you try to connect to):
New-PSSession : [Server] Connecting to remote server Server failed
If you tried to connect to the server named for example MyServer01.example.com you'd receive the error like below (truncated):
PS C:\> New-PSSession -ComputerName "MyServer01.example.com"
New-PSSession : [MyServer01.example.com] Connecting to remote server MyServer01.example.com failed (...)
Even though you state that you try to execute
$s = New-PSSession -ComputerName $Server
You actually execute (notice missing dollar sign)
$s = New-PSSession -ComputerName Server
The above was also taken from the error message you pasted. I'd suggest to first skip the variable and try to enter server path in the command itself to verify it's working:
$s = New-PSSession -ComputerName "MyServer01.example.com"
And then, if it works, put the path in variable and test again.
The error you're receiving FullyQualifiedErrorId : NetworkPathNotFound generally means that the name you're passing to the -ComputerName parameter can't be resolved.
Perhaps try running Test-Connection $Server to troubleshoot what's happening there.
Your variable $Server contains wrong value. You have to assign valid computer name to $Server.

PowerShell Stopping and Starting Windows Services on Remote Computer

I have a very basic PowerShell that accepts a list of Windows Server and Services on them and then stops the Services
Get-Service -ComputerName machine1 -Name service1 -ErrorAction Stop | Stop-Service -WarningAction SilentlyContinue
Although I had explicitly mentioned -ErrorAction as Stop, in a case if one of the Server is not reachable, the Powershell doesn't come back. How do I change this behaviour at least in a way to stop processing after a certain amount of time as "n" secs which again can be passed thru parameter?
Incorporating both comments, we end up with following
Enclose the current script in a Test-Connection that allows you to first verify if a computer is actually reachable:
if (Test-Connection -ComputerName machine1 -Quiet)
{
all your current code
}

how to validate New-ssh Session in Powershell

I have downloaded SSH-Sessions by Joakim Svendsen which uses SSH.NET and installed the PowerShell module in the Jenkins Windows server
In Jenkins, I have the following PowerShell script:
Import-Module SSH-Sessions
$lastExitCode = 0
$devApp1 = "10.0.1.109"
$devApp2 = "10.0.1.110"
Write-Output "Deployment started in $devApp1......"
New-SshSession -ComputerName $devApp1 -Username test -Password test#123
The problem is that the Jenkins job doesn't get failed when the connectivity fails. The Jenkins output is:
Unable to connect to 10.0.1.109: Exception calling "Connect" with "0" argumen
t(s): "No connection could be made because the target machine actively refused
it"
Finished: SUCCESS
How can I fix this issue?
Using this documentation, I would do something like this:
New-SshSession -ComputerName $devApp1 -Username test -Password test#123
if (!$SshSessions.$devApp1.Connected) {
throw "Session to $devApp1 is not connected"
}
Or this:
New-SshSession -ComputerName $devApp1 -Username test -Password test#123
$Session = Get-SshSession -ComputerName $devApp1
if (!$Session.Connected) {
throw "Session to $devApp1 is not connected"
}
Obviously, if you've got multiple connections to $devApp1 this code will not work, but the examples in the doc suggest it won't allow you to do that. For whatever reason New-SshSession doesn't support the -PassThru parameter, nor does it seem to return the session, nor does it allow you to specify a variable for the session. Instead the design uses a global variable: $SshSessions. Not the way I'd design it.
You might want to look into Posh-SSH. I don't remember if that is designed better, but I don't remember this kind of issue. It also uses the SSH.Net library. Alternately, WinSCP has a .Net assembly that is very easy to use from PowerShell.