2010年11月4日星期四

后台服务程序怎么弹窗?(转)

  1. function RunUserProcess(lpFileName,lpCommand:string;swFlags:DWORD):DWord;
  2. var
  3.   dwProcessId: DWord;
  4.   hToken, hProcess: THandle;
  5.   si: STARTUPINFO;
  6.   pi: PROCESS_INFORMATION;
  7. begin
  8.   Result := 0;
  9.   GetWindowThreadProcessId(FindWindow('Shell_TrayWnd', nil), @dwProcessId);
  10.   hProcess := OpenProcess(PROCESS_ALL_ACCESS, False, dwProcessId);
  11.   if hProcess <> 0 then
  12.   begin
  13.     OpenProcessToken(hProcess, TOKEN_ALL_ACCESS, hToken);
  14.     try
  15.       ZeroMemory(@si, SizeOf(STARTUPINFO));
  16.       si.cb := SizeOf(STARTUPINFO);
  17.       Si.lpDesktop := PChar('Winsta0\Default');
  18.       si.wShowWindow := swFlags;
  19.       si.dwFlags := STARTF_USESHOWWINDOW;
  20.       CreateProcessAsUser(hToken, PChar(lpFileName), PChar(' '+lpCommand), nil, nil, False, CREATE_NEW_CONSOLE or  NORMAL_PRIORITY_CLASS, nil, nil, si, pi);
  21.       Result := Pi.dwProcessId;
  22.     finally
  23.       CloseHandle(hProcess);
  24.     end;
  25.   end;
  26. end;
复制代码
RunUserProcess(IE路径,网页地址,弹窗模式);

摘自:http://bbs.bearcome.com/viewthread.php?tid=56965&page=1

2010年11月3日星期三

用Delphi编写Windows服务(转)

摘自:http://hi.baidu.com/xuchuantao17/blog/item/c1f3759beadf17bfc8eaf4d3.html

一、Windows服务简介

  服务程序(Service Application)是一种运行于WinNT的后台程序,每个服务程序(Service Application)中可能包含若干个服务(Service),每个服务就是其中的一个线程(该服务也可以创建多个子线程)。采用服务,应用程序可以获得特殊的权限,而且不会被用户通过Win2000的任务管理器直接结束程序,所以服务常常用来实现一些特殊的目标。

  通过Win2000控制面板中的服务管理工具,我们可以设置/查看服务的特性:

  (1)服务名称;(2)显示名称;(3)描述;(4)启动类型;(5)依赖关系;

  其中,服务名称是标识给服务的。

  以Win2000的C:\WINNT\System32\services.exe程序为例子,该Exe文件对应一个Service Application,是该服务程序的可见实体;该exe中包含多个服务(Service),例如Alerter,Dhcp(DHCP Client),Messenger等。当我们结束一个服务的时候,该服务所在的Service Application中的其他服务并没有被终止。

在Delphi中,Borland的工程师为我们提供了TServiceApplication,TService,TServiceThread等类,封装了大量细节,简化了服务程序的开发

二、TServiceApplication

在Delphi中,类TServiceApplication就对应上述的ServiceApplication。利用Delphi的开发环境,我们新建一个Service Application Project,同时就创建了一个继承自TService的类。项目文件中的Application对象就是一个TServiceApplication实例。每个TServiceApplication包含若干个TService对象,正好对应上述的服务程序和服务之间的数量关系。

通过阅读TServiceApplication和TService类的定义,可以得知,TServiceApplication从TComponent类继承而来,TService从类TDataModule基础而来,Application对象负责各个TService对象的Create和Destroy。跟踪下列代码

  Application.CreateForm(TService1, Service1);

  可以发现创建的TService对象的Owner都是Application对象;在VCL FrameWork中Owner总是负责Destroy各个Component对象(VCL的TComponent类采用了Composite模式),所以TServiceApplication也将Destroy各个TService对象。

  下面跟踪TServiceApplication.Run的代码,可以发现TServiceApplication首先解析运行参数,实现了服务的Install和Uninstall。然后,初始化一个ServiceStartTable数组,该数组包含了各个service对象的服务名称和运行入口;最后创建一个TServiceStartThread 对象,该对象是一个线程对象,从线程调用API:StartServiceCtrlDispatcher来启动ServiceStartTable中指定的若干个服务;而ServiceApplication主线程就不断循环,处理消息,比如接收请求来停止/暂停某个服务。

三、TService

