方法一:
在ProjectInstaller.cs重写 install() ,Uninstall()方法
public override void Install(IDictionary stateServer)
{
Microsoft.Win32.RegistryKey system,
//HKEY_LOCAL_MACHINE/Services/CurrentControlSet
currentControlSet,
//.../Services
services,
//.../<Service Name>
service,
//.../Parameters - this is where you can put service-specific configuration
config;
try
{
//Let the project installer do its job
base.Install(stateServer);
//Open the HKEY_LOCAL_MACHINE/SYSTEM key
system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
//Open CurrentControlSet
currentControlSet = system.OpenSubKey("CurrentControlSet");
//Go to the services key
services = currentControlSet.OpenSubKey("Services");
//Open the key for your service, and allow writing
service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
//Add your service's description as a REG_SZ value named "Description"
service.SetValue("Description","PI实时数据采集:能源--每天8点或20点取一次数据;汽车衡--每天1点取一次数据;设备状态--每分钟取一次数据。");
//(Optional) Add some custom information your service will use...
//允许服务与桌面交互
service.SetValue("Type",0x00000110);
config = service.CreateSubKey("Parameters");
}
catch(Exception e)
{
Console.WriteLine("An exception was thrown during service installation:/n" + e.ToString());
}
}
public override void Uninstall(IDictionary stateServer)
{
Microsoft.Win32.RegistryKey system,
currentControlSet,
services,
service;
try
{
//Drill down to the service key and open it with write permission
system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
currentControlSet = system.OpenSubKey("CurrentControlSet");
services = currentControlSet.OpenSubKey("Services");
service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
//Delete any keys you created during installation (or that your service created)
service.DeleteSubKeyTree("Parameters");
//...
}
catch(Exception e)
{
Console.WriteLine("Exception encountered while uninstalling service:/n" + e.ToString());
}
finally
{
//Let the project installer do its job
base.Uninstall(stateServer);
}
}
我们写一个服务,有时候要让服务启动某个应用程序,就要修改服务的属性,勾选允许服务与桌面交互,
可以用修改注册表实现,我们必须在安装后操作,所以请重写Installer的OnAfterInstall。
protected override void OnAfterInstall(System.Collections.IDictionary savedState) { RegistryKey rk = Registry.LocalMachine; string key = @" SYSTEM/CurrentControlSet/Services/ " + this .sInstaller.ServiceName; RegistryKey sub = rk.OpenSubKey(key, true ); int value = ( int )sub.GetValue( " Type " ); if (value < 256 ) { sub.SetValue( " Type " , value | 256 ); } base .OnAfterInstall(savedState); }onstart的时候修改注册表 [HKEY_LOCAL_MACHINE/SYSTEM/CurrentControlSet/Services/你的服务名] "Type"=dword:00000010 key value+256 比如现在00000010是16+256=272 16进制就是00000110
方法三:使用System.ServiceProcess.ServiceControllerConnectionOptions coOptions = new ConnectionOptions();coOptions.Impersonation = ImpersonationLevel.Impersonate;ManagementScope mgmtScope = new System.Management.ManagementScope(@"root/CIMV2", coOptions);mgmtScope.Connect();ManagementObject wmiService;wmiService = new ManagementObject("Win32_Service.Name='" + ServiceController.ServiceName + "'");ManagementBaseObject InParam = wmiService.GetMethodParameters("Change");InParam["DesktopInteract"] = true;ManagementBaseObject OutParam = wmiService.InvokeMethod("Change", InParam, null);ServiceController.Start();描述:在自己写的一个系统服务程序,需要经常用到“允许与桌面进行交互”的设置,网上很多使用修改注册表的形式实现,我测试过,修改注册表后,选中的勾是选上了,
但不能弹出应用程序;据说重启电脑后可以,但我不想重启,实际应用也不允许重启,故没有测试重启是否可行的情况。如图:
例如:
当我需要运行服务程序的时候,弹出我的应用程序,则要在Windows服务“允许服务与桌面交互”中打勾,
当我不想弹出应用程序界面的时候,则去掉其中的勾选。
实现方式:
1.在服务程序安装时编程实现,ProjectInstaller.cs
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel; using System.Configuration.Install; //using System.Linq; using Microsoft.Win32; //对注册表操作一定要引用这个命名空间 namespace MonitorService { [RunInstaller(true)] public partial class ProjectInstaller : Installer { public ProjectInstaller() { InitializeComponent(); //this.Context.Parameters["ServerCode"].ToString(); // 读取安装时输入的服务器编号 } private void ProjectInstaller_AfterInstall(object sender, InstallEventArgs e) { //设置允许服务与桌面交互 SetServiceTable("MonitorService"); } /// <summary> /// 设置允许服务与桌面交互 ,修改了注册表,要重启系统才能生效 /// </summary> /// <param name="ServiceName">服务程序名称</param> private void SetServiceTable(string ServiceName) { RegistryKey rk = Registry.LocalMachine; string key = @"SYSTEM/CurrentControlSet/Services/" + ServiceName; RegistryKey sub = rk.OpenSubKey(key, true); int value = (int)sub.GetValue("Type"); sub.SetValue("Type", value | 256); } } }
2.注册表修改
onstart的时候修改注册表 [HKEY_LOCAL_MACHINE"SYSTEM"CurrentControlSet"Services"你的服务名] "Type"=dword:00000010 key value+256 比如现在00000010是16+256=272 16精制就是00000110
3.SC程序修改, 允许与桌面进行交互
在dos命令提示符下输入: sc config MonitorService type= interact type= own
回车即可。
可以用批处理的方式实现,把下面代码保存为 myservice.bat 即可:
rem 配置服务程序为允许与桌面进行交互方式 @echo "准备停止服务程序..." sc stop MyService @echo "设置允许与桌面进行交互方式允许" sc config MyService type= interact type= own @echo "正在重新启动服务..." sc start MyService @echo "启动服务成功!"
取消“允许与桌面进行交互”
DOS命令提示符下运行下面语句即可:
sc config MyService type= own
经测试:1,2 可以选中“允许与桌面进行交互”,但启动服务的时候,不能弹出应用程序的界面。
3 可以完美实现所有要求。
至此,我遇到的问题也完美的得到解决。
用VS2003部署,让服务程序安装完后立即启动服务并且选中“允许服务与桌面交互”及添加服务描述的方法
- -----------立即启动--------------
- private void serviceInstaller1_AfterInstall(object sender, System.Configuration.Install.InstallEventArgs e)
- {
- ServiceController myService = new ServiceController("XJOAPigeonholeServer");
- myService.Start();
- myService.Dispose();
- }
- 添加描述:1.1没有直接方法,2.0里有直接的方法 ServiceInstaller.Description
- //----------------------------添加服务描述信息 开始 ------------
- public override void Install(IDictionary stateServer)
- {
- Microsoft.Win32.RegistryKey system,
- //HKEY_LOCAL_MACHINE/Services/CurrentControlSet
- currentControlSet,
- //.../Services
- services,
- //.../ <Service Name>
- service,
- //.../Parameters - this is where you can put service-specific configuration
- config;
- try
- {
- //Let the project installer do its job
- base.Install(stateServer);
- //Open the HKEY_LOCAL_MACHINE/SYSTEM key
- system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
- //Open CurrentControlSet
- currentControlSet = system.OpenSubKey("CurrentControlSet");
- //Go to the services key
- services = currentControlSet.OpenSubKey("Services");
- //Open the key for your service, and allow writing
- service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
- //Add your service's description as a REG_SZ value named "Description"
- service.SetValue("Description","XJOA系统自动归档服务(BeijiOffice)");
- //(Optional) Add some custom information your service will use...
- //允许服务与桌面交互
- service.SetValue("Type",0x00000110);
- config = service.CreateSubKey("Parameters");
- }
- catch(Exception e)
- {
- Console.WriteLine("An exception was thrown during service installation:/n" + e.ToString());
- }
- }
- public override void Uninstall(IDictionary stateServer)
- {
- Microsoft.Win32.RegistryKey system,
- currentControlSet,
- services,
- service;
- try
- {
- //Drill down to the service key and open it with write permission
- system = Microsoft.Win32.Registry.LocalMachine.OpenSubKey("System");
- currentControlSet = system.OpenSubKey("CurrentControlSet");
- services = currentControlSet.OpenSubKey("Services");
- service = services.OpenSubKey(this.serviceInstaller1.ServiceName, true);
- //Delete any keys you created during installation (or that your service created)
- service.DeleteSubKeyTree("Parameters");
- //...
- }
- catch(Exception e)
- {
- Console.WriteLine("Exception encountered while uninstalling service:/n" + e.ToString());
- }
- finally
- {
- //Let the project installer do its job
- base.Uninstall(stateServer);
- }
- }
- //---------------------------- 结束 ----------------------------
四、这一服务程序运行时没有图形界面?
不错,刚才直接运行mfc1.exe时我们看到了图形界面,但在服务列表中用右键菜单中的“启动”时却看不到任何界面。这该怎么办?
我们还需要在使用CreateService函数时(Install()中),加上一个参数,这样才能允许程序与桌面交互,也就是可以显示界面。这个参数是SERVICE_INTERACTIVE_PROCESS。
填加后的CreateService:
SC_HANDLE hService = ::CreateService( hSCM, m_szServiceName, m_szServiceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, szFilePath, NULL, NULL, _T("RPCSS"), NULL, NULL);
再次编译mfc1,卸载服务后,安装服务。我们可以看到,通过服务列表启动mfc1,原有的对话框出现了。
如需将服务设为自动启动,则将 SERVICE_DEMAND_START 改为 SERVICE_AUTO_START。