聊聊 Windows 服務(wù)

cover

什么是服務(wù)


維基百科: Architecture of Windows NTWindows service

The term "service" in this context generally refers to a callable routine, or set of callable routines. This is distinct from the concept of a "service process", which is a user mode component somewhat analogous to a daemon in Unix-like operating systems.

Microsoft 技術(shù)文檔 找的一些描述:

A service is an application type that runs in the system background and is similar to a UNIX daemon application. Services provide core operating system features, such as Web serving, event logging, file serving, help and support, printing, cryptography, and error reporting. With the Services snap-in, you can manage services on local or remote computers.

原文

A service is a long-running executable that does not support a user interface, and which might not run under the logged-on user account. The service can run without any user being logged on to the computer.

原文

Microsoft Windows services, formerly known as NT services, enable you to create long-running executable applications that run in their own Windows sessions. These services can be automatically started when the computer boots, can be paused and restarted, and do not show any user interface. These features make services ideal for use on a server or whenever you need long-running functionality that does not interfere with other users who are working on the same computer. You can also run services in the security context of a specific user account that is different from the logged-on user or the default computer account.

You can easily create services by creating an application that is installed as a service. For example, suppose you want to monitor performance counter data and react to threshold values. You could write a Windows Service application that listens to the performance counter data, deploy the application, and begin collecting and analyzing data.

原文

A service application conforms to the interface rules of the Service Control Manager (SCM). It can be started automatically at system boot, by a user through the Services control panel applet, or by an application that uses the service functions. Services can execute even when no user is logged on to the system.

A driver service conforms to the device driver protocols. It is similar to a service application, but it does not interact with the SCM. For simplicity, the term service refers to a service application in this overview.

原文PDF

按我的理解,服務(wù)就是一個(gè)抽象概念哪怔,是一套被設(shè)計(jì)用于管理那些 需要長(zhǎng)時(shí)間運(yùn)行屠阻、具有依賴關(guān)系戏阅、沒(méi)有用戶界面夜郁、不需要用戶登錄燃辖、需要特殊權(quán)限锯玛、可跟隨系統(tǒng)啟動(dòng)而自動(dòng)運(yùn)行的程序 的體系結(jié)構(gòu),而相關(guān)的數(shù)據(jù)庫(kù)踢涌、程序通孽、進(jìn)程都是其中不可或缺的一部分。用戶向系統(tǒng)注冊(cè)服務(wù)后便由系統(tǒng)來(lái)自動(dòng)調(diào)度服務(wù)而無(wú)需用戶參與睁壁。任務(wù)管理器的服務(wù)標(biāo)簽頁(yè)中背苦,每行數(shù)據(jù)可以表示一個(gè)服務(wù),實(shí)際數(shù)據(jù)存儲(chǔ)于注冊(cè)表中:

HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services

服務(wù)這個(gè)術(shù)語(yǔ)更傾向于描述程序的運(yùn)行方式潘明,比如以服務(wù)的方式運(yùn)行( run as a service )行剂。

Windows 中的服務(wù)和 Linux 中的服務(wù)從目的性上( 后臺(tái)運(yùn)行、開(kāi)機(jī)啟動(dòng)等 )來(lái)說(shuō)比較類似钳降,只不過(guò)實(shí)現(xiàn)方式和運(yùn)行機(jī)制有所不同厚宰。 Linux 服務(wù)通常會(huì)在 /etc/init.d 目錄下有一個(gè)對(duì)應(yīng)的配置腳本( 參考 ),比起在 Windows 上更直觀易懂,配置服務(wù)也更容易铲觉。

服務(wù)變更歷史

服務(wù)與程序和進(jìn)程的關(guān)系


類似的問(wèn)答

相關(guān)術(shù)語(yǔ)解釋

操作系統(tǒng)

Operating System

操作系統(tǒng)是管理計(jì)算機(jī)資源并為用戶提供服務(wù)的系統(tǒng)軟件,作為硬件與應(yīng)用軟件之間的接口撵幽,操作系統(tǒng)起著承上啟下的作用灯荧。

計(jì)算機(jī)系統(tǒng)大體上可以分為三個(gè)部分:硬件、系統(tǒng)軟件和應(yīng)用軟件盐杂。硬件是所有軟件運(yùn)行的物質(zhì)基礎(chǔ)逗载。而操作系統(tǒng)(簡(jiǎn)稱 OS)則是最重要的系統(tǒng)軟件。是管理計(jì)算機(jī)系統(tǒng)資源链烈、控制程序執(zhí)行的系統(tǒng)軟件厉斟。操作系統(tǒng)作為計(jì)算機(jī)用戶與計(jì)算機(jī)硬件之間的接口程序,向用戶和應(yīng)用軟件提供各種服務(wù)强衡,合理組織計(jì)算機(jī)工作流程擦秽,并為用戶使用計(jì)算機(jī)提供良好運(yùn)行環(huán)境。

操作系統(tǒng)的核心任務(wù)是管理計(jì)算機(jī)系統(tǒng)中的資源食侮。操作系統(tǒng)為用戶提供簡(jiǎn)單、有效的資源使用方法目胡,分配資源使用權(quán)锯七,解決資源爭(zhēng)用沖突,跟蹤資源使用狀況誉己,最大限度地實(shí)現(xiàn)資源共享眉尸,提高資源利用率。而操作系統(tǒng)地其他任務(wù)巨双,如擴(kuò)充機(jī)器功能噪猾、屏蔽使用細(xì)節(jié)、方便用戶使用筑累、合理組織工作流程袱蜡、管理人機(jī)界面等,都是圍繞著資源管理任務(wù)實(shí)現(xiàn)的慢宗。

資源

所謂資源坪蚁,泛指在計(jì)算機(jī)系統(tǒng)中,用戶能夠使用的各種硬件和軟件部分镜沽。計(jì)算機(jī)系統(tǒng)中可以使用的硬件資源主要是處理機(jī)敏晤、存儲(chǔ)器、輸入/輸出設(shè)備等缅茉。而軟件資源則包括相應(yīng)的程序和數(shù)據(jù)等嘴脾。

程序

Computer Program

在早期的計(jì)算機(jī)中,人們是直接用機(jī)器語(yǔ)言(即機(jī)器指令代碼)來(lái)編寫(xiě)程序的蔬墩,這種方式編寫(xiě)的程序稱為 手編程序 译打。這種用機(jī)器語(yǔ)言書(shū)寫(xiě)的程序耗拓,計(jì)算機(jī)完全可以“識(shí)別”并能執(zhí)行,所以又叫做 目的程序 扶平。

