0

I'm currently experiencing an issue with a WIX install pack for a Windows Service application that I am trying to put together. The install fails with the following error:

enter image description here

Recorded in the Event Logs a:

"The Tops Batch Processor service failed to start due to the following error: The service did not respond to the start or control request in a timely fashion."

The OnStart method comprises:

Protected Overrides Sub OnStart(ByVal args() As String)

    Try

        'Initialisation routine
        _logger.SendLog("TOPS Batch Processor service startup", NLog.LogLevel.Info, _fileCheckTimer, _fileCheckInterval, Nothing)
        Startup()

    Catch ex As Exception
        'Log the entry
        _logger.SendLog("Failed to start TOPS Batch Processor service", NLog.LogLevel.Error, _fileCheckTimer, _fileCheckInterval, ex)
        TearDown()
    Finally
        GC.Collect()
    End Try

End Sub

The method Startup includes a raft initialisation code which incorporates some threading.Timer objects which govern the activity of the service:

Public Sub Startup()

    Try

                    'Add event handler for catching setting changes
        AddHandler PIServerChange, AddressOf PIServerChanged
        AddHandler PIPointSourceChange, AddressOf PIPointSourceChanged

        _licensedTo = GetSetting("LicensedTo")
        _productName = GetSetting("ProductName")

        'Establish the root folder for application data, nlog fonfiguration and log output
        _rootFolder = Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData) & _
                                "\" & _licensedTo & "\" & _productName
        _nlogConfigPath = _rootFolder & "\config\nlog.config"
        _logFolder = _rootFolder & "\Logs\"

        'Get the timer intervals from the app config file
        _tagRefreshInterval = GetInterval("TagRefreshInterval")
        _fileCheckInterval = GetInterval("FileCheckInterval")
        _settingsRefreshInterval = GetInterval("SettingsRefreshInterval")

        'Instaniate the timer to refresh the memory cache of pi points (tags)
        _tagRefreshTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf TagRefresh), Nothing, Timeout.Infinite, Timeout.Infinite)
        'Instaniate the timer to check for new files to process
        _fileCheckTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf FileCheck), Nothing, Timeout.Infinite, Timeout.Infinite)
        'Instaniate the timer to check for dynamic setting changes
        _settingsTimer = New Threading.Timer(New Threading.TimerCallback(AddressOf SettingsRefresh), Nothing, Timeout.Infinite, Timeout.Infinite)

        'Initialise logging architecture
        _logger = New Logger(_nlogConfigPath, _logFolder, My.Settings.AppFullName, My.Application.Info.Version.ToString, False)
        _logger.SendLog("Started Tops Batch Processor Service", NLog.LogLevel.Warn)

        'Ensure that the application data folder structure is in place
        SetFolders()

        'Initialise the remaining class variables
        _successFolder = GetSetting("Processed")
        _failedFolder = GetSetting("Failed")
        _piPointSource = GetSetting("PIPointSource")
        _piTagFilter = "pointsource = '" & _piPointSource & "'"
        _tagRefreshMode = GetSetting("TagRefreshMode")

        'Establish PI Server Connection
        _piServerSetting = GetSetting("PIServer")
        _piPointSource = GetSetting("PIPointSource")
        _piServer = _piSdkApp.Servers(_piServerSetting)
        _topsPi = New TopsPI(_piServerSetting)

        'Obtain the initial tag listing from the PI Server @@ temp disable to test file specific tag refresh
        RefreshTags()

        '@@ Temp code _tagRefresh flag should be initilaised to true for synchronous file specific tag search
        '_tagRefreshCompleted = True

        'Re-start the timers with periodic signalling as per the specified check interval
        _settingsTimer.Change(_settingsRefreshInterval, _settingsRefreshInterval)
        _tagRefreshTimer.Change(_tagRefreshInterval, _tagRefreshInterval)
        _fileCheckTimer.Change(_fileCheckInterval, _fileCheckInterval)

        _started = True
    Catch ex As Exception
        _logger.SendLog("TOPS Batch Processor startup failure.", NLog.LogLevel.Error, ex)
    Finally

    End Try
