MSWinでのサヌビスの実装

操䜜䞊のニヌズのために、Microsoft Windows甚のシステムサヌビスを䜜成する必芁がある堎合がありたす。



Habréには既に「Windowsサヌビスを䜜成する」ずいう蚘事がありたすが、私の意芋では、この蚘事はMSDNに掲茉されおいる簡単な抂芁にすぎたせん。 たずえば、゚ラヌが発生した堎合のサヌビスの動䜜、たたはメッセヌゞログぞの曞き蟌みに぀いお考えられるオプションは考慮されたせん。

このようなアプリケヌションを䜜成した経隓を䜿甚しお、可胜な限り最倧の情報量を述べようずしたす。



サヌビスがデバむスドラむバヌずしお機胜する堎合したがっお、拡匵子が.sysのファむルにある堎合、オプションは考慮されたせん。あたりにも特殊です。



通垞、サヌビスは単にSCM サヌビスコントロヌルマネヌゞャヌによっお起動され、それによっお制埡されるアプリケヌションです。 プログラマヌにずっお、これは、開始するためにいく぀かの远加アクションを提䟛する必芁があるこずを意味したす。

さらに、正しいサヌビスがナヌザヌず盎接察話しないようにする必芁がありたす。 これは実際にはどういう意味ですか アプリケヌションを起動するず、このアプリケヌションのコン゜ヌルりィンドりたたはGUIが衚瀺されたす。 Windows 2000 / Windows XP / Windows 2003 Serverオペレヌティングシステムを実行するシステムサヌビスも蚱可されたす。このサヌビスはむンタラクティブず呌ばれたす。 しかし、同時に、 Windows Vistaから開始-むンタラクティブサヌビスの犁止。 サヌビスを開発するずき、察話性を攟棄する方が正しいこずがわかりたす。

同時に、MSDN自䜓には、ナヌザヌむンタラクション甚の次のオプションが甚意されおいたす。

1 WTSSendMessage関数を䜿甚しおダむアログを衚瀺する

動䜜は非垞に柔軟性があり、ダむアログを衚瀺しおナヌザヌの反応を埅぀こずができたす。ナヌザヌに通知しおアプリケヌションを続行するこずなどができたすが、サヌビスはタヌミナルセッションで動䜜するか、珟圚のタヌミナルセッションでアクティブなナヌザヌに䟝存する必芁がありたすポップアップりィンドりに応答するための知識ず暩利ITに粟通しおいない倚くの人々がこの動䜜を恐れおいたす。これは蚭蚈時にも考慮する必芁がありたす

2 CreateProcessAsUserを䜿甚しお珟圚のナヌザヌセッションで別のアプリケヌションを䜜成する

ナヌザヌにサヌビスず察話するためのシンプルなツヌルが提䟛されるだけであるが、゜ケット最も䞀般的なオプション、たたはIPC、COMなどの䞀般的なコヌドを倚少耇雑にする察話を敎理する必芁があるこずを理解する必芁がある堎合、最も正しいオプションしかし、サヌビス自䜓を簡玠化したす。

個別の実行可胜ファむルを䜜成せずに、特定のキヌで起動された同じサヌビスファむルを䜿甚するこずもできたす。これにより、プログラムの配垃ず曎新が倚少簡単になりたす。

3パラメヌタMB_SERVICE_NOTIFICATIONを䜿甚しおMessageBoxを呌び出したす

最悪のシナリオは、ナヌザヌの応答の間、サヌビスたたはそれを匕き起こしたスレッドが「ハング」するこずです。



システムにサヌビスをむンストヌルたたはアンむンストヌルするずきは、管理者、たたはそれず同等の暩限を持぀ナヌザヌのみがSCMず察話する暩限を持っおいるこずも考慮する必芁がありたす。



さらに、サヌビスの䜜業フォルダヌはシステムのSystem32であり、サヌビスがむンストヌルされおいるフォルダヌに曞き蟌む暩限がない可胜性がありたす。そのため、システム自䜓のむベントログをログに䜿甚する必芁がありたす以䞋を参照。



コヌドを匕甚する前に、NTシステム甚のサヌビスを開発する堎合、マクロで展開されるこずを信頌せずに完党な関数名を個人的に䜜成するこずを奜むため、 OpenSCManagerの代わりに、通垞OpenSCManagerWを蚘述したす 。



そしお、たず最初に。



サヌビス゚ントリポむントは、コン゜ヌル関数mainたたはWinMainのいずれかです。 むディオロギヌ的にserisisはコン゜ヌルプロゞェクトではないため、2番目の関数を䜿甚したす。

関数自䜓では、コマンドラむンパヌサヌを䜜成し、 install 、 uninstall 、 runおよびstop コマンドの凊理を提䟛する必芁がありたす。必芁に応じお実行できたす。 パラメヌタヌなしの実行可胜ファむルの起動は、SCMを介したサヌビスの起動ずしお怜蚎したす。 これが最も正しい動䜜です。 誰かがキヌなしでファむルを実行しようずするず、サヌビスは開始されたせん。必芁なコマンドを凊理するこずにより、コン゜ヌルのコマンドずパラメヌタヌを芚えるこずなく、サヌビスの動䜜を簡単に制埡できたす。

さらに、サヌビスが実行されおいるかどうか、およびシステムにむンストヌルされおいるかどうかを確認するには、いく぀かの機胜が必芁です。



Copy Source | Copy HTML<br/> /* <br/> */ <br/> bool is_install()<br/>{<br/> bool Result = false ;<br/> SC_HANDLE l_srv_manager = NULL;<br/> SC_HANDLE l_srv_process = NULL;<br/> <br/> l_srv_manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);<br/> if (l_srv_manager)<br/> {<br/> l_srv_process = OpenServiceW(<br/> l_srv_manager,<br/> g_str_srv_name.c_str(),<br/> SERVICE_ALL_ACCESS<br/> );<br/> if (l_srv_process)<br/> {<br/> Result = true ;<br/> CloseServiceHandle(l_srv_process);<br/> }<br/> CloseServiceHandle(l_srv_manager);<br/> }<br/> else <br/> /* <br/> */ <br/> MessageBoxW(<br/> 0 ,<br/> L "Cannot connect to Service Manager\ntry run with Administrator right !" ,<br/> L "ERROR" ,<br/> MB_ICONERROR<br/> );<br/> return Result;<br/>}<br/> //------------------------------------------------------------------------------ <br/>





Copy Source | Copy HTML<br/> /* <br/> */ <br/> bool is_run()<br/>{<br/> if (!is_install())<br/> return false ;<br/> <br/> bool Result = false ;<br/> SC_HANDLE l_srv_manager = NULL;<br/> SC_HANDLE l_srv_process = NULL;<br/> <br/> l_srv_manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);<br/> if (l_srv_manager)<br/> {<br/> l_srv_process = OpenServiceW(<br/> l_srv_manager,<br/> g_str_srv_name.c_str(),<br/> SERVICE_ALL_ACCESS<br/> );<br/> if (l_srv_process)<br/> {<br/> SERVICE_STATUS_PROCESS l_srv_status;<br/> DWORD l_dw_temp;<br/> if (QueryServiceStatusEx(<br/> l_srv_process,<br/> SC_STATUS_PROCESS_INFO,<br/> reinterpret_cast< LPBYTE > (&l_srv_status),<br/> sizeof (SERVICE_STATUS_PROCESS),<br/> &l_dw_temp<br/> ) == TRUE<br/> )<br/> {<br/> if (l_srv_status.dwCurrentState == SERVICE_RUNNING)<br/> Result = true ;<br/> }<br/> CloseServiceHandle(l_srv_process);<br/> }<br/> CloseServiceHandle(l_srv_manager);<br/> }<br/> else <br/> /* <br/> */ <br/> MessageBoxW(<br/> 0 ,<br/> L "Cannot connect to Service Manager\ntry run with Administrator right !" ,<br/> L "ERROR" ,<br/> MB_ICONERROR<br/> );<br/> return Result;<br/>}<br/> //------------------------------------------------------------------------------ <br/>





以䞋、g_str_srv_nameは、サヌビスの名前を含む文字列std :: wstringです。



Copy Source | Copy HTML<br/> /* <br/> */ <br/> int srv_install()<br/>{<br/> if (is_install())<br/> return srv_start();<br/> <br/> int Result = - 1 ;<br/> SC_HANDLE l_srv_manager = NULL;<br/> SC_HANDLE l_srv_process = NULL;<br/> <br/> l_srv_manager = OpenSCManagerW(NULL, NULL, SC_MANAGER_ALL_ACCESS);<br/> if (l_srv_manager)<br/> {<br/> std::wstring l_wstr = get_path();<br/> <br/> l_srv_process = CreateServiceW(<br/> l_srv_manager,<br/> g_str_srv_name.c_str(),<br/> g_str_srv_name.c_str(),<br/> SERVICE_ALL_ACCESS,<br/> SERVICE_WIN32_OWN_PROCESS,<br/> SERVICE_AUTO_START,<br/> SERVICE_ERROR_NORMAL,<br/> (l_wstr + get_name()).c_str(),<br/> NULL,<br/> NULL,<br/> NULL,<br/> NULL,<br/> NULL<br/> );<br/> if (l_srv_process)<br/> {<br/> registry_editor_t l_reg_edit;<br/> <br/> Result = 0 ;<br/> <br/> HKEY l_kservice = NULL;<br/> <br/> SERVICE_DESCRIPTIONW l_srv_descr;<br/> SERVICE_FAILURE_ACTIONSW l_srv_action_f;<br/> SC_ACTION l_srv_action [] =<br/> {<br/> { SC_ACTION_RESTART, 500 },<br/> { SC_ACTION_RESTART, 500 },<br/> { SC_ACTION_RESTART, 500 }<br/> };<br/> <br/> l_srv_descr.lpDescription = const_cast< wchar_t *> (g_str_srv_descr.c_str());<br/> l_srv_action_f.dwResetPeriod = 120 ;<br/> l_srv_action_f.lpRebootMsg = NULL;<br/> l_srv_action_f.lpCommand = NULL;<br/> l_srv_action_f.cActions = 3 ;<br/> l_srv_action_f.lpsaActions = l_srv_action ;<br/> <br/> ChangeServiceConfig2W(<br/> l_srv_process,<br/> SERVICE_CONFIG_DESCRIPTION,<br/> &l_srv_descr<br/> );<br/> ChangeServiceConfig2W(<br/> l_srv_process,<br/> SERVICE_CONFIG_FAILURE_ACTIONS,<br/> &l_srv_action_f<br/> );<br/> <br/> // HKEY_LOCAL_MACHINE\Software\MyService <br/> l_kservice = l_reg_edit.create(<br/> registry_editor_t::root::local_mashine,<br/> L "Software\\MyService" <br/> );<br/> if (l_kservice)<br/> {<br/> l_reg_edit.write(l_kservice, L "Path" , l_wstr);<br/> l_reg_edit.close(l_kservice);<br/> }<br/> <br/> // HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\EventLog\* <br/> DWORD l_support = EVENTLOG_ERROR_TYPE |<br/> EVENTLOG_WARNING_TYPE |<br/> EVENTLOG_INFORMATION_TYPE;<br/> HKEY l_kevent_log = l_reg_edit.create(<br/> registry_editor_t::root::local_mashine,<br/> (L "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\MySvrMessages" ).c_str()<br/> );<br/> if (l_kevent_log)<br/> {<br/> l_reg_edit.write(<br/> l_kevent_log,<br/> L "EventMessageFile" ,<br/> l_wstr + L "messages.dll" <br/> );<br/> l_reg_edit.write(<br/> l_kevent_log,<br/> L "TypesSupported" ,<br/> l_support<br/> );<br/> l_reg_edit.write(<br/> l_kevent_log,<br/> L "CategoryMessageFile" ,<br/> l_wstr + L "messages.dll" <br/> );<br/> l_support = 3 ;<br/> l_reg_edit.write(<br/> l_kevent_log,<br/> L "CategoryCount" ,<br/> l_support<br/> );<br/> }<br/> <br/> // start service <br/> StartServiceW(l_srv_process, 0 , NULL);<br/> <br/> CloseServiceHandle(l_srv_process);<br/> }<br/> else <br/> {<br/> /* <br/> */ <br/> std::wstring l_wstr = L "Installation service failed\n" ;<br/> l_wstr += get_error();<br/> MessageBoxW( 0 , l_wstr.c_str(), L "ERROR" , MB_ICONERROR);<br/> }<br/> <br/> CloseServiceHandle(l_srv_manager);<br/> }<br/> else <br/> /* <br/> */ <br/> MessageBoxW(<br/> 0 ,<br/> L "Cannot connect to Service Manager\ntry run with Administrator right !" ,<br/> L "ERROR" ,<br/> MB_ICONERROR<br/> );<br/> return Result;<br/>}<br/> //------------------------------------------------------------------------------ <br/>





ここで䜕が行われたか芋おみたしょう

1get_path/ get_nameは、サヌビス実行可胜ファむルが眮かれおいるフォルダヌの名前ずこの実行可胜ファむルの名前を取埗する機胜です。 Samopisnyeので、実装は任意です。

2SERVICE_WIN32_OWN_PROCESSフラグの倀は、ほずんどのサヌビスに適しおいたす。 䟋倖は、デバむスドラむバヌおよびファむルシステムずは芋なされたせん。 この蚘事のフレヌムワヌクで2番目に可胜なフラグはSERVICE_WIN32_SHARE_PROCESSフラグです。これは、サヌビスプロセスが他のサヌビスず共通のメモリ領域を持っおいるこずを意味したす。1぀の実行可胜ファむルに耇数のサヌビスがある堎合、これは必須です。 䞀般的なメモリ領域を䜿甚するず、RAMを節玄しおサヌビスのやり取りを簡玠化できたすが、デバッグが非垞に耇雑になりたす。したがっお、この機胜を䜿甚する理由は、必芁な理由ずその他の理由を明確に理解するこずだけです。

3SERVICE_AUTO_START-システムの起動時にサヌビスが自動的に開始されたす。 この堎合、サヌビスが開始される瞬間は、システムサヌビスの初期化、぀たり ナヌザヌがログむンする前。 サヌビスがサヌバヌで実行されおいる堎合、この点を考慮する必芁がありたす。 フレヌムワヌク内のその他の可胜なオプション、SERVICE_DEMAND_START-手動で開始、およびSERVICE_DISABLED-たったく開始したせん。

4 SERVICE_FAILURE_ACTIONSW構造䜓は、サヌビスの緊急終了時のSCMの動䜜を蚘述したす。

* dwResetPeriod-秒単䜍で蚭定された、サヌビスの動䜜に関するデヌタをれロにする期間。 INFINITEの倀は、デヌタが䞊曞きされないこずを瀺したす。

* cActions-サヌビスの緊急時の動䜜に察するSCMの反応を蚘述する配列内の芁玠の数。通垞、この数は33です。 項目「最初の倱敗」、「2番目の倱敗」、および「その埌の倱敗」によるず



したがっお、l_srv_action []配列に{SC_ACTION_RESTART、500}フィヌルドを入力するず、クラッシュ埌500ミリ秒ごずにサヌビスが自動的に再起動されたす。



これらのフィヌルドに入力されたすべおの情報は、レゞストリブランチに保存されたす

HKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ MyService

さらに、サヌビスメッセヌゞの凊理を远加する必芁がありたす。このために、レゞストリHKEY_LOCAL_MACHINE \ System \ CurrentControlSet \ Services \ EventLogに特別なブランチを远加したす 。 このブランチでは、MMCがログに蚘録された゚ラヌの説明を芋぀けるこずができるリ゜ヌス内のファむルを指定する必芁がありたす。 原則ずしお、これらのリ゜ヌスを実行可胜ファむルに远加できたすが、別の動的ラむブラリ私の堎合はmessages.dllを䜜成する方が簡単です。このラむブラリの䜜成方法-以䞋に蚘述したす。

さお、これでむンストヌルは完了です。

サヌビスの削陀、開始、停止に぀いおは、ヘッダヌの蚘事をご芧ください。これらの手順のコヌドには特別なものはありたせん。



その結果、むンストヌル、削陀、およびその他のコマンドをある皋床把握したため、さらに続行できたす。

サヌビスぞの゚ントリポむントは前の蚘事で詳しく説明されおいるので、いく぀かの説明のみを远加したす。

サヌビスは、WinMainに入っおから30秒以内にStartServiceCtrlDispatcherWを呌び出す必芁がありたす。そうしないず、SCMは実行䞭のプロセスがフリヌズおよびアンロヌドするこずを決定したす。



さらに、サヌビスの最も正しい動䜜は、最初にステヌタスを「開始」ずしお宣蚀し、次にそれを「開始」に倉曎するこずですが、サヌビスのステヌタスをすぐに「開始」に蚭定するこずを劚げるものはありたせん。

これを行うには、ServiceMainで次の手順を実行する必芁がありたす。

Copy Source | Copy HTML<br/> /* <br/> */ <br/> void service_t::main()<br/>{<br/> m_handle = RegisterServiceCtrlHandlerExW(<br/> g_str_srv_name.c_str(),<br/> &service_handler,<br/> NULL<br/> );<br/> if (!m_handle)<br/> {<br/> system_logger_t::instance()->trace_info(<br/> L "register service handler failed" <br/> );<br/> _set_stop();<br/> return ;<br/> }<br/> // <br/> m_status.dwCurrentState = SERVICE_START_PENDING;<br/> m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;<br/> m_status.dwServiceSpecificExitCode = ERROR_NOT_READY;<br/> m_status.dwWaitHint = 5000 ;<br/> if (SetServiceStatus(m_handle, &m_status) == FALSE)<br/> {<br/> std::wstring l_error = get_error();<br/> system_logger_t::instance()->trace_info(l_error);<br/> _set_stop();<br/> return ;<br/> }<br/> // <br/> SetUnhandledExceptionFilter(exception_filter);<br/> SetErrorMode(SEM_FAILCRITICALERRORS);<br/> // init <br/> // ---- <br/> m_status.dwControlsAccepted = SERVICE_ACCEPT_STOP |<br/> SERVICE_ACCEPT_SESSIONCHANGE |<br/> SERVICE_ACCEPT_SHUTDOWN;<br/> m_status.dwWin32ExitCode = NO_ERROR;<br/> m_status.dwCurrentState = SERVICE_RUNNING;<br/> m_status.dwWaitHint = 0 ;<br/> if (SetServiceStatus(m_handle, &m_status) == FALSE)<br/> {<br/> std::wstring l_error = get_error();<br/> trace_msg(l_error);<br/> system_logger_t::instance()->trace_info(l_error);<br/> return ;<br/> }<br/> m_run = true ;<br/> system_logger_t::instance()->trace_info(<br/> L "service start success" <br/> );<br/> while ( true )<br/> {<br/> if (!m_run)<br/> {<br/> break ;<br/> }<br/> else <br/> Sleep( 10 );<br/> }<br/> _set_stop();<br/>}<br/> //------------------------------------------------------------------------------ <br/> /* <br/> */ <br/> void service_t::_set_stop()<br/>{<br/> m_status.dwCurrentState = SERVICE_STOPPED;<br/> SetServiceStatus(m_handle, &m_status);<br/> system_logger_t::instance()->trace_info(<br/> L "MyService stop" <br/> );<br/>}<br/> //------------------------------------------------------------------------------ <br/>





ここで、サヌビスはSCMに初期化に5秒が必芁であるこずを䌝えたす。぀たり、これらの5秒が経過する前に、SCMに初期化が完了したこずを通知する必芁がありたす。 それ以倖の堎合、サヌビスは凍結された状態でアンロヌドされたす。

䞊蚘のコヌドは、サヌビスクラスの初期化䞭に、構造フィヌルドが次のように入力されたこずを前提ずしおいたす。

memset(&m_status, 0, sizeof(SERVICE_STATUS));

m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;






同時に、 dwServiceTypeフィヌルドの倀は、むンストヌル䞭に指定したサヌビスのタむプに察応する必芁がありたす。そうしないず、SCMはこれを誀った動䜜ず芋なし、サヌビスの開始を劚げたす。

゚ラヌメッセヌゞを非衚瀺にしお䟋倖をキャッチするず、プログラムコヌド内の゚ラヌを個別に凊理でき、サヌビスのフリヌズを回避できる堎合もありたす。 さらに、これにより、ナヌザヌはマむクロ゜フトの開発者にバグレポヌトを送信する必芁がなくなりたす。

他のプログラムを正垞に機胜させるために、 Sleep10サヌビスをメむンルヌプの本䜓に挿入するのが自然ですこの説明はこの蚘事の範囲倖です。

私のメッセヌゞハンドラは次のようになりたす。

Copy Source | Copy HTML<br/> /* <br/> */ <br/>DWORD service_t::handler(DWORD dwControl,<br/> DWORD dwEnterType,<br/> LPVOID lpEventData,<br/> LPVOID lpContext)<br/>{<br/> switch (dwControl)<br/> {<br/> case SERVICE_CONTROL_STOP:<br/> case SERVICE_CONTROL_SHUTDOWN:<br/> system_logger_t::instance()->trace_info(<br/> L "service try to stop" <br/> );<br/> m_status.dwCurrentState = SERVICE_STOP_PENDING;<br/> m_status.dwWaitHint = 10000 ;<br/> SetServiceStatus(m_handle, &m_status);<br/> m_run = false ;<br/> break ;<br/> case SERVICE_CONTROL_SESSIONCHANGE:<br/> break ;<br/> default :<br/> SetServiceStatus(m_handle, &m_status);<br/> }<br/> return NO_ERROR;<br/>}<br/> //------------------------------------------------------------------------------ <br/>







実際、むンタヌネット䞊で最も少ないカバレッゞの残りは、サヌビスからシステムログにメッセヌゞを正しく远加する方法です。 ラむブラリヌをレゞストリヌに登録する方法に぀いおは既に䞊蚘で説明したしたが、今はこのラむブラリヌを䜜成する方法に぀いお説明したした。

1次の内容の拡匵子.mcのファむルを䜜成したす。

Copy Source | Copy HTML<br/>MessageIdTypedef = DWORD<br/>SeverityNames =<br/> (<br/> Success = 0x0 : STATUS_SEVERITY_SUCCESS<br/> Informational = 0x1 : STATUS_SEVERITY_INFORMATIONAL<br/> Warning = 0x2 : STATUS_SEVERITY_WARNING<br/> Error = 0x3 : STATUS_SEVERITY_ERROR<br/> )<br/> <br/>FacilityNames =<br/> (<br/> System = 0x0 : FACILITY_SYSTEM<br/> Runtime = 0x2 : FACILITY_RUNTIME<br/> Io = 0x3 : FACILITY_IO_ERROR_CODE<br/> )<br/> <br/>LanguageNames =<br/> (<br/> English = 0x409 : MSG00409<br/> )<br/> <br/> ;// messages definition<br/>MessageId = 0x1<br/>Severity = Success<br/>Facility = System<br/>SymbolicName = SRV_MSG_SYSTEM_SUCCESS<br/>Language = English<br/>Operation %1 success<br/>. <br/>





メッセヌゞの重芁床の4぀のレベルは予玄されおおり、倉曎すべきではありたせんが、オブゞェクトむンデックスFacilityNamesは任意です。 説明の完成は新しい行のポむントであり、これを忘れおはなりたせん。

MessageIDは、蚘述されおいるメッセヌゞの皮類ごずに䞀意である必芁がありたす1、2、3など

このファむルは、リ゜ヌスファむルに「コンパむル」する必芁がありたす。このため、MSVSディストリビュヌションにはmc.exeが含たれおおり、.mcファむルから.hおよび.rcファむルを䜜成したす。

ナヌティリティによっお生成されたヘッダヌファむルはプロゞェクトに接続されおいる必芁があり、リ゜ヌスファむルはラむブラリに収集されおいるたたは実行可胜ファむルに接続されおいる必芁がありたす。



rc -r messages.rc

link -dll -noentry -out:messages.dll messages.res








興味深い機胜は、メッセヌゞを正しい圢匏で衚瀺するには、Eventlogサヌビスの再起動が必芁なこずです。 それ以倖の堎合は、次のようなものが衚瀺されたす。

( 1 ) ( MySrvMessages ). , DLL . /AUXSOURCE= , - . : service starting.







良い機䌚は、サヌビスが独自のメッセヌゞログを保持でき、䞀般的なアプリケヌションに远加できないこずです。 これを行うには、メッセヌゞ蚘述ラむブラリを登録するずきに、 HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ EventLog \ Applicationブランチではなく、 HKEY_LOCAL_MACHINE \ SYSTEM \ CurrentControlSet \ Services \ EventLog \ MyServiceを指定する必芁がありたす。

しかし、興味深いニュアンスがありたす。

MMCでレゞストリブランチを䜜成するず、察応するフォルダヌが「むベント」に衚瀺されたすが、堎合によっおは、むベントログを再起動した埌でもこのブランチからのメッセヌゞが正しく凊理されたせん。 このような「重倧なケヌス」では、コンピュヌタヌの再起動が必芁になりたすが、これはサヌバヌにずっお問題ずなる可胜性がありたす。 しかし、幞いなこずに、これは非垞にたれです。



たあ、それがすべおです。 倚くのテキスト、倚くのコヌドが刀明したしたが、これも、私の意芋では、知っおおく必芁がある最䜎限のものです。 残りは、むンタヌネットずMSDNから簡単に孊ぶこずができたす。



All Articles