473,405 Members | 2,282 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,405 software developers and data experts.

Unable to properly set the InteractiveProcess property on a windows service

Hello,

I have written a windows service and created an installer for it.
The service runs under the system accounts. When started, it launches a
GUI.
By default, the InteractiveProcess property of the service is not set
(this can be checked by right-clicking on the service in the Services
window (Admin tools>Services), choosing Properties, LogOn tab). In
order to enable my service to launch a GUI at startup, I added the
following lines in my installer :

public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
SetInteractWithDesktop();
}
private void SetInteractWithDesktop()
{
RegistryKey fm;
ServiceType type;

fm =
Registry.LocalMachine.OpenSubKey(@"SYSTEM\CURRENTC ONTROLSET\SERVICES\myserv",
true);
type = ServiceType.InteractiveProcess |
ServiceType.Win32OwnProcess;
fm.SetValue("Type", (int)type);
fm.Close();

}

This modifies the appropriate Registry key in order to enable the
InteractiveProcess property.

If I install this service and run it : it does not display my GUI.
However, if I check in Admin tools>Services>*myserv*Properties>LogOn
tab, I can see the box ticked for "Allow service to interact with
Desktop", which is the expected behavior.

Now if I untick and tick again this box, press ok, and start my
service, it works fine, displaying the GUI correctly.

I'm wondering whether the registry key Im changing when installing the
service, is the only one to be changed in order to enable interaction
with the desktop.

Any ideas that could help me ?

Cheers,

Tibo

Apr 7 '06 #1
2 4649
Changing the registry key will only affect how the service control manager
handles the service the next time it reads the registry key. Normally this
occurs the next time the system boots. It takes effect after you manually
change it because the SCM is the one modifying the registry key value. If
you want the changes to take effect immediately you need to use the
unmanaged SCM API calls to create the service using the correct service type
flags. There may be a way to modify it after it has been created - you'd
have to do some research to find out.

The way I install my service so that the service type is set to Interactive
is to override the installer class and to manually invoke the call to
CreateService, specifying the parameters myself. The actual call in the
installer code looks like this...

// set up call....lots of code here...
Win32Interop.CreateService( serviceName,displayName, description,
null,assemblypath,ServiceStartMode.Automatic,
ServiceType.InteractiveProcess | ServiceType.Win32OwnProcess );
where Win32Interop.CreateService is defined as...

public static void CreateService(
string serviceName,string displayName,string description,
string dependsOn,string assemblyFile,
System.ServiceProcess.ServiceStartMode startType,
System.ServiceProcess.ServiceType serviceType
)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
scHandle = OpenSCManager(null,null,SC_MANAGER_ALL_ACCESS);
if ( scHandle != INVALID_HANDLE_VALUE )
{
hService = CreateService(scHandle, serviceName,
displayName, SERVICE_ALL_ACCESS, (uint)serviceType,
(uint)startType,SERVICE_ERROR_NORMAL,
assemblyFile, null, null, dependsOn, null, null);
}
if (hService == IntPtr.Zero) // did it create the service???
// "Error creating windows service."
throw new Win32Exception(
Marshal.GetLastWin32Error(),
LocalizationManager.Resources.GetString("ServiceIn staller_CreateService")
);
}
finally
{
if (hService != IntPtr.Zero)
CloseServiceHandle(hService); // close both handles
if (scHandle != IntPtr.Zero)
CloseServiceHandle(scHandle);
}

} // CreateService

where I defined the signature of the API as
[DllImport("advapi32", SetLastError = true)]
private static extern IntPtr CreateService(IntPtr hSCManager, string
serviceName, string displayName,
uint dwDesiredAccess, uint serviceType, uint startType, uint
errorControl,
string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId,
string lpDependencies,
string lpServiceStartName, string lpPassword);

This has the added benefit of allowing me to specify the service
description - for some reason it was not part of the 1.1 API.