End Sub

I have used similar techniques for previous Windows Services that I have written without any problems. As far as I can make out, the OnStart method isn't even getting fired which implies that the problem may be with the WIX installer rather than with the application. This impression is further supported by the fact that even with 'Start="disabled"' I get exactly the same error message. Accordingly I have provided the product.wxs file for reference:

<MajorUpgrade DowngradeErrorMessage="A newer version of [ProductName] is already installed." />
<MediaTemplate EmbedCab="yes" />
<Property Id="ARPSYSTEMCOMPONENT">0</Property>
<Feature Id="ProductFeature" Title="TOPS Batch Processor" Level="1">
  <!-- This next section deals with the install/de-install of App Program File elements -->
  <ComponentRef Id="cmpDirSPEN" />
  <ComponentRef Id="cmpDirTopsBatch" />
  <ComponentRef Id="cmpTopsBatchExe" />
  <ComponentRef Id="cmpTopsBatchPdb" />
  <ComponentRef Id="cmpCommonDll" />
  <ComponentRef Id="cmpCommonPdb" />
  <ComponentRef Id="cmpLoggingDll" />
  <ComponentRef Id="cmpLoggingPdb" />
  <ComponentRef Id="cmpTopsBatchConfig" />
  <ComponentRef Id="cmpNlogDll" />
  <ComponentRef Id="cmpNlogXml" />

  <!-- This next section deals with the install/de-install of App Data elements i.e. Logs, Templates, Config area etc...-->
  <ComponentRef Id="cmpDirSPENAppData" />
  <ComponentRef Id="cmpDirTopsBatchAppData" />
  <ComponentRef Id="cmpDirTopsBatchStaging" />
  <ComponentRef Id="cmpDirTopsBatchProcessed" />
  <ComponentRef Id="cmpDirTopsBatchLogs" />
  <ComponentRef Id="cmpDirTopsBatchFailed" />
  <ComponentRef Id="cmpDirTopsBatchConfigNLog" />      
  <ComponentRef Id="cmpFilTopsBatchConfigNLog" />
</Feature>
 </Product>
   <Fragment>
