全國最多中醫師線上諮詢網站-台灣中醫網
發文 回覆 瀏覽次數:1768
推到 Plurk!
推到 Facebook!

WindowsServcie的製作

答題得分者是:harpist
P.D.
版主


發表:572
回覆:3897
積分:3689
註冊:2006-10-31

發送簡訊給我
#1 引用回覆 回覆 發表時間:2016-03-24 16:07:05 IP:118.169.xxx.xxx 未訂閱
請問各位,我要實作一支Service的Winows應用軟體(純VCL,非FiremMonkey)我先產出一個ServiceProject,然後再加入DataSnapServer的系統,以往在Delphi年代,建立Serivce時會自動加入一支Form成為MainForm,但現在xe10沒有這支Form的存在,而我new一個Form,到Option中,卻仍看不到這支Form的存在(想說設定成mainform)不清楚現在xe系列對service處理的概念,samples中也找不到相關的演示不知各位有沒有這方面的經驗,可以製作出一支service,然後在右下角的工作列中能出現trayicon且點選後可以show出這個form的方式ps.我目前是有實作出serviceexe,但無法達成上述的要求另外,我發現,當我把這支service.exe/install(用這種方式加入),到服務中啟動是以System的身份執行,我必須手動把System改為Administrator身份,有沒有指令可直接改變
P.D.
版主


發表:572
回覆:3897
積分:3689
註冊:2006-10-31

發送簡訊給我
#2 引用回覆 回覆 發表時間:2016-03-24 18:01:29 IP:118.169.xxx.xxx 未訂閱
有找到一點曙光
在 program source 中加入 Vcl.Forms(原本沒有), 就會有main Form 的效果, 但似乎此舉也令程式變成application而非 servcie mode 了
(至少目前測到的情況是如此)
JamesJuan
中階會員


發表:2
回覆:75
積分:80
註冊:2003-04-08

發送簡訊給我
P.D.
版主


發表:572
回覆:3897
積分:3689
註冊:2006-10-31

發送簡訊給我
#4 引用回覆 回覆 發表時間:2016-03-25 00:13:52 IP:118.169.xxx.xxx 未訂閱
感謝回覆

仔細看了以上三篇內文, 能力有點超出我的"預算", 積極努力找尋Delphi Code 的寫法中...
harpist
資深會員


發表:3
回覆:251
積分:430
註冊:2002-10-03

發送簡訊給我
#5 引用回覆 回覆 發表時間:2016-03-25 09:16:51 IP:61.219.xxx.xxx 訂閱
Vista之後 Service 與 User 被分隔在不同的 Session,簡單說 Service 的桌面與 User 登入的桌面是不同的。
所以除寫 Service 要另寫在 User Session 執行的 trayicon ,由 Service 去呼叫執行 trayicon 在 User Session。
需要 Service 與 trayicon 溝通可用 Inter-Process Communication 即可。


bool CheckProcess(AnsiString Pn)
{
BOOL bRet = false;
HANDLE hProcessSnap=NULL;
PROCESSENTRY32 pe32={0};
hProcessSnap=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if(hProcessSnap!=INVALID_HANDLE_VALUE)
{
pe32.dwSize=sizeof(PROCESSENTRY32);
if(Process32First(hProcessSnap, &pe32))
{
do
{
AnsiString exef = (AnsiString)pe32.szExeFile;
if(exef.UpperCase()==Pn.UpperCase())
{
bRet = true;
break;
}
}
while(Process32Next(hProcessSnap, &pe32));
}
CloseHandle(hProcessSnap);
}
return bRet;
}
//---------------------------------------------------------------------------
BOOL RunProcess(LPCSTR lpImage)
{
if(!lpImage)
{
return FALSE;
}
if(!CheckProcess("EXPLORER.EXE"))
{
return FALSE;
}
HANDLE hToken;
if(!GetTokenByName(hToken,"EXPLORER.EXE"))
{
return FALSE;
}
STARTUPINFO si;
PROCESS_INFORMATION pi;

ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb= sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");

BOOL bResult = CreateProcessAsUser(hToken,lpImage,NULL,NULL,NULL,
FALSE,NORMAL_PRIORITY_CLASS,NULL,NULL,&si,&pi);
CloseHandle(hToken);
if(bResult)
{
OutputDebugString("CreateProcessAsUser ok!\r\n");
}
else
{
OutputDebugString("CreateProcessAsUser false!\r\n");
}
return bResult;
}
bool RunAsActiveSession(char* lpFile)
{
bool bresult = false;

HINSTANCE m_hDll = LoadLibrary("Kernel32.dll");
FARPROC f = GetProcAddress(m_hDll, "WTSGetActiveConsoleSessionId");
typedef DWORD (WINAPI *WTSGetActiveConsoleSessionId)();
if(f)
{
DWORD dwSessionId = ((WTSGetActiveConsoleSessionId)f)();
HANDLE hUserToken = NULL;
if(WTSQueryUserToken(dwSessionId,&hUserToken))
{
SetTokenInformation(hUserToken, TokenSessionId, &dwSessionId, sizeof(DWORD));
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(STARTUPINFO));
si.cb = sizeof(STARTUPINFO);
si.lpDesktop = TEXT("winsta0\\default");

LPVOID pEnv = NULL;
DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
CreateEnvironmentBlock(&pEnv, hUserToken, FALSE);
if(CreateProcessAsUser(hUserToken,lpFile,NULL,NULL,NULL,FALSE,dwCreationFlag,NULL,NULL,&si,&pi))
{
// MessageText = "CreateProcessAsUser:" AnsiString(lpFile);
// WriteDebugLog(MessageText,"");
}
else
{
// MessageText = "CreateProcessAsUser:" SysErrorMessage(GetLastError()) AnsiString(lpFile);
// WriteDebugLog(MessageText,"");
}
CloseHandle(hUserToken);
bresult = true;
}
else
{
// AnsiString MessageText = "WTSQueryUserToken:" SysErrorMessage(GetLastError());
// WriteDebugLog(MessageText,"");
}

}
FreeLibrary(m_hDll);
return bresult;
}

