2010年11月5日金曜日

StartsStr関数,EndsStr関数

プログラムの作成中にHelpを眺めていてたまたま目についた関数

StartsStrは、ある文字列が指定したサブ文字列で始まるかをチェックする関数
EndsStrは、ある文字列が指定したサブ文字列で終わるるかをチェックする関数
ともに大文字小文字は別物として扱います。

上記のようなチェックを大文字小文字区別しないで行う関数もあり、
それぞれ、StartsText,EndsTexstです。

以下、サンプル

  1. WriteLn('大文字小文字区別して比較');  
  2.       if StartsStr('so','So What ?'then  
  3.       begin  
  4.        WriteLn('はじまるよ')  
  5.       end  
  6.       else  
  7.       begin  
  8.        WriteLn('はじまらない')  
  9.       end;  
  10.   
  11.       WriteLn('大文字小文字区別なしに比較');  
  12.       if StartsText('so','So what ?'then  
  13.       begin  
  14.        WriteLn('はじまるよ')  
  15.       end  
  16.       else  
  17.       begin  
  18.        WriteLn('はじまらない')  
  19.       end;  

でも、これらの関数っていつからあったのだろうか?
手元の環境で調べたところ少なくともDelphi2007には
あったようだけど

2010年11月3日水曜日

Purgeもどき

仕事で使っているアプリケーションがExeName_YYYYMMDDHHNNSS.Logのような
ログファイルを一杯作るので、消してくれという依頼があった。

ただし、このフォルダには、上記のログを作るファイルがいくつかああって
3世代程度は残してくれという依頼があった。

昔、仕事で触ってたOpenVmsのファイルシステムにはバージョンというのが
あって、古いバージョンのファイルを消すPurgeコマンドがあり
これとにたようなものが欲しいなということで、とりあえず作ってみた。
(本家には似ても似つかぬ、あくまでももどきですが。)

使い方は、

PurgeMock "パージファイルマスク" /D:パージファイルがあるフォルダ /G:残す世代数

で、/R: を指定することで、パージファイルマスクに正規表現が使用できます。

また、ファイルの更新日時を基準に/G:で指定した数だけ残るよう古い日付のものを
削除しますが、 /T:を指定することでファイルの作成日時を基準にPurgeすることが
できます。

なお、パージファイルマスクにより、複数の異なるファイル名のファイルが削除対象
となりえますが、このツールでは、このような場合のことを想定しておりません。
(/G:で指定した数になるようにばっさり消します。)

以下、ソース(delphi Xeがあればコンパイル可能です。)を置いておきます。
ライセンスは、MITライセンスとします。
ソース使用は自由ですが、無保証とします。

まずはメイン。

  1. program PurgeMock;  
  2.   
  3. {$APPTYPE CONSOLE}  
  4.   
  5. uses  
  6.   SysUtils,  
  7.   PurgeMockImp in 'PurgeMockImp.pas',  
  8.   MidasLib  
  9.   ;  
  10.   
  11. function CreatePurgeMockParams : TPurgeMockParams;  
  12. var  
  13.   PurgeMockParams : TPurgeMockParams;  
  14.  i : Integer;  
  15. begin  
  16.   
  17.   PurgeMockParams := TPurgeMockParams.Create;  
  18.   try  
  19.     try  
  20.    PurgeMockParams.Init(Paramstr(0));  
  21.    for i := 1 to ParamCount -1 do  
  22.       begin  
  23.        PurgeMockParams.SetPurgeParam(Paramstr(i));  
  24.       end;  
  25.     except  
  26.       PurgeMockParams.Free;  
  27.       PurgeMockParams := nil;  
  28.     end;  
  29.   
  30.   finally  
  31.     Result := PurgeMockParams;  
  32.   end;  
  33.   
  34. end;  
  35.   
  36. var  
  37.   PurgeMockParams : TPurgeMockParams;  
  38.   DoPurgeMock     : TPuregMock;  
  39.   Ret : Integer;  
  40.   
  41. begin  
  42.   try  
  43.     { TODO -oUser -cConsole メイン : ここにコードを記述してください }  
  44.     PurgeMockParams := CreatePurgeMockParams;  
  45.     if Assigned(PurgeMockParams) then  
  46.     begin  
  47.       DoPurgeMock := TPuregMock.Create(PurgeMockParams);  
  48.       try  
  49.         Ret := DoPurgeMock.Purge;  
  50.       finally  
  51.         DoPurgeMock.Free;  
  52.       end;  
  53.       PurgeMockParams.Free;  
  54.     end;  
  55.   
  56.   
  57.   except  
  58.     on E: Exception do  
  59.       Writeln(E.ClassName, ': ', E.Message);  
  60.   end;  
  61. end.  

次に、パージコマンドの本体

  1. unit PurgeMockImp;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   SysUtils  
  7.  ,DB  
  8.   ,DBClient  
  9.   ;  
  10.   
  11. type  
  12.   TPurgeTimeStamp = (ptCreate, ptUpdate);  
  13.   
  14.   TPurgeMockParams = class  
  15.   private  
  16.     FTargetDir: String;  
  17.     FUseRegularExpression: Boolean;  
  18.     FFileMask: String;  
  19.     FLeavingGenerations: Integer;  
  20.     FPurgeTimeStamp: TPurgeTimeStamp;  
  21.     procedure SetTargetDir(val: String);  
  22.     procedure SetUseRegularExpression(val: Boolean);  
  23.     procedure SetFileMask(val: String);  
  24.     procedure SetLeavingGenerations(val: Integer);  
  25.     procedure SetPurgeTimeStamp(val: TPurgeTimeStamp);  
  26.   public  
  27.     property TargetDir: String read FTargetDir write SetTargetDir;  
  28.     property UseRegularExpression: Boolean read FUseRegularExpression  
  29.       write SetUseRegularExpression;  
  30.     property FileMask: String read FFileMask write SetFileMask;  
  31.     property LeavingGenerations: Integer read FLeavingGenerations  
  32.       write SetLeavingGenerations;  
  33.     property PurgeTimeStamp: TPurgeTimeStamp read FPurgeTimeStamp  
  34.       write SetPurgeTimeStamp;  
  35.     procedure Init(ExePath: String);  
  36.   procedure SetPurgeParam(PurgeParam : String);  
  37.   end;  
  38.   
  39.   TPuregMock = class  
  40.   public  
  41.     constructor Create(Params: TPurgeMockParams);  
  42.     function Purge: Integer;  
  43.     destructor Destroy; override;  
  44.   strict private  
  45.     FPurgeMockParams: TPurgeMockParams;  
  46.     FPurgeMockDataSet : TClientDataSet;  
  47.     function MakePurgeFileList: Integer;  
  48.     function ExecPurge: Integer;  
  49.     function CreatePurgeDataSet : TClientDataSet;  
  50.   end;  
  51.   
  52.   function TryParseCmdLineSw(ParameterString : String; Sw : Array of String; var ParamValue : String; IgnoreCase: Boolean = true) : boolean;  
  53.   
  54. implementation  
  55.   
  56. Uses  
  57.    StrUtils  
  58.   ,IOUtils  
  59.   ,Types  
  60.   ,RegularExpressionsCore  
  61.   ;  
  62.   
  63. procedure TPurgeMockParams.SetTargetDir(val: String);  
  64. begin  
  65.   FTargetDir := val;  
  66. end;  
  67.   
  68. procedure TPurgeMockParams.SetUseRegularExpression(val: Boolean);  
  69. begin  
  70.   FUseRegularExpression := val;  
  71. end;  
  72.   
  73. procedure TPurgeMockParams.Init(ExePath: String);  
  74. begin  
  75.   
  76.  FTargetDir := ExtractFileDir(ExePath);  
  77.  FUseRegularExpression := false;  
  78.  FileMask := '*.*';  
  79.  FLeavingGenerations := 1;  
  80.  FPurgeTimeStamp := ptUpdate;  
  81.   
  82. end;  
  83.   
  84. procedure TPurgeMockParams.SetFileMask(val: String);  
  85. begin  
  86.   FFileMask := val  
  87. end;  
  88.   
  89. procedure TPurgeMockParams.SetLeavingGenerations(val: Integer);  
  90. begin  
  91.  if Val >= 0 then  
  92.   begin  
  93.    FLeavingGenerations := val;  
  94.   end  
  95.   else  
  96.   begin  
  97.    FLeavingGenerations := 0;  
  98.   end;  
  99. end;  
  100.   
  101. procedure TPurgeMockParams.SetPurgeParam(PurgeParam: String);  
  102. var  
  103.   ValueStr : String;  
  104. begin  
  105.   
  106.  if TryParseCmdLineSw(PurgeParam,['/D:','-D:'],ValueStr) then  
  107.   begin  
  108.    FTargetDir := ValueStr;  
  109.     Exit;  
  110.   end;  
  111.   
  112.  if TryParseCmdLineSw(PurgeParam,['/U:','-U:'],ValueStr) then  
  113.   begin  
  114.    FUseRegularExpression := true;  
  115.     Exit;  
  116.   end;  
  117.   
  118.  if TryParseCmdLineSw(PurgeParam,['/G:','-G:'],ValueStr) then  
  119.   begin  
  120.    LeavingGenerations := StrToIntDef(ValueStr,1);  
  121.     Exit;  
  122.   end;  
  123.   
  124.  if TryParseCmdLineSw(PurgeParam,['/T:','-T:'],ValueStr) then  
  125.   begin  
  126.    FPurgeTimeStamp := ptCreate;  
  127.     Exit;  
  128.   end;  
  129.   
  130.  if TryParseCmdLineSw(PurgeParam,[],ValueStr) then  
  131.   begin  
  132.     FFileMask := ValueStr;  
  133.     Exit;  
  134.   end;  
  135.   
  136. end;  
  137.   
  138. procedure TPurgeMockParams.SetPurgeTimeStamp(val: TPurgeTimeStamp);  
  139. begin  
  140.   FPurgeTimeStamp := val;  
  141. end;  
  142.   
  143. constructor TPuregMock.Create(Params: TPurgeMockParams);  
  144. begin  
  145.   inherited Create;  
  146.   FPurgeMockParams := Params;  
  147. end;  
  148.   
  149. function TPuregMock.Purge: Integer;  
  150. begin  
  151.   
  152.   Result := -1;  
  153.   
  154.  FPurgeMockDataSet := CreatePurgeDataSet;  
  155.   if Assigned(FPurgeMockDataSet) then  
  156.   begin  
  157.     if MakePurgeFileList > 0 then  
  158.     begin  
  159.       Result := ExecPurge;  
  160.     end;  
  161.     FPurgeMockDataSet.EmptyDataSet;  
  162.     FPurgeMockDataSet.Active := false;  
  163.     FPurgeMockDataSet.Free;  
  164.   end;  
  165.   
  166. end;  
  167.   
  168. function TPuregMock.CreatePurgeDataSet: TClientDataSet;  
  169. var  
  170.  PurgeDataSet : TClientDataSet;  
  171.  FD : TFieldDef;  
  172. begin  
  173.  PurgeDataSet := TClientDataSet.Create(nil);  
  174.   try  
  175.     try  
  176.    FD := PurgeDataSet.FieldDefs.AddFieldDef;  
  177.       FD.Name := 'FileName';  
  178.       FD.DataType := ftString;  
  179.       FD.Size := 1024;  
  180.   
  181.    FD := PurgeDataSet.FieldDefs.AddFieldDef;  
  182.       FD.Name := 'TimeStamp';  
  183.       FD.DataType := ftDatetime;  
  184.   
  185.       PurgeDataSet.CreateDataSet;  
  186.       PurgeDataSet.AddIndex('Purge_Idx','TimeStamp;FileName',[]);  
  187.       PurgeDataSet.IndexName := 'Purge_Idx';  
  188.   
  189.     Except  
  190.      if Assigned(PurgeDataSet) then PurgeDataSet.Free;  
  191.       PurgeDataSet := nil;  
  192.     end;  
  193.   finally  
  194.    Result := PurgeDataSet;  
  195.   end;  
  196. end;  
  197.   
  198. destructor TPuregMock.Destroy;  
  199. begin  
  200.   if Assigned(FPurgeMockParams) then  
  201.   begin  
  202.     FPurgeMockParams := nil;  
  203.   end;  
  204.   
  205.   inherited Destroy;  
  206. end;  
  207.   
  208. function TPuregMock.MakePurgeFileList: Integer;  
  209. var  
  210.  SearchOption: TSearchOption;  
  211.  SearchDir : TDirectory;  
  212.   SearchFileMask : String;  
  213.   LList: TStringDynArray;  
  214.   FileFullName,FileName : String;  
  215.   CanAddList : Boolean;  
  216.   PerlRegEx: TPerlRegEx;  
  217.   PurgeFile : TFile;  
  218.   
  219. begin  
  220.   
  221.   Result := 0;  
  222.   
  223.   //使っても使わなくても正規表現用のクラスをオープンしておく。  
  224.   PerlRegEx:= TPerlRegEx.Create;  
  225.   try  
  226.     SearchOption := TSearchOption.soTopDirectoryOnly;  
  227.     SearchFileMask := FPurgeMockParams.FileMask;  
  228.   
  229.   
  230.     if FPurgeMockParams.UseRegularExpression then  
  231.     begin  
  232.       PerlRegEx.RegEx := SearchFileMask;  
  233.       SearchFileMask := '*.*';  
  234.     end;  
  235.   
  236.     try  
  237.       LList := SearchDir.GetFiles(FPurgeMockParams.FTargetDir,SearchFileMask, SearchOption);  
  238.       FPurgeMockDataSet.Active := true;  
  239.       for FileFullName in LList do  
  240.       begin  
  241.         CanAddList := true;  
  242.         if FPurgeMockParams.UseRegularExpression then  
  243.         begin  
  244.           FileName := ExtractFileName(FileFullName);  
  245.           PerlRegEx.Subject := FileName;  
  246.           CanAddList := PerlRegEx.Match;  
  247.         end;  
  248.   
  249.         if CanAddList then  
  250.         begin  
  251.           //パージ対象リストに追加  
  252.           FPurgeMockDataSet.Append;  
  253.           FPurgeMockDataSet.FieldByName('FileName').AsString := FileFullName;  
  254.           if FPurgeMockParams.FPurgeTimeStamp = ptCreate then  
  255.           begin  
  256.            FPurgeMockDataSet.FieldByName('TimeStamp').AsDateTime := PurgeFile.GetCreationTime(FileFullName);  
  257.           end  
  258.           else  
  259.           begin  
  260.            FPurgeMockDataSet.FieldByName('TimeStamp').AsDateTime := PurgeFile.GetLastAccessTime(FileFullName);  
  261.           end;  
  262.           FPurgeMockDataSet.Post;  
  263.         end;  
  264.       end;  
  265.       Result := FPurgeMockDataSet.RecordCount;  
  266.   
  267.     except  
  268.       Result := -1;  
  269.     end;  
  270.   finally  
  271.   if Assigned(PerlRegEx) then PerlRegEx.Free;  
  272.   
  273.   end;  
  274. end;  
  275.   
  276. function TPuregMock.ExecPurge: Integer;  
  277. var  
  278.  DeleteCount : integer;  
  279.   DeleteFileName : string;  
  280.   PurgeFile : TFile;  
  281. begin  
  282.   DeleteCount := 0;  
  283.   
  284.   try  
  285.     FPurgeMockDataSet.Active := true;  
  286.     FPurgeMockDataSet.First;  
  287.   
  288.     while not(FPurgeMockDataSet.Eof) do  
  289.     begin  
  290.       DeleteFileName := FPurgeMockDataSet.FieldByName('FileName').AsString;  
  291.       PurgeFile.Delete(DeleteFileName);  
  292.       inc(DeleteCount);  
  293.   
  294.       //レコードをDeleteした場合は、Next不要なので注意  
  295.       FPurgeMockDataSet.Delete;  
  296.       if FPurgeMockDataSet.RecordCount <= FPurgeMockParams.LeavingGenerations then Break;  
  297.     end;  
  298.    Result := DeleteCount;  
  299.   
  300.   Except  
  301.    Result := -1;  
  302.   end;  
  303. end;  
  304.   
  305. function TryParseCmdLineSw(ParameterString : String;  
  306.                            Sw : Array of String;  
  307.                            var ParamValue : String;  
  308.                            IgnoreCase: Boolean) : boolean;  
  309. var  
  310.  i : integer;  
  311. begin  
  312.   
  313.  Result := false;  
  314.   
  315.   if Length(Sw) = 0 then  
  316.   begin  
  317.    //SW指定がない場合はそのままの文字列を返す  
  318.    ParamValue := ParameterString;  
  319.     Result := true;  
  320.   end  
  321.   else  
  322.   begin  
  323.    for i := low(Sw) to high(Sw) do  
  324.     begin  
  325.       if IgnoreCase then  
  326.       begin  
  327.         if StartsText(Sw[i],ParameterString) then  
  328.         begin  
  329.           Result := true;  
  330.           ParamValue := ReplaceText(ParameterString,Sw[i],'');  
  331.           Break;  
  332.         end;  
  333.       end  
  334.       else  
  335.       begin  
  336.         if StartsStr(Sw[i],ParameterString) then  
  337.         begin  
  338.           Result := true;  
  339.           ParamValue := ReplaceStr(ParameterString,Sw[i],'');  
  340.           Break;  
  341.         end;  
  342.       end;  
  343.     end;  
  344.   end;  
  345.   
  346. end;  
  347.   
  348. end.  

サービスの起動と停止

現在、進行中の案件で、サービスの再起動を定期的に行う必要が
あるので、Delphiでできるかどうか調べてみた。

Delphi PrismではdotNetFreameworkに標準で用意されたクラスが使えるので
簡単だが、Delphi(Win32)では用意されていないみたいだ。

さらに調べたところ、Jedi Code Library(Jcl)には、サービスを扱うクラス
(TJclSCManager,TJclNTService)が用意されていることを知ったので、
実際に検証してみた。

以下、検証用に作ったサンプル(サービスの列挙と指定したサービスの
停止と起動)です。

  1. unit Unit1;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, StdCtrls, ExtCtrls;  
  8.   
  9. type  
  10.   TForm1 = class(TForm)  
  11.     Button1: TButton;  
  12.     ListBox1: TListBox;  
  13.     LabeledEdit1: TLabeledEdit;  
  14.     Button2: TButton;  
  15.     Button3: TButton;  
  16.     Label1: TLabel;  
  17.     procedure Button1Click(Sender: TObject);  
  18.     procedure Button3Click(Sender: TObject);  
  19.     procedure ListBox1Click(Sender: TObject);  
  20.   private  
  21.     { Private 宣言 }  
  22.   public  
  23.     { Public 宣言 }  
  24.   end;  
  25.   
  26. var  
  27.   Form1: TForm1;  
  28.   
  29. implementation  
  30.   
  31. uses  
  32.     JclSvcCtrl  
  33.   , TypInfo  
  34.   ;  
  35.   
  36. {$R *.dfm}  
  37.   
  38. procedure TForm1.Button1Click(Sender: TObject);  
  39. var  
  40.   SvcMgr : TJclSCManager;  
  41.   i : Integer;  
  42. begin  
  43. //  
  44.   SvcMgr := TJclSCManager.Create();  
  45.   
  46.   try  
  47.     SvcMgr.Refresh(true);  
  48.     ListBox1.Clear;  
  49.     for i := 0 to SvcMgr.ServiceCount -1 do  
  50.     begin  
  51.       ListBox1.Items.Add(SvcMgr.Services[i].ServiceName);  
  52.     end;  
  53.   
  54.   
  55.   finally  
  56.     SvcMgr.Free;  
  57.   end;  
  58.   
  59. end;  
  60.   
  61. procedure TForm1.Button3Click(Sender: TObject);  
  62. var  
  63.   SvcMgr : TJclSCManager;  
  64.   Svc : TJclNTService;  
  65. begin  
  66. //  
  67.   //if True then  
  68.   SvcMgr := TJclSCManager.Create();  
  69.   try  
  70.     SvcMgr.Refresh(true);  
  71.     if (SvcMgr.FindService(LabeledEdit1.Text,Svc)) Then  
  72.     begin  
  73.       if TComponent(Sender).Tag = 1 then  
  74.       begin  
  75.         Svc.Start;  
  76.       end  
  77.       else  
  78.       begin  
  79.         Svc.Stop;  
  80.       end;  
  81.       Label1.Caption := GetEnumName(TypeInfo(TJclServiceState),Ord(Svc.ServiceState)) ;  
  82.     end;  
  83.   finally  
  84.     SvcMgr.Free;  
  85.   end;  
  86.   
  87.   
  88. end;  
  89.   
  90. procedure TForm1.ListBox1Click(Sender: TObject);  
  91. var  
  92.   SvcMgr : TJclSCManager;  
  93.   Svc : TJclNTService;  
  94. begin  
  95.   if ListBox1.ItemIndex >=0 then  
  96.   begin  
  97.     LabeledEdit1.Text := ListBox1.Items.Strings[ListBox1.ItemIndex];  
  98.     SvcMgr := TJclSCManager.Create();  
  99.     try  
  100.       SvcMgr.Refresh(true);  
  101.       if (SvcMgr.FindService(LabeledEdit1.Text,Svc)) Then  
  102.       begin  
  103.         Label1.Caption := GetEnumName(TypeInfo(TJclServiceState),Ord(Svc.ServiceState));  
  104.       end;  
  105.     finally  
  106.       SvcMgr.Free;  
  107.     end;  
  108.   
  109.   end;  
  110.   
  111. end;  
  112.   
  113. end.  



なお、jclには上記クラスを使用したサンプルプログラムがありますので詳細については
そちらを参照して下さい。

2010年11月2日火曜日

JvScheduledEventsを試してみる。

仕事で、とあるプロセスを定刻起動する必要があった。

OS標準のタスクスケジューラを使用してもよっかったが
起動できるのがバッチファイルか単独のEXEになるので
もううちょっと処理を柔軟にしたいと思いJVCLの
JvScheduledEventsを試してみた。

TJvScheduledEventsは、画面でスケジューリングの
設定が可能であるが、今回は、スケジュールを外部
ファイルに持たせたかったので、プラグラム中で
設定することにした。

以下、サンプルで試したソース。

  1. unit Unit1;  
  2.   
  3. interface  
  4.   
  5. uses  
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,  
  7.   Dialogs, JvScheduledEvents, StdCtrls, ExtCtrls, ComCtrls, JvComponentBase,  
  8.   JvCreateProcess;  
  9.   
  10. type  
  11.   TForm1 = class(TForm)  
  12.     Button1: TButton;  
  13.     DateTimePicker1: TDateTimePicker;  
  14.     Label1: TLabel;  
  15.     LabeledEdit1: TLabeledEdit;  
  16.   
  17.     procedure FormCreate(Sender: TObject);  
  18.     procedure FormDestroy(Sender: TObject);  
  19.     procedure Button1Click(Sender: TObject);  
  20.   private  
  21.     { Private 宣言 }  
  22.     FJvScheduledEvents : TJvScheduledEvents;  
  23.     procedure JvScheduledEventsExecute(Sender: TJvEventCollectionItem;  
  24.               const IsSnoozeEvent: Boolean);  
  25.   public  
  26.     { Public 宣言 }  
  27.   end;  
  28.   
  29. var  
  30.   Form1: TForm1;  
  31.   
  32. implementation  
  33.   
  34. uses  
  35.   JclSchedule;  
  36.   
  37. {$R *.dfm}  
  38.   
  39. procedure TForm1.Button1Click(Sender: TObject);  
  40. var  
  41.   EventItem : TJvEventCollectionItem;  
  42.   IJclSched : JclSchedule.IJclSchedule;  
  43.   IDaySched : IJclDailySchedule;  
  44.   IDyaFreq : IJclScheduleDayFrequency;  
  45.   
  46. begin  
  47.   EventItem := FJvScheduledEvents.Events.Add;  
  48.   IJclSched := EventItem.Schedule;  
  49.   
  50.    //イベントアイテムのスケジュール自体は、  
  51.    //IJclScheduleで受けますが、実態はTJclScheduleで  
  52.    //IJclScheduleのほか  
  53.    //IJclScheduleDayFrequency,  
  54.    //IJclDailySchedule,  
  55.     //IJclWeeklySchedule,  
  56.    //IJclMonthlySchedule,  
  57.    //IJclYearlySchedule  
  58.    //を継承しています。  
  59.   
  60.    IJclSched.RecurringType := srkDaily;  
  61.   
  62.    IDaySched := (IJclSched as IJclDailySchedule);  
  63.    if Assigned(IDaySched) then  
  64.    begin  
  65.       //毎日実行する場合は、EveryWeekDayをFalseにして  
  66.       //間隔を1(日)にします。  
  67.       IDaySched.EveryWeekDay := false;  
  68.       IDaySched.Interval := 1;  
  69.    end;  
  70.   
  71.    IDyaFreq := (IJclSched as IJclScheduleDayFrequency);  
  72.    if Assigned(IDyaFreq) then  
  73.    begin  
  74.       IDyaFreq.StartTime := DateTimeToTimeStamp(Self.DateTimePicker1.Time).Time;  
  75.       IDyaFreq.EndTime   := IDyaFreq.StartTime;  
  76.       IDyaFreq.Interval := 1;  
  77.    end;  
  78.   
  79.    EventItem.Name := LabeledEdit1.Text;  
  80.    EventItem.OnExecute := JvScheduledEventsExecute;  
  81.    EventItem.Start;  
  82.   
  83. end;  
  84.   
  85. procedure TForm1.FormCreate(Sender: TObject);  
  86. begin  
  87.   FJvScheduledEvents := TJvScheduledEvents.Create(Self);  
  88. end;  
  89.   
  90. procedure TForm1.FormDestroy(Sender: TObject);  
  91. begin  
  92.   FJvScheduledEvents.Events.Clear;  
  93.   FJvScheduledEvents.Free;  
  94. end;  
  95.   
  96. procedure TForm1.JvScheduledEventsExecute(Sender: TJvEventCollectionItem;  
  97.   const IsSnoozeEvent: Boolean);  
  98. var  
  99.   JvCreateProcess: TJvCreateProcess;  
  100. begin  
  101.   
  102.   JvCreateProcess := TJvCreateProcess.Create(Self);  
  103.   try  
  104.     JvCreateProcess.CommandLine := Sender.Name;  
  105.     JvCreateProcess.WaitForTerminate := true;  
  106.     JvCreateProcess.Run;  
  107.   
  108.   finally  
  109.     JvCreateProcess.Free;  
  110.   end;  
  111.   
  112.   
  113. end;  
  114.   
  115. end.  

ポイントは、以下の2つかと思います。


  1. JclScheduleをUsesに加えることと
  2. TJvEventCollectionItem.Scheduleの戻り値がIJclSchedule型であるが実態はTJclSchedule型でIJclScheduleのほかIJclScheduleDayFrequency,IJclDailySchedule,IJclWeeklySchedule,IJclMonthlySchedule,
    IJclYearlyScheduleを継承していて設定したいスケジュールにあわせて適切にキャストする必要があること

今回のサンプルは、『ボタンを押したら指定した時刻にメモ帳を起動する』というタイマーで処理しても
十分なものですが、リフレクション、パッケージの動的ロードなどを使えば、もっと面白いことが
できそうな気がします。