472,342 Members | 1,467 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,342 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 4542
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...
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...
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...
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...
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...
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...
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...
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...
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...
0
by: concettolabs | last post by:
In today's business world, businesses are increasingly turning to PowerApps to develop custom business applications. PowerApps is a powerful tool...
0
better678
by: better678 | last post by:
Question: Discuss your understanding of the Java platform. Is the statement "Java is interpreted" correct? Answer: Java is an object-oriented...
0
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge...
0
by: Matthew3360 | last post by:
Hi there. I have been struggling to find out how to use a variable as my location in my header redirect function. Here is my code. ...
2
by: Matthew3360 | last post by:
Hi, I have a python app that i want to be able to get variables from a php page on my webserver. My python app is on my computer. How would I make it...
0
by: AndyPSV | last post by:
HOW CAN I CREATE AN AI with an .executable file that would suck all files in the folder and on my computerHOW CAN I CREATE AN AI with an .executable...
0
hi
by: WisdomUfot | last post by:
It's an interesting question you've got about how Gmail hides the HTTP referrer when a link in an email is clicked. While I don't have the specific...
0
by: Matthew3360 | last post by:
Hi, I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web...

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.