Showing posts with label Delphi 2010. Show all posts
Showing posts with label Delphi 2010. Show all posts

Thursday, 13 December 2012

Capturing console output with Delphi 2010/XE (revised)

Following my previous post (Capturing console output with Delphi 2010/XE) and with all the great comments received on it, I have decided to publish the new solution provided by Lübbe Onken which solves the hanging issue when capturing the output for different kind of commands like ping, netstat, etc. The problem occurs on the last ReadFile which this solution will fix.
Here I'm summarizing Lübbe Onken comments on this issue:
"The current implementation assumes that if the external process is not finished yet, there must be something available to be read from the read pipe. This is not necessarily the case. If we use PeekNamedPipe to check for available data before entering the internal repeat loop, everything is fine.
I also put the CloseHandle into try ... finally and moved Application.ProcessMessages behind the internal read loop, because IMHO the screen update is better handled after processing the callback than before. But this is just cosmetic."

Here you can find the source code:


usage:

I want to say thanks to everyone who spend time looking at this issue and for making the community work and grow.
Jordi

Saturday, 2 June 2012

Mocking methods

I have been using Mock objects a lot with Delphi and I have implemented a small example and that you can find available in my personal repository on Google code. This simple example plays with the signature of the methods and uses delegates to return what we want to return. There are lots of ways to mock objects and lots of really good available frameworks: PascalMock, Ultra Basic MockObjects, DelphiMocks, etc. but sometimes we just want to mock some of the methods reintroducing a new signature. This simple example has helped me a lot in my unit testing and I hope you find it enough interesting to use it.


Basically we need an Interface to Mock which will contain all the contracts of the instance. TMock will be mocking the Interface and we need to set up the methods on the mockable class in a particular way using delegates. With this method TMock will be able to inject a new delegate and use it in our unit testing.

The declaration of TMock is quite neat:

type
  IMock = interface
  end;

  TMock<T> = class(TInterfacedObject,IMock)
  private
    FMockClass : T;
  public
    function SetUp() : T;
    constructor Create(mockingClass : T);
  end;

{ TMock<T> }

constructor TMock<T>.Create(mockingClass: T);
begin
  FMockClass := mockingClass;
end;

function TMock<T>.SetUp(): T;
begin
  Result :=  FMockClass;
end;
Then the IServer interface will have two methods which I want to mock. The delegates on the IServer will have to be extended as a property to then be able to overwrite them during the unit testing.

  //Contract definition to be Mocked.
  IServer<T, TResult> = Interface
    //Send structure
    function GetSendMessage() : TFuncParam<T, TResult>;
    procedure SetSendMessage(const Value: TFuncParam<T, TResult>);
    property SendMessage : TFuncParam<T, TResult> read GetSendMessage write SetSendMessage;
    //Receive structure
    function GetReceiveMessage() : TFunc<T>;
    procedure SetReceiveMessage(const Value: TFunc<T>);
    property ReceiveMessage : TFunc<T> read GetReceiveMessage write SetReceiveMessage;
  End;

It is really important to define the visibility of the methods on the implementation side so the mock only sees the methods we really want to redefine.

Then when the mock test is defined, it will only display the methods available to inject:
To set up the test, we only need to use the following declaration:

procedure TestTProtocolServer.TestCommunicateWithMock;
var
  ReturnValue: Boolean;
  Server: IServer<String, Boolean>;
  mock : TMock<IServer<String, Boolean>>;
begin
  Server := TServer.Create;

  mock := TMock<IServer<String, Boolean>>.Create(Server);

  //Set up the mocking methods using delegates:
  mock.SetUp().SendMessage := (function (message : string) : boolean
  begin
    result := True; //Return always true whatever the message is
  end);

  mock.SetUp().ReceiveMessage := (function () : string
  begin
    //Return the same message the server would reply
    result := 'This is the message from the server!';
  end);

  FProtocolServer := TProtocolServer.Create(mock.SetUp());
  try
    ReturnValue := FProtocolServer.Communicate;
    CheckTrue(ReturnValue, 'Communication with the Server Failed');
  finally
    Server := nil;
    mock.Free;
    FProtocolServer.Free;
    FProtocolServer := nil;
  end;
end;

With this simple method we can reuse existing code and just rewrite what we need to mock as the method we are calling depends on other objects/libraries, etc which are not testable. Note that this is not a framework, it is just a simple example where I need to mock a method and I don't want to use any of the existing frameworks. I like the way moq works and I wanted something similar (I wish we had lambda expressions, maybe one day!):

var mock = new Mock<ITest>();

mock.Setup(p => p.SendMessage(Is.Any<String>))
    .Returns(true)

It has loads of drawbacks as you will need to change the signature of your methods using delegates and sometimes it is not easy to do it, but I have been using it and it does the job.

Please, have a look at the repository and do not hesitate to leave any comment.

Saturday, 25 February 2012

How to run an application under active session account from a Windows service using Delphi

