4

I have a task to deploy two Windows services created using Topshelf to a test server as part of our continuous integration build process.

My MSBuild target file is as follows:

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <Target Condition="'$(ConfigurationName)'=='Release'" Name="StopService">
    <Exec Command="powershell.exe -NonInteractive -executionpolicy Unrestricted -command &quot;&amp; { &amp;&apos;.\ServiceStop.ps1&apos; } &quot;" ContinueOnError="true" />
  </Target>

</Project>

This executes a Powershell script (well, a couple of lines) situated within the same folder within the project called ServiceStop.ps:

$service = get-service -ComputerName MyServerName -Name 'MyServiceName'

stop-service -InputObject $service -Verbose

The problem

When I queue a new build from within TFS, the script does successfully execute; however, the get-service command fails to find the service in question - despite the fact that it is definitely there and running. The specific error from the build log is as follows:

Get-Service : Cannot find any service with service name 'MyServiceName' (TaskId:198)

When the script is run locally from my machine, the service on the remote machine is found and stopped successfully, making me think it is some sort of permissions issue.

What I've tried

I have very limited experience with Powershell. I read that credentials could be stored within a Powershell object like so:

$pw = Read-Host -AsSecureString "Enter password"
$pw | ConvertFrom-SecureString | Out-File -Path .\storedPassword.txt

$password = get-content .\storedPassword.txt | convertto-securestring
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist "myAdminAccountName",$password

However, it would appear that get-service does not have any method to pass credentials to it.

I also experimented with using PSExec to remotely start and stop the service, but ran into similar issues.

Some questions I reviewed

Using PowerShell credentials without being prompted for a password

Powershell stop-service error: cannot find any service with service name

Powershell Get-WmiObject Access is denied

Saving credentials for reuse by powershell and error ConvertTo-SecureString : Key not valid for use in specified state

I have spent more time on this issue than I can really afford, so would appreciate any help / guidance / comments that may help.

Thank you!

UPDATE

I was able to confirm that the Powershell script was receiving information from the MSBuild task, as the log showed Powershell output.

However, I ran out of time to find a solution and instead worked around the issue by dropping the updated services binaries onto the target server and wrote a Powershell script that installed them from there.

Thanks a lot to those that commented on the issue.

Community
  • 1
  • 1
hawkoftheeye
  • 63
  • 1
  • 5
  • I'm not sure whether it can help but I'd start with initial diagnostic - launch get-service without name parameter (with ComputerName only) and ensure (using manual check) that this command does actually reach your server, and isn't executed locally – Alexey Shcherbak Mar 17 '14 at 10:14
  • Try with [SC.exe](http://technet.microsoft.com/en-us/library/cc754599.aspx) – KMoraz Mar 17 '14 at 15:58
  • Or `gwmi win32_service -credential`. – noam Mar 18 '14 at 15:47

2 Answers2

0

It appears that nothing is being passed from the MSBuild target file to the powershell script. You are defining the name of the service involved via ' marks, so its taking that rather than what the MSBuild target file is doing.

I would suggest you find out how to pass this variable, otherwise the script won't be able to pick this up correctly.

  • Thanks a lot for your comments. I shall revisit this issue later on today and advise as to the outcome. – hawkoftheeye Mar 18 '14 at 09:21
  • The MSBuild target file is definitely passing parameters to Powershell. I was able to confirm this as the full command was visible within the log file. However, I ran out of time to look at this. THanks a lot for your comments. – hawkoftheeye Mar 24 '14 at 09:34
0

I'm making a complete stab in the dark, but your service name needs the TopShelf instance name including when you call get-service.

For example your service might be called "MyWindowsService" but what you need to programmatically look for is "MyWindowsService$default"

Paul
  • 1,483
  • 14
  • 32