PowerShell Stop-Service/Start-Service not working on a specific server - powershell

I have three servers, let's call them Deploy1, Deploy2, Target.
All servers are running Windows Server 2008R2, fully updated.
A domain user, admin1, is configured as administrator on all servers, and this is the user I'm running all the commands with.
The following command works on Deploy1:
Get-Service "MyService" -ComputerName Target | Stop-Service
When running the same command on Deploy2, the command fails with the following message:
Cannot find any service with service name 'MyService'.
On Deploy2, the following command works, and displays the service and its status.
Get-Service "MyService" -ComputerName Target
Now, I know there are other ways to stop/start services via PowerShell, but I like this one as it automatically waits for the server to actually stop/start.
So what could be wrong with Deploy2?

Powershell v2.0 has a bug (feature?) in how the object returned by Get-Service is implemented. It does not actually set the ComputerName property correctly. Because of this, it can only affect local services. If you upgrade to Windows Management Framework 3.0 (and consequently Powershell v3) the bug is fixed and will work correctly.

Does this work? If not, is there an error produced?
(Get-Service "MyService" -ComputerName Target).Stop()

Related

Double-Hop Errors when running Skype for Business Cmdlets

I am attempting to automate the Skype for Business Server installation process in Powershell, I have a script that remotes into specified machines and begins preparing them as Front-End servers. The problem lies when certain SfB cmdlets (SfB commands are all of the form "verb-Cs...", ex. Get-CsUser or Get-CsPool) are run in remote sessions, they throw the double-hop error:
Exception: Active Directory error "-2147016672" occurred while searching for domain controllers in domain...
This is after running Enable-CsComputer, which enables the computer's role-based off its definition in the topology (topology was published successfully). The user object is in all required groups (RTCUniversalServerAdmins, Schema Admins, CsAdministrators & Local Admin rights on all SfB Servers). Oddly enough, the command 'Import-CsConfiguration -localstore" does not throw errors, and it's in the same remote session. There may be other local or domain groups that I need to be in, but I cannot pinpoint exactly which and have not seen them documented in the Skype build guides. Skype commands that have parameters to specify targets or just pull data, such as Get-CsPool or Get-CsAdForest, do not have errors because they are run in the local scope. The Enable-CsComputer has no parameter for the computer name, it has to be executed from that machine itself.
Enabling CredSSP delegation on each server is not an option, and I'm not understanding why there is a "second hop" in this command! If the second hop was a resource on a file server or database, that would make sense, and be easy to solve, but in this case, I can't track it. Can anyone tell me what I may be missing?
Here's a code sample to try and illustrate. From the jumbox I get the pool data to create an array, and a session is opened to each machine:
$ServerArray =get-cspool -identity $poolName
$i=0
$SessionArray = #{}
foreach($server in $ServerArray.Computers){$SessionArray[$i] = new-PsSession -ComputerName $server}
foreach($session in $SessionArray.values){
invoke-Command -session $session -scriptBlock {
#remote commands:
import-csConfiguration -<config file path> -localstore; #no errors
enable-CsReplica; #no errors
enable-cscomputer; #double hop error here
}}
If I log into that machine and run the same command, it executes fine but the intention of the project is to automate it on an arbitrary number of machines.
It looks like it's just trying to authenticate to a domain controller, which is reasonable. You'll have to approach this like any other double-hop issue.
Microsoft has an article dedicated to the double hop issue, and has a few solutions other than CredSSP that you can look at: Making the second hop in PowerShell Remoting

how to get winrm to use powershell 7 for remote sessions by default