<!-- The following section deals with the deployment of the application data files including logs, templates and userguide elements-->
<Directory Id="TARGETDIR" Name="SourceDir">
  <Directory Id="CommonAppDataFolder" Name="CommonAppData" >
    <Directory Id="dirSPENAppData" Name="SP Energy Networks">
      <Directory Id="dirTopsBatchAppData" Name="Tops Batch Processor">
        <Component Id="cmpDirTopsBatchAppData" Guid="{AGUID}" KeyPath="yes">
          <CreateFolder Directory="dirTopsBatchAppData" />
          <RemoveFile Id="PurgeTopsBatchAppData" Name="*.*" On="uninstall" />
          <RemoveFolder Id="idDirTopsBatchAppData" On="uninstall" Directory="dirTopsBatchAppData" />
        </Component>
        <Directory Id="dirTopsBatchLogs" Name="Logs">
          <Component Id="cmpDirTopsBatchLogs" Guid="{AGUID}">
            <CreateFolder Directory="dirTopsBatchLogs" />
            <RemoveFile Id="PurgeTopsBatchLogs" Name="*.*" On="uninstall" />
            <RemoveFolder Id="idDirTopsBatchLogsRemove" On="uninstall" Directory="dirTopsBatchLogs" />
          </Component>
        </Directory>
        <Directory Id="dirTopsBatchStaging" Name="Staging">
          <Component Id="cmpDirTopsBatchStaging" Guid="{AGUID}">
            <CreateFolder Directory="dirTopsBatchStaging" />
            <RemoveFile Id="PurgeTopsBatchStaging" Name="*.*" On="uninstall" />
            <RemoveFolder Id="idDirTopsBatchStagingRemove" On="uninstall" Directory="dirTopsBatchStaging" />
          </Component>
        </Directory>
        <Directory Id="dirTopsBatchProcessed" Name="Processed">
          <Component Id="cmpDirTopsBatchProcessed" Guid="{AGUID}">
            <CreateFolder Directory="dirTopsBatchProcessed" />
            <RemoveFile Id="PurgeTopsBatchProcessed" Name="*.*" On="uninstall" />
            <RemoveFolder Id="idDirTopsBatchProcessedRemove" On="uninstall" Directory="dirTopsBatchProcessed" />
          </Component>
        </Directory>
        <Directory Id="dirTopsBatchFailed" Name="Failed">
          <Component Id="cmpDirTopsBatchFailed" Guid="{AGUID}">
            <CreateFolder Directory="dirTopsBatchFailed" />
            <RemoveFile Id="PurgeTopsBatchFailed" Name="*.*" On="uninstall" />
            <RemoveFolder Id="idDirTopsBatchFailedRemove" On="uninstall" Directory="dirTopsBatchFailed" />
          </Component>
        </Directory>
        <Directory Id="dirTopsBatchConfigNLog" Name="Config">
          <Component Id="cmpDirTopsBatchConfigNLog" Guid="{AGUID}">
            <CreateFolder Directory="dirTopsBatchConfigNLog">
              <util:PermissionEx User="Users" GenericAll="yes"/>
            </CreateFolder>
            <RemoveFile Id="PurgeTopsBatchConfigNLog" Name="*.*" On="uninstall" />
            <RemoveFolder Id="idDirTopsBatchConfigNLogRemove" On="uninstall" Directory="dirTopsBatchConfigNLog" />
          </Component>
          <Component Id="cmpFilTopsBatchConfigNLog" Guid="*">
            <File Id="filTopsBatchConfigNLog" KeyPath="yes" Source="$(var.SourceDir)\nlog.config" />
          </Component>
        </Directory>
      </Directory>
      <Component Id="cmpDirSPENAppData" Guid="{AGUID}" KeyPath="yes">
        <RemoveFile Id="PurgeSPENAppData" Name="*.*" On="uninstall" />
        <RemoveFolder Id="idDirSPENAppData" On="uninstall" Directory="dirSPENAppData" />
      </Component>
    </Directory>
  </Directory>

  <!-- The following section deals with the deployment of the program files-->
  <Directory Id="ProgramFilesFolder">
    <Directory Id="dirSPEN" Name="SP Energy Networks">
      <Component Id="cmpDirSPEN" Guid="{AGUID}" KeyPath="yes">
        <CreateFolder Directory="dirSPEN" />
        <RemoveFile Id="PurgeSPEN" Name="*.*" On="uninstall" />
        <RemoveFolder Id="idDirSPEN" On="uninstall" Directory="dirSPEN" />
      </Component>
      <Directory Id="dirTopsBatch" Name="Tops Batch Processor">
        <Component Id="cmpDirTopsBatch" Guid="{AGUID}" KeyPath="yes">
          <CreateFolder Directory="dirTopsBatch" />
          <RemoveFile Id="PurgeTopsBatch" Name="*.*" On="uninstall" />
          <RemoveFolder Id="idDirTopsBatch" On="uninstall" Directory="dirTopsBatch" />
        </Component>
        <Component Id="cmpTopsBatchExe" Guid="{AGUID}">
          <File Id="filTopsBatchExe" KeyPath="yes" Source="$(var.SourceDir)\TopsBatch.exe" />
          <ServiceInstall Id="cmpTopsBatchExe" Type="ownProcess" Name="TopsBatch" DisplayName="Tops Batch Processor"
                      Description="Transmission Operations batch processing utility" Start="disabled" Account="LocalSystem" ErrorControl="normal">
            <util:PermissionEx  User="Everyone" ServicePauseContinue="yes" ServiceQueryStatus="yes"
                    ServiceStart="yes" ServiceStop="yes" ServiceUserDefinedControl="yes" />
          </ServiceInstall>
          <ServiceControl Id="cmpTopsBatchExe" Start="install" Stop="both" Remove="uninstall" Name="TopsBatch" Wait="no" />
        </Component>
        <Component Id="cmpTopsBatchPdb" Guid="*">
          <File Id="filTopsBatchPdb" KeyPath="yes" Source="$(var.SourceDir)\TopsBatch.pdb" />
        </Component>
        <Component Id="cmpCommonDll" Guid="*">
          <File Id="filCommonDll" KeyPath="yes" Source="$(var.SourceDir)\Common.dll" />
        </Component>
        <Component Id="cmpCommonPdb" Guid="*">
          <File Id="filCommonPdb" KeyPath="yes" Source="$(var.SourceDir)\Common.pdb" />
        </Component>
        <Component Id="cmpLoggingDll" Guid="*">
          <File Id="filLoggerDll" KeyPath="yes" Source="$(var.SourceDir)\Logging.dll" />
        </Component>
        <Component Id="cmpLoggingPdb" Guid="*">
          <File Id="filLoggerPdb" KeyPath="yes" Source="$(var.SourceDir)\Logging.pdb" />
        </Component>
        <Component Id="cmpTopsBatchConfig" Guid="*">
          <File Id="filTopsBatchConfig" KeyPath="yes" Source="$(var.SourceDir)\TopsBatch.exe.config" />
        </Component>
        <Component Id="cmpNlogDll" Guid="*">
          <File Id="filNlogDll" KeyPath="yes" Source="$(var.SourceDir)\NLog.dll" />
        </Component>
        <Component Id="cmpNlogXml" Guid="*">
          <File Id="filNlogXml" KeyPath="yes" Source="$(var.SourceDir)\NLog.xml" />
        </Component>
      </Directory>
    </Directory>
  </Directory>
