I have an application which consists of a service and an executable. Essentially it's a forms application that is responsible for starting and stopping a service under specific circumstances.
On Windows XP the application manages this fine using the following code:
ServiceController controller = new ServiceController();
controller.MachineName = ".";
controller.ServiceName = "XXXXXXXXXX";
controller.Stop();
controller.WaitForStatus(ServiceControllerStatus.Stopped, new TimeSpan(0, 0, 10));
controller.Start();
But on Windows 7, even though I've started the application as an administrator, I get the following exception:
System.InvalidOperationException: Cannot open XXXXXXXXXXXXX service on computer '.'. ---> System.ComponentModel.Win32Exception: Access is denied
--- End of inner exception stack trace ---
at System.ServiceProcess.ServiceController.GetServiceHandle(Int32 desiredAccess)
at System.ServiceProcess.ServiceController.Start(String[] args)
at System.ServiceProcess.ServiceController.Start()
Is there anything I can do programmatically to resolve this?
When you say that you started the application as Administrator, do you mean under an account in the Administrators group, or via a UAC prompt that requests administrator credentials? Without the UAC credentials prompt (or actually running as the Administrator account, not an account within the Administrators group), your application does not have permissions to modify services, so the exception you're seeing is correct.
This bit of example code can check if your application is running as an administrator, and if not, launch a UAC prompt.
public static class VistaSecurity
{
public static bool IsAdministrator()
{
WindowsIdentity identity = WindowsIdentity.GetCurrent();
if (null != identity)
{
WindowsPrincipal principal = new WindowsPrincipal(identity);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
return false;
}
public static Process RunProcess(string name, string arguments)
{
string path = Path.GetDirectoryName(name);
if (String.IsNullOrEmpty(path))
{
path = Environment.CurrentDirectory;
}
ProcessStartInfo info = new ProcessStartInfo
{
UseShellExecute = true,
WorkingDirectory = path,
FileName = name,
Arguments = arguments
};
if (!IsAdministrator())
{
info.Verb = "runas";
}
try
{
return Process.Start(info);
}
catch (Win32Exception ex)
{
Trace.WriteLine(ex);
}
return null;
}
}