TService类继承自类 TDataModule,这意味着我们可以加入大量的VCL控件,实现丰富的功能。此外,我们还可以处理OnStart,OnPause,OnStop,OnContinue,OnCreate,OnShutDown等事件。其中需要说明的是:OnStop表示该服务被停止;而OnShutDown表示该ServiceApplication停止运行,这意味着其他服务也被终止了;两者含义是不一样的。

 

  前面讲过,ServiceApplication通过调用StartServiceCtrlDispatcher来启动各个服务。StartServiceCtrlDispatcher启动TService的入口,该入库就是TService.Main。TService.Main首先注册该服务,然后调用TService.DoStart。TService.DoStart创建一个内部TServiceThread成员对象,这是一个线程对象;考察TServiceThread.Execute可以得知,当我们处理的TService1. OnExecute,那么TService会把所有的请求委托给该TServiceThread成员对象处理,该对象以默认的方式处理所有的请求。

  TService. ServiceExecute是TService的主体内容。一个服务要正常运行,除了需要处理它要关注的目标(比如监听某个端口、执行某个任务等)外,还要响应外部命令/请求:比如终止、暂停、恢复该服务。因此可以考虑创建一个专门的线程来完成该任务,而在ServiceExecute中处理外面命令/请求。因此代码如下:

       while not Terminated do begin

              ServiceThread.ProcessRequests(False);

       end;

  当然,也可以在OnExecute中处理某些任务,如监听某个端口,但是这常常会导致该Service不能及时响应Stop/Pause等请求。当OnExecute执行完了,该服务实际上就完成了任务要结束了(terminate)。

Windows的服务是一个比较实用的功能,你的程序可以在Windows未进行登录的时候就开始运行,不受用户注销的影响,也不容易被用户误关闭。

但是编写服务也许不是一件容易的事情,幸好Delphi给我们提供了一个模板,可以很容易的编写一个标准的Windows服务程序。

首先,在Delphi内新建一个Service Application。

此时,Delphi已经给我们建好了一个Service程序的框架,我们只需要把我们的代码加到合适的位置就行了。

一般情况下,Service内需要一个线程来不断的工作,也许定时器也可以,但线程工作起来更好。

Delphi会生成一个可视化的Service容器,你可以一些必要的控件在它上面,但是由于它是服务程序,是没有界面显示的,因此不建议在上面安放Edit之类的控件,服务只是应该做处理工作的,显示界面应该由其它的程序来完成。Service控件的DisplayName属性是显示在管理工具-》服务的左边的名称的内容,而Name属性则是服务名称,当你用命令提示符来启动、停止服务时,就需要用到。

在事件OnStart内,我们应该完成启动线程的工作。

如:
ServiceStart
procedure TS2HConv.ServiceStart(Sender: TService;
var Started: Boolean);
var Reg:TRegistry;
LogFileName,LogPath:String;
slTemp:TStringList;

begin

CoInitialize(
nil);
Reg:
=TRegistry.Create;
Reg.RootKey:
=HKEY_LOCAL_MACHINE;
Reg.OpenKey(
'\SoftWare\BHome\Education',True);
LogPath:
=Trim(Reg.ReadString('LogPath'));
SourceConnStr:
=Trim(Reg.ReadString('SourceConnStr'));
if Trim(LogPath)='' then
LogPath:
='C:\';
Reg.CloseKey;
Reg.Free;

if RightStr(LogPath,1)<>'\' then
LogPath:
=LogPath+'\';
LogFileName:
=LogPath+FormatDateTime('yyyymmdd',Now)+'Log.txt';
Try
if not FileExists(LogFileName) then begin
slTemp:
=TStringList.Create;
slTemp.Clear;
slTemp.SaveToFile(LogFileName);
slTemp.Free;
end;
AssignFile(LogFile, LogFileName);
Append(LogFile);
Except
Started:
=False;
Exit;
End;
Started:
=True;

try
AC_Source:
=TADOConnection.Create(nil);
Q_Source:
=TADOQuery.Create(nil) ;
Q_Source.Connection:
=AC_Source;

try
AC_Source.Close;
AC_Source.ConnectionString:
=SourceConnStr;
AC_Source.Open;
SYSLog(
'与源数据库连接成功!');
DBOK:
=True;
Except
on E:Exception 
do begin
DBOK:
=False;
SYSLog(
'数据库连接失败!'+E.Message);
end;
End;

MyPHSThread :
= TPHSSendThread.Create();
MyPHSThread.FreeOnTerminate:
=True;
MyPHSThread.Priority:
= tpLower ;

end;

在OnStop事件内,我们应该
停止线程,并释放打开的资源,需要注意的是当你停止线程时,一般用Terminate方法,在线程内用Terminated属性来判断是否需要结束线程,而由于是线程,和主进程是时间运行的,有可能你刚好在进行Terminate时,线程已经刚进行过Terminated判断,正在进行比较费时的处理工作,而此时主进程立即执行Terminate后就进行释放资源的工作时,会造成线程执行错误,因此应该等到线程真正的正确停止后,主进程才能进行资源释放工作。

