Powershell Workflow to reboot computers - powershell

Code:
workflow Test-RemoteReboot{
param ([string[]]$serverNames)
foreach -parallel($server in $serverNames){
Restart-Computer -PSComputerName $server -Wait -Force
}
}
Test-RemoteReboot SP,SP2
Issue:
this is a small excerpt from a pretty long workflow I built in powershell. By all accounts, this should work but I get the following error (even when running this script in isolation):
Microsoft.PowerShell.Utility\Write-Error : The running command stopped because the preference variable "ErrorActionPreference" or common parameter is set to Stop: The computer SP2 is
skipped. Fail to retrieve its LastBootUpTime via the WMI service with the following error message: The RPC server is unavailable. (Exception from HRESULT: 0x800706BA).
At line:433 char:25
+ ... Receive-Job -Job $job -Wait -Verbose -Debug -ErrorAction ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], ActionPreferenceStopException
+ FullyQualifiedErrorId : System.Management.Automation.ActionPreferenceStopException,Microsoft.PowerShell.Commands.WriteErrorCommand
+ PSComputerName : [localhost]
I looked into the RPC server unavailable issue. Firewall is down, RPC Service is running, Servers are on domain, Workflow running from domain member computer, as domain admin. I can successfully PSRemote into the machines and do whatever. I can even do this:
workflow Test-LocalRebootRemotely{
param ([string[]]$serverNames)
foreach -parallel($server in $serverNames){
InlineScript { Restart-Computer -Force } -PSComputerName $server
}
}
Test-LocalRebootRemotely SP,SP2
The problem is, is that I need a return value to determine if I need to reboot and handle other logic outside of the remote computer. I do notice that there is an abnormal pause just before it errors. So maybe it is a timeout? anyone have a similar issue?

You can try the Restart-Computer cmdlet with the -Protocol WSMan parameter instead of the default DCOM over RPC protocol (-Protocol DCOM).
This would confirm that your RPC network packets are blocked somewhere.

Related

How Can I handle Errors in PS [duplicate]

