DelFusa Blog 総本山

プログラミングの話題とかです。

NEW | PAGE-SELECT | NEXT

≫ EDIT

スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

| スポンサー広告 | --:-- | comments(-) | trackbacks(-) | TOP↑

≫ EDIT

Delphi Script Host


           _____________
   ∧,,∧∩  /
  ミ*゚Д゚*ミ < いくぜー
  (ミ   ミ   \
 ~ミ ,,, ミ      ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
   し' `J



ということで、Delphi Script Host を実装してみました。
もちろん、dcu配布の確認はマダポなので
いまのところは、
アンタんちで手に入るの、dcc32.exeとかdcuとか使って試してくださませ。


そのDelphiScript Hostってのは、
何をするかっていうと、
「デルファイソースを実行するだけで結果を返す。」

そんな、WSHの.vsファイルや.jsファイルと同じことを、.dsファイルで
つくっちまいましょうという、アイデアです。

ソースは下の方で公開しますが
Library部分が不足しているので、コンパイルできないっす。
でも、漏れのところでは動いています。


これを実装するためには、D2006でもD2005でもD7でもD6でもいいでしょう。
ただし、広範囲のユーザーに使ってもらうためには
コマンドラインコンパイラ配布がよい、と言われている(本当?)
D2007でしか考えにくいですね。

人気の高いD6personalのユーザーを対象にしたアプリ、
もしくは、TurboDelphiの無料版ユーザー限定アプリとして
DSHを使ってもらうという配布形式も考えられますね。


※ちなみに、漏れはここ5年来、WSHが
Windows Scripting Host だとずっと思ってました。すっかり、ここの影響。
http://www.roy.hi-ho.ne.jp/mutaguchi/wsh/index.html
Windows Script Host なのね。


で、Delphi Script Host の漏れの手元のソースを皿しておきます。
苦い感じに、DelFusa Library を使っているので、そのままじゃ動きません。
※以前にダウソしているやつがいれば、使ってください。たった今現在は公開休止。
概念理解でよろしく。

というか、まあ、一部の関数やクラスなので
自分で実装するのは難しい事ではないはずぞ。

まづは、ファイルの配置をお知らせするです。
こんな構成にしてみました。

  DelphiScriptHost
    dcc32
      bin
        dcc32.cfg ※これはコマンドライン引数代替用ファイル
        DCC32.EXE
        dcc32.jp ※これはDCC32.EXEを日本語対応するのに必要らしい
        rlink32.dll
      delfusa
        ※漏れのLibraryのdcuが配置
        
      lib
        ※C:\Program Files\CodeGear\RAD Studio\5.0\lib\
        ※のdcu全部
      mydcu
※ユーザーがdcuを作る場合の置き場所

    dsh.dpr
    dsh.dproj
    dsh.exe
    MessageUnit.dcu
    MessageUnit.dfm
    MessageUnit.pas
    output
      test_writeln.exe
※exe出力用フォルダ
    testsource
      test_error.ds
      test_msg.ds
      test_writeln.ds
※動作確認用の単純なソース

    AssociationFunction.ds
※関連づけ処理をする為のDelphi(Script?)ソース

もちろん、ここで、binの中とlibの中のファイルの配布が問題になるわけです。

んでもって、
dcc32.cfg、の内容。

  -Q
  -E"..\..\output"
  -N0"..\mydcu"
  -u"..\lib";"..\delfusa";"..\mydcu";

Exeやdcuの出力先指定、
使えるLibraryの場所指定、してますね。



program dsh;
uses
 SysUtils, Classes,
 SystemUnit, ShellUnit, StringUnitHeavy, BatFileUnit, FileList,
 MessageUnit in 'MessageUnit.pas' ;

//フォルダの中身のファイルとフォルダを全て削除する
//指定フォルダは削除しない。
//※この手続きの中身はどうでもいい。
procedure DeleteFileInFolder(FolderPath: String);
var
 FileList: TFileList;
 OutputList: TStringList;
 i: Integer;
begin
 FileList := TFileList.Create(nil); try
 OutputList := TStringList.Create; try

 FileList.DestStrings := OutputList;
 FileList.FileListType := flNormal;
 FileList.Directory := FolderPath;
 FileList.SubFolderList;

 for i := OutputList.Count - 1 downto 0 do
 begin
  DeleteFile(OutputList[i]);
 end;
 OutputList.Clear;

 FileList.FileListType := flFolder;
 FileList.SubFolderList;
 for i := OutputList.Count - 1 downto 0 do
 begin
  RemoveDir(OutputList[i]);
 end;

 finally OutputList.Free; end;
 finally FileList.Free; end;
end;

//※出力フォルダ
function OutputFolderPath: String;
begin
 Result := AppFolderPath+PathDelim+'output'+PathDelim;
end;

//コンパイラのパス
function CompilerFilePath: String;
begin
 Result := AppFolderPath+PathDelim+'dcc32'+PathDelim+'bin'+PathDelim+'DCC32.EXE';
end;

var
 MessageForm: TMessageForm;
 ParameterText: String;
 OutputText: String;
 CommandText: String;

 ExeOutputCheckList: TFileList;
 i: Integer;
 ExecuteFlag: Boolean;
begin
 try
//※パラメータから自分の名前部分を除去
  ParameterText := StringReplace(CmdLine, '"'+ParamStr(0)+'" ', '', [rfIgnoreCase]);
  OutputText := '';
//※出力フォルダの中身を綺麗にしてみる
  DeleteFileInFolder(OutputFolderPath);

  if ParameterText<>EmptyStr then
  begin
//※カレントをコンパイラパスと同じにする
   ChDir(AppFolderPath+PathDelim+'dcc32'+PathDelim+'bin');

//※コマンドライン出力を受け取る為にややこしい事はしていない
//※BATファイルをつくりパイプでテンポラリファイルにカキコミ
//※それをファイル読み出しして出力受け取る。
   CommandText :=
    'DCC32 '+ ParameterText;
   OutputText := CommandDumpResult(CommandText);
  end;

//※実行ファイル(exe)が出力されているかどうかを調べてみつける
  ExeOutputCheckList := TFileList.Create(nil); try
  ExeOutputCheckList.DestStrings := TStringList.Create; try
  ExeOutputCheckList.Directory := OutputFolderPath;
  ExeOutputCheckList.FileListType := flNormal;
  ExeOutputCheckList.List;
  ExecuteFlag := False;
  for i := 0 to ExeOutputCheckList.DestStrings.Count -1 do
  begin
   if AnsiSameText(ExtractFileExt(ExeOutputCheckList.DestStrings[i]), '.exe') then
   begin
    ExecuteFlag := True;
    EasyShellExecuteCmdLine(ExeOutputCheckList.DestStrings[i], True);
   end;
  end;
  finally ExeOutputCheckList.DestStrings.Free; end;
  finally ExeOutputCheckList.Free; end;

//※実行ファイルが無かった場合には
//※エラー行数表示、ダイアログが出るように手配。(WSHっぽく)
  if not ExecuteFlag then
  begin
   MessageForm := TMessageForm.Create(nil); try
   MessageForm.ParameterEdit.Text := ParameterText;
   MessageForm.OutputMemo.Text := AdjustLineBreaks( OutputText );
   MessageForm.ShowModal;
   finally MessageForm.Free; end;
  end;

 except
  on E:Exception do
   Writeln(E.Classname, ': ', E.Message);
 end;
end.



で、こいつで何ができるかというと。

***.ds、ってファイルを
dsh.exeってのにD&Dしたらさっくりと、内部でコンパイルされて、、
  エラーならエラーメッセ表示。(エラー行数は表示されるよん)
exeが出来てたらexe実行。

※もちろん***.dprや***.pasでもexe作成したりできる。

そして、
AssociationFunction.ds を dsh.exeにD&Dしたら
.dsファイルが、dsh.exeに関連付くので

もはや、.dsファイルを起動するだけでコンパイル実行されまする。

これは、つくってる最中に試してわかったんですが

Unit.pasをUnit.dsにして、実行。(内部でdcuも作られてる)
Project.dprをProject.dsにして、実行。

したら、それだけでProject.exeが起動しちゃうんですよね。
Form付きの普通のアプリ。

で、面白いのが、

dsh.exeに対して、dsh.dprをD&Dしても、outputフォルダには新しいdsh.exeが
作成されていまして、、、

自分自身をさっくりコンパイルしている感覚が味わえてしまいました。


さて、、、、と、、


            ∫    _________
   ∧,,∧     ∬   /
   ミ,,゚Д゚彡っ━~  <  どう使う?
_と~,,  ~,,,ノ_.  ∀   \ 
    ミ,,,,/~), │ ┷┳━   ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄ ̄
 ̄ ̄ ̄ .じ'J ̄ ̄| ┃
 ̄ ̄ ̄ ̄ ̄ ̄ ̄  ┻

ちょっと、Hostなだけにホストな気分なAAにしてみましたが。

夢膨らんだ?かしら。
ホストなだけに、夢を売ってみますかしら。


まづは、dcc32.exeはともかく、
dcu配布が可能かどうかを祈りませう。



スポンサーサイト

| 未分類 | 00:52 | comments:3 | trackbacks:0 | TOP↑

COMMENT

そういえば、コマンドラインでのdcc32の実行に対する戻り値を得るためにbatを使ってsます。
こんなソウスー。
function CommandDumpResult(Command: String): String;
var
 CommandBatFilePath, DumpFilePath: String;
 CommandBatText: String;
begin
 CommandBatFilePath := ExtractFilePath(ParamStr(0)) +
  'TmpCommand.bat';
 DumpFilePath := ExtractFilePath(ParamStr(0)) +
  'DumpResult.tmp';
 CommandBatText := Command + ' >> ' + '"' + DumpFilePath + '"' + sLineBreak;
 SaveStringToFile(CommandBatFilePath, CommandBatText);
 EasyCreateProcessCmd(CommandBatFilePath, True, False);
 Result := LoadStringFromFile(DumpFilePath);
 DeleteFile(CommandBatFilePath);
 DeleteFile(DumpFilePath);
end;
簡単でしょ?
紛れもなく堕落しています。

様々な処理をしたりなんかしたりして、こんな事をせずに取得できる方法があるのは、二百も三百も承知なのですが、
[Delphi-ML:31027] [Tips] ConsoleRedirect Library
個人的な偏った信条から、不採用です。(w

知ってる人は苦笑い。知らない人はスルーしてください。
どうせオプソにするから、採用したい人は、改造してくださいな。

| ミ・д・彡 | 2007/07/14 01:03 | URL |

DCUはコンパイラバージョンに依存するぞー。
# C/C++で言うobjファイルだから。

だから、D6やTurboのDCU持ってきてもコンパイルが通らない。
最悪、アップデータの違いでも通らない。

"コンパイラのバージョンが違います"

エラーが出るから、やっぱりD2007かTD2007(出たら)から持ってくるしかないよ。
# もちろん、旧Delphiの*.pasからD2007で
# *.dcuを生成できればOKだよ。

| DEKO | 2007/07/14 01:29 | URL | ≫ EDIT

こんばんはーですー。

そうですね。むしろ、dsh.exeの方を旧Versionで
コンパイルしちゃえばいいかと思いまして。
DCC32.exeとdcuのversionが一致してれば全然問題ないわけで

ということは、コマンドラインコンパイラが配布されてなくても
無料版Delphiユーザーのみ、.dsファイルの仕組みが使える
という形態もありかも。と、思った次第です。

| ミ・д・彡 | 2007/07/14 02:08 | URL |















非公開コメント

TRACKBACK URL

http://delfusa.blog65.fc2.com/tb.php/61-9352f99f

TRACKBACK

PREV | PAGE-SELECT | NEXT

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。