I have a service that I need to be able to start and stop with a button. I am using a ServiceController in a seperate program and everything works as intended when I run thi
You have a few options:
1) You can require that your application runs as an administrator. Every time your application starts, you will be prompted with the UAC (on Windows 7 and Vista) and your application will be elevated to the required level.
Run .NET application as administrator
2) Your application can request an elevation when the action is required to stop and start the service. It would do this by starting another application at a higher level and this other application will do the actual start and stop.
How to elevate privileges only when required?
3) Preferred option, IMHO - You should build your service to run all of the time but just not do anything other than listen for requests via TCP/IP, Named Pipes or some other communication mechanism. Your service can then start or stop a thread that performs the real work.
4) You can modify the service rights. Here are some posts that give some information on this (I would still prefer option 3):
Start / Stop a Windows Service from a non-Administrator user account
http://msmvps.com/blogs/erikr/archive/2007/09/26/set-permissions-on-a-specific-service-windows.aspx
http://fstaal01.home.xs4all.nl/swsc-us.html
Update
I have changed some text and added option 4 based on Harry's comment. It seems that there are ways of tweaking the permissions. These require administrator rights initially but if you bundle something like swsc (third link) with your installation, you could use it to set the rights for you. I am not sure if there are any license implications for doing this. Alternatively, you could use a variant of the code he pasted.
The code I have is in C, but it shouldn't be too hard to adapt to VB - or you could put it in a DLL. Alternatively, you could launch a command shell and use the sc sdset
command.
wchar_t sddl[] = L"D:"
L"(A;;CCLCSWRPWPDTLOCRRC;;;SY)"
// default permissions for local system
L"(A;;CCDCLCSWRPWPDTLOCRSDRCWDWO;;;BA)"
// default permissions for administrators
L"(A;;CCLCSWLOCRRC;;;AU)"
// default permissions for authenticated users
L"(A;;CCLCSWRPWPDTLOCRRC;;;PU)"
// default permissions for power users
L"(A;;RP;;;IU)"
// added permission: start service for interactive users
;
DWORD InstallService()
{
SC_HANDLE manager, service;
PSECURITY_DESCRIPTOR sd;
DWORD err;
wchar_t apppath[MAX_PATH + 2];
// Note: because this is only called from main() which exits
// immediately afterwards, no attempt is made to close the
// handles generated.
if (!ConvertStringSecurityDescriptorToSecurityDescriptor(sddl,
SDDL_REVISION_1, &sd, NULL))
{
err = GetLastError();
printf("Error %u creating security descriptor.\n", err);
return err;
}
if (!GetModuleFileName(0, apppath, MAX_PATH + 1))
{
err = GetLastError();
printf("Error %u fetching module name.\n", err);
return err;
}
if (_wcsicmp(apppath + wcslen(apppath) - wcslen(exename), exename) != 0)
{
printf("Application name mismatch: %ls\n",
apppath + wcslen(apppath) - wcslen(exename));
return ERROR_INVALID_FUNCTION;
}
manager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE);
if (!manager)
{
err = GetLastError();
printf("Error %u connecting to service manager.\n", err);
return err;
}
service = CreateService(manager,
servicename,
displayname,
WRITE_DAC,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
apppath,
0,
0,
NULL,
NULL,
NULL);
if (!service)
{
err = GetLastError();
printf("Error %u installing service.\n", err);
return err;
}
if (!SetServiceObjectSecurity(service, DACL_SECURITY_INFORMATION, sd))
{
err = GetLastError();
printf("Error %u setting service security.\n", err);
return err;
}
printf("Service successfully installed.\n");
return 0;
}