To run an application from a service impersonating an user account, first we need to install "JEDI API Library & Security Code Library" as it contains different interesting OS callings which are really useful in order to achieve our purposes. Once the library has been unzipped, create your own service where the library is located and add the following paths to your search path in your project options:

Then instead of using CreateProcess function to execute an application, we need to use CreateProcessAsUser function. The new process runs in the security context of the user represented by the specified token. The service must be run by the  LocalSystem account which is a predefined local account used by the service control manager. To be able to use the function from jedi-apilib which retrieves the token from the current user we need to use WTSQueryUserToken ( WtsGetActiveConsoleSessionID, hToken ) function. This function will only work under LocalSystem account which has SE_TCB_NAME property enabled, otherwise the query will be false.

Use the following example within your service:



Related links:

Saturday, 18 February 2012

Use ADPlus to troubleshoot hangs and crashes in our Delphi applications

It's again debugging time and in this post I'm going to put forward how to use ADPlus to troubleshoot hangs or crashes of our Delphi applications. As I'm sure you know, applications are getting more and more complicated using different libraries and third party tools and sometimes it is quite difficult to find out where the current problem is located. It has happened to me quite often that a tool or app blows app without reason, without a proper exception (even though all exception handling mechanisms are there) so the final user never gets any indication about what's wrong. With few simple steps from this article you will be able to set up ADPlus correctly, attach it to your running process and then create the crash dump for its further analysis. Let's start with debugging time!.

Installing Debugging tools for windows:
This is the Swiss knife for any good developer. Bring it always with you as it is really helpful. You can download the library from here. Just install it and save it to and USB to be portable. Then spend time using it, not only using ADPlus but also with Windbg, as it is crucial that you know about how to analyse the crash dump.

Setting up our Delphi Applications:
To be sure our Delphi app is correctly identified, we need to generate the map file and then use an external tool to convert all that information to symbols.
Edit in the project options to generate debug information and a detailed map file. Then using map2dbg we will transform the map file into debug symbols (.dbg files).
Once your project is correctly set up, build it and you will get the map file. Download the latest version of map2dbg v1.3 and copy map2dbg.exe where your project is located and run the following command line:

C:\testAdPlus>map2dbg.exe Project1.exe
Converted 6882 symbols.

You will now see a .dbg file with all necessary information for ADPlus.

Setting up the Symbols:
Once again, if we run ADPlus without setting up the symbols, we will only see address of memory without descriptions:
Call stack below ---
*** ERROR: Module load completed but symbols could not be loaded for C:\testAdPlus\Project1.exe
 # ChildEBP RetAddr  Args to Child              
WARNING: Stack unwind information not available. Following frames may be wrong.
00 0012f550 004832bd 01aba8c0 0045f20b 0012f700 Project1+0xb3295
01 0012f698 00487615 0012f91c 01aba8c0 0012f9a8 Project1+0x832bd
02 0012f6e4 0045eed1 01aba8c0 0012f91c 01aba8c0 Project1+0x87615
03 0012f710 00487768 00050980 0012f9a8 01acb650 Project1+0x5eed1
04 0012f86c 00487615 00000111 0012f91c 09010401 Project1+0x87768
05 0012f8b8 004a7c25 0012f9a8 00000111 01acb650 Project1+0x87615
06 0012f8e4 00486cb3 0012f8f8 00486ccb 0012f914 Project1+0xa7c25
07 0012f914 0043fd4a 00000111 00000980 00050980 Project1+0x86cb3
08 0012f92c 762cfd72 000209ae 00000111 00000980 Project1+0x3fd4a

Setting up _NT_SYMBOL_PATH environment variable:
Create a new general environment variable with the following name: _NT_SYMBOL_PATH and the following value:
symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols.
Where C:\Symbols is the path to your symbols. This is the same parameter set in WinDbg which I explained in my previous post (monitoring atom table part I).

Setting up ADPlus:
We can either run ADPlus using a simple configuration or use the configuration file which is much more complete. In any case, the fastest way is using the simple configuration which will help us to get the expected outcome.
C:\Program Files\Debugging Tools for Windows (x86)>adplus -crash -pmn Project1.exe -o C:\Adplus -mss c:\symbols

This configuration will run ADPlus looking for crashes, waiting for Project1.exe and it will output the results in C:\ADPlus and it will use the symbols from C:\Symbols.

Sample test:
This small piece of code will help me to generate a small access violation and then ADPlus will catch the crashing and it will generate the crash dump.

procedure TForm1.Button1Click(Sender: TObject);
begin
  try
    SimulateSystemException;
  finally
    Close;
  end;
end;

procedure TForm1.SimulateSystemException;
var
  p: PChar;
begin
  p := PChar(5);
  p^ := #9; //Access Violation here
end;

Once ADPlus is running, run your project, in my case Project1.exe and wait until it crashes (in my case it is just simulated so, the crash dump is instantly generated).

You will get a new line in the cmd window telling you:
Attaching to 4812 - Project1 in crash mode 02/18/2012 00:16:00

