请问开机用服务运行起的程序,如何不显示界面的问题

chengpengy 2014-08-27 04:49:58
小弟在win7下写了个服务程序,用它在开机的时候启动另外一个外部程序,外部程序运行后即隐藏窗口,在右下角加一个系统托盘图标.

现在发现的问题是,开机后外部程序在任务管理器中有进程,但是不显示托盘图标.,登陆桌面后再点击外部程序可以正常运行,只是在开机启动的时候有问题。

我一行一行注释,发现是因为在外部程序的formcreate里有一条application.showmainform:=false;,把它去掉之后,再开机就正常的有托盘了,想请问下什么原因,改成什么才能开机正常见托盘,隐藏窗口

在oncreate里
写application.mainform.visible:=false会报错
写form1.visible:=false无效
写showwindow(application.handle,sw_hide);
setwindowlong(application.handle,gwl_exstyle,ws_ex_toolwindow);
或者再加个application.minimize;开机后有托盘,但是窗体不隐藏

谢谢大家指点一下!


...全文
831 16 打赏 收藏 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
chengpengy 2014-08-29
  • 打赏
  • 举报
回复
今天有试了试,都百发百中了! 用system用户的服务程序B,取得活动session的token,然后settokeninformation,创建一个system用户的A,在A的create里加了个循环判断,保证托盘添加成功,后来再运行,没发现再有问题了! 为什么开机服务启动的时候,我这里的托盘大多情况都会失败,这个还不太清楚,不过算是解决了,谢谢大家! 15楼大哥提到的建一个自己的用户,是说在安装程序的时候吗? 我现在这个程序只要在管理员用户下双击,就会自动注册个服务,也还算方便,回头再试那种方法吧,谢谢哦!
  • 打赏
  • 举报
回复
既然B用CreateProcessAsUser启动A,那不应该“开机启动后,A的用户名是system”啊。
chengpengy 2014-08-28
  • 打赏
  • 举报
回复
是自己的一个小程序A,A运行后隐藏了窗口,并产生一个系统托盘。然后单独有个服务程序B,开机的时候会调用一下A,想实现A开机启动。 现在的情况是 1、开机后A的进程在任务管理器里有,但不见托盘,准确的说是有时候有,有时候没有,没有的时候多 2、如果把A改成运行后不隐藏窗口,那么开机可以见到A的窗口,但托盘也是时有时无 3、开机启动后,A的用户名是system 4、win7和xp都试了,一样的效果 5、B在start调用A,用的 WTSGetActiveConsoleSessionId WTSQueryUserToken openprocesstoken AdjustTokenPrivileges DuplicateTokenEx SetTokenInformation CreateEnvironmentBlock CreateProcessAsUser A如果设置成运行显示窗口,那么A可以开机运行成功,这说明调exe没啥问题吧,可是托盘呢,跑到哪个桌面去了
  • 打赏
  • 举报
回复
你可以自己创建一个用户,参考emule的代码,它可以以自己的用户权限运行,但是显示在登录的任意用户的托盘区。
lyhoo163 2014-08-28
  • 打赏
  • 举报
回复
外部程序是否别人的程序,还是你编译的程序?
chengpengy 2014-08-28
  • 打赏
  • 举报
回复
function CreateProcessWithLogonW(lpUserName, lpDomain, lpPassword: LPCWSTR; dwLogonFlags: DWORD; lpApplicationName: LPCWSTR; lpCommandLine: LPWSTR; dwCreationFlags: DWORD; lpEnvironment: Pointer; lpCurrentDirectory: LPCWSTR; const lpStartupInfo: STARTUPINFOW; var lpProcessInformation: PROCESS_INFORMATION): BOOL; stdcall; CreateProcessWithLogonW调用的时候还需要用户和密码么? 那如果不知道当前用哪个用户登录怎么办呢,用token那一系列,至少还可以从服务用system用户启动
chengpengy 2014-08-28
  • 打赏
  • 举报
回复
我在A的formcreate加了个while not Shell_NotifyIcon(...) do ; 重启试了3次,晕,竟然都有托盘图标了,ok了 难道就是因为这个地方有时候会失败么,还是A正常运行也是偶然现象,很好奇到底是为哈么 11楼大哥提醒用CreateProcessWithLogonW,我也试试哈
chengpengy 2014-08-28
  • 打赏
  • 举报
回复
嗯,不显示托盘图标的时候,会不会是Shell_NotifyIcon失败了,我要不要加个while(not Shell_NotifyIcon(...)),直到确保成功呢 我试试
  • 打赏
  • 举报
回复
那你应该使用CreateProcessWithLogonW,而不是CreateProcessAsUser。
hj8090 2014-08-28
  • 打赏
  • 举报
回复
在A程序中加个Timer,定时让托盘图标显示。
chengpengy 2014-08-28
  • 打赏
  • 举报
回复
是这样的 用openprocesstoken取下B的tokenid 用WTSGetActiveConsoleSessionId取下当前活动session的id 用AdjustTokenPrivileges开下权限 用DuplicateTokenEx复制B为一个新tokenid 用SetTokenInformation组合下B的新tokenid和活动sessionid 再用CreateProcessAsUser建立一个新的进程 所以建立的新进程是system用户,登进桌面以后,服务B的会话id是0,启动的程序A会话id是1,用户都是system,现在的问题是,A如果写成不隐藏窗体,那么开机启动后可以见到窗体,但托盘时有时无,如果写成隐藏窗体,那么托盘也是时有时无 后来我尝试这样 用WTSGetActiveConsoleSessionId取下当前活动session的id 用WTSQueryUserToken取当前活动sessionid对应的tokenid 用AdjustTokenPrivileges开下权限 用DuplicateTokenEx复制为一个新tokenid 再用CreateProcessAsUser建立一个新的进程 开机启动后,A的用户是administrator了,会话id为1,但托盘仍是时有时无,有时甚至A也启动不了了,都是一阵一阵的 救命啊
ptvbs 2014-08-27
  • 打赏
  • 举报
回复
把form整成无边框透明
xiaoxian251 2014-08-27
  • 打赏
  • 举报
回复
create 是最小化主窗口
chengpengy 2014-08-27
  • 打赏
  • 举报
回复
试了试后又发现,我把外部程序放到程序-启动菜单里,同时有服务会启动再加上程序-启动菜单里也有,开机后程序的用户名是administrator,基本上百发百中都能正常运行,如果不放程序-启动菜单,只用服务启动,不管托盘成功没有,用户名是system,只不过托盘时灵时不灵,有时候能出现,有时候没反应,那就是说程序-启动菜单比服务的start事件要靠前么?因为我写的只有一个进程实例可以运行,否则关掉自己,所以先运行的那个用户名才是administrator,用服务启动外部程序,托盘时灵时不灵这个问题,求助求助啊
chengpengy 2014-08-27
  • 打赏
  • 举报
回复
我也想到这了,试了一下,果然开机就正常启动了,正高兴,又重启了一次,又不行了。。 反复的试了几次发现,在工程里加或不加,托盘都有不出现的时候,竟然不是百发百中,这是什么情况呢? 服务启外部程序的时候,用的wtsgetactiveconsolesessionid,然后倒换的token,难道有的时候托盘都建到别的桌面去了? 现在启一些有界面的程序没啥问题,带托盘的就时灵时不灵的,求解求解啊
hj8090 2014-08-27
  • 打赏
  • 举报
回复
工程单元里: Application.ShowMainForm := False;

1,184

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