This question already has an answer here:
How to handle failed variable assignments in powershell? [duplicate]
(1 answer)
Closed 2 years ago.
I'm trying to catch the error from service restart using function. The issue Im having that catch is not doing anything through the script.
Function Service_Restart ($Servers, $Service){
try {
Write-Host "$CurrentDateTime - Restarting Service $Service on Servers $Servers"
ForEach($Serv in $Servers){
Get-Service -ComputerName $Serv -Name $Service | Restart-Service
}
} catch [System.ServiceProcess.ServiceController] {
$error[0].Exception
}
Service_Restart Server1 ServiceName
I'm expecting to see an one line error not the full stack, however I see the entire error.
What I like to see as an example
Restart-Service : Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer 'Localhost'.
However I'm seeing
Restart-Service : Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer 'Localhost'.
At C:\user\UTILS_Version3.ps1:48 char:62
+ ... Get-Service -ComputerName $Serv -Name $Service | Restart-Service
+ ~~~~~~~~~~~~~~~
+ CategoryInfo : CloseError: (System.ServiceProcess.ServiceController:ServiceController) [Restart-Service], ServiceCommandException
+ FullyQualifiedErrorId : CouldNotStopService,Microsoft.PowerShell.Commands.RestartServiceCommand
If I run $error[0].Exception manually I get the result I'm looking for but not through the function.
PS C:\Users\> $error[0].Exception
Service 'Adobe Acrobat Update Service (AdobeARMservice)' cannot be stopped due to the following error: Cannot open AdobeARMservice service on computer '127.0.0.1'.
PS C:\Users\>
When using try and catch, you must be working with terminating errors. Since some errors are non-terminating, you can force them to be terminating. To ensure your commands generate terminating errors, you can use the common parameter -ErrorAction Stop. Alternatively, you can set $ErrorActionPreference = 'Stop' and all commands within the session will implicitly apply -ErrorAction Stop.
In a catch block, $_ or $PSItem is the caught ErrorRecord object. When handling a specific error, it is best to use the error type's full name. You can retrieve that with $_.Exception.GetType().Fullname in the catch block or $error[0].Exception.GetType().Fullname outside of try {} catch {}.
Putting this all together, you can do the following:
try {
Get-Service -ComputerName $Serv -Name $Service -ErrorAction Stop |
Restart-Service -ErrorAction Stop
} catch [Microsoft.PowerShell.Commands.ServiceCommandException] {
$_.Exception
}
See About Try Catch Finally for more information.

Powershell forum with button calling script

I have a powershell forum for level 1.
Now it has been asked to add a button that calls an script for solving automatic outlook issues.
The script works when i call it direct on the computer itself (via .\outlook.ps1)
When i add it to the button it does not work.
The button itself works and is visible.
example code:
$button_Outlookrest_Click={
Get-ComputerTXTBOX
Add-logs -text "$ComputerName - Create new Outlook profile"
function button{
Copy-Item -Path "D:\path\Repair_outlook_Profile.ps1" -Destination "\\$ComputerName\C$\local" -Recurse
Invoke-Command -ComputerName $ComputerName -ScriptBlock {C:\local\Repair_outlook_Profile.ps1}
}
}
I have tested the code individual, and the following is working:
Copy-Item -Path "D:\path\Repair_outlook_Profile.ps1" -Destination "\\replaced-with-targetcomputer\C$\local" -Recurse
When i whant to call the script, i use the following:
Invoke-Command -ComputerName $ComputerName -ScriptBlock {C:\local\Repair_outlook_Profile.ps1}
However, above text provides me below error:
PS C:\Users\admin> Invoke-Command -ComputerName targetcomputer -ScriptBlock {C:\local\Repair_outlook_Profile.ps1}
[targetcomputer] Connecting to remote server targetcomputer failed with the following error message : WinRM cannot
complete the operation. Verify that the specified computer name is valid, that the computer is accessible over the
network, and that a firewall exception for the WinRM service is enabled and allows access from this computer. By
default, the WinRM firewall exception for public profiles limits access to remote computers within the same local
subnet. For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OpenError: (clienttarget:String) [], PSRemotingTransportException
+ FullyQualifiedErrorId : WinRMOperationTimeout,PSSessionStateBroken
i want to avoid them using powershell, as its not the idea of this button.
in the script itself, it does not copy the file to the target computer, it does not run the script using the invoke command.
Is this blocked by company firewall?
Do i have something wrong in my code?
An example button that works without any problem is:
$button_DriverQuery_Click={
$button_DriverQuery.Enabled = $False
Get-ComputerTxtBox
$DriverQuery_command="cmd.exe"
$DriverQuery_arguments = "/k driverquery /s $ComputerName"
Start-Process $DriverQuery_command $DriverQuery_arguments
$button_DriverQuery.Enabled = $true
}
Only this aditional button does not work. And i cannot figure it out at the moment.
What am i doing wrong here?
thank you.

powershell remote script execution errors

I notice an error " Connecting to remote server usa-chicago failed with the following error message : Access is denied. For more information, see the
about_Remote_Troubleshooting Help topic
CategoryInfo : OpenError: (usa-chicago:String) [], PSRemotingTransportException
FullyQualifiedErrorId : AccessDenied,PSSessionStateBroken
". Below is the snippet used. Any suggestions?
All the machines are inside a workgroup.
$computers = gc "C:\servers.txt"
$source = "\\usa-chicago\c$\temp\one.jar"
$destination = "c$\july1\folder1\"
foreach ($computer in $computers) {
Invoke-Command -Computername $computer -ScriptBlock { & Copy-Item $using:source -Destination \\$using:computer\$using:destination -Force }
}
Does your user account have access both to the computer and also the share you try to copy something to? It could be that you hit the dreaded 'second hop' problem with PowerShell Remoting: https://learn.microsoft.com/en-us/powershell/scripting/learn/remoting/ps-remoting-second-hop?view=powershell-7
If this is the problem, there are some workarounds for that. What i like to do is:
In the Invoke Command, create a Scheduled Task with the commands you'd like to execute and pass the credentials into it, execute it, and delete it after.

PowerShell Stopping and Starting Services with Server names masked by DNS Alias

I have a simple PowerShell that accepts a file as a parameter that contains Server-Name, Service-Name and Timeout specified in seconds and the powershell stops/starts the services based on the command. I have 10 servers where application related services are configured and I'm using Workload automation capabilities to run this code on any server with the same parameter file and powershell present on all 10 servers.
All of this works fine with server names hardcoded in the param file. We have n+2 Infrastructure, and I created DNS Aliases for all the 10 servers to make Active-Standby switchover little easy. Now the problem comes with stop/start script. Ex: If the script gets invoked in Server 7, all the services will be shutdown except for the ones in Server 7 and I get below error:
Get-Service : Cannot find any service with service name
'Application-Server7'. At line:1 char:1
+ Get-Service -ComputerName app7test -Name Application-Server7
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Application-Server7:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
I just tested one-liner command using PowerShell ISE on the computer "appnewora79" and below are the results.
This works fine:
Get-Service -ComputerName appnewora79 -Name Application-Server7
Status Name DisplayName
------ ---- -----------
Stopped Application-Ser... Application-Server7
This fails:
Get-Service -ComputerName app7test -Name Application-Server7
Get-Service : Cannot find any service with service name 'Application-Server7'
At line:1 char:1
+ Get-Service -ComputerName app7test -Name Application-Server7
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Application-Server7:String) [Get-Service], ServiceCommandException
+ FullyQualifiedErrorId : NoServiceFoundForGivenName,Microsoft.PowerShell.Commands.GetServiceCommand
Any suggestions to overcome this, please?
I tried below as well:
It all works when the server name is hardcoded. If I change it to DNS Alias name then Get-Service fails on the server where it is executing while fetching service details only related to the same server.
On the Server-1, if I run below commands, they all work fine
Get-Service -ComputerName servername1
Get-Service -ComputerName servername2
Get-Service -ComputerName servername3
If I update the above command with server dns alias and execute them on Server-1, then only the first command fails, i.e.. the command with the same server name masked with DNS fails, If I run the same commands on server 2, then the second one alone fails
Get-Service -ComputerName dnsalias1
Get-Service -ComputerName dnsalias2
Get-Service -ComputerName dnsalias3
I tried, test-connection with DNS alias names and they go thru fine. Tried Get-WmiObject -Class WIN32_service with computer name masked as DNS alias and it goes thru fine. I'm lost as to what could be the issue.
Below is the error message with Get-Service alone:
Get-Service : Cannot open Service Control Manager on computer 'dnsalias1'. This operation might require other privileges.
At line:5 char:1
+ Get-Service -ComputerName dnsalias1
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Get-Service], InvalidOperationException
+ FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.PowerShell.Commands.GetServiceCommand
I found a kind of different way to resolve this as per suggestion received in PowerShell Google+ forum.
I used Resolve-DnsName to get hold of IP4Address of the server and then passed it for stopping and starting windows services and this works.