Once it crashes, go to C:\ADPlus folder and you will get a new folder with current date and the crash dump in it.

Analysing crash dump with Windbg:
Just open Windbg, load the first crash dump (FirstChance_Process_Shut_Down) and use the following commands:

0:000> !sym noisy
noisy mode - symbol prompts on
0:000> .reload Project1.exe
0:000> !analyze -v
ERROR: FindPlugIns 8007007b
*******************************************************************************
*                                                                             *
*                        Exception Analysis                                   *
*                                                                             *
*******************************************************************************

DBGHELP: kernel32 - public symbols  c:\symbols\kernel32.pdb\FCCF6FAC09804D49A4BB256A77F519572\kernel32.pdb
DBGHELP: Project1.exe is stripped.  Searching for dbg file
SYMSRV:  c:\symbols\Project1.dbg\4F3D9543457000\Project1.dbg not found
SYMSRV:  http://msdl.microsoft.com/download/symbols/Project1.dbg/4F3D9543457000/Project1.dbg not found
DBGHELP: .\Project1.dbg - file not found
DBGHELP: .\exe\Project1.dbg - path not found
DBGHELP: .\symbols\exe\Project1.dbg - path not found
DBGHELP: Project1.exe missing debug info.  Searching for pdb anyway
DBGHELP: Can't use symbol server for Project1.pdb - no header information available
DBGHELP: Project1.pdb - file not found
*** WARNING: Unable to verify checksum for Project1.exe
*** ERROR: Module load completed but symbols could not be loaded for Project1.exe
DBGHELP: Project1 - no symbols loaded
DBGHELP: user32 - public symbols c:\symbols\user32.pdb\CFD2C4C8EB9C406D8B6DC29512EB176A2\user32.pdb
DBGHELP: ole32 - public symbols c:\symbols\ole32.pdb\EDE30219D57144FAAC83675A6573D1982\ole32.pdb

Once processed, we can actually spot that the symbols are missing. This is because we need to place the symbols at the location defined by Windbg -> c:\symbols\Project1.dbg\4F3D9543457000\Project1.dbg. Just copy your dbg file into defined location and try again reloading Project1.exe from Windbg command line.

Now we can analyse again the crash dump and get all the information needed about the crash. This time with the correct symbols:

Call stack below ---
*** WARNING: Unable to verify checksum for C:\Users\jordi coll\Desktop\testAdPlus\Project1.exe
 # ChildEBP RetAddr  Args to Child              
00 0012f550 00473c9d 008fa8c0 00455747 0012f700 Project1!Unit1.TForm1.SimulateSystemException+0x5
01 0012f698 00477ff5 0012f91c 008fa8c0 0012f9a8 Project1!Controls.TControl.Click+0x75
02 0012f6e4 0045540d 008fa8c0 0012f91c 008fa8c0 Project1!Controls.TWinControl.WndProc+0x56d
03 0012f710 00478148 00010d2e 0012f9a8 0090b650 Project1!StdCtrls.TButtonControl.WndProc+0x71
04 0012f86c 00477ff5 00000111 0012f91c 09010401 Project1!Controls.DoControlMsg+0x28
05 0012f8b8 004984b1 0012f9a8 00000111 0090b650 Project1!Controls.TWinControl.WndProc+0x56d
06 0012f8e4 00477693 0012f8f8 004776ab 0012f914 Project1!Forms.TCustomForm.WndProc+0x599
07 0012f914 0043c146 00000111 00000d2e 00010d2e Project1!Controls.TWinControl.MainWndProc+0x2f
08 0012f92c 762cfd72 00010d26 00000111 00000d2e Project1!Classes.StdWndProc+0x16
09 0012f958 762cfe4a 00380fc8 00010d26 00000111 USER32!InternalCallWinProc+0x23
0a 0012f9d0 762d0943 00000000 00380fc8 00010d26 USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])
0b 0012fa10 762d0b36 00fd2450 00fd23e8 00000d2e USER32!SendMessageWorker+0x4b7 (FPO: [Non-Fpo])
0c 0012fa30 74d1b4ba 00010d26 00000111 00000d2e USER32!SendMessageW+0x7c (FPO: [Non-Fpo])
0d 0012fa50 74d1b51c 00a54518 00000000 00080032 comctl32!Button_NotifyParent+0x3d (FPO: [Non-Fpo])
0e 0012fa6c 74d1b627 54010001 00000001 0012fb48 comctl32!Button_ReleaseCapture+0x112 (FPO: [Non-Fpo])
0f 0012facc 762cfd72 00010d2e 00000202 00000000 comctl32!Button_WndProc+0xa98 (FPO: [Non-Fpo])
10 0012faf8 762cfe4a 74cb70f8 00010d2e 00000202 USER32!InternalCallWinProc+0x23
11 0012fb70 762d09d3 00000000 74cb70f8 00010d2e USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])
12 0012fba0 762d0979 74cb70f8 00010d2e 00000202 USER32!CallWindowProcAorW+0x97 (FPO: [Non-Fpo])
13 0012fbc0 004780f5 74cb70f8 00010d2e 00000202 USER32!CallWindowProcW+0x1b (FPO: [Non-Fpo])
14 0012fd44 00477ff5 00000202 008fa8c0 0012fd80 Project1!Controls.TWinControl.DefaultHandler+0xdd
15 0012fd90 0045540d 0012fe64 00000202 008fa8c0 Project1!Controls.TWinControl.WndProc+0x56d
16 0012fdd0 0043c146 00000202 00000000 00080032 Project1!StdCtrls.TButtonControl.WndProc+0x71
17 0012fde8 762cfd72 00010d2e 00000202 00000000 Project1!Classes.StdWndProc+0x16
18 0012fe14 762cfe4a 00380fbb 00010d2e 00000202 USER32!InternalCallWinProc+0x23
19 0012fe8c 762d018d 00000000 00380fbb 00010d2e USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])
1a 0012fef0 762d022b 00380fbb 00000000 00010d2e USER32!DispatchMessageWorker+0x322 (FPO: [Non-Fpo])
1b 0012ff00 004a15d2 0012ff24 00010001 0012ff70 USER32!DispatchMessageW+0xf (FPO: [Non-Fpo])
1c 0012ff1c 004a1617 00010d2e 00000202 00000000 Project1!Forms.TApplication.ProcessMessage+0x122
1d 0012ff40 004a1942 0012ff54 004a194c 0012ff70 Project1!Forms.TApplication.HandleMessage+0xf
1e 0012ff70 004a9c96 0012ffc4 00405a14 0012ff88 Project1!Forms.TApplication.Run+0xce
1f 0012ff88 7610d0e9 7ffdd000 0012ffd4 77711603 Project1!Project1.Project1+0x4e
20 0012ff94 77711603 7ffdd000 7736d39e 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
21 0012ffd4 777115d6 004a9c48 7ffdd000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])
22 0012ffec 00000000 004a9c48 7ffdd000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