用某種高級(jí)語(yǔ)言或匯編語(yǔ)言編寫(xiě)的程序稱為源程序 帆离,源程序不能直接在計(jì)算機(jī)上執(zhí)行。如果源程序是用匯編語(yǔ)言編寫(xiě)的结澄,則需要一個(gè)匯編程序?qū)⑵浞g成目標(biāo)程序后才能執(zhí)行哥谷。如果源程序是用某種高級(jí)語(yǔ)言編寫(xiě)的,則需要對(duì)應(yīng)的解釋程序或者編譯程序?qū)ζ溥M(jìn)行翻譯麻献,然后在機(jī)器上運(yùn)行们妥。

通常用源代碼( Source code ,人類可讀的符合程序設(shè)計(jì)語(yǔ)言規(guī)范書(shū)寫(xiě)的文本文件 )表示源程序勉吻,而程序泛指目的程序监婶,即可執(zhí)行的文件( Executable ),不需要關(guān)聯(lián) 打開(kāi)方式 就能雙擊打開(kāi)的文件齿桃。在 Windows 中除了常見(jiàn)的 exe 文件和批處理文件外惑惶,還可以用注冊(cè)表查詢 HKEY_CLASSES_ROOT 中數(shù)據(jù)為 "%1" %* 的項(xiàng)。

軟件

Software

軟件是一系列文檔带污、程序以及其正常運(yùn)行所需的相關(guān)數(shù)據(jù)的集合。我們常說(shuō)的軟件( 手機(jī)上的 APP )一般指的是運(yùn)行在操作系統(tǒng)之上的應(yīng)用軟件( Application )香到,比如 QQ 鱼冀,打開(kāi)安裝目錄可以看到除了 exe 文件外還有一堆其他的文件。

應(yīng)用軟件是指計(jì)算機(jī)用戶利用計(jì)算機(jī)的軟件悠就、硬件資源為某一專門的應(yīng)用目的而開(kāi)發(fā)的軟件千绪。例如,科學(xué)計(jì)算梗脾、工程設(shè)計(jì)荸型、數(shù)據(jù)處理、事務(wù)處理和過(guò)程控制等方面的程序炸茧,以及文字處理軟件帆疟、表格處理軟件、輔助設(shè)計(jì)軟件(CAD)和實(shí)時(shí)處理軟件等宇立。

應(yīng)用與任務(wù)

App & Task

對(duì)應(yīng) win10 任務(wù)管理器中進(jìn)程標(biāo)簽頁(yè)下的應(yīng)用分類踪宠,每個(gè)應(yīng)用展開(kāi)后會(huì)有任務(wù)。應(yīng)用是存在前臺(tái)窗口與用戶進(jìn)行交互的主進(jìn)程妈嘹,任務(wù)是其子進(jìn)程或者抽象出來(lái)的窗口柳琢。像常用的 合并任務(wù)欄按鈕 設(shè)置項(xiàng),沒(méi)合并前顯示全部的窗口任務(wù),合并后只顯示應(yīng)用柬脸。( 打開(kāi)任務(wù)欄設(shè)置

它們和進(jìn)程之間的對(duì)應(yīng)關(guān)系不太好描述他去,自行感受吧:

  • 打開(kāi)兩個(gè)文件夾窗口后,可以看到 1 個(gè)資源管理器應(yīng)用倒堕、 2 個(gè)文件夾任務(wù)灾测、 1 個(gè) explorer.exe 進(jìn)程。
  • 使用 regedit -m 命令打開(kāi)兩個(gè)注冊(cè)表編輯器垦巴,可以看到 2 個(gè)應(yīng)用媳搪、 每個(gè)應(yīng)用 1 個(gè)任務(wù)、 2 個(gè) regedit.exe 進(jìn)程骤宣。
  • 打開(kāi) nginx 后不顯示應(yīng)用和任務(wù)秦爆,但可以看到 2 個(gè) nginx.exe 后臺(tái)進(jìn)程。
  • VMware 虛擬機(jī)憔披,最小化在托盤時(shí)不顯示應(yīng)用和任務(wù)等限,而雙擊打開(kāi)后可以看到 1 個(gè)應(yīng)用、 2 個(gè)任務(wù)芬膝、 3 個(gè)進(jìn)程望门。
進(jìn)程

Process

進(jìn)程是程序的一次執(zhí)行,該程序可以和其他程序并發(fā)執(zhí)行锰霜。進(jìn)程通常是由程序筹误、數(shù)據(jù)和進(jìn)程控制塊(PCB)組成的。

在操作系統(tǒng)中锈遥,通常使用 進(jìn)程(process) 這一概念描述程序的動(dòng)態(tài)執(zhí)行過(guò)程纫事。通俗地講勘畔,程序是靜態(tài)實(shí)體所灸,而進(jìn)程是動(dòng)態(tài)實(shí)體,是執(zhí)行中的程序炫七。進(jìn)程不僅僅包含程序代碼爬立,也包含了當(dāng)前的狀態(tài)(這由程序計(jì)數(shù)器和處理機(jī)中的相關(guān)寄存器表示)和資源。因此万哪,如果兩個(gè)用戶用同樣一段代碼分別執(zhí)行相同功能的程序侠驯,那么其中的每一個(gè)都是一個(gè)獨(dú)立的進(jìn)程。雖然其代碼是相同的奕巍,但是數(shù)據(jù)卻未必相同吟策。

進(jìn)程是可并發(fā)執(zhí)行的程序在一個(gè)數(shù)據(jù)集合上的運(yùn)行過(guò)程,是系統(tǒng)進(jìn)行資源分配和調(diào)度的基本單位的止,是線程的容器檩坚。迄今為止對(duì)這一概念還沒(méi)有一個(gè)確切的統(tǒng)一的描述。一個(gè)進(jìn)程是特定程序的一個(gè)實(shí)例( instance ),在運(yùn)行過(guò)程中可以創(chuàng)建自己的子進(jìn)程匾委。 后臺(tái)進(jìn)程 就是不與用戶進(jìn)行交互( 隱藏起來(lái) )的進(jìn)程拖叙。

程序和進(jìn)程就是 名詞現(xiàn)在進(jìn)行時(shí) 的關(guān)系,常見(jiàn)的比喻是菜譜和做菜過(guò)程赂乐。

服務(wù)程序

一種符合 服務(wù)控制管理器 (SCM) 接口規(guī)范的應(yīng)用程序挖滤,即 Service Program ,是服務(wù)啟動(dòng)實(shí)際所執(zhí)行的可執(zhí)行文件运嗜。( 詳見(jiàn)下文 )

以上引用內(nèi)容摘自 計(jì)算機(jī)組成原理第 4 版軟件設(shè)計(jì)師教程(第三版)(修訂版) 壶辜,多年以后再回顧教材發(fā)現(xiàn)上課學(xué)的東西早忘得一干二凈了,還好書(shū)留著可以當(dāng)詞典用担租。

它們之間的關(guān)系:

  • 用戶雙擊 > 運(yùn)行 程序 > 產(chǎn)生 進(jìn)程 砸民。
  • 啟動(dòng)服務(wù) > 運(yùn)行 服務(wù)程序 > 產(chǎn)生 服務(wù)進(jìn)程

這些術(shù)語(yǔ)本就比較抽象奋救,再加上翻譯岭参、口語(yǔ)化、場(chǎng)景( 開(kāi)發(fā)還是使用 )等等因素就容易造成歧義令人困惑尝艘。就像 1+1=2 一樣演侯,不需要糾結(jié)為什么是這樣,只需要知道這是約定成俗的背亥,了解多了自然就懂了秒际。這些術(shù)語(yǔ)的存在是為了幫助人們更容易理解復(fù)雜抽象的計(jì)算機(jī)軟件體系結(jié)構(gòu)〗坪海口語(yǔ)中的服務(wù)通常在各個(gè)語(yǔ)境中分別指代服務(wù)本身娄徊、服務(wù)程序和服務(wù)進(jìn)程,能明白其中的含義就行了盾戴。

什么是服務(wù)控制管理器 (SCM)


Service Control Manager (SCM) is a special system process under the Windows NT family of operating systems, which starts, stops and interacts with Windows service processes. It is located in the %SystemRoot%\System32\services.exe executable. Service processes interact with SCM through a well-defined API, and the same API is used internally by the interactive Windows service management tools such as the MMC snap-in Services.msc and the command-line Service Control utility sc.exe. Terminating this file is used as a method of causing the Blue Screen of Death.

維基百科

我們都知道服務(wù)設(shè)置為自動(dòng)后就能開(kāi)機(jī)啟動(dòng)寄锐,而這個(gè)操控者就是 SCMSCM 是一個(gè)特殊的系統(tǒng)進(jìn)程尖啡,它執(zhí)行各種與服務(wù)有關(guān)的任務(wù)橄仆。它跟隨系統(tǒng)啟動(dòng)而運(yùn)行,之后它便會(huì)啟動(dòng)所有設(shè)置了 自動(dòng)啟動(dòng) 的服務(wù)以及它們所依賴的 手動(dòng)啟動(dòng) 的服務(wù)衅斩。SCM 維護(hù)了一個(gè)數(shù)據(jù)庫(kù)來(lái)存儲(chǔ)已安裝的服務(wù)盆顾,并提供了安全統(tǒng)一的方式來(lái)管理它們。

SCM 就是整個(gè)服務(wù)體系的核心畏梆,由它直接管理服務(wù)的一切配置和行為您宪,它提供一系列 函數(shù) 供其他程序調(diào)用以間接控制服務(wù):

  • 維護(hù)已安裝服務(wù)的數(shù)據(jù)庫(kù)惫搏。
  • 在系統(tǒng)啟動(dòng)時(shí)或按需啟動(dòng)服務(wù)和驅(qū)動(dòng)程序服務(wù)。
  • 枚舉已安裝的服務(wù)和驅(qū)動(dòng)程序服務(wù)蚕涤。
  • 維護(hù)運(yùn)行服務(wù)和驅(qū)動(dòng)服務(wù)的狀態(tài)信息筐赔。
  • 將控制請(qǐng)求傳輸?shù)秸谶\(yùn)行的服務(wù)。
  • 鎖定和解鎖服務(wù)數(shù)據(jù)庫(kù)揖铜。