</Directory>

If I respond by clicking the 'Ignore' button and allow the install pack to complete and check the installation elements under the Program File and the CommonAppDataFolder areas everything seems to have installed correctly.

Hoping that someone out there has a solution to this as it is driving me insane :-\

Kind Regards Paul J.

Paul Johnson
  • 213
  • 3
  • 14
  • Does this service need a password? If you hit `ignore`, can you manually start the service after installation from `Windows Key` + `R` => `services.msc`? What is up with `Debugger.Break` in the source code? – Stein Åsmul Oct 17 '18 at 12:11
  • @Stein Asmul: The service is installed under the system account, no password is required. The debugger code was inserted by me in an attempt to verify whether the app code was actually running. Have now removed the Debugger.Break line from the sample code. – Paul Johnson Oct 17 '18 at 12:15
  • Could it be failing in `_logger.SendLog`? – Andrew Morton Oct 17 '18 at 12:21
  • Andrew, I'm not sure it is even getting into code. The Logging architecture has been tested comprehensively from a normal windows client test harness. – Paul Johnson Oct 17 '18 at 12:28
  • The NLog dll and xml files are correctly placed in the program files folder 'Program Files\SP Energy Networks\Tops Batch Processor'. The only thing that is different about a conventional Nlog implementation is that I incorporate a logid which is recorded in the Nlog.config file. Corporate security prevents any writing the to C: Drive so as per the product.wxs the 'Nlog.config' file is located in '\SP Energy Networks\Tops Batch Processor\Config' – Paul Johnson Oct 17 '18 at 12:30
  • We need to know if the service starts properly if you manually start it via services.msc? Often it ends up being an issue in a configuration file. Also try to comment out all logging, but my bet is you have already tried that. – Stein Åsmul Oct 17 '18 at 14:03
  • Yep already tried commenting out all the logging, same result. If I attempt to start from the services.msc I get: Error 1053: The service did not respond to the start or control request in a timely fashion. – Paul Johnson Oct 17 '18 at 15:13
  • Have you tried manually registering your service after building it and without installing it with wix ? I mean taking the raw binary output from your release folder and using the sc create command to register it. Check this : https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/sc-create. If it still fails to start it means that the problem is not related to Wix – Léo D. Oct 17 '18 at 16:28
  • Just adding [**an "ideas list" for debugging**](https://stackoverflow.com/a/49637913/129130). – Stein Åsmul Oct 17 '18 at 23:35

0 Answers0