<le*****@gmail.com> wrote in message
news:11*********************@j33g2000cwa.googlegro ups.com...
Hello,

I have written a windows service and created an installer for it.
The service runs under the system accounts. When started, it launches a
GUI.
By default, the InteractiveProcess property of the service is not set
(this can be checked by right-clicking on the service in the Services
window (Admin tools>Services), choosing Properties, LogOn tab). In
order to enable my service to launch a GUI at startup, I added the
following lines in my installer :

public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
SetInteractWithDesktop();
}
private void SetInteractWithDesktop()
{
RegistryKey fm;
ServiceType type;

fm =
Registry.LocalMachine.OpenSubKey(@"SYSTEM\CURRENTC ONTROLSET\SERVICES\myserv",
true);
type = ServiceType.InteractiveProcess |
ServiceType.Win32OwnProcess;
fm.SetValue("Type", (int)type);
fm.Close();

}

This modifies the appropriate Registry key in order to enable the
InteractiveProcess property.

If I install this service and run it : it does not display my GUI.
However, if I check in Admin tools>Services>*myserv*Properties>LogOn
tab, I can see the box ticked for "Allow service to interact with
Desktop", which is the expected behavior.

Now if I untick and tick again this box, press ok, and start my
service, it works fine, displaying the GUI correctly.

I'm wondering whether the registry key Im changing when installing the
service, is the only one to be changed in order to enable interaction
with the desktop.

Any ideas that could help me ?

Cheers,

Tibo

Apr 7 '06 #2
Cheers for that explanation, you're the man !!

I'm posting here my solution
Note : I also borrowed some code from the useful following resources :

http://www.codeproject.com/csharp/cs...erviceinst.asp
http://www.codeproject.com/csharp/se...stallerext.asp
************************************************** **********************************************
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Configuration.Install;
using System.ComponentModel;
using System.ServiceProcess;

