2012年11月27日火曜日

ActiveX.Exeもどき

マイクロソフトさんのCodeRecipeサイトに.EXEにあるクラスを動的に呼び出して使う例が載っていたのでこれをPrismでやってみた。

以下ソース

まずは、EXEのメインルーチン

unit DirZipImp;

namespace ConsoleApplication1;

interface



type
  ConsoleApp = class
  public
    class method Main(args: array of String);
  end;

implementation

class method ConsoleApp.Main(args: array of String);
begin
  // add your own code here
  Console.WriteLine('ならやめれば、うそよ');
 Console.ReadLine();
end;

end.

次に、EXEに含まれるクラス

namespace ActiveXExeLib;

interface

uses
  System.Collections.Generic,
  System.Text;

type
  Class1 = public class
  private
  protected
  public
  method CallYourName : String;
  end;

implementation

method Class1.CallYourName: String;
begin
 result := 'いーや';
end;


最後に上記のクラスライブラリを動的に呼び足してるExe

namespace ConsoleApplication2;

interface

uses
 System.Reflection;



type
  ConsoleApp = class
  public
    class method Main(args: array of String);
  end;

implementation

class method ConsoleApp.Main(args: array of String);
var
 m : &Assembly;

begin

  // add your own code here
  //Console.WriteLine('Hello World.');

 m := &Assembly.LoadFrom(args[0]);
 var instance1: Dynamic := Activator.CreateInstance(m.GetType('ActiveXExeLib.Class1'));
 Console.WriteLine(instance1.CallYourName());
 Console.ReadLine();

end;

end.

ConsoleApplication1.exeを呼び出すと

'ならやめれば、うそよ'

と表示され

ConsoleApplication2.Exeを引数に ConsoleApplication1.exe を与えて呼び出すと

'いーや'

と表示されます。


なお、Assemblyは、Prism(Oxgene)の予約語なので、手前&をつけないと.Netのクラスと
認識されないので注意が必要です。

また、Dynamicを型推論の意味でつかうには、RemObjects.Oxgene.Dynamic.dllの
参照登録が必要となります。


2011年4月3日日曜日

Guid文字列を得る

Delphi PrismでGuidを得るには、System.Guidを使用します。

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
begin
  var myguid := System.Guid.NewGuid;
  label1.Text := myguid.ToString(); 
end;

DelphiXE(Wi32)には、System.Guid構造体と同じように動作するHelperが実装されて
います。

2010年4月17日土曜日

Processのリストを表示する。

最近、VBAでプロセスを列挙する必要があったので、Prism(というか.Net)でやってみた

以下、コード(ボタンを押すとリストボックスにプロセスリストを表示する。)

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
ProcessList : array of  System.Diagnostics.Process;
begin

ProcessList := System.Diagnostics.Process.GetProcesses();

for each ps : System.Diagnostics.Process in ProcessList do
begin
listbox1.Items.Add(ps.ProcessName);
end;
end;


簡単すぎて涙が出てきた。Enum系のCallbackを使用する場合の
煩雑さがなくてよいです。

追記

Delphi Win32版で書いてみました。NT4.0をサポートしないといけない場合は、
やっぱり結構大変ですね。

2009年10月26日月曜日

ファイルリストを取取得する。

.NetFramworkでは、ファイル名のリストを取得するだけなら
System.IO.Directory.GetFilesメソッドで簡単に取得できます。

以下、サンプル



method MainForm.buttonExecGetFile_Click(sender: System.Object; e: System.EventArgs);
var
FileList : Array of String;
FileName : String;
begin

Self.listBoxResult.Items.Clear();

if Self.checkBoxFindSubDir.Checked then
begin
FileList := System.IO.Directory.GetFiles(Self.textBoxStartPath.Text,'*',System.IO.SearchOption.AllDirectories);
end
else
begin
FileList := System.IO.Directory.GetFiles(Self.textBoxStartPath.Text,'*',System.IO.SearchOption.TopDirectoryOnly);
end;

For FileName in FileList do
begin
listBoxResult.Items.Add(FileName);
end;
end;

2009年9月5日土曜日

Tem Japanのソースを移植してみる(RTTI)

Team JapanブログのDelphi2010のRTTI機能に関するポストのソースを
Delphi Prismで記述してみた。

以下ソース


method MainForm.BuildSql(obj : System.Object) : String;
var
FldList : String;
ValList : String;
t : System.Type;
PropArry : Array of PropertyInfo;
pv : Object;

begin

//渡された型を取り出して
t := obj.GetType();

//プロパティの一覧を取得する
PropArry := t.GetProperties();

//全てのフィールド(プロパティ)を操作してInsert分を作成
FldList := '';
ValList := '';
for each Prop : PropertyInfo in PropArry do
begin
FldList := FldList + Prop.Name + ',';
pv := Prop.GetValue(obj, nil);
//Value句 文字列は''で囲
if (pv.GetType().Name = 'String') then
begin
ValList := ValList + ''''+ pv.ToString() + ''',';
end
else
begin
ValList := ValList + pv.ToString() + ",";
end;

end;

Var Sb := new System.Text.StringBuilder();
Sb.AppendLine('INSERT INTO ' + t.Name + '(' + FldList.Remove(FldList.Length - 1) + ')');
Sb.AppendLine('Values (' + ValList.Remove(ValList.Length - 1) + ')');

Result := Sb.ToString();

end;



ちなみにC#で書くと



private String BuildSQL(object o)
{
//渡された型を取り出して
Type t = o.GetType();

//プロパティの一覧を取得する
System.Reflection.PropertyInfo[] PropArry = t.GetProperties();

//全てのフィールド(プロパティ)を操作してInsert分を作成
string FldList = "";
string ValList = "";

foreach (PropertyInfo Prop in PropArry)
{
FldList = FldList + Prop.Name + ",";
Object pv = Prop.GetValue(o, null);

//Value句 文字列は''で囲
if (pv.GetType().Name == "String")
{
ValList = ValList + "'" + pv.ToString() + "',";
}
else
{
ValList = ValList + pv.ToString() + ",";
}
}

StringBuilder Sb = new StringBuilder();
Sb.AppendLine("INSERT INTO " + t.Name + "(" + FldList.Remove(FldList.Length - 1) + ")");
Sb.AppendLine("Values (" + ValList.Remove(ValList.Length - 1) + ")");

return (Sb.ToString());

}


こんな感じかな

2009年8月31日月曜日

クラスのインスタンスを動的に作成する。

Delphi2010と同じ動きをするDelphi Prismのソースです。

まずは、実行用のフォームの処理です。


namespace WindowsApplication1;

interface

uses
System.Drawing,
System.Collections,
System.Collections.Generic,
System.Linq,
System.Windows.Forms,
System.ComponentModel,
System.Reflection,
SakaTestSpace;

type
///
/// Summary description for MainForm.
///

MainForm = partial class(System.Windows.Forms.Form)
private
method button1_Click(sender: System.Object; e: System.EventArgs);
protected
method Dispose(disposing: Boolean); override;
public
constructor;
end;



implementation


{$REGION Construction and Disposition}
constructor MainForm;
begin
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
end;

method MainForm.Dispose(disposing: Boolean);
begin
if disposing then begin
if assigned(components) then
components.Dispose();

//
// TODO: Add custom disposition code here
//
end;
inherited Dispose(disposing);
end;
{$ENDREGION}

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
SakaTestIntf : SakaTestSpace.ISakaTest;
CreateClassName : String;
t : System.Type;
obj : System.Object;
Assem : System.Reflection.Assembly;

begin

//使用するアセンブリをロードする
Assem := System.Reflection.Assembly.Load('ClassLibrary1');

t := Assem.GetType('SakaTestSpace.' + textBox1.Text);

obj := Activator.CreateInstance(t);

if obj <> nil then
begin
SakaTestIntf := (obj As SakaTestSpace.ISakaTest);
if SakaTestIntf <> nil then
begin
label3.Text := SakaTestIntf.SayMessage();
end;
end;
end;

end.



次に検証に使ったクラスです。


namespace SakaTestSpace;

interface

uses
System.Collections.Generic,
System.Linq,
System.Text;

type
ISakaTest = public interface
method SayMessage : String;
end;

type
TSakaTest = public class(ISakaTest)
private
protected
public
method SayMessage : String ; virtual;
end;

TSakaTest1 = public class(TSakaTest)
private
protected
public
method SayMessage : String; override;
end;

TSakaTest2 = public class(TSakaTest)
private
protected
public
method SayMessage : String; override;
end;


implementation

method TSakaTest.SayMessage : String;
begin
Result := "";
end;

method TSakaTest1.SayMessage : String;
begin
Result := 'Delphi Prism First Message';
end;

method TSakaTest2.SayMessage : String;
begin
Result := 'Delphi Prism Second Message';
end;

end.


PrismのほうがActivatorクラスが使える分、楽だ(短い処理で実現可能)と思う

2009年8月29日土曜日

Rttiを試して見るその2(プリズム版)

別ブログで書いたDelphi2010のメソッドコール
ソースと同等のソースをDelphi Prismで書いてみた。


namespace WindowsApplication1;

interface

uses
System.Drawing,
System.Collections,
System.Collections.Generic,
System.Linq,
System.Windows.Forms,
System.ComponentModel,
System.Reflection;


type
///
/// Summary description for MainForm.
///

MainForm = partial class(System.Windows.Forms.Form)
private
method button1_Click(sender: System.Object; e: System.EventArgs);
protected
method Dispose(disposing: Boolean); override;
public
constructor;
method SakaSum(a, b : Integer) : Integer;
end;

implementation

{$REGION Construction and Disposition}
constructor MainForm;
begin
//
// Required for Windows Form Designer support
//
InitializeComponent();

//
// TODO: Add any constructor code after InitializeComponent call
//
end;

method MainForm.Dispose(disposing: Boolean);
begin
if disposing then begin
if assigned(components) then
components.Dispose();

//
// TODO: Add custom disposition code here
//
end;
inherited Dispose(disposing);
end;
{$ENDREGION}

method MainForm.button1_Click(sender: System.Object; e: System.EventArgs);
var
rtm : System.Reflection.MethodInfo;
Args : Array of System.Object;
Rst : System.Object;
MyType : System.Type;
begin
MyType := System.Type.GetType('WindowsApplication1.' + Self.Name);

rtm := MyType.GetMethod('SakaSum');

if rtm <> nil Then
begin

Args := new System.Object[2];
Args[0] := Convert.ToInt32(textBox1.Text);
Args[1] := Convert.ToInt32(textBox2.Text);
Rst := rtm.Invoke(Self,Args);
label5.Text := Rst.ToString();

end;
end;

method MainForm.SakaSum(a, b : Integer) : Integer;
begin
Result := a + b;
end;

end.