app.config is breaking my windows service?

J

jason

Hello everyone,

I have written a very simple windows service in .NET 2.0 C#. The
following is its OnStart() method:

protected override void OnStart(string[] args)
{
try
{
//Config.Load(AppDomain.CurrentDomain.BaseDirectory +
"TaskCenter.config");
Worker = new Thread(new ThreadStart(Work));
Worker.SetApartmentState(ApartmentState.STA);
Worker.Start();
}
catch (Exception ex)
{
Error.ProcessServiceError(ex, MachineName,
"192.168.16.2", "Local");
}
}

The Worker thread is also incredibly simple:

private void Work()
{
while (true)
{
Thread.Sleep(1000);
try
{
DataTable dt = Task.GetToDoList();
Task t = new Task();

foreach (DataRow dr in dt.Rows)
{
t.Populate((Guid)dr["taskid"]);
t.Execute();
}
}
catch (Exception ex)
{
Error.ProcessServiceError(ex, MachineName,
"192.168.16.2", "Local");
}
}
}

Error and Task both come from a class library (also .NET 2.0 in C#).
When I originally wrote this service, I stubbed out the
Task.GetToDoList method to just write to a log file. In that stubbed
out world, everything worked correctly. I could install the service
using InstallUtil.exe, I could start the service in the control panel,
I could attach to the service using the VS debugger, and watch it step
through the code with the predicted results.

The problem started when I tried to replace the stub with real code.
The real version of the GetToDoList method needs to talk to the
database. The class library includes a reusable data utility class
that expects the consuming application to have a configuration
settings file, and gets the configuration strings from the
ConfigurationManager class.

No problems there, the class library gets that information just fine
when used by the ASP.NET website and the web service which were also
written to use the class library.

The problem is only with the windows service configuration. I added an
app.config file to the project through the VS2005 menu system (Add ->
New item -> Application Configuration). The application configuration
file started off nearly empty, and I only modified it to include the
necessary connection string:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<add name="Database"
connectionString="Server=12.3.4.56;Database=mydb;uid=user;pwd=password;"/</configuration>

Suddenly, after adding this file, the windows service won't start.
Installation still succeeds with InstallUtil, but when I attempt to
start the service I get "Error 1053" stating that the service did not
respond to the start request in a timely manner. From everything I've
read on the net, this is often caused by an unhandled exception in
OnStart(). I don't think that's the case this time though, since the
application works just fine without the configuration file.

To further get evidence to this end, I went to the Debug folder for
the windows service and renamed the MyService.exe.config file to
M.E.C. Suddenly the service starts just fine (didn't even need to
reinstall it). However when I rename the file back, the service fails
to start again.

I am assuming that the problem is in the app.config file itself, and
that the service is choking when it tries to read the document in at
start-time. Anyone have any ideas? Something obviously missing from
the config file maybe?

Thanks for any help,

Jason
 
J

jason

Please ignore the line that reads:

//Config.Load(AppDomain.CurrentDomain.BaseDirectory +
"TaskCenter.config");

That is an erroenous comment to this question. That was my attempt to
load a custom XML file for configuration, which wouldn't work because
that circumvents the entire ConfigurationManager, which the class
library requires. I just forgot to take it out before I pasted the
code.

Thanks,

Jason
 
S

sloan

With service running config files...I use the "externalize the files" trick.

app.config

<?xml version = "1.0" encoding = "utf-8" ?>
<configuration>

<appSettings file="CustomAppSettings.config" >
</appSettings>

<connectionStrings configSource="ExternalConnectionStrings.config" />

</configuration>



CustomAppSettings.config

<appSettings>

<add key="key1" value="value1" />






</appSettings>




ExternalConnectionStrings.config
<connectionStrings>

<add name="MainDatabaseConnectionString"
connectionString="server=.;database=MyDatabase;User
ID=user1;password=password1" providerName="System.Data.SqlClient"/>

</connectionStrings>



It helped ease the service deployment for me.


Now..you gotta do some post build event logic to copy those extra config
files.




To give credit where its due.

http://www.eggheadcafe.com/tutorial...180-c1f564b41f85/some-aspnet-20-configur.aspx

is where I got the heads up on some of this stuff.






jason said:
Hello everyone,