調(diào)用這些函數(shù)的程序根據(jù)職能主要分為以下幾類:

服務(wù)程序

Service Program

為一個(gè)或多個(gè)服務(wù)提供可執(zhí)行代碼的應(yīng)用程序茴丰。主要用到了連接 SCM 和修改服務(wù)狀態(tài)的函數(shù)。一些 服務(wù)程序 還會(huì)通過(guò)命令行參數(shù)實(shí)現(xiàn)自 安裝 的功能天吓,比如 mysqld --install 贿肩。

通常 服務(wù)程序 作為控制臺(tái)程序直接運(yùn)行而不是通過(guò)服務(wù)運(yùn)行時(shí)會(huì)報(bào)錯(cuò):

# 參考 StartServiceCtrlDispatcher 的返回值
1063 (ERROR_FAILED_SERVICE_CONTROLLER_CONNECT)

服務(wù)配置程序

Service Configuration Program

主要用于增刪改查 SCM 數(shù)據(jù)庫(kù)中服務(wù)配置信息的程序。雖然可以通過(guò)注冊(cè)表管理數(shù)據(jù)庫(kù)龄寞,但還是應(yīng)該只使用 SCM 提供的相關(guān)函數(shù)以確保配置的正確性汰规。系統(tǒng)自帶的命令行工具 Sc.exe 就包含此類功能。

服務(wù)控制程序

Service Control Program

主要用于 啟動(dòng)服務(wù)程序控制服務(wù)進(jìn)程 的程序物邑,后面簡(jiǎn)稱 SCP 溜哮。它們只是向 SCM 發(fā)送請(qǐng)求,再由 SCM 轉(zhuǎn)發(fā)給服務(wù)色解。系統(tǒng)自帶的命令行工具 Sc.exe 茂嗓、net.exe 就包含此類功能。

SCM 以串行的方式依次處理請(qǐng)求科阎,一個(gè)服務(wù)處理完一個(gè)請(qǐng)求后 SCM 才會(huì)發(fā)送下一個(gè)請(qǐng)求述吸。因此如果服務(wù)正忙于處理請(qǐng)求時(shí) ,之后的 StartServiceControlService 都會(huì)阻塞锣笨,超時(shí)( 30 秒 )直接返回錯(cuò)誤蝌矛。

SCM 同時(shí)是一個(gè) RPC 服務(wù)器,因此服務(wù)配置和服務(wù)控制程序可以管理遠(yuǎn)程主機(jī)上的服務(wù)错英。

進(jìn)一步了解服務(wù)


服務(wù)屬性

所有屬性值詳見(jiàn)下面的鏈接:

提一下 ServiceName 入撒、 DisplayNameDescription 這三個(gè)屬性走趋, ServiceName 才是每個(gè)服務(wù)的唯一標(biāo)識(shí)衅金,比較時(shí)不區(qū)分大小寫(xiě)噪伊,另外兩個(gè)則是顯示名稱和描述簿煌,是為了幫助用戶識(shí)別這個(gè)服務(wù)的作用。另外鉴吹, DisplayName 還用于 NET START 命令姨伟。然而在 任務(wù)管理器服務(wù) 以及其他第三方工具的界面中通常只顯示兩個(gè)字段( 名稱和描述 ),內(nèi)容則是這三個(gè)屬性混用或者組合而成的豆励,很混亂夺荒。

服務(wù)類型