PowerShell Remote Access Configuration

Trying to configure remote PowerShell access on a server but cannot avoid access denied errors.
What I have done:
Register-PSSessionConfiguration
-Name EngrStudentAdmin
-RunAsCredential domain\delegatedAdmin
-StartupScript 'C:\Scripts\Students\Welcome.ps1'
-ShowSecurityDescriptorUI
(on a single line - displaying above for readability)
Using the permissions GUI, I granted the group DelegatedAdmins Read and Execute permissions. The startup script is just filler.
$welcome = 'Welcome to ' + $env:COMPUTERNAME
Write-Host $welcome
Attempting to connect to the endpoint with
Invoke-Command
-ComputerName $server
-ConfigurationName EngrStudentAdmin
-ScriptBlock { hostname }
fails with the error
AuthorizationManager check failed.
+ CategoryInfo : OpenError: (engr-mgr1.domain.edu:String) [], RemoteException
+ FullyQualifiedErrorId : PSSessionStateBroken
The execution policy on the server is RemoteSigned and the startup script is signed.
The account used to access the server is a member of the DelegatedAdmins group.
Opening a local shell as delegatedAdmin shows that the account has permission to run the startup script.
Using a member of the local admins group, the Invoke-Command, without the ConfiguationName switch (i.e. connecting to the default endpoint), executes so the winrm service is running and PSRemoting enabled.
The delegatedAdmin account has no profile.
What am I missing?
Check that the WMI service is enabled and running, if it's disabled try starting it and then retrying.
Also check the properties of the actual file, it might have been blocked.
are both Domain joined? If not you might take several further steps.
In general: Try this on the remote system: Enable-PSRemoting -Force -Verbose If you see nothing, it was already applied. If not, this will make alle necessary changes for you.
Just in case: Check your Firewall settings :-)
As Dewi mentioned: Check the WMI Service.
Here is a quick hack to enable it (if you want to enforce it):
# Configure WMI
Set-Item -Path wsman:\localhost\client\trustedhosts -Value * -Force -Confirm:$False
# Restart
Restart-Service -Name WinRM -Force
Last but not least: Use the -verbose switch to see more details.
Like this:
New-PSSession -ComputerName $ComputerName -Credential $credencial -Verbose
Cheers
Josh