4
votes

I am currently working on a Windows Service as a non-GUI part of our application.

I wrote a Service which, in Debug conditions, perfectly works. This means I debug by having my static void Main() as following:

#if(!DEBUG)
    ServiceBase[] ServicesToRun;
    ServicesToRun = new ServiceBase[] 
    { 
        new TRAservice() 
    };
    ServiceBase.Run(ServicesToRun);
#else
    TRAservice Service = new TRAservice();
    Service.CanHandlePowerEvent = false;
    Service.CanHandleSessionChangeEvent = false;
    Service.CanPauseAndContinue = true;
    Service.CanShutdown = true;
    Service.CanStop = true;
    Service.ServiceName = "TRAservice";
    Service.AutoLog = false;
    Service.SetMethod();
    Service.TRAmethod();
#endif

To do some implementation testing, I added a ProjectInstaller and I install my service via the VStools cmd prompt, installutil servicename.exe. (For reference, I include the constructor of the service with the OnStart in the bottom of this post.)

However, when I then try to START the service, I get the following error: error

In my event viewer I get 4 messages (2 information (Windows error reports), 2 errors):

ErrorError

I have tried a lot of things, including, but not limited to, removing the debug lines out of the constructor (as elsewhere suggested), rebooting, installing from Release (instead of Debug)...

I will take any suggestion to fix this problem. Thanks in advance.

public TRAservice()
{
    InitializeComponent();

    CanHandlePowerEvent = false;
    CanHandleSessionChangeEvent = false;
    CanPauseAndContinue = true;
    CanShutdown = true;
    CanStop = true;
    ServiceName = "TRAservice";
    AutoLog = false;

    sSource = "TRAservice";
    sLog = "TRAlog";

    if (!EventLog.SourceExists(sSource))
    {
        EventLog.CreateEventSource(sSource, sLog);
    }

    eventLog1 = new System.Diagnostics.EventLog();
    eventLog1.Source = sSource;
    eventLog1.Log = sLog;

    eventLog1.WriteEntry("Service started", EventLogEntryType.Information, 1, 100);

    scheduleTimer = new Timer();
    scheduleTimer.Interval = 10;
    scheduleTimer.Elapsed += new ElapsedEventHandler(scheduleTimer_Elapsed);;
}

protected override void OnStart(string[] args)
{
    eventLog1.WriteEntry("Service started", EventLogEntryType.Information, 1, 100);
    flag = true;
    sw = true;
    lastRun = DateTime.Now;
    scheduleTimer.Start();
}
2
Creating the event source should be done in your installer class rather than in your service class' constructor - the service will be installed with admin permissions but it may not always run under admin permissions.Damien_The_Unbeliever
Thank you. When I implement your suggestion, I get the following error when I install the service: An exception occurred during the Install phase. System.ArgumentException: Source TRAservice already exists on the local computer. However I remove it from the register, this error keeps popping up. Any suggestions?Shishdem

2 Answers

4
votes

In my windows service, I added a console application project and made that the default startup project. I use this to debug the same code base the windows service starts. I have the working code in a separate class library project.

My windows service project only has a service.cs file, projectinstaller.cs and the app.config files that I've duplicated to my console application. I'm not using any compiler directives to run different sets of code.

Please see this MSDN page. This page and the sub-pages were very helpful in getting my windows service installed and running. It references Visual Studio 2003, yet works just fine for my Visual Studio 2013, .net 4.5.1 windows service app.

A configuration I did was to create a new solution configuration called Debug - Local. I also create a powershell script to uninstall the service, build the solution and install the service as this configuration. This way I can use the Debug configuration for my daily work and not have to worry about having files locked.

The file location of the script is ~/repoRoot/Tools and the solution is in ~/repoRoot/src Here's my powershell script: p.s. I've only run this in a powershell window running as administrator and haven't tried the run as administrator part...

#######################
# Run as Administrator
#######################
If (-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator"))
{   
#"No Administrative rights, it will display a popup window asking user for Admin rights"

$arguments = "& '" + $myinvocation.mycommand.definition + "'"
Start-Process "$psHome\powershell.exe" -Verb runAs -ArgumentList $arguments

break
}

cls

#############################################################
# Set environment variables for Visual Studio Command Prompt
#############################################################
function Set-VsCmd
{
    param(
        [parameter(Mandatory, HelpMessage="Enter VS version as 2010, 2012, or 2013")]
        [ValidateSet(2010,2012,2013)]
        [int]$version
    )
    $VS_VERSION = @{ 2010 = "10.0"; 2012 = "11.0"; 2013 = "12.0" }
    $targetDir = "c:\Program Files (x86)\Microsoft Visual Studio $($VS_VERSION[$version])\VC"
    if (!(Test-Path (Join-Path $targetDir "vcvarsall.bat"))) {
        "Error: Visual Studio $version not installed"
        return
    }
    pushd $targetDir
    cmd /c "vcvarsall.bat&set" |
    foreach {
      if ($_ -match "(.*?)=(.*)") {
        Set-Item -force -path "ENV:\$($matches[1])" -value "$($matches[2])"
      }
    }
    popd
    write-host "`nVisual Studio $version Command Prompt variables set." -ForegroundColor Yellow
}

Set-VsCmd 2013

#######################
# Stop windows service
#######################
$srvName = "Enterprise CQRS Service"
$serviceStop = Get-Service $srvName
"$srvName is now " + $serviceStop.status
Stop-Service $srvName

$TestService = Get-Service $srvName | Select-Object 'Status'
While($TestService | where {$_.Status -eq 'Running'}) {
    Write-Host '.'-NoNewLine 
  Sleep 2   
}
Write-Host "$srvName is now" $TestService.status -ForegroundColor Yellow

#################################
# Build Service as Debug - Local
#################################

# Set the solution file path
$scriptPath = Split-Path -parent $MyInvocation.MyCommand.Definition

$solutionFile = Join-Path $scriptPath "../src/Enterprise CQRS Service.sln"

# Build the Debug - Local configuration
msbuild $solutionFile /p:Configuration='Debug - Local'

##############################
# Uninstall & Instal Service
##############################

# Set the exe file path
$exePath = Join-Path $scriptPath "../src/Enterprise.Services.Windows/bin/Debug - Local/Enterprise.Services.Windows.exe"

# Uninstall the service
installutil /u $exePath

# Install the service
installutil $exePath

# Start the service
$servicePrior = Get-Service $srvName
"$srvName is now " + $servicePrior.status
Start-Service $srvName
$serviceAfter = Get-Service $srvName
$foregroundColor = "Green"
if($serviceAfter.status -ne "Running")
{
    $foregroundColor = "Red"
}
Write-Host "$srvName is now" $serviceAfter.status -ForegroundColor $foregroundColor

Hope this helps!

0
votes

I meet this probplem a few days ago, i was trying to install a .Net 4.5 service to Windows 2012 server. Anyway, I installed to .Net 3.5 framework to Windows Service 2012 it worked fine.