With the release of powershell 7, seems like it is time to move past ps 5.1 so I have installed in on a couple of servers to give it a go.
However I when I create a session to these servers from my pc with ps7 I am always running ps5.1 on the remote machine.
Invoke-Command -ComputerName name -ScriptBlock {
Write-Host $env:COMPUTERNAME
$PSVersionTable.PsVersion
}
Which outputs 5.1.17763.316. Any ideas how to get the remote session to use version 7.0.0 preferably by default?
Update
making some progress with this, so though I would share.
On the remote machine in powershell 7 run the following command
Enable-PSRemoting
This will create some PsSessionConfigurations which you can see with the following command..
Get-PSSessionConfiguration
Now you can do the following to create sessions from powershell 7
Invoke-Command -ComputerName ServerName -ScriptBlock { $PsVersionTable.PSVersion } -ConfigurationName Powershell.7
$session = New-PSSession ServerName -ConfigurationName Powershell.7
Invoke-Command -Session $session -ScriptBlock { $PsVersionTable.PSVersion }
This now uses ps 7 on the remote session, happy days. Now how to make this happen by default...? From this github issue :
set the default microsoft.powershell endpoint to any PowerShell they
choose
Which I think is what I want to do so switched back to ps 5.1 and tried this command:
Get-PSSessionConfiguration -Name microsoft.powershell | Set-PSSessionConfiguration -PSVersion 7.0
Only to get the following output:
Set-PSSessionConfiguration : Cannot bind parameter 'PSVersion' to the
target. Exception setting "PSVersion": "The value 7.0 is not valid for
the PSVersion parameter. The available values are 2.0, 3.0, 4.0, 5.0,
5.1."
though I would try this in ps7 so switched back by running pwsh and ran the same command again to get he following...
Write-Error: No session configuration matches criteria
"microsoft.powershell".
So still not quite sure how to make ps7 the default... :(
Note:
It is the remoting client that determines what remoting endpoint (session configuration) to connect to on the server machine - see below.
Therefore, your own attempt,
# WRONG
Get-PSSessionConfiguration -Name microsoft.powershell |
Set-PSSessionConfiguration -PSVersion 7.0
is ineffective, because Set-PSSessionConfiguration modifies endpoint configurations on the server machine, it doesn't control the client's behavior.
Note that the fundamental prerequisite is that PowerShell remoting must be enabled on the server machine, which can be achieved either by opting to do so during installation via the MSI GUI installer, or by running Enable-PSRemoting - with admin privileges - later.Tip of the hat to Lars Fosdal.
Doing so from PowerShell (Core) creates the standard session configuration(s) named PowerShell.<version> that clients can opt to connect to - see below.
To list all configurations defined on a server, run Get-PSSessionConfiguration with admin privileges.
On a client machine, you can set a default for what session configuration defined on the server (remote machine) to connect to, via the $PSSessionConfigurationName preference variable.
E.g., to target PowerShell 7 by default:
# When remoting, default to running PowerShell Core v7.x on the
# the target machines:
$PSSessionConfigurationName = 'PowerShell.7'
If you add the above to your $PROFILE file, future sessions will target PowerShell 7 by default.
See this answer for more information, which also shows how to target a given server configuration in the context of individual commands.
Note: Changing what endpoint PowerShell [Core] targets by default - which as of 7.2 is still Window PowerShell - is being considered: see GitHub issue #11616.

Get status of service on a remote server

I need to find the status of a service on a remote computer. Though I can use the following command:
Write-Host (Get-Service -ComputerName "remoteServerName" -Name "serviceName").Status
which would give me correct status of service. However I have PowerShell 1.0 installed on the server where i need to run this script. -ComputerName parameter doesn't work for PowerShell 1.0. Currently I'm not supposed to install higher version of PowerShell.
Any idea how to get the status of a service in PowerShell 1.0?
First and foremost (and I can't stress this point enough): If the operating system supports it you should upgrade to at least PowerShell v2.0. No exception. If the system doesn't support PowerShell 2 or newer it's already out of support and should have been replaced/upgraded months ago.
With that said, you can use either WMI (as suggested by #vonPryz):
Get-WmiObject -Computer 'remoteServerName' -Class Win32_Service -Filter "DisplayName='ServiceName'"
or sc.exe (as suggested by #Kayasax):
& sc.exe \\remoteServerName query 'ServiceName'
Of these two WMI is the more PoSh approach, as it doesn't require parsing text output.

Why would Get-Service not find the service with powershell

I am having problems with a powershell script.
I wrote a script that would search for a windows service with a specific name, and it would Stop or Start this service.
It works when I run it on a server which I log into with a service account that I know that can access the service console. However when it runs off of my build server, the script is no longer able to find the services. I tried giving the service account that runs script the same privaledges as the other service account but that doesn't seem to work.
[System.ServiceProcess.ServiceController]$service = Get-Service -Name $ServiceName -ComputerName $Remoteserver -ErrorAction SilentlyContinue
That is the line that is not longer able to find the service. What am I doing wrong. Is there a way to impersonate a user that can find the service? Any help would be appreciated.
You could try supplying the credentials of the service account using the -Credential parameter. However, since you imply that it used to work with the account that runs the script remotely and no longer does, I think a more likely culprit is that $ServiceName used to only match one service on the target computer, and now there is another service whose name matches that string. If more than one service matches the -Name parameter, Get-Service returns an array of ServiceController objects.
Try running it without ErrorAction -SilentlyContinue. If you get the following error message, then that's what's happening:
Cannot convert the "System.Object[]" value of type "System.Object[]" to type "System.ServiceProcess.ServiceController".
If you get a different error message, please add the full error message to the question.

Get status of a process started by Invoke-WmiMethod

New to PowerShell, but loving the fact that I can do so much so quickly so far :)
Anyways, I am starting a remote process in a PowerShell script thusly:
$compname = "MY-PC"
$myinstallcmd = "c:\install\myprog.exe /s"
$proc = Invoke-WmiMethod -class Win32_Process -name Create -ArgumentList ($myinstallcmd) -ComputerName $compname
On most of the PCs I've tried, the Invoke-WmiMethod cmdlet works fine, but on one PC, it's hanging. What I'm now looking to do is get the status of the running process, and if it's hung up, kill it and log the kill, and then move on.
I did find a possible method to do this in the post
Starting a process remotely in Powershell, getting %ERRORLEVEL% in Windows - however, when I try to do the Register-WmiEvent on the process $proc.ProcessId, I'm getting the dreaded 0x80070005 (E_ACCESSDENIED) error... I am running the PowerShell host as domain admin.
Can anyone please suggest a way that I can get a status on the process I've started, and be able to take an action based on the status?
Thanks!
Update: I guess you are missing remote system credentials:
Try passing the credentials to remote system using -Credential parameter. This takes a PSCredential Object and hence you can do something like:
$cred = Get-Credential
Register-WMIEvent -Credential $cred <and other parameters here>
See if any of the following resolves the access denied error:
0x80070005 (DCOM ACCESS_DENIED)
This error occurs when the connected user is not recognized or is restricted in some fashion by the remote server (for example, the user might be locked out). This happens most often when accounts are in different domains. Recent changes to WMI security can also cause this error to occur:
Blank passwords, formerly permitted, are not allowed in Windows XP and Windows Server 2003.
WMI does not allow asynchronous callbacks to a Windows 98 client. A call like SWbemServices.ExecNotificationQueryAsync from a Windows 98 computer to a Windows XP computer will result in an Access Denied error returned to the Windows 98 machine.
The DCOM configuration access setting might have been changed.
If the target computer is running Windows XP, the Forceguest value under the registry key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa might be set to force the Guest account off (value is zero).
Source: http://technet.microsoft.com/en-us/library/ee692772.aspx