0:000> kvn
 # ChildEBP RetAddr  Args to Child              
00 0012ff30 774a5370 7747b148 ffffffff 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])
01 0012ff34 7747b148 ffffffff 00000000 0012ff58 ntdll!ZwTerminateProcess+0xc (FPO: [2,0,0])
02 0012ff44 76f241ec 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x7a (FPO: [Non-Fpo])
03 0012ff58 00405f73 00000000 0012ff88 00000000 kernel32!ExitProcess+0x12 (FPO: [1,0,0])
04 0012ff70 004a9c9b 0012ffc4 00405a14 0012ff88 Project1!System.Halt0+0xf3
05 0012ff88 76f2d0e9 7ffd3000 0012ffd4 77481603 Project1!Project1.Project1+0x53
06 0012ff94 77481603 7ffd3000 77aa9471 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])
07 0012ffd4 774815d6 004a9c48 7ffd3000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])
08 0012ffec 00000000 004a9c48 7ffd3000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])

The only remaining thing is to analyse the crash dump trying to identify which are the regions involved in the crash and tackle them!.

Happy ninja debugging!.

Related links:

Tuesday, 31 January 2012

Projecting 3D points to a 2D screen coordinate system

In this article I will put forward a small function to project 3D points to a 2D coordinate system. I have used VLO framework to display all the points after the calculation of different common functions. The most difficult part is to correctly project 3D points into a 2D perspective. Basically the way to display the points is by using a viewport and setting it up correctly. Once all the points are calculated, we need to apply the transformations matrix to position the viewport and then draw the 3D object projected into a 2D canvas from the viewport perspective. The following function will use rotation matrix to correctly position the points. 

Sample code:
procedure T3DMesh.CalcPoints();
function d3Dto2D (viewport: T3DViewPort; point : T3DPoint; centre : T2DPoint; zoom : double) : T2DPoint;
var
  p : T3DPoint;
  t : T3DPoint;
  d2d : T2DPoint;
begin
  p.x := viewport.x + point.x;
  p.y := viewport.y + point.y;
  p.z := viewport.z + point.z;

  t.x := (x * cos(viewport.roll)) - (z * sin(viewport.roll));
  t.z := (x * sin(viewport.roll)) + (z * cos(viewport.roll));
  t.y := (y * cos(viewport.pitch)) - (t.z * sin(viewport.pitch));
  z := (t.y * cos(viewport.pitch)) - (t.z * sin(viewport.pitch));
  x := (t.x * cos(viewport.yaw)) - (t.y * sin(viewport.yaw));
  y := (t.x * sin(viewport.yaw)) + (t.y * cos(viewport.yaw));
  d2d := nil;
  if z > 0 then
  begin
      d2d := T2DPoint.Create(((x / z) * zoom) + centre.x, ((y / z) * zoom) + centre.y);
  end;
  result := d2d;
end ;

var
  listPoint : TObjectList;
  i: Integer;
  j: Integer;
  x, y, z: Double;
  d2dpoint : T2DPoint;