名稱 數(shù)值 說(shuō)明
SERVICE_ADAPTER 0x00000004 保留的瞒渠。
SERVICE_FILE_SYSTEM_DRIVER 0x00000002 文件系統(tǒng)驅(qū)動(dòng)程序服務(wù)。
SERVICE_KERNEL_DRIVER 0x00000001 設(shè)備驅(qū)動(dòng)程序服務(wù)技扼。
SERVICE_RECOGNIZER_DRIVER 0x00000008 保留的伍玖。
SERVICE_WIN32_OWN_PROCESS 0x00000010 獨(dú)占一個(gè)進(jìn)程的服務(wù)蟋座。
SERVICE_WIN32_SHARE_PROCESS 0x00000020 與其他服務(wù)共享一個(gè)進(jìn)程的服務(wù)秽誊。
SERVICE_USER_OWN_PROCESS 0x00000050 在登錄的用戶帳戶下運(yùn)行的獨(dú)占服務(wù)矮固。
SERVICE_USER_SHARE_PROCESS 0x00000060 在登錄的用戶帳戶下運(yùn)行的共享服務(wù)顽腾。
SERVICE_INTERACTIVE_PROCESS 0x00000100 可交互的服務(wù) 蓄髓。Windows Vista 起服務(wù)不能直接與用戶交互锡足。

服務(wù)可以通過(guò)調(diào)用 SetServiceBits 函數(shù)來(lái)注冊(cè)其他類型信息别洪。調(diào)用 NetServerGetInfoNetServerEnum 函數(shù)獲取支持的服務(wù)類型飘弧。( 來(lái)源

SERVICE_INTERACTIVE_PROCESS 需要和 SERVICE_WIN32_OWN_PROCESSSERVICE_WIN32_SHARE_PROCESS 組合使用榄笙,并且要在 LocalSystem 帳戶上下文中運(yùn)行邪狞。

  • 驅(qū)動(dòng)程序服務(wù) 的運(yùn)行和管理方式有所不同,本文先不做深入了解了茅撞。
  • 用戶服務(wù) 在用戶登錄時(shí)使用模板創(chuàng)建帆卓,退出時(shí)刪除,起到用戶級(jí)別的隔離米丘。名稱形如 OneSyncSvc_ff97b 鳞疲,這個(gè)后綴是每次登錄后隨機(jī)生成的。
  • 保護(hù)反惡意軟件服務(wù)

服務(wù)啟動(dòng)類型

名稱 數(shù)值 說(shuō)明
SERVICE_AUTO_START 0x00000002 系統(tǒng)啟動(dòng)時(shí)由 SCM 自動(dòng)啟動(dòng)的服務(wù)蠕蚜。詳見(jiàn) 自動(dòng)啟動(dòng)服務(wù) 尚洽。DelayedAutostart 設(shè)為 1 時(shí)表示 自動(dòng)(延遲啟動(dòng))
SERVICE_BOOT_START 0x00000000 由系統(tǒng)加載程序啟動(dòng)的設(shè)備驅(qū)動(dòng)程序靶累。此值僅對(duì)驅(qū)動(dòng)程序服務(wù)有效腺毫。
SERVICE_DEMAND_START 0x00000003 手動(dòng),當(dāng)進(jìn)程調(diào)用 StartService 函數(shù)時(shí)由 SCM 啟動(dòng)的服務(wù) 挣柬。詳見(jiàn) 按需啟動(dòng)服務(wù) 潮酒。
SERVICE_DISABLED 0x00000004 禁止啟動(dòng)的服務(wù)。嘗試啟動(dòng)此類服務(wù)會(huì)返回 錯(cuò)誤代碼 ERROR_SERVICE_DISABLED 邪蛔。
SERVICE_SYSTEM_START 0x00000001 IoInitSystem 函數(shù)啟動(dòng)的設(shè)備驅(qū)動(dòng)程序急黎。此值僅對(duì)驅(qū)動(dòng)程序服務(wù)有效。

服務(wù)狀態(tài)

名稱 數(shù)值 說(shuō)明
SERVICE_CONTINUE_PENDING 0x00000005 服務(wù)正在恢復(fù)侧到。
SERVICE_PAUSE_PENDING 0x00000006 服務(wù)正在暫停勃教。
SERVICE_PAUSED 0x00000007 服務(wù)已暫停。
SERVICE_RUNNING 0x00000004 服務(wù)正在運(yùn)行匠抗。
SERVICE_START_PENDING 0x00000002 服務(wù)正在啟動(dòng)故源。
SERVICE_STOP_PENDING 0x00000003 服務(wù)正在停止。
SERVICE_STOPPED 0x00000001 服務(wù)未運(yùn)行汞贸。

服務(wù)運(yùn)行后需要及時(shí)正確地向 SCM 更新自己最新的 狀態(tài) 绳军,這樣 SCP 才能通過(guò) SCM 查詢服務(wù)的狀態(tài)印机。服務(wù)的狀態(tài)決定了服務(wù)和 SCM 之間該如何交互。例如门驾,如果服務(wù)正處于 SERVICE_STOP_PENDING 狀態(tài)射赛,則 SCM 不會(huì)向服務(wù)發(fā)送進(jìn)一步的控制請(qǐng)求,因?yàn)榇藸顟B(tài)指示服務(wù)正在關(guān)閉奶是。

The following table shows the action of the SCM in each of the possible service states.

服務(wù)的初始化狀態(tài)是 SERVICE_STOPPED 咒劲,主要的合法轉(zhuǎn)換過(guò)程見(jiàn)下圖:

服務(wù)狀態(tài)轉(zhuǎn)換

服務(wù)程序啟動(dòng)過(guò)程

看不到 StartService 的底層實(shí)現(xiàn),我猜測(cè) SCM 啟動(dòng)服務(wù) 的大概流程應(yīng)該是這樣的( 參考 ):

  • SCP 調(diào)用 StartService 诫隅。

  • SCM 準(zhǔn)備啟動(dòng)服務(wù)腐魂。

    • 獲取 服務(wù)鎖

      確保同一時(shí)刻只有一個(gè)服務(wù)在啟動(dòng)逐纬,只有在啟動(dòng)服務(wù)時(shí)才會(huì)獲取鎖蛔屹,并且不再允許除 SCM 外的其他進(jìn)程控制鎖。( 參考

    • 從注冊(cè)表中讀取服務(wù)路徑( ImagePath )用于啟動(dòng)進(jìn)程( 包含啟動(dòng)參數(shù) )豁生。

    • 從數(shù)據(jù)庫(kù)查找 帳戶 信息并登錄兔毒,加載用戶配置。

  • 如果多個(gè)服務(wù)共享一個(gè)進(jìn)程且該進(jìn)程已存在則獲取進(jìn)程對(duì)應(yīng)的連接甸箱。

  • 否則創(chuàng)建新的服務(wù)進(jìn)程( 將登錄令牌分配給進(jìn)程 )育叁,等待建立連接。

    入口點(diǎn) 中調(diào)用 StartServiceCtrlDispatcher

    • 建立主線程和 SCM 之間的連接( 命名管道 )芍殖。
    • 將主線程作為 dispatcher 線程 駐留在一個(gè)循環(huán)內(nèi)接收來(lái)自 SCM 的請(qǐng)求豪嗽。
    • 直到發(fā)生錯(cuò)誤或者進(jìn)程中所有服務(wù)都結(jié)束了才會(huì)使主線程繼續(xù)往下執(zhí)行。

    默認(rèn)超過(guò) 30 秒沒(méi)有調(diào)用 StartServiceCtrlDispatcher 會(huì)直接終止進(jìn)程豌骏。

    事件查看器 > 自定義視圖 > 管理事件 > 服務(wù)啟動(dòng)失敗

    修改超時(shí)時(shí)間 ( 重啟才會(huì)生效 ):

    HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control
        ServicesPipeTimeout = 60000
    
  • 連接建立時(shí)龟梦, SCM 發(fā)送 啟動(dòng)請(qǐng)求 并傳遞啟動(dòng)參數(shù)。

    當(dāng)收到通知用于執(zhí)行 ServiceMain 的線程創(chuàng)建成功后窃躲, StartService 就直接返回以繼續(xù)執(zhí)行 SCP 中的代碼( 可定期 查詢 或者 監(jiān)聽(tīng) 服務(wù)的最新?tīng)顟B(tài) )计贰。

  • SCM 繼續(xù)等待進(jìn)程退出( 表示啟動(dòng)失敗 )或者報(bào)告 SERVICE_RUNNING 狀態(tài)。

    如果服務(wù)在 80 秒內(nèi)沒(méi)有更新其狀態(tài)蒂窒,則 SCM 會(huì)認(rèn)為服務(wù)發(fā)生了錯(cuò)誤躁倒,將記錄一個(gè)事件并停止服務(wù)( 不確定是否會(huì)終止進(jìn)程 )。

  • 當(dāng) SCM 得知服務(wù)正在運(yùn)行后便會(huì) 釋放 服務(wù)鎖 洒琢。

dispatcher 線程 的請(qǐng)求處理流程:

  • 啟動(dòng)請(qǐng)求

    新建線程調(diào)起此服務(wù)對(duì)應(yīng)的 ServiceMain 并通知 SCM 線程創(chuàng)建成功秧秉。

    • 調(diào)用 RegisterServiceCtrlHandler 注冊(cè) Service Control Handler 函數(shù)以監(jiān)聽(tīng)來(lái)自 SCM控制請(qǐng)求

      由于調(diào)用 SetServiceStatus 依賴于 RegisterServiceCtrlHandler 返回的 服務(wù)狀態(tài)句柄 纬凤,所以只有將 RegisterServiceCtrlHandler 放置在 ServiceMain 中最開(kāi)始的位置才能夠在發(fā)生錯(cuò)誤時(shí)總能將狀態(tài)更新為 SERVICE_STOPPED 福贞。

    • 執(zhí)行服務(wù)初始化邏輯并更新服務(wù)狀態(tài)為 SERVICE_RUNNING 撩嚼。

      初始化過(guò)程應(yīng)盡可能快( 不超過(guò) 1 秒 )停士,否則要考慮特殊方法去優(yōu)化挖帘。

    • 執(zhí)行服務(wù)實(shí)際的業(yè)務(wù)邏輯。

      避免直接調(diào)用 ExitThread 來(lái)結(jié)束線程恋技,這樣做會(huì)跳過(guò)清理任務(wù)而導(dǎo)致內(nèi)存泄漏拇舀。

  • 控制請(qǐng)求ControlService

    在當(dāng)前線程上下文中調(diào)起 Handler ,根據(jù)請(qǐng)求的 控制代碼 執(zhí)行對(duì)應(yīng)的業(yè)務(wù)代碼蜻底。

    Handler 被調(diào)用的時(shí)候骄崩,如果業(yè)務(wù)代碼會(huì)導(dǎo)致服務(wù)狀態(tài)發(fā)生變化則一定要記得調(diào)用 SetServiceStatus ,如果不會(huì)導(dǎo)致?tīng)顟B(tài)變化則不需要調(diào)用薄辅。

    控制代碼 除了已規(guī)定的幾種外還可以是用戶自定義的代碼( 128-255 )如果有 權(quán)限 的話要拂。

以上流程只是我根據(jù)文檔整理出來(lái)的,跟著代碼走一遍也許能有進(jìn)一步的理解站楚⊥讯瑁看文檔的時(shí)候注意結(jié)合 About ServicesUsing Services 窿春、winsvc 拉一,因?yàn)橐粋€(gè)概念的內(nèi)容可能會(huì)分散在三個(gè)部分中。

什么是 Svchost


前面提到了 與其他服務(wù)共享一個(gè)進(jìn)程的服務(wù) 旧乞,可以在多個(gè)服務(wù)之間共享代碼蔚润,一個(gè)常見(jiàn)的例子就是服務(wù)主機(jī) Svchost.exe ,它用來(lái)托管系統(tǒng)內(nèi)部的服務(wù)( DLL 形式 )尺栖。

Svchost.exe服務(wù)主機(jī) 嫡纠,或 SvcHost )是一個(gè)系統(tǒng)進(jìn)程,它可以承載 Windows NT 系列操作系統(tǒng)中的一個(gè)或多個(gè) Windows 服務(wù) 延赌。Svchost 在共享服務(wù)進(jìn)程的實(shí)現(xiàn)中是必不可少的货徙,其中多個(gè)服務(wù)可以共享一個(gè)進(jìn)程以減少資源消耗。將多個(gè)服務(wù)組合到一個(gè)進(jìn)程中可以節(jié)省計(jì)算資源皮胡,這一考慮是 NT 設(shè)計(jì)人員特別關(guān)心的痴颊,因?yàn)閯?chuàng)建 Windows 進(jìn)程比其他操作系統(tǒng)( 例如 Unix 系列 )需要更多時(shí)間和消耗更多內(nèi)存。但是屡贺,如果其中一項(xiàng)服務(wù)導(dǎo)致未處理的異常蠢棱,則整個(gè)進(jìn)程可能會(huì)崩潰。此外甩栈,最終用戶可能更難以識(shí)別組件服務(wù)泻仙。

svchost 進(jìn)程是在 Windows 2000 中引入的,盡管從 Windows NT 3.1 開(kāi)始就存在對(duì)共享服務(wù)進(jìn)程的底層支持量没。

它正確的位置應(yīng)該位于系統(tǒng)盤根目錄的 \Windows\system32 目錄下( 64 位系統(tǒng)則亦在系統(tǒng)盤根目錄的 \Windows\SysWOW64 )玉转。 如果在其他地方看到,那么很可能是病毒程序殴蹄。

維基百科

微軟的 文檔 中明確指出了 Svchost.exe 保留供操作系統(tǒng)使用究抓,不應(yīng)由非 Windows 服務(wù)使用猾担,開(kāi)發(fā)者應(yīng)實(shí)現(xiàn)自己的服務(wù)托管程序 ,所以使用 Svchost.exe 偽裝自己的行為就是在 耍流氓 刺下。

早期的 Windows 一般只有有數(shù)幾個(gè) svchost 進(jìn)程绑嘹,之后才慢慢增多并劃分成不同的主機(jī)組,不同組的服務(wù)在不同實(shí)例中運(yùn)行橘茉。服務(wù)組是根據(jù)安全需求劃分的工腋。

Windows 10 1703 起有了新的改動(dòng):內(nèi)存大于 3.5 GB 的機(jī)器自動(dòng)為每個(gè)共享服務(wù)( 有例外 )分配一個(gè)單獨(dú)進(jìn)程。所以在任務(wù)管理器中看到密密麻麻一堆 svchost 進(jìn)程是很正常的現(xiàn)象畅卓。單獨(dú)進(jìn)程會(huì)造成內(nèi)存開(kāi)銷增大( 大概 500 MB )擅腰,但好處是加強(qiáng)了安全性、穩(wěn)定性翁潘、可擴(kuò)展性惕鼓,降低了故障排除的開(kāi)銷,以及更細(xì)致的資源管理和診斷數(shù)據(jù)唐础。( 參考

Svchost 參考資料

編寫(xiě)在 Svchost 中運(yùn)行的 DLL

注冊(cè)任何程序?yàn)榉?wù)


一個(gè)標(biāo)準(zhǔn)的 服務(wù)程序 必須包含以下幾點(diǎn) SCM 接口規(guī)范:

并不是說(shuō) SCM 會(huì)檢測(cè)程序里是否暴露了這幾個(gè)函數(shù), 而是一個(gè)服務(wù)想要正常運(yùn)行就需要進(jìn)程和 SCM 之間建立連接并能夠響應(yīng) SCM 發(fā)出的請(qǐng)求( 正確更新?tīng)顟B(tài) ) 屁柏,要實(shí)現(xiàn)這一目的就不得不利用上面的幾個(gè)函數(shù)啦膜。比如用 sc 命令可以成功創(chuàng)建一個(gè)記事本的服務(wù),啟動(dòng)服務(wù)的時(shí)候記事本也能打開(kāi)淌喻,但因?yàn)闆](méi)法調(diào)用 StartServiceCtrlDispatcher 僧家, 30 秒之后就會(huì)被 SCM 強(qiáng)制關(guān)閉并提示啟動(dòng)失敗。

我們?nèi)粘J褂玫能浖谠O(shè)計(jì)的時(shí)候大多沒(méi)有考慮以服務(wù)的形式運(yùn)行裸删,自然就不滿足上面的接口規(guī)范八拱。如果我們非要以服務(wù)的形式運(yùn)行就需要在它們和 SCM 之間構(gòu)建一座橋梁, SCM 通過(guò)這個(gè) 第三者 來(lái)間接控制進(jìn)程,就像 Svchost 那樣肌稻。

找了幾個(gè)工具可以實(shí)現(xiàn)將任何程序注冊(cè)為 合法的 Windows 服務(wù) 清蚀。工具可以放在任何位置,不必放在系統(tǒng)目錄下灯萍,腳本在程序目錄下執(zhí)行轧铁。

RunAsSrv

最后更新時(shí)間: 2006-08-03

缺失 MSVCP71.DLLMSVCR71.DLL 每聪,下載后放到 exe 同級(jí)目錄下或者安裝 微軟常用運(yùn)行庫(kù)合集 可以解決旦棉。

可能會(huì)被殺軟報(bào)病毒,介意者慎用药薯。

runassrv add /cmdline:"C:\Users\test\Desktop\nginx\nginx.exe" /name:nginx_runassrv

SrvStart

最后更新時(shí)間: 2000-06-30

很古老的工具绑洛,號(hào)稱支持 Windows NT 4 之后的所有 Windows 版本。配置項(xiàng)很多童本,文檔也不是很清楚真屯,調(diào)通有點(diǎn)費(fèi)勁。

set name=nginx_srvstart
set startup_dir=C:\Users\test\Desktop\nginx
set startup=%startup_dir%\nginx.exe
set shutdown="%startup%" -p "%startup_dir%" -s stop
:: 寫(xiě)入配置文件
(
echo [%name%]
echo startup_dir=%startup_dir%
echo startup=%startup%
echo shutdown=%shutdown%
) > nginx.ini
:: 創(chuàng)建服務(wù)
srvstart install %name% -c "%cd%\nginx.ini"

RunAsService

最后更新時(shí)間: 2020-10-01

需要安裝 .NET Framework 3.5 穷娱。官網(wǎng) 下載的不是最新的代碼绑蔫,僅支持 execom 類型的文件作為啟動(dòng)命令。

需要在管理員命令提示符中運(yùn)行泵额,否則會(huì)看不到任何信息配深。

RunAsService install "nginx_RunAsService" "C:\Users\test\Desktop\nginx\nginx.exe" -p "C:\Users\test\Desktop\nginx"

如果應(yīng)用子進(jìn)程異常關(guān)閉了會(huì)導(dǎo)致無(wú)法直接關(guān)閉服務(wù),需要手動(dòng)殺死 RunAsService.exe 進(jìn)程嫁盲。

srvany

srvany.exeMicrosoft Windows Resource Kits 工具集的一個(gè)實(shí)用的小工具篓叶,用于將任何 EXE 程序作為 Windows 服務(wù)運(yùn)行。

官網(wǎng)已經(jīng)找不到了羞秤,只能通過(guò)第三方下載( 參考 )缸托。支持 暫停/恢復(fù)

由于它只是一個(gè)服務(wù)外殼并沒(méi)有提供安裝命令瘾蛋,需要自己手動(dòng)創(chuàng)建服務(wù):

set name=nginx_srvany
set startup_dir=C:\Users\test\Desktop\nginx
set startup=%startup_dir%\nginx.exe
set "AppParameters= "
set reg_path=HKLM\SYSTEM\CurrentControlSet\services\%name%\Parameters
:: 安裝服務(wù)
sc create %name% binPath= "%cd%\srvany.exe"
:: 配置注冊(cè)表中的服務(wù)參數(shù)
reg add "%reg_path%" /f /v AppDirectory /t REG_SZ /d "%startup_dir%"
reg add "%reg_path%" /f /v Application /t REG_SZ /d "%startup%"
reg add "%reg_path%" /f /v AppParameters /t REG_SZ /d "%AppParameters%"

有人專門為它寫(xiě)了一個(gè)管理工具 SrvanyUI ( 已內(nèi)置 srvany )俐镐,還包括了對(duì)系統(tǒng)服務(wù)的管理,可以擺脫注冊(cè)表操作哺哼。

SrvanyUI

NSSM

最后更新時(shí)間: 2017-05-16

nssm is a service helper which doesn't suck. srvany and other service helper programs suck because they don't handle failure of the application running as a service.

提供了其他工具沒(méi)有的異常處理機(jī)制京革,注冊(cè)表的結(jié)構(gòu)類似于 srvany 。也可通過(guò) Chocolatey 的方式安裝幸斥, Chocolatey 中的 nginx 就是通過(guò)這種方式創(chuàng)建服務(wù)的匹摇。

nssm install nginx_nssm "C:\Users\test\Desktop\nginx\nginx.exe"

也可以使用命令打開(kāi)服務(wù)的配置界面:

nssm install nginx_nssm
NSSM 安裝服務(wù)

winsw

Windows Service Wrapper

根據(jù)配置文件來(lái)加載安裝和啟動(dòng)配置 ,類似于 SrvStart 的升級(jí)版甲葬。 V2 版本創(chuàng)建一個(gè)服務(wù)就要復(fù)制一份程序的做法略顯笨重廊勃,在 V3 版本中增加了全局方式。

V2 版本的配置過(guò)程:

set "name=nginx_winsw"
set startup_dir=C:\Users\test\Desktop\nginx
set startup=%startup_dir%\nginx.exe
copy /y WinSW-x64.exe %name%.exe
:: 寫(xiě)入配置文件
(
echo id: %name%
echo name: ''
echo description: ''
echo executable: '"%startup%"'
echo arguments: -p "%startup_dir%"
echo stopArguments: -p "%startup_dir%" -s stop
) > %name%.yml
:: 安裝服務(wù)
%name%.exe install

整體使用下來(lái) NSSM 體驗(yàn)最好,功能多使用也方便坡垫。 winsw 也不錯(cuò)梭灿,畢竟有配置文件更適合復(fù)雜配置以及批量安裝和遷移。而 SrvanyUIUI 最強(qiáng)大的冰悠,上手難度最低適合普通用戶堡妒。

此類工具畢竟需要高權(quán)限,出于安全方面考慮還是建議使用開(kāi)源項(xiàng)目溉卓。

nginx 服務(wù)

nginx 說(shuō)實(shí)話不太適合做成服務(wù)的形式皮迟,管理起來(lái)也比較麻煩,而且上面的工具中除了 NSSMSrvStart 外都不能正常關(guān)閉服務(wù)桑寨,不是進(jìn)程沒(méi)殺全就是其他的異常伏尼。我更喜歡的做法:

  • 把快捷方式丟到開(kāi)始菜單的啟動(dòng)項(xiàng)( shell:startup )中用于開(kāi)機(jī)啟動(dòng)。

  • 再建兩個(gè)快捷方式改參數(shù)丟到任務(wù)欄工具欄中用于關(guān)閉和重啟:

    :: 關(guān)閉
    nginx -s stop
    :: 重啟
    nginx -s reload
    

C# 編寫(xiě)服務(wù)程序


這里演示如何在 Visual Studio 中創(chuàng)建可向事件日志中寫(xiě)入消息的 Windows 服務(wù)應(yīng)用程序尉尾。( 如何調(diào)試

具體步驟可以看 微軟文檔 爆阶,只是機(jī)翻的文檔很別扭,我重新整理了一下沙咏。

.NET 5.0 SDK 或更高版本 中可以使用 BackgroundService 創(chuàng)建 Windows 服務(wù)辨图。( demo

下載安裝 Visual Studio

新版安裝程序還是很清爽的,按需選擇肢藐,不像以前那樣一股腦安裝各種不需要的東西故河,太占空間了。

只是為了測(cè)試窖壕,勾選 .NET 桌面開(kāi)發(fā) 即可忧勿,安裝占用空間( 不壓縮 C 盤 )大概 7.36 G

安裝 Visual Studio

新建項(xiàng)目

管理員權(quán)限 運(yùn)行 VS 并新建項(xiàng)目 WindowsServiceTest 瞻讽。

語(yǔ)言選擇 C# 鸳吸,平臺(tái)選擇 Windows ,選中 Windows 服務(wù) 模板速勇。( 可直接搜索 )

.NET Framework 4.7.2

新建服務(wù)項(xiàng)目

修改代碼

解決方案資源管理器 中晌砾,選擇默認(rèn)創(chuàng)建的 Service1.cs 右鍵重命名( F2 )為 MyNewService.cs切換到代碼視圖

  • Program.cs

    using System.ServiceProcess;
    
    namespace WindowsServiceTest
    {
        internal static class Program
        {
            /// <summary>
            /// 應(yīng)用程序的主入口點(diǎn)烦磁。
            /// </summary>
            static void Main(string[] args)
            {
                ServiceBase[] ServicesToRun = new ServiceBase[]
                {
                    new MyNewService(args)
                };
                ServiceBase.Run(ServicesToRun);
            }
        }
    }
    
  • MyNewService.cs

    設(shè)置屬性 CanPauseAndContinue 是為了啟用 暫停/恢復(fù) 功能养匈,可以在 屬性 窗口直接設(shè)置,這里直接寫(xiě)死在初始化代碼里都伪。

    修改 ServiceName 屬性值為 MyNewService可選

    注意有兩個(gè)參數(shù):一個(gè)是構(gòu)造方法中的初始化參數(shù)呕乎,另一個(gè)是 OnStart 方法中的啟動(dòng)參數(shù)。

    using System;
    using System.Diagnostics;
    using System.ServiceProcess;
    using System.Timers;
    
    namespace WindowsServiceTest
    {
        public partial class MyNewService : ServiceBase
        {
            private readonly EventLog eventLog;
    
            private Timer timer;
    
            private int eventId = 1;
    
            public MyNewService(string[] args)
            {
                InitializeComponent();
                CanPauseAndContinue = true;
    
                eventLog = new EventLog();
                if (!EventLog.SourceExists("MySource"))
                {
                    EventLog.CreateEventSource("MySource", "MyNewLog");
                }
                eventLog.Source = "MySource";
                eventLog.Log = "MyNewLog";
    
                eventLog.WriteEntry("Init: " + string.Join(",", args));
            }
    
            protected override void OnStart(string[] args)
            {
                eventLog.WriteEntry("In OnStart: " + string.Join(",", args));
    
                // Set up a timer that triggers every minute.
                timer = new Timer();
                timer.Interval = 60000; // 60 seconds
                timer.Elapsed += new ElapsedEventHandler(this.OnTimer);
                timer.Start();
            }
    
            public void OnTimer(object sender, ElapsedEventArgs args)
            {
                eventLog.WriteEntry("Monitoring the System", EventLogEntryType.Information, eventId++);
            }
    
            protected override void OnStop()
            {
                eventLog.WriteEntry("In OnStop.");
            }
    
            protected override void OnPause()
            {
                timer.Stop();
                eventLog.WriteEntry("In OnPause.");
            }
    
            protected override void OnContinue()
            {
                timer.Start();
                eventLog.WriteEntry("In OnContinue.");
            }
        }
    }
    

生成服務(wù)程序

解決方案資源管理器 中陨晶,右鍵項(xiàng)目名選擇 生成 猬仁。( Ctrl + B

已啟動(dòng)生成…
1>------ 已啟動(dòng)生成: 項(xiàng)目: WindowsServiceTest, 配置: Debug Any CPU ------
1>  WindowsServiceTest -> C:\Users\test\source\repos\WindowsServiceTest\WindowsServiceTest\bin\Debug\WindowsServiceTest.exe
========== 生成: 成功 1 個(gè),失敗 0 個(gè),最新 0 個(gè)湿刽,跳過(guò) 0 個(gè) ==========

生成的 exe 文件默認(rèn)是不能直接運(yùn)行的( 可以修改 )的烁,需要注冊(cè)為服務(wù)才行。

Windows 服務(wù)啟動(dòng)失敗

安裝服務(wù)

可以使用通用的 sc 命令進(jìn)行注冊(cè)诈闺,就是詳細(xì)配置會(huì)繁瑣一點(diǎn)渴庆。

:: 注意等號(hào)與值中間有個(gè)空格
sc create MyNewServiceSC binpath= "C:\Users\test\source\repos\WindowsServiceTest\WindowsServiceTest\bin\Debug\WindowsServiceTest.exe"

也可以按教程中的方法:

添加安裝程序

解決方案資源管理器 中,右鍵服務(wù)名( MyNewService.cs查看設(shè)計(jì)器 雅镊,在 設(shè)計(jì)器 窗口中右鍵 添加安裝程序 襟雷。

添加安裝程序
修改執(zhí)行用戶

選中 serviceProcessInstaller1 ,在 屬性 中修改 AccountLocalSystem 漓穿。

這個(gè)就是任務(wù)管理器中看到的進(jìn)程所屬的用戶嗤军,涉及到權(quán)限的問(wèn)題注盈。( 參考

serviceProcessInstaller > Account
修改服務(wù)配置( 可選

選中 serviceInstaller1 晃危,在 屬性 中修改服務(wù)名稱、顯示名稱老客、描述等僚饭。

不修改就是默認(rèn)的 Service1

serviceInstaller

重新生成服務(wù)程序( Ctrl + B )使安裝配置生效胧砰。

打開(kāi) 開(kāi)發(fā)者命令提示
開(kāi)發(fā)者命令提示
執(zhí)行安裝命令
cd WindowsServiceTest\bin\Debug
:: 需要管理員權(quán)限
installutil WindowsServiceTest.exe

:: 卸載
installutil.exe /u WindowsServiceTest.exe

啟動(dòng)服務(wù)

任務(wù)管理器 > 服務(wù) > 隨便選中一個(gè)服務(wù)右鍵 > 打開(kāi)服務(wù)

服務(wù)詳情

驗(yàn)證結(jié)果

Win + X > 事件查看器 > 應(yīng)用程序和服務(wù)日志 > MyNewLog

看不到 MyNewLog 需要先啟動(dòng)服務(wù)后再重新打開(kāi) 事件查看器 鳍鸵。

事件查看器

因?yàn)橥ㄓ眠壿嫸挤庋b在 ServiceBase 里面了,只需要添加自己的業(yè)務(wù)代碼尉间,比起 C++ 實(shí)現(xiàn)的 demo 要簡(jiǎn)單很多偿乖。編寫(xiě) 多線程服務(wù) 或者復(fù)雜應(yīng)用時(shí)可能會(huì)遇到一些問(wèn)題( 參考 )。

參考文章


結(jié)語(yǔ)


以上內(nèi)容是我根據(jù)日常使用經(jīng)驗(yàn)再結(jié)合有限的資料整理而成眠副,難免有錯(cuò)誤的地方画切,歡迎指正。相關(guān)內(nèi)容比較多囱怕,全部引用太占篇幅了霍弹,感興趣的話就多點(diǎn)點(diǎn)文中給出的外鏈。


轉(zhuǎn)載請(qǐng)注明出處:https://github.com/anyesu/blog/issues/41

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末娃弓,一起剝皮案震驚了整個(gè)濱河市典格,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌台丛,老刑警劉巖耍缴,帶你破解...
    沈念sama閱讀 218,755評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡私恬,警方通過(guò)查閱死者的電腦和手機(jī)债沮,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)本鸣,“玉大人疫衩,你說(shuō)我怎么就攤上這事∪俚拢” “怎么了闷煤?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,138評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)涮瞻。 經(jīng)常有香客問(wèn)我核蘸,道長(zhǎng),這世上最難降的妖魔是什么跨琳? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,791評(píng)論 1 295
  • 正文 為了忘掉前任诈唬,我火速辦了婚禮,結(jié)果婚禮上宁否,老公的妹妹穿的比我還像新娘窒升。我一直安慰自己,他們只是感情好慕匠,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,794評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布饱须。 她就那樣靜靜地躺著,像睡著了一般台谊。 火紅的嫁衣襯著肌膚如雪蓉媳。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,631評(píng)論 1 305
  • 那天锅铅,我揣著相機(jī)與錄音酪呻,去河邊找鬼。 笑死狠角,一個(gè)胖子當(dāng)著我的面吹牛号杠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播丰歌,決...
    沈念sama閱讀 40,362評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼姨蟋,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了立帖?” 一聲冷哼從身側(cè)響起眼溶,我...
    開(kāi)封第一講書(shū)人閱讀 39,264評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎晓勇,沒(méi)想到半個(gè)月后堂飞,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體灌旧,經(jīng)...
    沈念sama閱讀 45,724評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年绰筛,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了枢泰。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,040評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡铝噩,死狀恐怖衡蚂,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情骏庸,我是刑警寧澤毛甲,帶...
    沈念sama閱讀 35,742評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站具被,受9級(jí)特大地震影響玻募,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜一姿,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,364評(píng)論 3 330
  • 文/蒙蒙 一七咧、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧啸蜜,春花似錦坑雅、人聲如沸辈挂。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,944評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)终蒂。三九已至蜂林,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間拇泣,已是汗流浹背噪叙。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,060評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留霉翔,地道東北人睁蕾。 一個(gè)月前我還...
    沈念sama閱讀 48,247評(píng)論 3 371
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像债朵,于是被迫代替她去往敵國(guó)和親子眶。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,979評(píng)論 2 355

推薦閱讀更多精彩內(nèi)容