public class myServiceInstaller :
System.ServiceProcess.ServiceInstaller
{

#region Misc Win32 Interop Stuff
// Win32 function to unlock the service database.
[DllImport("advapi32.dll")]
public static extern bool
UnlockServiceDatabase(IntPtr hSCManager);

// Win32 function to lock the service database to perform
write operations.
[DllImport("advapi32.dll")]
public static extern IntPtr
LockServiceDatabase(IntPtr hSCManager);

// Win32 function to open the service control manager
[DllImport("advapi32.dll")]
public static extern
IntPtr OpenSCManager(string lpMachineName, string
lpDatabaseName, int dwDesiredAccess);

// Win32 function to open a service instance
[DllImport("advapi32.dll")]
public static extern IntPtr
OpenService(IntPtr hSCManager, string lpServiceName,
int dwDesiredAccess);
// Win32 function to close a service related handle.
[DllImport("advapi32.dll")]
public static extern bool
CloseServiceHandle(IntPtr hSCObject);

[DllImport("advapi32.dll")]
public static extern bool ChangeServiceConfigA(
int hService, ServiceType dwServiceType, int
dwStartType,
int dwErrorControl, string lpBinaryPathName, string
lpLoadOrderGroup,
int lpdwTagId, string lpDependencies, string
lpServiceStartName,
string lpPassword, string lpDisplayName);

private const int SC_MANAGER_ALL_ACCESS = 0xF003F;
private const int SERVICE_ALL_ACCESS = 0xF01FF;
private const int SERVICE_NO_CHANGE = -1;
#endregion

private void LogInstallMessage(string msg)
{
Console.WriteLine(msg);
}

public myServiceInstaller()
: base()
{
base.Committed += new
InstallEventHandler(this.UpdateServiceConfig);
}

private void UpdateServiceConfig(object sender,
InstallEventArgs e)
{
IntPtr scmHndl = IntPtr.Zero;
IntPtr svcHndl = IntPtr.Zero;
IntPtr tmpBuf = IntPtr.Zero;
IntPtr svcLock = IntPtr.Zero;

bool rslt = false;

try
{
// Open the service control manager
scmHndl = OpenSCManager(null, null,
SC_MANAGER_ALL_ACCESS);
if (scmHndl.ToInt32() <= 0)
{
LogInstallMessage("Failed to Open Service
Control Manager");
return;
}
// Lock the Service Database
svcLock = LockServiceDatabase(scmHndl);
if (svcLock.ToInt32() <= 0)
{
LogInstallMessage("Failed to Lock Service
Database for Write");
return;
}
// Open the service
svcHndl = OpenService(scmHndl, base.ServiceName,
SERVICE_ALL_ACCESS);
if (svcHndl.ToInt32() <= 0)
{
LogInstallMessage("Failed to Open Service ");
return;
}

rslt = ChangeServiceConfigA((int)svcHndl,
ServiceType.Win32OwnProcess |
ServiceType.InteractiveProcess,
SERVICE_NO_CHANGE,
SERVICE_NO_CHANGE,
null,
null,
0,
null,
null,
null,
null);
if (!rslt)
LogInstallMessage("Could not set the
service type.");
else
LogInstallMessage("Service type set.");
}
catch (Exception ex)
{
LogInstallMessage(ex.Message);
}
finally
{
if (scmHndl != IntPtr.Zero)
{
// Unlock the service database
if (svcLock != IntPtr.Zero)
{
UnlockServiceDatabase(svcLock);
svcLock = IntPtr.Zero;
}
// Close the service control manager handle
CloseServiceHandle(scmHndl);
scmHndl = IntPtr.Zero;
}
// Close the service handle
if (svcHndl != IntPtr.Zero)
{
CloseServiceHandle(svcHndl);
svcHndl = IntPtr.Zero;
}
// Free the memory
if (tmpBuf != IntPtr.Zero)
{
Marshal.FreeHGlobal(tmpBuf);
tmpBuf = IntPtr.Zero;
}
}
}
}
}
}

David Levine wrote:
Changing the registry key will only affect how the service control manager
handles the service the next time it reads the registry key. Normally this
occurs the next time the system boots. It takes effect after you manually
change it because the SCM is the one modifying the registry key value. If
you want the changes to take effect immediately you need to use the
unmanaged SCM API calls to create the service using the correct service type
flags. There may be a way to modify it after it has been created - you'd
have to do some research to find out.

The way I install my service so that the service type is set to Interactive
is to override the installer class and to manually invoke the call to
CreateService, specifying the parameters myself. The actual call in the
installer code looks like this...

// set up call....lots of code here...
Win32Interop.CreateService( serviceName,displayName, description,
null,assemblypath,ServiceStartMode.Automatic,
ServiceType.InteractiveProcess | ServiceType.Win32OwnProcess );
where Win32Interop.CreateService is defined as...

public static void CreateService(
string serviceName,string displayName,string description,
string dependsOn,string assemblyFile,
System.ServiceProcess.ServiceStartMode startType,
System.ServiceProcess.ServiceType serviceType
)
{
IntPtr scHandle = IntPtr.Zero;
IntPtr hService = IntPtr.Zero;
try
{
scHandle = OpenSCManager(null,null,SC_MANAGER_ALL_ACCESS);
if ( scHandle != INVALID_HANDLE_VALUE )
{
hService = CreateService(scHandle, serviceName,
displayName, SERVICE_ALL_ACCESS, (uint)serviceType,
(uint)startType,SERVICE_ERROR_NORMAL,
assemblyFile, null, null, dependsOn, null, null);
}
if (hService == IntPtr.Zero) // did it create the service???
// "Error creating windows service."
throw new Win32Exception(
Marshal.GetLastWin32Error(),
LocalizationManager.Resources.GetString("ServiceIn staller_CreateService")
);
}
finally
{
if (hService != IntPtr.Zero)
CloseServiceHandle(hService); // close both handles
if (scHandle != IntPtr.Zero)
CloseServiceHandle(scHandle);
}

} // CreateService

where I defined the signature of the API as
[DllImport("advapi32", SetLastError = true)]
private static extern IntPtr CreateService(IntPtr hSCManager, string
serviceName, string displayName,
uint dwDesiredAccess, uint serviceType, uint startType, uint
errorControl,
string lpBinaryPathName, string lpLoadOrderGroup, string lpdwTagId,
string lpDependencies,
string lpServiceStartName, string lpPassword);

This has the added benefit of allowing me to specify the service
description - for some reason it was not part of the 1.1 API.

<le*****@gmail.com> wrote in message
news:11*********************@j33g2000cwa.googlegro ups.com...
Hello,

I have written a windows service and created an installer for it.
The service runs under the system accounts. When started, it launches a
GUI.
By default, the InteractiveProcess property of the service is not set
(this can be checked by right-clicking on the service in the Services
window (Admin tools>Services), choosing Properties, LogOn tab). In
order to enable my service to launch a GUI at startup, I added the
following lines in my installer :

public override void Install(IDictionary stateSaver)
{
base.Install(stateSaver);
SetInteractWithDesktop();
}
private void SetInteractWithDesktop()
{
RegistryKey fm;
ServiceType type;

fm =
Registry.LocalMachine.OpenSubKey(@"SYSTEM\CURRENTC ONTROLSET\SERVICES\myserv",
true);
type = ServiceType.InteractiveProcess |
ServiceType.Win32OwnProcess;
fm.SetValue("Type", (int)type);
fm.Close();

}

This modifies the appropriate Registry key in order to enable the
InteractiveProcess property.

If I install this service and run it : it does not display my GUI.
However, if I check in Admin tools>Services>*myserv*Properties>LogOn
tab, I can see the box ticked for "Allow service to interact with
Desktop", which is the expected behavior.

Now if I untick and tick again this box, press ok, and start my
service, it works fine, displaying the GUI correctly.

I'm wondering whether the registry key Im changing when installing the
service, is the only one to be changed in order to enable interaction
with the desktop.

Any ideas that could help me ?

Cheers,

Tibo


Apr 7 '06 #3

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: SPG | last post by:
Hi, We have a standard windows app writeen in C# that uses an ActiveX dll to send us events. This works fine as a Windows app, but as soon as we compile as a service, no more events. I have...
16
by: Serdar Kalaycý | last post by:
Hi everybody, My problem seems a bit clichè but I could not work around. Well I read lots of MSDN papers and discussions, but my problem is a bit different from them. When I tried to run the...
22
by: EP | last post by:
When running my asp.net hosting service (asp.net without IIS), on server 2003 with IIS not installed, I get the following when trying to process a request. "System.DllNotFoundException: Unable to...
2
by: Randall Powell | last post by:
I am in the process of developing a Windows Service which will: (1) monitor multiple network shares; (2) marshal text file transfers into an SQL Server 2000 instance; and (3) provide messaging...
2
by: geno | last post by:
Hello, When using VB.Net to connect ot a web service, I am getting the error The underlying connection was closed: Unable to connect to the remote server What could be causing this? ...
6
by: kmpodury | last post by:
PLEASE HELP!!!!!! Here is the exception that I am getting Exception: System.ArgumentException Message: The directory name W:\AudioFiles is invalid. Source: System at...
3
by: tshad | last post by:
I created a service in VS 2003 and the code works fine as an application, but not as a service. It installs fine, but when I try to start it, it tells me it was unable to start. Am I missing...
1
by: Izzy | last post by:
I created a windows service using VS 2005 in VB.NET and it runs on my Windows XP Pro machine just fine, now I'm want to install it on one of my servers which is a Windows 2000 Terminal server...
8
by: asherLaci | last post by:
Hi, I developed 2 applications: 1) ASP.NET Web Service 2) Windows application, that communicate with the Web service using SOAP In the Web service I can read any text file but i can't write...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.