设为首页 收藏本站
查看: 700|回复: 0

The step-by-step guide of making a C# (or VB.NET) Windows 7 Trigger Start Servic

[复制链接]

尚未签到

发表于 2015-5-8 12:57:17 | 显示全部楼层 |阅读模式
  Windows 7 introduces a new feature called Trigger-start Service. In this article, you will see a step-by-step guide of making a Windows 7 Trigger-start Service in Visual C# (or VB.NET).
  Services and background processes have tremendous influence on the overall performance of the system. If we could just cut down on the total number of services, we would reduce the total power consumption and increase the overall stability of the system. The Windows 7 Service Control Manager has been extended so that a service can be automatically started and stopped when a specific system event, or trigger, occurs on the system. The new mechanism is called Service Trigger Event. A service can register to be started or stopped when a trigger event occurs. This eliminates the need for services to start when the system starts, or for services to poll or actively wait for an event; a service can start when it is needed, instead of starting automatically whether or not there is work to do. Examples of redefined trigger events include arrival of a device of a specified device interface class or availability of a particular firewall port. A service can also register for a custom trigger event generated by an Event Tracing for Windows (ETW) provider.
  CSWin7TriggerStartService and VBWin7TriggerStartService samples in All-In-One Code Framework demonstrate how to make trigger-start Windows Service in Visual C# and VB.NET. The sample services are configured to start when a generic USB disk becomes available. It also shows how to trigger-start when the first IP address becomes available and trigger-stop when the last IP address becomes unavailable. The start and stop events are reported in Application event log.
Sample Prerequisite:
  Windows Server 2008 R2 and Windows 7
Service trigger events are not supported until Windows Server 2008 R2 and Windows 7.
Deployment of the Sample Service
  A. Setup
  Installutil.exe CSWin7TriggerStartService.exe
  It installs CSWin7TriggerStartService.exe into SCM as a Windows Service. If the current operating system support trigger-start service, the command prompt outputs "Configuring trigger-start service...", otherwise, it prints "The current system does not support trigger-start service.".
  B. Cleanup
  Installutil.exe /u CSWin7TriggerStartService.exe
  It uninstalls CSWin7TriggerStartService from SCM.
Step-by-step Creation Guide of the Sample
  
A.
Creating an ordinary Windows Service project
  Step1. In Visual Studio 2008, add a new Visual C# / Windows / Windows Service project named CSWin7TriggerStartService.
  Step2. Rename the default Service1 to TriggerStartService. Open the service in designer and set the ServiceName property to be CSWin7TriggerStartService. Drag and drop an event log component from toolbox to the design view, and set its Log property to be Application, and its Source to be CSWin7TriggerStartService. The event log component will be used to log some application messages.
  Step3. Right-click in the design view, and select Add Installer on the context menu. This creates the project installer components:
  serviceProcessInstaller1
serviceInstaller1
  Set the Account property of serviceProcessInstaller1 to be Local System, so the service will be run as Local System. Also rename serviceInstaller1 as triggerStartServiceInstaller, and make its ServiceName property CSWin7TriggerStartService. Keep everything else the default value.
  B. Adding P/Invoke signatures for native APIs and structs related to SCM
  Add a ServiceNative.cs file and define P/Invoke signatures for native APIs like ChangeServiceConfig2, QueryServiceConfig2 and the related structs and enumerations.
  C. Configuring the service to trigger-start when a generic USB disk becomes available (or trigger-start when the first IP address becomes available and trigger-stop when the last IP address becomes unavailable.)
  Services can be registered as trigger-start from the sc.exe command line utility (using the sc triggerinfo command and need to run the Command Shell as Administrator), or using the ChangeServiceConfig2 API programmatically. The service installer utility of .NET Windows Services (InstallUtil) does not support triggerinfo switch, so we do it programmatically. ProjectInstaller's AfterInstall event allows us to execute some codes after the serivce is installed. We are going to register the service as trigger-start in this event handler.
  Step1. Add AfterInstall event handler for triggerStartServiceInstaller:
private void triggerStartServiceInstaller_AfterInstall(object sender, InstallEventArgs e)
{  }
  
  Step2. Determine if the current operating system is Windows 7 and above.
  Service trigger events are not supported until Windows Server 2008 R2 and Windows 7. Windows Server 2008 R2 and Windows 7 have major version 6 and minor version 1.
if (Environment.OSVersion.Version.Major > 6 ||
   (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor >= 1))
{  }
  
  Step3. Set service trigger start on USB arrival.
  To modify service configuration programmatically, the Win32 API function ChangeServiceConfig2 must be called with the appropriate parameters.
  1. Allocate a SERVICE_TRIGGER_SPECIFIC_DATA_ITEM structure
a) Set its dwDataType member to SERVICE_TRIGGER_DATA_TYPE_STRING
b) Set its cbData member to the length of the string L"USBSTOR\\GenDisk" in bytes
c) Set its pData member to that string.
  2. Allocate a SERVICE_TRIGGER structure
a) Set its dwTriggerType member to SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL
b) Set its dwAction member to SERVICE_TRIGGER_ACTION_SERVICE_START
c) Set its pTriggerSubtype member to the address of the GUID_DEVINTERFACE_DISK GUID
d) Set its cDataItems member to 1 and its pDataItems member to the address of the structure allocated in the previous step.
  3. Allocate a SERVICE_TRIGGER_INFO structure
a) Set its cTriggers member to 1 and its pTriggers member to the address of the structure allocated in the previous step.
  4. Call the ChangeServiceConfig2 function with the SERVICE_CONFIG_TRIGGER_INFO information level and pass to it the address of the structure allocated in the previous step.
  Please note that the above data structures are initially allocated on managed heap. We need to marshal them to the native memory by calling Marshal.AllocHGlobal and Marshal.StructureToPtr, and free the native memory after use (Marshal.FreeHGlobal). The complete code of setting service tigger start on USB arrival is:
using (ServiceController sc = new ServiceController(serviceName))
{
    // Marshal Guid struct GUID_DEVINTERFACE_DISK to native memory
    IntPtr pGuidUSBDevice = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(Guid)));
    Marshal.StructureToPtr(GUID_DEVINTERFACE_DISK, pGuidUSBDevice, false);

    // Allocate and set the SERVICE_TRIGGER_SPECIFIC_DATA_ITEM structure
    SERVICE_TRIGGER_SPECIFIC_DATA_ITEM deviceData;
    deviceData.dwDataType = ServiceTriggerDataType.SERVICE_TRIGGER_DATA_TYPE_STRING;
    deviceData.cbData = (uint)(USBHardwareId.Length + 1) * 2;
    IntPtr pUSBHardwareId = Marshal.StringToHGlobalUni(USBHardwareId);
    deviceData.pData = pUSBHardwareId;
    // Marshal the SERVICE_TRIGGER_SPECIFIC_DATA_ITEM struct to native memory
    IntPtr pDeviceData = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(
        SERVICE_TRIGGER_SPECIFIC_DATA_ITEM)));
    Marshal.StructureToPtr(deviceData, pDeviceData, false);

    // Allocate and set the SERVICE_TRIGGER structure
    SERVICE_TRIGGER serviceTrigger;
    serviceTrigger.dwTriggerType =
        ServiceTriggerType.SERVICE_TRIGGER_TYPE_DEVICE_INTERFACE_ARRIVAL;
    serviceTrigger.dwAction =
        ServiceTriggerAction.SERVICE_TRIGGER_ACTION_SERVICE_START;
    serviceTrigger.pTriggerSubtype = pGuidUSBDevice;
    serviceTrigger.cDataItems = 1;
    serviceTrigger.pDataItems = pDeviceData;
    // Marshal the SERVICE_TRIGGER struct to native memory
    IntPtr pServiceTrigger = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(
        SERVICE_TRIGGER)));
    Marshal.StructureToPtr(serviceTrigger, pServiceTrigger, false);

    // Allocate and set the SERVICE_TRIGGER_INFO structure.
    SERVICE_TRIGGER_INFO serviceTriggerInfo = new SERVICE_TRIGGER_INFO();
    serviceTriggerInfo.cTriggers = 1;
    serviceTriggerInfo.pTriggers = pServiceTrigger;
    // Marshal the SERVICE_TRIGGER_INFO struct to native memory
    IntPtr pServiceTriggerInfo = Marshal.AllocHGlobal(Marshal.SizeOf(typeof(
        SERVICE_TRIGGER_INFO)));
    Marshal.StructureToPtr(serviceTriggerInfo, pServiceTriggerInfo, false);

    // Call ChangeServiceConfig2 with the SERVICE_CONFIG_TRIGGER_INFO level
    // and pass to it the address of the SERVICE_TRIGGER_INFO structure.
    bool bSuccess = ServiceNative.ChangeServiceConfig2(
        sc.ServiceHandle.DangerousGetHandle(),
        ServiceConfig2InfoLevel.SERVICE_CONFIG_TRIGGER_INFO, pServiceTriggerInfo);
    int errorCode = Marshal.GetLastWin32Error();

    // Clean up the native resources
    Marshal.FreeHGlobal(pGuidUSBDevice);
    Marshal.FreeHGlobal(pUSBHardwareId);
    Marshal.FreeHGlobal(pDeviceData);
    Marshal.FreeHGlobal(pServiceTrigger);
    Marshal.FreeHGlobal(pServiceTriggerInfo);

    // If the service failed to be set as trigger start, throw the error
    // returned by the ChangeServiceConfig2 function.
    if (!bSuccess)
    {
        Marshal.ThrowExceptionForHR(errorCode);
    }
}
  
  Step4. Set service trigger start on IP address arrival.
  The process is similar to setting service trigger start on USB arrival. You can find the complete code in ProjectInstaller.cs (or .vb).
  D. Determinging if service trigger event is enabled inside the service
  Unlike auto-start services which typically poll for interesting events using periodic timers, trigger-start services act when a trigger starts them and then deactivate (stop) themselves when there is no more work to perform.
  Step1. Inside OnStart, check whether the service is configured to trigger-start using the IsTriggerStartService method. IsTriggerStartService calls QueryServiceConfig2 to query SERVICE_TRIGGER_INFO. If SERVICE_TRIGGER_INFO.cTriggers > 0, trigger-start is enabled.
if (IsTriggerStartService())
{
    this.eventLog1.WriteEntry("Service trigger events are enabled.");

    // Consider stopping the service
    //this.Stop();
}
else
{
    this.eventLog1.WriteEntry("Service trigger events are NOT enabled.");

    // Usually use a timer to poll the status
    // ...
}
  
  
How to Get the Samples
  The CSWin7TriggerStartService and VBWin7TriggerStartService samples are available in All-In-One Code Framework (AIO). You can download the releases later than All-In-One Code Framework 2009-7-30, or download a changeset whose ID is larger than 26497. After the download, please open the AIO 2008 - Windows 7.sln solution file under the AIO\Visual Studio 2008 folder, and you can see both samples.
Feedback

If you have any feedback or questions about the samples, please feel free to post it to the discussion board or directly send it to us. Thanks.

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-64991-1-1.html 上篇帖子: Windows 7 产品密钥是否安全 下篇帖子: 【转】Windows 7 API Internet Connection Sharing(ICS) 与 Wireless Hosted Network构建本地A
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表