如:
ServiceStop

服务程序(Service Application)的描述如何在程序中实现?

摘自:http://topic.csdn.net/t/20040610/17/3081286.html

如WIN2000中服务SERVER,描述是:提供   RPC   支持、文件、打印以及命名管道共享。
我在CSDN上搜索了一下,但没有一个解决了,
我查了一下注册表,其实服务的描述都放到注册表了,
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services
我想我可以用写注册表的方法,
-------------------------------------------------------------------------------------------
procedure   TMyService.ServiceAfterInstall(Sender:   TService);
var
    reg:   TRegistry;
begin
    reg   :=   TRegistry.Create;
    try
        with   reg   do   begin
            RootKey   :=   HKEY_LOCAL_MACHINE;
            if   OpenKey( 'SYSTEM\CurrentControlSet\Services\ '+Name,false)   then
begin
                WriteString( 'Description ', 'This   is   the   service   description ');
            end;
            CloseKey;
        end;
    finally
        reg.Free;
    end;
end;

资源文件的应用(转)

摘自:http://www.7880.com/Info/Article-373944a0.html

建立一个RC文件,本示例程序:SwfFile.rc
RC文件其实就是一个资源文件的描述文本。然后可以输入一些我们要定义的资源,示例:
Flash SwfFile1 Thanks.SWF
然后用BRCC32把这个RC文件编译成SwfFile.RES。
BRCC32 SwfFile.rc保存为Swf.bat批处理文件。
在Delphi的工程文件中使用 $R 编译指令让Delphi包括资源到EXE文件里面。
{$R SwfFile.RES}
此时我们可以在单一的执行文件中调用资源了。示例代码如下:
//资源文件流的应用
procedure FlashResToFile(const ResName, ResType, FileName: string);
var
  FlashRes: TResourceStream;
begin
  FlashRes := TResourceStream.Create(HInstance, ResName, PChar(ResType));
  try
    FlashRes.SaveToFile(FileName); //将资源保存为文件,即还原文件
  finally
    FlashRes.Free;
  end;
end;
//执行资源文件中的Flash播放文件
procedure TFlashResFrm.PlayResFileBtnClick(Sender: TObject);
begin
  if FileExists(ExtractFilePath(ParamStr(0)) + 'Thanks.SWF') then
    DeleteFile(ExtractFilePath(ParamStr(0)) + 'Thanks.SWF');
    FlashResToFile('FLASH', 'SwfFile1', 'Thanks.SWF');
    ShockwaveFlash1.Movie := ExtractFilePath(ParamStr(0)) + 'Thanks.SWF';
    ShockwaveFlash1.Play;
end;

通常在Delphi的应用程序中会调用到很多的资源,例如图片,动画(AVI),声音,甚至于别的执行文件。
ResICO ICON "example.ico"              //加入图标
ResCursor Cursor "example.cur"         //加入光标
ResBitmap Bitmap "example.bmp"         //加入位图
ResAVI AVI "example.avi"               //加入视频
ResWav WAVE "example.wav"              //加入视频

{$R ResDefine.RES}

procedure TResourceForm.FormCreate(Sender: TObject);
begin
  Application.Icon.Handle := LoadIcon(hInstance,'ResICO');
  Application.Title := '资源文件使用集合';
  ResourceForm.Caption := '资源文件使用集合--[Delphi编程驿站:http://yckxzjj.vip.sina.com]';
end;

procedure TResourceForm.Image1MouseMove(Sender: TObject;
  Shift: TShiftState; X, Y: Integer);
begin
  //把MMSystem加入到Interface的uses单元中
  PlaySound('ResWav',HInstance,Snd_ASync or Snd_Memory or snd_Resource) ;
end;

procedure TResourceForm.AVIPlayBtnClick(Sender: TObject);
begin
  Animate1.ResName :='ResAVI' ; //资源标识
  Animate1.Active :=True ;
end;

procedure TResourceForm.BmpShowBtnClick(Sender: TObject);
begin
  //Image1.Picture.Bitmap.Handle :=LoadBitmap(hInstance,'ResBitmap');
  Image1.Picture.Bitmap.LoadFromResourceName(hInstance,'ResBitmap');
  Image1.Visible := True;
end;

procedure TResourceForm.CursorUpdateBtnClick(Sender: TObject);
begin
  Screen.Cursors[1] :=LoadCursor(hInstance,'ResCursor');
  //Image1.Cursor := 1;
  ResourceForm.Cursor :=1;
end;

在 delphi的exe文件中嵌入另外一个exe文件(转)