I have written a very simple windows service in .NET 2.0 C#. The
following is its OnStart() method:

protected override void OnStart(string[] args)
{
try
{
//Config.Load(AppDomain.CurrentDomain.BaseDirectory +
"TaskCenter.config");
Worker = new Thread(new ThreadStart(Work));
Worker.SetApartmentState(ApartmentState.STA);
Worker.Start();
}
catch (Exception ex)
{
Error.ProcessServiceError(ex, MachineName,
"192.168.16.2", "Local");
}
}

The Worker thread is also incredibly simple:

private void Work()
{
while (true)
{
Thread.Sleep(1000);
try
{
DataTable dt = Task.GetToDoList();
Task t = new Task();

foreach (DataRow dr in dt.Rows)
{
t.Populate((Guid)dr["taskid"]);
t.Execute();
}
}
catch (Exception ex)
{
Error.ProcessServiceError(ex, MachineName,
"192.168.16.2", "Local");
}
}
}

Error and Task both come from a class library (also .NET 2.0 in C#).
When I originally wrote this service, I stubbed out the
Task.GetToDoList method to just write to a log file. In that stubbed
out world, everything worked correctly. I could install the service
using InstallUtil.exe, I could start the service in the control panel,
I could attach to the service using the VS debugger, and watch it step
through the code with the predicted results.

The problem started when I tried to replace the stub with real code.
The real version of the GetToDoList method needs to talk to the
database. The class library includes a reusable data utility class
that expects the consuming application to have a configuration
settings file, and gets the configuration strings from the
ConfigurationManager class.

No problems there, the class library gets that information just fine
when used by the ASP.NET website and the web service which were also
written to use the class library.

The problem is only with the windows service configuration. I added an
app.config file to the project through the VS2005 menu system (Add ->
New item -> Application Configuration). The application configuration
file started off nearly empty, and I only modified it to include the
necessary connection string:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<add name="Database"
connectionString="Server=12.3.4.56;Database=mydb;uid=user;pwd=password;"/</configuration>

Suddenly, after adding this file, the windows service won't start.
Installation still succeeds with InstallUtil, but when I attempt to
start the service I get "Error 1053" stating that the service did not
respond to the start request in a timely manner. From everything I've
read on the net, this is often caused by an unhandled exception in
OnStart(). I don't think that's the case this time though, since the
application works just fine without the configuration file.

To further get evidence to this end, I went to the Debug folder for
the windows service and renamed the MyService.exe.config file to
M.E.C. Suddenly the service starts just fine (didn't even need to
reinstall it). However when I rename the file back, the service fails
to start again.

I am assuming that the problem is in the app.config file itself, and
that the service is choking when it tries to read the document in at
start-time. Anyone have any ideas? Something obviously missing from
the config file maybe?

Thanks for any help,

Jason
 
J

jason

I'm an even bigger dork than I thought. It's always something
retarded. My app.config looks like this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<add name="Database"
connectionString="Server=12.3.4.56;Database=mydb;uid=user;pwd=password;"/</configuration>

Which is missing the <connectionStrings> element entirely! I changed
it to this:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<connectionStrings>
<add name="Database"
connectionString="Server=12.3.4.56;Database=mydb;uid=user;pwd=password;"/</connectionStrings>
</configuration>

And it worked just fine. Thanks for the suggestion though, I will keep
it in mind when it comes to deployment strategies!

And thanks to anyone else that corrects my oversight :)

Jason
 
S

sloan

Well, whichever way you figured it out..you got it. :)
That's the big thing!

(Of course its easy to see now .. that you've pointed it out)


I use the otherFile.config method...because alot of times in a
Service....there are settings which I will change from dev to production
and then there are settings I won't.

Because several people can alter the values...I can actually assign privs to
people as needed.
Instead of giving them the keys to the whole shabang.

So user1 can change connection strings.
User2 can only change app settings.

its anal, but sometimes in a large multi user environment, you need it.

I have WCF stuff as well, and I have those split out to different files.

I didn't like it at first, but like it now.

Aka, "Uh yeah, Junior Developer, why are you opening that file.. there's
nothing in there you need to change"

I can't do that with the entire app.config file when it has alot /lotta
stuff.

...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top