Going to do my best to answer the questions - though you seem to have quite
a few. I've put a block of asterisks at the end of my response since this is
going to be quite large after answering everything. If you have any other
questions please feel free to ask. I work with Windows services a lot. :o)
Why do I need to rename my project to the service name?
You don't, I do it to keep everything consistent.
Why do I need to set the "ServiceName" property to my service name?
Because Windows uses this when registering the service, and they must be
unique. Also, if we're on the same page, this is the value used as your
service name when writing events to the event log. Though I could be wrong,
I'm not 100% sure which property you're talking about.
Why do I need to set a property within my code to the service name?
See above.
Are all these required or am I just doing this for consistency purposes?
They're required. If you provide incorrect information the service will have
problems when registering. Which will usually throw an exception that you'll
be able to see if you're registering the service with InstallUtil at the
command prompt.
It pops up a dialoge asking me for service credentials. I'm not sure why
because I've defined them within my "ProjectInstaller.cs". But I was
getting this prior to setting any properties under the
"ProjectInstaller.cs" file. Why do I get this?
Windows services run under a non-interactive user account on the machines.
Typically when a service is first created in Visual Studio the default
settings require a user account the service will run as. You can change this
by opening your ProjectInstaller.cs file (double click it to bring up the
designer) and select your processInstaller component that should be visible.
If you want the service to run as a system account just change the account
to the account type you want. Be cautious about doing this, the system
accounts have unrestricted rights to the machine the service is running on.
The ServiceAccount.User enum requires if the Username and Password
properties on the component aren't set, when the service is being installed
the account information must be prompted. The reason you have to give the
full account (including domain/machine name) is because the service needs
the entire credential when it's starting.
If I wanted to use a tool such as AdvancedInstaller from
http://www.caphyon.com/, what would I need to do? Would I need any of
these propteries set within the "ProjectInstallerDesigner.cs" file?
Does AdvancedInstaller allow me to browse to the .EXE, add it to my
package, and then allow me to hardcode or prompt the user for what they
want?
What's the best way to do this?
This would be a question better suited to be asked by the software vendor. I
typically just use the Setup project available within Visual Studio for
deploying services.
NOTE: InstallUtil will not be available on your target machines as it is not
included with the .NET Framework. You will need to use an installer package
to get the service registered on the deployment machine. Also, about that -
you will need to use a custom installer action pointed to your service
executable to get the installer package to register your service. The
System.Configuration.Install.Installer class (which is the base class for
the ProjectInstaller) you made, handles registering the service with the
machine. You can use .NET Reflector if you want to actually take a look at
the code in the class how it uses the Win32 API and pinvoke if you're
interested in looking under the hood. :o)
After the service is installed, I appear to have two services:
SimpleService2
Hello-World
SimpleService2 won't start.
Hello-World starts and appears to work as expected. I can pause, etc.
without issue and items are appearing in event log.
Executing "InstallUtil -u WindowsService2.exe" appears to get rid of both
services.
I assume SimpleService2 is appearing because that is the name that I use
within the "SimpleService.cs" file??
This would be a result of not using a consistent service name throughout the
service. My suggestion would be to do a Find All within the IDE and search
for "SimpleService2" throughout your application and make sure it's updated
to the proper service name.
I assume the crendtial dialogue is coming from this service and not
Hello-World because it appears to have the correct credentials.
How do I get rid of the dialoge all together?
See the above answer on the project installer.
How do I get rid of "SimpleService" installation, since it appears to not
work anyway.
Change the service name in your application back to the original value,
register the service again and finally remove it again. This will get the
old service removed from the machine (hopefully) so it won't be listed.
HINT: When working with Windows services I have found it best to create a
batch file to install and uninstall the services into the program files
folder on my machine when testing. When InstallUtil is executed against the
service assembly the configuration in that executable is what is used during
the install/uninstall process. If you build the software before uninstalling
the old version this is what can result.
************************************************** ************************
************************************************** ************************
"dm3281" <dm****@nospam.netwrote in message
news:43**********************************@microsof t.com...
I'm really starting to hate writing services -- or trying to, anyway.
Why do I need to rename my project to the service name?
Why do I need to set the "ServiceName" property to my service name?
Why do I need to set a property within my code to the service name?
Are all these required or am I just doing this for consistency purposes?
Now for my real question/problem:
I have written this service and have this in my "SimpeService.cs":
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.ServiceProcess;
using System.Text;
namespace WindowsService2
{
public partial class SimpleService : System.ServiceProcess.ServiceBase
{
private System.Timers.Timer timer;
/// <summary>
/// Required deisgner variable
/// </summary>
public SimpleService()
{
// This call is required by the Windows.Forms Component
Designer
InitializeComponent();
this.timer = new System.Timers.Timer();
this.timer.Enabled = true;
timer.Interval = 5000;
timer.Elapsed += new
System.Timers.ElapsedEventHandler(timer_Elapsed);
CanPauseAndContinue = true;
this.ServiceName = "Hello-World Service";
}
void timer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
EventLog.WriteEntry("Hello World!");
//throw new Exception("The method or operation is not
implemented.");
}
protected override void OnStart(string[] args)
{
// TODO: Add code here to start your service.
EventLog.WriteEntry("Hello-World Service Started");
timer.Enabled = true;
}
protected override void OnStop()
{
// TODO: Add code here to perform any tear-down necessary to
stop your service.
EventLog.WriteEntry("Hello-World Service Paused");
timer.Enabled = false;
}
protected override void OnPause()
{
EventLog.WriteEntry("Hello-World Service paused");
timer.Enabled = false;
}
protected override void OnContinue()
{
EventLog.WriteEntry("Hello-World Service continued");
timer.Enabled = true;
}
}
}
This is in my "ProjectInstaller.cs" and I have set the service properties,
etc:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace WindowsService2
{
[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
private ServiceInstaller serviceInstaller;
private ServiceProcessInstaller processInstaller;
public ProjectInstaller()
{
InitializeComponent();
processInstaller = new ServiceProcessInstaller();
serviceInstaller = new ServiceInstaller();
// Service will run under system account
processInstaller.Account = ServiceAccount.LocalSystem;
// Service will have Start Type of Manual
serviceInstaller.StartType = ServiceStartMode.Manual;
serviceInstaller.ServiceName = "Hello-World Service";
Installers.Add(serviceInstaller);
Installers.Add(processInstaller);
}
}
}
My "Program.cs" has no changes:
using System.Collections.Generic;
using System.ServiceProcess;
using System.Text;
namespace WindowsService2
{
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
static void Main()
{
ServiceBase[] ServicesToRun;
// More than one user Service may run within the same process.
To add
// another service to this process, change the following line
to
// create a second service object. For example,
//
// ServicesToRun = new ServiceBase[] {new Service1(), new
MySecondUserService()};
//
ServicesToRun = new ServiceBase[] { new SimpleService() };
ServiceBase.Run(ServicesToRun);
}
}
}
Now, when I compiel the above, it all compiles fine.
I then jump to Admin Command Prompt and do a "installutil
WindowsService2.exe" and it does the following:
It pops up a dialoge asking me for service credentials. I'm not sure why
because I've defined them within my "ProjectInstaller.cs". But I was
getting this prior to setting any properties under the
"ProjectInstaller.cs" file. Why do I get this?
The format of the credentials appears to only accept
"machinename\username" and nothing else. It took me a while to figure
this out! Arrghhh
After the service is installed, I appear to have two services:
SimpleService2
Hello-World
SimpleService2 won't start.
Hello-World starts and appears to work as expected. I can pause, etc.
without issue and items are appearing in event log.
Executing "InstallUtil -u WindowsService2.exe" appears to get rid of both
services.
I assume SimpleService2 is appearing because that is the name that I use
within the "SimpleService.cs" file??
I assume the crendtial dialogue is coming from this service and not
Hello-World because it appears to have the correct credentials.
How do I get rid of the dialoge all together?
How do I get rid of "SimpleService" installation, since it appears to not
work anyway.
Any help would be appreciated.