設置c#windows服務描述及允許服務與桌面交互的幾種方法(作者博客還有一大堆C#創建服務的文章)


方法一:

在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.ServiceController

            ConnectionOptions 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部署,讓服務程序安裝完后立即啟動服務並且選中“允許服務與桌面交互”及添加服務描述的方法

 

<textarea cols="50" rows="15" name="code" class="c-sharp">-----------立即啟動-------------- 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, //.../ &lt;Service Name&gt; 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); } } //---------------------------- 結束 ---------------------------- </textarea>

 

 

四、這一服務程序運行時沒有圖形界面?

不錯,剛才直接運行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。

http://blog.csdn.net/jiangxinyu/article/details/5397060


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM