差異處

這裏顯示兩個版本的差異處。

連向這個比對檢視

Both sides previous revision 前次修改
下次修改
前次修改
cpp:sc:queryservicelockstatus [2016/04/19 11:35]
tony [Introduction]
cpp:sc:queryservicelockstatus [2023/06/25 09:48] (目前版本)
行 1: 行 1:
-{{tag>​cpp Windows}}+{{tag>​cpp Windows ​SCM}}
 ====== QueryServiceLockStatus ​ ====== ====== QueryServiceLockStatus ​ ======
 ===== Introduction ===== ===== Introduction =====
 某些third-party api會在runtime去新增service,以減少使用者在安裝上的負擔。然而在系統重新啟動時,SCM會lock service database,如果新增service將會造成block。此源自:​ [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms686321(v=vs.85).aspx|link]] 某些third-party api會在runtime去新增service,以減少使用者在安裝上的負擔。然而在系統重新啟動時,SCM會lock service database,如果新增service將會造成block。此源自:​ [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms686321(v=vs.85).aspx|link]]
 <​code>​ <​code>​
-A service cannot call StartService during initialization. The reason is that the SCM locks the service control database during initialization,​ so a call to StartService will block. After the service reports to the SCM that it has successfully started, it can call StartService.+A service cannot call StartService during initialization. The reason is that the SCM locks the
 +service control database during initialization,​ so a call to StartService will block. After the  
 +service reports to the SCM that it has successfully started, it can call StartService.
 </​code>​ </​code>​
 +因此,我們可以先檢查SCM database是否lock,再決定我們接下來該怎麼做。
 ===== How to? ===== ===== How to? =====
 +要解決這問題,可以使用:​
 +  * API: QueryServiceLockStatus。
 +  * Command line: sc querylock。
 +首先來看看QueryServiceLockStatus:​
 +<code cpp>
 +BOOL IsSCMRelease(){
 + SC_HANDLE hSCManager;
 + LPQUERY_SERVICE_LOCK_STATUS hStatus;
 + DWORD dwBytesNeeded;​
 + BOOL ret;
 +
 + hSCManager=OpenSCManager(NULL,​ NULL, SC_MANAGER_QUERY_LOCK_STATUS);​
 +
 + if (hSCManager) {
 + hStatus = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc(LPTR,​ sizeof(QUERY_SERVICE_LOCK_STATUS)+256);​
 + if( hStatus == NULL ) {
 + clog << "​LocalAlloc failed. Error: " << GetLastError() << endl;
 + return FALSE;
 + }
 +
 + if( !QueryServiceLockStatus( hSCManager, hStatus, sizeof(QUERY_SERVICE_LOCK_STATUS)+256,​ &​dwBytesNeeded)){
 + clog << "​Can'​t query lock status. Error: " << GetLastError() << endl;
 + ret = FALSE;
 + } else {
 + ret = hStatus->​fIsLocked == 0;
 + }
 +
 + CloseServiceHandle(hSCManager);​
 + LocalFree(hStatus);​
 + return ret;
 + }
 +
 + clog << "​Can'​t open SCManager."​ << endl;
 +
 + return FALSE;
 +}
 +
 +</​code>​
 +若透過command line:
 +<code bash>
 +C:​\Users\tonylin>​chcp 437 & sc querylock
 +Active code page: 437
 +[SC] QueryServiceLockStatus SUCCESS
 +        IsLocked ​     : FALSE
 +        LockOwner ​    :
 +        LockDuration ​ : 0 (seconds since acquired)
 +</​code>​
 ===== Reference ===== ===== Reference =====
   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms684938(v=vs.85).aspx|MSDN - QueryServiceLockStatus]]   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms684938(v=vs.85).aspx|MSDN - QueryServiceLockStatus]]
   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms686321(v=vs.85).aspx|MSDN - StartService]]   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms686321(v=vs.85).aspx|MSDN - StartService]]
   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms685104(v=vs.85).aspx|MSDN - SCM Handles]]   * [[https://​msdn.microsoft.com/​zh-tw/​library/​windows/​desktop/​ms685104(v=vs.85).aspx|MSDN - SCM Handles]]
 +  * [[http://​www.tenouk.com/​cpluscodesnippet/​changewindowserviceconfig.html|sample code]]
 +  * [[https://​technet.microsoft.com/​zh-tw/​sqlserver/​ms684953|QUERY_SERVICE_LOCK_STATUS structure]]
 =====    ===== =====    =====
 ---- ----
 \\ \\
 ~~DISQUS~~ ~~DISQUS~~