摘自:http://hi.baidu.com/ilovesafety/blog/item/99213e3eb2bb80f5838b13f3.html

原理:

     把需要包含的exe放入到进资源文件中,和原来的程序一起编译成一个exe文件,在程序第一次运行时释放出这个exe,然后调用这个exe文件。

步骤:

     1、创建rc文件。可以用任意文本编辑器来写。文件格式为:"资源名 资源类型 文件名"。

           对于资源类型,如果是exe文件,应该是EXEFILE, 如果是二进制文件,则是RCDATA。  

           这里创建一个文件float.rc:

代码

      2、将这个rc文件转换成res文件。

         复制float.rc到DELPHI安装目录里的bin文件夹, 执行brcc32 float.rc,生成float.res

     3、将这个res文件包含至工程文件中。

代码

1{$R    float.res}

    4、提取RES中的float.EXE。

代码
1procedure TFormMain.IEEE7541Click(Sender: TObject);
2
3  var
4     t : TResourceStream;
5  begin
6
7  if FileExists('float.exe') then
8     WinExec('float.exe',Sw_normal)
9  else
10    begin
11       try
12         t := TResourceStream.Create(HInstance,'AEXE','EXEFILE'); //其中HInstance为一个句柄常量;rwww为资源名;exefile为资源类型
13        t.SaveToFile('float.exe');
14       finally
15         t.free;
16      end;
17       WinExec('float.exe',Sw_normal);
18    end;
19  end;

delphi的RC文件格式写法

RC文件实际上是文本文件

新建一个TEXT文件,然后保存成扩展名为的RC文件(纯文本格式),

然后可以建立了,

例如:

 IC1 ICON I1.ICO
CUR1 CURSOR C1.CUR
BMP1 BMP B1.BMP

每行都分成三部分,调用名 类型 实际文件名
(文件格式为:"资源名 资源类型 文件名")

接下来可以用 brcc32 编译

在Delphi中如何使用RC文件中的字符串表(转)

摘自:http://www.yuloo.com/news/0910/314603.html

  在Delphi中如何使用RC文件中的字符串表
  首先用Notepad或Resource workshop 4.5建立RC文件。
  结构如下
  /****************************************************************************
  rcdemo.rc
  produced by Borland Resource Workshop
  *****************************************************************************/
  #include \"urcdemo.pas\"
  STRINGTABLE
  {
  IDS_HELLO, \"I am glad to see you.\"
  IDS_RC, \"This programming is created by %s.\"
  }
  然后用BRCC.EXE 或BRCC32.exe把rcdemo.rc编译成rcdemo.res文件,接着把rcdemo.res改名
  为rcdemo.rc文件。 如用Resource workshop 4.5会产生一个PAS单元文件,本例为urcdemo.pas
  内容如下:
  (****************************************************************************
  urcdemo.pas
  produced by Borland Resource Workshop
  *****************************************************************************)
  unit urcdemo;
  interface
  const
  IDS_HELLO= 2;
  IDS_RC = 1;
  implementation
  end.
  利用此项技术可实现错误处理中字符串问题存储问题和程序的本地化问题。
  范例:
  unit ufmRCDemo;
  interface
  uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;
  type
  TForm1 = class(TForm)
  GroupBox1: TGroupBox;
  Button1: TButton;
  Button2: TButton;
  GroupBox2: TGroupBox;
  Button3: TButton;
  Button4: TButton;
  procedure Button1Click(Sender: TObject);
  procedure Button2Click(Sender: TObject);
  procedure Button3Click(Sender: TObject);
  procedure Button4Click(Sender: TObject);
  private
  { Private declarations }
  public
  { Public declarations }
  end;
  var
  Form1: TForm1;
  implementation
  uses urcdemo;
  {$R rcdemo.rc}
  {$R *.dfm}
  {利用windows API}
  procedure TForm1.Button1Click(Sender: TObject);
  var
  arystr: array [0..255] of char;
  begin
  windows.LoadString(hInstance, IDS_RC, arystr, sizeof(arystr));
  ShowMessage(arystr);
  end;
  procedure TForm1.Button2Click(Sender: TObject);
  var
  arystr: array [0..255] of char;
  begin
  windows.LoadString(hInstance, IDS_Hello, arystr, sizeof(arystr));
  ShowMessage(arystr);
  end;
  {利用Delphi原生函数}
  procedure TForm1.Button3Click(Sender: TObject);
  begin
  ShowMessage(LoadStr(IDS_Hello));
  end;
  procedure TForm1.Button4Click(Sender: TObject);
  begin
  ShowMessage(LoadStr(IDS_RC));
  end;
  end.
  注意:16位格式于32位格式的差异。
  实例下载:http://www.megspace.com/computers/coreware/