begin
  listPoint := TObjectList.Create;
  listPoint2 := TObjectList.Create;

  x :=-2.0;
  y := -2.0;
  z := 0.0;
  for i := 0 to 40 do
  begin
    y := -2.0;
    for j := 0 to 40 do
    begin
      z := cos((x * x + y * y) * 2) * exp(-1 * ((x * x) + (y * y)));
      listPoint.Add(T3DPoint.Create(x,y,z));
      y := y + 0.1;
    end;
    x := x + 0.1;
  end;

  for i := 0 to listPoint.count - 1 do
  begin
    d2dpoint := d3Dto2D(viewport, T3DPoint(listPoint[i]), centre, zoom);
    if Assigned(d2dpoint) then
      listPoint2.Add(d2dpoint);
  end;
  listPoint.Free;
end;


Examples:
z = sin(x) * cos (y):

z = cos((x^2+y^2)*2) * exp-(((x^2)+(y^2))):

z = x^2*exp(-x*x)*y^2*exp(-y*y):


With parameters:

Related links:

Friday, 30 December 2011

Finite automata to Regular Grammar with Thundax P-Zaggy

Moving ahead with FA, now we can generate the right-linear grammar that corresponds to the finite automata generated. The system is pretty simple and basically what the algorithm does is to go recursively through every state and to store the production (A → bC) using the info from the transition and both states.

P-Zaggy will use description text to assign unique variable names to each state. Each transition in the graph matches a production in the right-linear grammar. For example (right side image), the transition from “A” to “B” along the transition “a” matches the production “A → aB”. This production will be automatically added into the production list in the "Finite Automaton (simulation)" tab. To generate the full grammar, just open your finite automata and press "Get grammar" button to get the linear grammar. Now as any final state carries the production to λ, λ symbol has been added to the system as empty string.

In the following image you will see a general example with the automatically generated grammar:


Example with λ string:


Demo video:

Get the latest version from here:

Looking back/ahead:
This would be the last post of the year 2011 and I'm taking this moment to review all the good stuff I have been publishing in my blog, from the physics engine to different code snippets and all of them with the help of a big an bright Delphi community. I always find difficult to get round to writing more often but I always have my notebook with me and every time and idea pops out I am there to catch it. I have an endless list of really interesting stuff I would like to tackle and I hope next year would be more fruitful as there are less than 50 articles for this year (even though the visits have been increased to almost 6K per month wow!, I am grateful for that!). I am also blissfully happy for putting grain of salt in the community as I have widely used the knowledge of others and it is great to pay back.
Next year I will be implementing different algorithms and I will be focusing on grammars, compilers and AI as I am very keen on those subjects and as you already know I like a lot visual stuff (And everything or almost everything with my loved Delphi). I'm preparing a roadmap about different utilities I have in mind and stay tuned for new and very interesting stuff!.
Happy new year 2012!.
Jordi Corbilla

Related links:

Thursday, 29 December 2011

Finite Automata with Thundax P-Zaggy part II

Going on with the further enhancement of P-Zaggy (part I) to use its graph creation capability to run and simulate DFA, I have released a new version (v1.2.0 build 180) which allows you to check a bunch of strings in batch. One the DFA is defined, we can easily test our input strings by adding them into the list and the application will check every item and it will populate the status with "accepted/rejected" message. This version still only works with one char regular expressions (^[A-Z]$) so more complex expressions (^[A-Z]+$) will be used but not correctly adapted.

Examples:


Related links:

Finite Automata with Thundax P-Zaggy part I

I have moved forward the development of Thundax P-Zaggy with the addition of a Finite Automata builder and simulator. "A deterministic finite automaton (DFA) also known as deterministic finite state machine is a finite state machine that accepts/rejects finite strings of symbols and only produces a unique computation (or run) of the automaton for each input string. (wikipedia)". Building the automata with P-Zaggy is quite simple, so let's start by building a DFA for the following language: 
L = {ba | abna, n > 0}.
As it is shown in the previous image, the DFA would be as follows:


With the tool we would be able to create our diagrams placing the states and transitions. Once the diagram is set up, all transitions need to have the transition string to change the ongoing state and initial and final states need to be selected (using right click and selecting "Mark as Start Node" for Initial state and "Mark as End Node" for Final state).



We can start the simulation with very simple steps. Firstly, select the tab called "Finite Automaton (simulation)" and enter the test input string to test. Then press start button to internally initialize the graph as a DFA and press step to process every character of the input string while the diagram is changing states and showing you which is the actual state and whether the string is being accepted or rejected. To set up a single loop transition, select the node and with right click select "Set connector loop" and add text for the transition.


In this beta version, we can also use Regular Expressions in our transitions thanks to the widespread use of regular expressions inside Delphi XE. 