------
~§~迷時師渡,悟了自渡~§~
編輯記錄
harpist 重新編輯於 2016-03-25 09:25:34, 註解 無‧
harpist 重新編輯於 2016-03-25 09:26:20, 註解 無‧
jcjroc
高階會員


發表:21
回覆:276
積分:114
註冊:2002-09-18

發送簡訊給我
#6 引用回覆 回覆 發表時間:2016-03-25 11:51:49 IP:59.124.xxx.xxx 訂閱
你的Service需要UI嗎??
如果需要,那UI的用途是啥?
從NT6開始,Service 的Session已經跟桌面分開了,所以只能分離Service的UI使其成為獨立程式.
執行身分是可以在Service的Property修改的.
至於UI跟Service間的溝通方式,最好的方式是RPC,會使用RPC的原因是可以不管通訊,程式寫法也比較簡單,但RPC的程式我只用過VC寫,C Builder 我沒用過.

===================引 用 P.D. 文 章===================
請問各位,我要實作一支Service的Winows應用軟體(純VCL,非FiremMonkey)我先產出一個ServiceProject,然後再加入DataSnapServer的系統,以往在Delphi年代,建立Serivce時會自動加入一支Form成為MainForm,但現在xe10沒有這支Form的存在,而我new一個Form,到Option中,卻仍看不到這支Form的存在(想說設定成mainform)不清楚現在xe系列對service處理的概念,samples中也找不到相關的演示不知各位有沒有這方面的經驗,可以製作出一支service,然後在右下角的工作列中能出現trayicon且點選後可以show出這個form的方式ps.我目前是有實作出serviceexe,但無法達成上述的要求另外,我發現,當我把這支service.exe/install(用這種方式加入),到服務中啟動是以System的身份執行,我必須手動把System改為Administrator身份,有沒有指令可直接改變
P.D.
版主


發表:572
回覆:3897
積分:3689
註冊:2006-10-31

發送簡訊給我
#7 引用回覆 回覆 發表時間:2016-03-26 00:26:41 IP:118.160.xxx.xxx 未訂閱
其實我現在正是以 service + user 的方式在作業, 
因為我需要透過手機傳到 server , 然後要讓 server 這邊做一些事(但不是遙控)
所以我用的是 datasnap server datasnap client(手機) 方式進行
手機送了一個訊息給 server, server收到後可能對資料庫做一些事, 或送一些訊息給手機, 或對程式做xxx等等..
因此, 在 server 端起一個 service 負責接收,
因為 service 無法做 UI(我的 ui 可能會有一些設定, 或操作要執行), 所以由 serrvice 再去呼叫 這支UI的應用程式(用SHELLEXECUTE)
但現在的問題在於
SERVICE INSTALL時的身份會是 SYSTEM, 而 UI 程式身份是 administrator, 導致由 system呼叫的 ui 是無法執行
(因為我的 ui 有加入 trayicon 功能, 這樣的呼叫, ui 是可以背模式執行, 但沒有辦法出現在前台螢幕操作)
雖然我手動把service 改為以 Administrator 登入 (因為如果用 Sysytem登入, 指定可以有互動桌面是沒用的)
但仍然不能有ui運作, 所以還有點困擾

目前我解決的辦法就是寫兩支 應用程式, 一支同樣是 datasnap server, 一支是 ui 程式, 但缺點就是 windows必須有使用者登入桌面才能有用, 這也是我想用 service 的目的!
harpist
資深會員


發表:3
回覆:251
積分:430
註冊:2002-10-03

發送簡訊給我
#8 引用回覆 回覆 發表時間:2016-03-26 02:09:26 IP:112.105.xxx.xxx 訂閱
我上面貼的程式碼你看一下,我以前就是這樣使用,Service 請用 CreateProcessAsUser 去執行UI。
我的程式架構是 Service 監控電腦...,UI給使用者的選項跟一些功能,類似Service是核心服務,UI只是設定介面,當你關掉UI還是可以從Service檢查再執行UI在使用者的桌面。相關API研究一下應該就沒問題了。

===================引 用 P.D. 文 章===================
其實我現在正是以 service user 的方式在作業,
因為我需要透過手機傳到 server , 然後要讓 server 這邊做一些事(但不是遙控)
所以我用的是 datasnap server datasnap client(手機) 方式進行
手機送了一個訊息給 server, server收到後可能對資料庫做一些事, 或送一些訊息給手機, 或對程式做xxx等等..
因此, 在 server 端起一個 service 負責接收,
因為 service 無法做 UI(我的 ui 可能會有一些設定, 或操作要執行), 所以由 serrvice 再去呼叫 這支UI的應用程式(用SHELLEXECUTE)
但現在的問題在於
SERVICE INSTALL時的身份會是 SYSTEM, 而 UI 程式身份是 administrator, 導致由 system呼叫的 ui 是無法執行
(因為我的 ui 有加入 trayicon 功能, 這樣的呼叫, ui 是可以背模式執行, 但沒有辦法出現在前台螢幕操作)
雖然我手動把service 改為以 Administrator 登入 (因為如果用 Sysytem登入, 指定可以有互動桌面是沒用的)
但仍然不能有ui運作, 所以還有點困擾

目前我解決的辦法就是寫兩支 應用程式, 一支同樣是 datasnap server, 一支是 ui 程式, 但缺點就是 windows必須有使用者登入桌面才能有用, 這也是我想用 service 的目的!
------
~§~迷時師渡,悟了自渡~§~
P.D.
版主


發表:572
回覆:3897
積分:3689
註冊:2006-10-31

發送簡訊給我
#9 引用回覆 回覆 發表時間:2016-03-27 00:13:37 IP:118.160.xxx.xxx 未訂閱
感謝提供code 的部份, 不過我看不懂 c 的內容, 我會再花一點時間去了解這段
===================引 用 harpist 文 章===================
我上面貼的程式碼你看一下,我以前就是這樣使用,Service 請用 CreateProcessAsUser 去執行UI。
我的程式架構是 Service 監控電腦...,UI給使用者的選項跟一些功能,類似Service是核心服務,UI只是設定介面,當你關掉UI還是可以從Service檢查再執行UI在使用者的桌面。相關API研究一下應該就沒問題了。

pcplayer99
尊榮會員


發表:142
回覆:740
積分:591
註冊:2003-01-21

發送簡訊給我
#10 引用回覆 回覆 發表時間:2016-09-27 11:54:01 IP:183.239.xxx.xxx 訂閱
换一换概念。

1. Service 用于服务。用 Service 的理由是,电脑一开它就来了。无需用户登录桌面。
2. APP 通过网络访问 Service (网络是 DataSnap 方式还是其它方式,都可以。比如我喜欢用 WebService 方式)。
3. 如果需要一个桌面 UI 对 Service 做一些设定,或显示 Service 的一些工作状态,单独另外写一个 UI 程式。它同样通过网络访问 Service。
系統時間:2018-01-19 21:17:04
聯絡我們 | Delphi K.Top討論版
本站聲明
1. 本論壇為無營利行為之開放平台,所有文章都是由網友自行張貼,如牽涉到法律糾紛一切與本站無關。
2. 假如網友發表之內容涉及侵權,而損及您的利益,請立即通知版主刪除。
3. 請勿批評中華民國元首及政府或批評各政黨,是藍是綠本站無權干涉,但這裡不是政治性論壇!