From the same screen we can test our regular expressions and check whether if they match or not. There are still some issues to tackle like "empty string" and other considerations that I would be delving into detail in the following days. I am also working on a Layered-Tree-Draw Algorithm using Reingold-Tilford Algorithm and the enhancement of the better recognition of more complex regular expressions.

Have a look at this preview of the functioning of the graph, it is really worth it:


Stay tuned and give P-Zaggy a try from here:
Related links:

Saturday, 10 December 2011

Install multiple instances of the same Delphi application service

In this article you will find an example on How to install multiple instances of the same Delphi application service under Windows. This topic was raised a few years ago in StackOverflow and I have decided to give more details about how to use multiple instances of the same service.
The service needs to be unique in name and the best way to sort this out is using a parameter to describe the service in a unique way. The service itself will use this parameter to compose its name even though it is using the same  executable. In this example I will identify the services when installing the service using the command line with the following instruction: "myService /install Param1". Param1 will be used to compose the internal service name as myServiceParam1. If we want to use another instance, just install a second service with a different param name as: myService /install Param2.

To achieve this is pretty simple, just create the service using your Delphi XE and then create the methods ServiceBeforeUninstall and ServiceCreate:


Notice the System.ParamStr(2) that will use the second parameter which was input from the command line. The first parameter is the /install command needed to install the service.

After the execution of the following commands:

myService /install Param1
myService /install Param2

You will see two installed services using the same executable:


To uninstall them, use the opposite command:

myService /uninstall Param1
myService /uninstall Param2

But this is not ending here. Now the services are installed, but neither the service name is set nor the description. To achieve this, we need to use the ChangeServiceConfig functions from WinSvc - Service Control Manager unit.

Have a look at the complete source code:

This solution is using the example provided by koochangmin on his Delphi blog. If you have a closer look at the ServiceAfterInstall method, you will find the composition of the name and description which will be used to populate the values in the service:


That is the way the service needs to be created in order to let the application use the parameters in runtime.

If you have any problem uninstalling the services, just use the SC command to delete the service:

sc delete ServiceExampleParam1

Related links:

Monday, 22 August 2011

Building my own Delphi Physics Engine part IX

I'm quite familiar with GDI, the graphics provided under Microsoft and which is widely used in Windows applications. TDPE is now ready to use Direct2D as now it's fully supported by Delphi 2010 and XE. According to MSDN, Direct2D is: a hardware-accelerated, immediate-mode, 2-D graphics API that provides high performance and high quality rendering for 2-D geometry, bitmaps, and text. The Direct2D API is designed to interoperate well with GDI, GDI+, and Direct3D.
As I'm testing this under Windows Vista, I've had to upgrade my windows version to Service Pack 2 and then I've installed the following update (KB971512 - The Windows Graphics, Imaging, and XPS Library contain the latest advancements in modern graphics technologies for gaming, multimedia, imaging and printing applications.). Direct2D is already installed in Windows 7.

We can use the same methods from TCanvas for our TDirect2DCanvas as they derive from the same ancestor TCustomCanvas. But you need to check the documentation for differences in the way they work.

A simple way to use Direct2D is as follows:

uses
    Direct2D, D2D1;

procedure Paint();
begin
    if TDirect2DCanvas.Supported then
    begin
        d2dCanvas := TDirect2DCanvas.Create(Canvas, ClientRect);
        try
            d2dCanvas.RenderTarget.beginDraw;
            d2dCanvas.RenderTarget.Clear(D2D1ColorF(clBlack));
            d2dCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);
            // drawing goes here
            Paint(d2dCanvas);
            d2dCanvas.RenderTarget.EndDraw;
        finally
            FreeAndNil(d2dCanvas);
        end;
    end;
end;

Here is the result of the Physics Engine using a Direct2D Render and a GDI Render:





You will see the difference when switching from GDI to Direct2D as the performance is quite different. When it comes to Direct2D, my computer is getting quite slower as my graphic card is not powerful at all and we can see that it takes a while to render the image.


GDI uses Pixel graphics but Direct2D can supports vector graphics as well, in which mathematical formulas are used to draw the lines and curves. Vector graphics provides high quality rendering independent of resolution of the device, while the pixelated graphics has dependency with resolution which may results in choppy graphics.

Most of the GDI APIs are not using anti-aliasing and transparency. Ofcrouse there are functions to do so but always there’s programming cost for taking advantage of these features. Also if we apply transparency and anti-aliasing, the computations are done using CPU. Direct2D can take advantage of graphics hardware and delegate the computationally intensive tasks to GPU


Get the latest version here: ThundaxBallDemo v1.584.
Interaction:
'd' will drop a box with a random colour and a constant angular velocity.
'f' will drop a circle with a random colour and a constant angular velocity.
'mouse interaction' mouse is able to grab items.
'q' Enable/Disable GDI or Direct2D rendering.

Note: You need to have installed Direct2D to run the app using Direct2D, otherwise GDI will be used.

Related links:

Wednesday, 10 August 2011

Building my own Delphi Physics Engine part VIII

TDPE is almost ready and it will not take long to release the first stable library!. I am eager to continue working on the project trying to sort out different physic scenarios  to make my dynamic engine even more realistic. Do not hesitate to give it a try as you will find the experience quite interesting. I am still working on the n-edge object and the cutting tool and trying to refactor all the code to cope with a layer architecture. Using this concept, I want to structure my system in a way that every component works using a certain level of abstraction. As you see in the next figure, every object is allocated in the screen while there is another layer which is responsible for the collision detection and another one for the forces interaction. You will notice in the video that there are still little issues to tackle regarding the object interaction as sometimes we can experience overlapping.


In the figure above, you can see that now the items are not rigid and they interact with each other as they were real items. Notice that the square item will go through the round shape of the circle.



Enjoy the video!.

Get the latest executable here: ThundaxBallDemo v1.504.
Interaction:
'd' will drop a box with a random color and a constant angular velocity
'f' will drop a circle with a random color and a constant angular velocity
'mouse interaction' mouse is able to grab items

Related links:

Sunday, 10 July 2011

Continuous Integration for your Delphi projects using Jenkins CI

Going on with the utilization of Msbuild, I'm putting forward this post using Jenkins CI (Continuous Integration) previously known as Hudson, for your Delphi projects under Windows Vista. In a nutshell, Jenkins provides an easy-to-use so-called continuous integration system, making it easier for developers to integrate changes to the project, and making it easier for users to obtain a fresh build. The automated, continuous build increases the productivity. (Source: What is Jenkins?). With these simple steps I'll lead you throughout the whole installation and configuration of your first Delphi built project using Jenkins CI and MsBuild.

1 . Download the latest version of Jenkins CI.
Use the following link to download the latest windows installer, in my case v1.419. The default installation path is C:\Program Files\Jenkins and there you'll find the service wrapper jenkins.exe and the Java web archive (jenkins.war) that is very useful to start the Jenkins if you have difficulties installing it with a container. It's very easy to run Jenkins by itself using the command: java -jar jenkins.war (which uses Winstone as a container).


2. Setting up environment variables.
To make sure that Jenkins runs perfectly, we need to set up the JENKINS_HOME environment variable:

3. Adding administrator privileges to Jenkins windows service.
We need to be sure that the service has enough permissions to be running. To do this, go to console and type down "services.msc". Then look for Jenkins service and add the log on information using an administrator account.
I had a lot of troubles trying to execute MSBuild from Jenkins until I realised that the service didn't have enough permissions.

4. Installing Jenkins CI plug-ins.
Once everything is done, we can go on with Jenkins and open a web explorer and type http://localhost:8080. Now we need to add the following plug-ins: Jenkins MSBuild Plugin and Hudson Setenv Plugin. To install them go to "Manage Jenkins"-> "Manage Pluggins" -> Available and look for them. Then, save the changes at the end of the page and reload Jenkins.
Once installed, you'll find them under the Installed section:

5. Configure MSBuild.
Now the plug-in is ready, and we need to supply the path of our MSBuild. Go to "Manage Jenkins" -> "Configure Jenkins" and add the Msbuild information in the MSbuild section:

6. Adding environment variables.
As we are trying to build Delphi projects we need to set up Jenkins with the same environment variables included in rsvars.bat batch file. Go to "Manage Jenkins" -> "Configure Jenkins" and add the following environment variables according to your Delphi version:

7. Setting up your project.
Start a new job with your project description and choose the "Build a free-style software project" type. And add the following MSbuild information to build your project (dproj file):

8. Build your Project.
Everything is ready to do the build. Now execute the "Build now" option and you'll see your project being compiled and built using MSBuild.

Now, you can add your Delphi projects and improve the quality of your software.

Related Links:

Monday, 4 July 2011

Delphi Msbuild

Msbuild has been included since Delphi 2007 to automate our Delphi builds and manage our projects in a better way. I have developed a custom application to provide automated Builds for Delphi (2007 / 2009 / 2010 / XE -Win32) using MSBuild. The app called Thundax Delphi Builder is available here for free. This little tool generates a batch file to call the list of projects and it displays the information using a TMemo getting the info from the console window using a pipe with the capture method from my previous post.
If you take a look at my application, you will see a output section and a configuration section. In the configuration section we need to add the list of projects to compile/build, the path of our Delphi binaries and the different MSBuild commands we want to execute.


As soon as all the parameters are correct, we can hit the "Build" button. The Build button generates a batch file called build.bat. This batch file contains the list of all our projects with the correct commands for MSBuild. Just take a look at the generated batch file and you will understand what is this doing.

First of all, it sets the environment variables for the target compiler. It means that if you enter in the "Bin" section  the path to your DelphiXE binaries, it will set MSBuild for DelphiXE. To do this, we only need to run rsvars.bat batch file which contains:

@SET BDS=C:\Program Files (x86)\Embarcadero\RAD Studio\7.0
@SET BDSCOMMONDIR=C:\Users\Public\Documents\RAD Studio\7.0
@SET FrameworkDir=C:\Windows\Microsoft.NET\Framework\v2.0.50727
@SET FrameworkVersion=v2.0.50727
@SET FrameworkSDKDir=
@SET PATH=%FrameworkDir%;%FrameworkSDKDir%;%PATH%
@SET LANGDIR=EN

Of course this tools is just a "little tool" to help you understand how Msbuild works and how to invoke it from the command line. I use continuous integration tools and some day I will talk about one of them, for example Hudson continuous integration.

PS: If you want to download the app, download my Calc Hash to make sure that the MD5 hash is correct. To check it, download the app, remove the " (0c3c3ab27a6000d8881974a411959828)." hash and check the file with the calc. If the app is correct, you should get the same hash.

Related links:

Capturing console output with Delphi 2010/XE

This new method supersedes the previous one using TDosCommand. It's been tested and it works with Delphi 2010 and Delphi XE, so it's worth to give it a try. It's really easy to use and I'm preparing a little tool with it.

//Anonymous procedure approach by Lars Fosdal
type
    TArg<T> = reference to procedure(const Arg: T);

procedure TForm1.CaptureConsoleOutput(const ACommand, AParameters: String; CallBack: TArg<PAnsiChar>);
const
    CReadBuffer = 2400;
var
    saSecurity: TSecurityAttributes;
    hRead: THandle;
    hWrite: THandle;
    suiStartup: TStartupInfo;
    piProcess: TProcessInformation;
    pBuffer: array [0 .. CReadBuffer] of AnsiChar;
    dBuffer: array [0 .. CReadBuffer] of AnsiChar;
    dRead: DWord;
    dRunning: DWord;
begin
    saSecurity.nLength := SizeOf(TSecurityAttributes);
    saSecurity.bInheritHandle := True;
    saSecurity.lpSecurityDescriptor := nil;

    if CreatePipe(hRead, hWrite, @saSecurity, 0) then
    begin
        FillChar(suiStartup, SizeOf(TStartupInfo), #0);
        suiStartup.cb := SizeOf(TStartupInfo);
        suiStartup.hStdInput := hRead;
        suiStartup.hStdOutput := hWrite;
        suiStartup.hStdError := hWrite;
        suiStartup.dwFlags := STARTF_USESTDHANDLES or STARTF_USESHOWWINDOW;
        suiStartup.wShowWindow := SW_HIDE;

        if CreateProcess(nil, pChar(ACommand + ' ' + AParameters), @saSecurity, @saSecurity, True, NORMAL_PRIORITY_CLASS, nil, nil, suiStartup, piProcess) then
        begin
            repeat
                dRunning := WaitForSingleObject(piProcess.hProcess, 100);
                Application.ProcessMessages();
                repeat
                    dRead := 0;
                    ReadFile(hRead, pBuffer[0], CReadBuffer, dRead, nil);
                    pBuffer[dRead] := #0;

                    //OemToAnsi(pBuffer, pBuffer);
                    //Unicode support by Lars Fosdal
                    OemToCharA(pBuffer, dBuffer);
                    CallBack(dBuffer);
                until (dRead < CReadBuffer);
            until (dRunning <> WAIT_TIMEOUT);
            CloseHandle(piProcess.hProcess);
            CloseHandle(piProcess.hThread);
        end;
        CloseHandle(hRead);
        CloseHandle(hWrite);
    end;
end;


usage:
    CaptureConsoleOutput('java -version', '', 
                procedure(const Line: PAnsiChar) 
                begin
                    Memo1.Lines.Add(String(Line)); 
                end
     );


With all the help I got from Lars, I've released a version of the function for test purposes. You can download the app from here (Thundax Output).

Example:

Updated 13/12/2012:
Check out the latest algorithm in the most updated and revised post:


Related links:

Tuesday, 21 June 2011

Building my own Delphi Physics Engine part VII

After several weeks working on my TDPE I think I managed it to get the desired outcome and now the displayed items show more realistic features. In my previous versions, neither angular velocity nor mass was interacting in terms of moving an object and now, using different mathematical algorithms, the gravity and angular velocity are considered for every item. That means that as soon as a collision is originated, the resultant force will lean back or forward the object and it will be rotating or moving until the forces of the system reach a value close to zero.
This new approach has included a massive refactoring of the existing code to cope with this new behaviour that will deliver spectacular performances. During the following weeks I'm going to  focus on the cutting tool as now I only have to extent the 4-edges collision object to n-edges. Once I have the n-edges collision object then I would be able to generate small chunks of it and each piece would have its own behaviour giving you the feeling that the object has really been broken.


As it's shown in the image, when most or more than a half of the object is out of the base (in blue), the red box should lean forward and fall according to the laws of physics (falling using rotation instead of falling straight how it was before in previous versions).

The following video will show the results of applying the latest algorithms to my Engine:


Enjoy the video!.

Get the latest executable here: ThundaxBallDemo v1.349.
If you want to drop a box, press 'd' and a new red box will fall.

Related links: