<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:atom="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0"><channel><atom:id>tag:blogger.com,1999:blog-7022755517551007355</atom:id><lastBuildDate>Sat, 26 May 2012 11:42:21 +0000</lastBuildDate><category>Redes</category><category>Graph Visualization</category><category>bugs</category><category>Lazarus</category><category>R2build</category><category>Object oriented programming</category><category>Files</category><category>Alpha-beta pruning</category><category>Windows</category><category>NAS</category><category>DBase</category><category>Syntax Highlighting</category><category>Simuladores</category><category>RSA</category><category>JQuery</category><category>inheritance</category><category>TDD</category><category>Trac</category><category>WMI</category><category>Backup</category><category>Encryption Algorithms</category><category>University</category><category>OLE</category><category>Delphi</category><category>Digital Identity</category><category>Penjili</category><category>AGILE</category><category>Persistence</category><category>IPTC</category><category>Services</category><category>Entrepreneur</category><category>Subversion</category><category>UTF-8</category><category>Dijkstra</category><category>Diaspora</category><category>Photography</category><category>Prim Algorithm</category><category>Scada</category><category>Perl</category><category>DevExpress</category><category>Concordion</category><category>Fuzzy</category><category>Extreme Programming</category><category>Prezi</category><category>Zaluum</category><category>Compression</category><category>Google SketchUp</category><category>VBA</category><category>Unicode</category><category>AspectJ</category><category>flickr</category><category>Eclipse</category><category>Scrum</category><category>CruiseControl</category><category>TFN</category><category>redmine</category><category>J2EE</category><category>JEDI</category><category>Free Pascal</category><category>.NET</category><category>Excel</category><category>Death March</category><category>ruby</category><category>gnuplot</category><category>QR2</category><category>Cryptography</category><category>Python</category><category>fundamental rights</category><category>VLO Framework</category><category>Microsoft</category><category>Currency</category><category>English</category><category>Google insight</category><category>Matlab</category><category>OpenSSL</category><category>Mock</category><category>Indy</category><category>Abstract Factory</category><category>lua</category><category>ebook</category><category>Direct2D</category><category>Steve Jobs</category><category>Artificial Intelligence</category><category>Videos</category><category>Access</category><category>Kanban</category><category>Scripts</category><category>Processing</category><category>Tron</category><category>Speech SDK</category><category>SSL</category><category>Components</category><category>email signature</category><category>JSON</category><category>Pair Programming</category><category>Facebook</category><category>Servlet</category><category>Routes</category><category>Icons</category><category>Base64</category><category>Peaberry</category><category>Molecules</category><category>Continuous Integration</category><category>Certification</category><category>Software configuration</category><category>Profiling</category><category>Cloud Computing</category><category>Debian</category><category>EADS</category><category>Google wave</category><category>Jobs</category><category>Image processing</category><category>InnoSetup</category><category>PCB</category><category>Google</category><category>JDBC</category><category>Open Source</category><category>PHP</category><category>copyright</category><category>Atom table</category><category>Google Chrome</category><category>Chaining Method</category><category>neuroplasticity</category><category>XML-RPC</category><category>Genetic Algorithms</category><category>TBookMark</category><category>twitter</category><category>Interface oriented programming</category><category>Tools</category><category>Data Recovery</category><category>Hardware</category><category>Subclipse</category><category>Ubuntu</category><category>film</category><category>communications</category><category>Advanced Encryption Standard</category><category>wetware</category><category>TED</category><category>Utilities</category><category>Delphi 2010</category><category>NetStat</category><category>Delphi XE</category><category>SQL</category><category>Regular Expressions</category><category>Jflex</category><category>FIT</category><category>Hibernate</category><category>Geek</category><category>Kernel</category><category>Parsing</category><category>Skills</category><category>Thiessen</category><category>ReportBuilder</category><category>Productivity</category><category>Flash</category><category>RSS</category><category>Computational geometry</category><category>UOC</category><category>ActiveX</category><category>Visprint</category><category>Ribbon Controls</category><category>News</category><category>Pragmatic Programming</category><category>LINQ</category><category>TStringGrid</category><category>MySQL</category><category>DLL</category><category>ZeosDBO</category><category>XML</category><category>Fractals</category><category>Extensions</category><category>Blogger</category><category>TKinter</category><category>Vijeo Citect</category><category>Refactoring</category><category>social networks</category><category>Compilers</category><category>DUnit</category><category>CUP</category><category>Voronoi</category><category>HTML</category><category>Pathfinding</category><category>Debug</category><category>neuroscience</category><category>Registro Windows</category><category>VNC</category><category>Industrial Automation</category><category>Hacking</category><category>JavaScript</category><category>Exceptions</category><category>Education</category><category>Google Maps</category><category>Windows Mobile</category><category>Modbus</category><category>Design patterns</category><category>MVC</category><category>Messaging</category><category>Sharing</category><category>Dependency Injection</category><category>Comparison</category><category>IT</category><category>SQL Server</category><category>RTTI</category><category>P-Zaggy</category><category>Security</category><category>Robotics</category><category>protobuf</category><category>TCustomAttributes</category><category>Augmented Reality</category><category>C++</category><category>Configuration library</category><category>WSDL</category><category>Virtual machines</category><category>SMTP</category><category>code rush</category><category>2D</category><category>Aspect oriented programming</category><category>Winsock</category><category>JUnit</category><category>Operating System</category><category>IDE Delphi</category><category>Data Bases</category><category>Unit Testing</category><category>API Windows</category><category>ADO</category><category>TCanvas</category><category>WorkFlow</category><category>eReader</category><category>Clipboard</category><category>JBoss</category><category>OSGi</category><category>Internet</category><category>Physics</category><category>games</category><category>ERP</category><category>Generics</category><category>Google Noop</category><category>Java</category><category>Science</category><category>Industrial Control</category><category>Web Service</category><category>API</category><category>Force-Directed Graph</category><category>Delegates</category><category>SOAP</category><category>COM Objects</category><category>Maths</category><category>Jenkins</category><category>3D</category><category>google guice</category><category>GEO</category><category>Exif</category><category>Convex Hull</category><category>password</category><title>Random thoughts on coding &amp; technology</title><description>Blog dedicated to software development in Delphi and others, Agile Development, eXtreme programming, Pragmatic thinking and learning, technology, entrepreneurship, photography and science.</description><link>http://thundaxsoftware.blogspot.com/</link><managingEditor>noreply@blogger.com (Jordi Corbilla)</managingEditor><generator>Blogger</generator><openSearch:totalResults>466</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/RandomThoughtsOnCodingTechnology" /><feedburner:info uri="randomthoughtsoncodingtechnology" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-3061345913870771758</guid><pubDate>Thu, 05 Apr 2012 21:28:00 +0000</pubDate><atom:updated>2012-04-05T23:34:33.152+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Unit Testing</category><category domain="http://www.blogger.com/atom/ns#">TCustomAttributes</category><category domain="http://www.blogger.com/atom/ns#">DUnit</category><title>DUnit and TCustomAttributes</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1fuOvLhBKYA/T33_4wv00NI/AAAAAAAAC7w/ICngCq62Ty0/s1600/bricks.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-1fuOvLhBKYA/T33_4wv00NI/AAAAAAAAC7w/ICngCq62Ty0/s1600/bricks.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In this article I am playing with &lt;a href="http://en.wikipedia.org/wiki/Unit_testing"&gt;Unit tests&lt;/a&gt; and &lt;a href="http://docwiki.embarcadero.com/VCL/en/System.TCustomAttribute"&gt;TCustomAttributes&lt;/a&gt; as I am working on different ideas to build up a lightweight testing framework. &amp;nbsp;Basically I liked the idea of &lt;a href="http://nunit.org/?p=testCase&amp;amp;r=2.5"&gt;TestCase&lt;/a&gt; attribute from &lt;b&gt;&lt;a href="http://www.nunit.org/"&gt;NUnit&lt;/a&gt;&lt;/b&gt; and I wanted to do something similar using TCustomAttributes and accessing those attributes using the &lt;b&gt;Delphi RTTI&lt;/b&gt; library. To understand better my purposes have a look at the following example extracted from &lt;b&gt;NUnit&lt;/b&gt; webpage:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;pre class="brush: delphi"&gt;[TestCase(12,3,4)]&lt;br /&gt;[TestCase(12,2,6)]&lt;br /&gt;[TestCase(12,4,3)]&lt;br /&gt;public void DivideTest(int n, int d, int q)&lt;br /&gt;{&lt;br /&gt;  Assert.AreEqual( q, n / d );&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;This simple example will execute three times the method or test using the parameters defined on the test case attributes. What if we could perform something similar? Would not be cool?&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Here is what I have done so far:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-uVVST3tJwVo/T34JpivbbjI/AAAAAAAAC74/J9yEo_G8-wo/s1600/TestUnit1.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="202" src="http://4.bp.blogspot.com/-uVVST3tJwVo/T34JpivbbjI/AAAAAAAAC74/J9yEo_G8-wo/s400/TestUnit1.bmp" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;Creation of the Custom Attributes:&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: delphi"&gt;type&lt;br /&gt;  TUserPasswordAttribute = class(TCustomAttribute)&lt;br /&gt;  private&lt;br /&gt;    FPassword: string;&lt;br /&gt;    FUserName: string;&lt;br /&gt;    Fresponse: Boolean;&lt;br /&gt;    procedure SetPassword(const Value: string);&lt;br /&gt;    procedure SetUserName(const Value: string);&lt;br /&gt;    procedure Setresponse(const Value: Boolean);&lt;br /&gt;  public&lt;br /&gt;    constructor Create(aUserName: string; aPassword: string; aResponse : Boolean);&lt;br /&gt;    property UserName: string read FUserName write SetUserName;&lt;br /&gt;    property Password: string read FPassword write SetPassword;&lt;br /&gt;    property response : Boolean read Fresponse write Setresponse;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TUserAgeAttribute = class(TCustomAttribute)&lt;br /&gt;  private&lt;br /&gt;    FAge: integer;&lt;br /&gt;    FUserName: String;&lt;br /&gt;    Fresponse: Boolean;&lt;br /&gt;    procedure SetAge(const Value: integer);&lt;br /&gt;    procedure SetUserName(const Value: String);&lt;br /&gt;    procedure Setresponse(const Value: Boolean);&lt;br /&gt;  public&lt;br /&gt;    property UserName : String read FUserName write SetUserName;&lt;br /&gt;    property Age : integer read FAge write SetAge;&lt;br /&gt;    property response : Boolean read Fresponse write Setresponse;&lt;br /&gt;    constructor Create(aUserName : string; aAge : Integer; aResponse : Boolean);&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;{ TUserPasswordAttribute }&lt;br /&gt;&lt;br /&gt;constructor TUserPasswordAttribute.Create(aUserName, aPassword: string; aResponse : Boolean);&lt;br /&gt;begin&lt;br /&gt;  SetUserName(aUserName);&lt;br /&gt;  SetPassword(aPassword);&lt;br /&gt;  Setresponse(aResponse);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserPasswordAttribute.SetPassword(const Value: string);&lt;br /&gt;begin&lt;br /&gt;  FPassword := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserPasswordAttribute.Setresponse(const Value: Boolean);&lt;br /&gt;begin&lt;br /&gt;  Fresponse := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserPasswordAttribute.SetUserName(const Value: string);&lt;br /&gt;begin&lt;br /&gt;  FUserName := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TUserAgeAttribute }&lt;br /&gt;&lt;br /&gt;constructor TUserAgeAttribute.Create(aUserName: string; aAge: Integer; aResponse : Boolean);&lt;br /&gt;begin&lt;br /&gt;  SetUserName(aUserName);&lt;br /&gt;  SetAge(aAge);&lt;br /&gt;  Setresponse(aResponse);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserAgeAttribute.SetAge(const Value: integer);&lt;br /&gt;begin&lt;br /&gt;  FAge := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserAgeAttribute.Setresponse(const Value: Boolean);&lt;br /&gt;begin&lt;br /&gt;  Fresponse := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUserAgeAttribute.SetUserName(const Value: String);&lt;br /&gt;begin&lt;br /&gt;  FUserName := Value;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;Those two custom attributes will serve as an example for what I intend to do. I need to test a login and some data from a current user and those bespoke attributes would be used by the test case.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;The Framework:&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: delphi"&gt;type&lt;br /&gt;  TAttributeProc = reference to procedure(CustomAttr: TCustomAttribute);&lt;br /&gt;&lt;br /&gt;  TFrameworkTestCase = class(TTestCase)&lt;br /&gt;  public&lt;br /&gt;    procedure TestAttributesMethod(CustomProc: TAttributeProc);&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;{ TFrameworkTestCase }&lt;br /&gt;&lt;br /&gt;procedure TFrameworkTestCase.TestAttributesMethod(CustomProc: TAttributeProc);&lt;br /&gt;var&lt;br /&gt;  ContextRtti: TRttiContext;&lt;br /&gt;  RttiType: TRttiType;&lt;br /&gt;  RttiMethod: TRttiMethod;&lt;br /&gt;  CustomAttr: TCustomAttribute;&lt;br /&gt;begin&lt;br /&gt;  ContextRtti := TRttiContext.Create;&lt;br /&gt;  try&lt;br /&gt;    RttiType := ContextRtti.GetType(Self.ClassType);&lt;br /&gt;    for RttiMethod in RttiType.GetMethods do&lt;br /&gt;      for CustomAttr in RttiMethod.GetAttributes do&lt;br /&gt;        CustomProc(CustomAttr);&lt;br /&gt;  finally&lt;br /&gt;    ContextRtti.Free;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;As you can see TFrameworkTestCase inherits from TTestCase and it adds the magic of reading the custom attributes and invoking the delegate as many times needed.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Using the small framework:&lt;/b&gt;&lt;br /&gt;&lt;pre class="brush: delphi; highlight: [26,27,28,29,31,32,33]"&gt;unit TestUnit1;&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;  Delphi DUnit Test Case&lt;br /&gt;  ----------------------&lt;br /&gt;  This unit contains a skeleton test case class generated by the Test Case Wizard.&lt;br /&gt;  Modify the generated code to correctly setup and call the methods from the unit&lt;br /&gt;  being tested.&lt;br /&gt;&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  TestFramework, Windows, Forms, Dialogs, Controls, Classes, RTTI, SysUtils, Variants,&lt;br /&gt;  Graphics, Messages, Unit1, StdCtrls;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  TestTLoginCase = class(TFrameworkTestCase)&lt;br /&gt;  strict private&lt;br /&gt;    FLogin: TLogin;&lt;br /&gt;  public&lt;br /&gt;    procedure SetUp; override;&lt;br /&gt;    procedure TearDown; override;&lt;br /&gt;  published&lt;br /&gt;    [TUserPasswordAttribute('User1', 'Password1', True)]&lt;br /&gt;    [TUserPasswordAttribute('User2', 'Password2', True)]&lt;br /&gt;    [TUserPasswordAttribute('User3', 'Password3', True)]&lt;br /&gt;    [TUserPasswordAttribute('User3', '', False)]&lt;br /&gt;    procedure TestUserLogin;&lt;br /&gt;    [TUserAgeAttribute('User1', 26, True)]&lt;br /&gt;    [TUserAgeAttribute('User2', 27, True)]&lt;br /&gt;    [TUserAgeAttribute('User3', 28, False)]&lt;br /&gt;    procedure TestUserAge;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;procedure TestTLoginCase.SetUp;&lt;br /&gt;begin&lt;br /&gt;  FLogin := TLogin.Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TestTLoginCase.TearDown;&lt;br /&gt;begin&lt;br /&gt;  FLogin.Free;&lt;br /&gt;  FLogin := nil;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TestTLoginCase.TestUserAge;&lt;br /&gt;var&lt;br /&gt;  aAge: integer;&lt;br /&gt;  aUserName: string;&lt;br /&gt;  aResponse : boolean;&lt;br /&gt;begin&lt;br /&gt;  TestAttributesMethod(procedure (CustomAttr : TCustomAttribute)&lt;br /&gt;    begin&lt;br /&gt;        if CustomAttr is TUserAgeAttribute then&lt;br /&gt;        begin&lt;br /&gt;          aUserName := TUserAgeAttribute(CustomAttr).UserName;&lt;br /&gt;          aAge := TUserAgeAttribute(CustomAttr).Age;&lt;br /&gt;          aResponse := TUserAgeAttribute(CustomAttr).Response;&lt;br /&gt;          Assert(aResponse=(FLogin.fetchDatauser(aUserName)=aAge), 'Incorrect value ' + aUserName);&lt;br /&gt;        end;&lt;br /&gt;    end);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TestTLoginCase.TestUserLogin;&lt;br /&gt;var&lt;br /&gt;  aPassword: string;&lt;br /&gt;  aUserName: string;&lt;br /&gt;  aResponse : boolean;&lt;br /&gt;begin&lt;br /&gt;  TestAttributesMethod(procedure (CustomAttr : TCustomAttribute)&lt;br /&gt;    begin&lt;br /&gt;        if CustomAttr is TUserPasswordAttribute then&lt;br /&gt;        begin&lt;br /&gt;          aUserName := TUserPasswordAttribute(CustomAttr).UserName;&lt;br /&gt;          aPassword := TUserPasswordAttribute(CustomAttr).Password;&lt;br /&gt;          aResponse := TUserPasswordAttribute(CustomAttr).Response;&lt;br /&gt;          Assert(FLogin.UserLogin(aUserName, aPassword)=aResponse, 'Incorrect user ' + aUserName);&lt;br /&gt;        end;&lt;br /&gt;    end);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;initialization&lt;br /&gt;RegisterTest(TestTLoginCase.Suite);&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Notice that every test case contains a set of &lt;b&gt;Custom attributes&lt;/b&gt; and they will be executed by using a delegate. I have included the Result parameter in the attribute so the test can know the result straight away and inform about it.&amp;nbsp;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-mb1KplJPRiw/T34MqyCpSeI/AAAAAAAAC8A/yHV49FyXM50/s1600/dunit.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="358" src="http://1.bp.blogspot.com/-mb1KplJPRiw/T34MqyCpSeI/AAAAAAAAC8A/yHV49FyXM50/s400/dunit.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/delphi-mock-wizard/"&gt;Delphi- mock wizard&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://dunit.sourceforge.net/"&gt;DUnit&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-3061345913870771758?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/fKS_A4c38MY/dunit-and-tcustomattributes.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-1fuOvLhBKYA/T33_4wv00NI/AAAAAAAAC7w/ICngCq62Ty0/s72-c/bricks.png" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/04/dunit-and-tcustomattributes.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2081492977282075589</guid><pubDate>Sun, 25 Mar 2012 21:20:00 +0000</pubDate><atom:updated>2012-03-25T23:20:40.643+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Chaining Method</category><category domain="http://www.blogger.com/atom/ns#">Aspect oriented programming</category><category domain="http://www.blogger.com/atom/ns#">Dependency Injection</category><category domain="http://www.blogger.com/atom/ns#">Delegates</category><category domain="http://www.blogger.com/atom/ns#">Generics</category><category domain="http://www.blogger.com/atom/ns#">LINQ</category><title>Fluent Interfaces example using Delphi part II</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-mv5eXSbGTX8/T2-GHobtetI/AAAAAAAAC7g/g2_Wo4bGazg/s1600/chain200.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-mv5eXSbGTX8/T2-GHobtetI/AAAAAAAAC7g/g2_Wo4bGazg/s1600/chain200.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Here is the second part of this interesting topic. As I'm still trying to redeem myself from my non popular &lt;a href="http://thundaxsoftware.blogspot.co.uk/2011/08/fluent-interfaces-example-using-delphi.html"&gt;first example&lt;/a&gt;, I'm sure this one will reach the expectations. For this example I'm trying to mimic the way &lt;a href="http://msdn.microsoft.com/en-us/library/bb397926.aspx"&gt;LINQ&lt;/a&gt; works, using &lt;b&gt;generics&lt;/b&gt; and &lt;b&gt;delegates&lt;/b&gt; and I have adapted my solution using &lt;b&gt;fluent Interfaces&lt;/b&gt; as well. This solution presents a &lt;i&gt;IQueryList&lt;/i&gt; which contains a TList&amp;lt;T&amp;gt; which can be queried like we were using SQL. So, we can select certain values and apply a where clause to filter the final list. This example will give you a hint on how to correctly implement fluent interfaces and how to extend this functionality for your applications.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-fF2XyCcsBEg/T2-Hu1Gl6EI/AAAAAAAAC7o/frm48_eCpSY/s1600/Unit1.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="390" src="http://2.bp.blogspot.com/-fF2XyCcsBEg/T2-Hu1Gl6EI/AAAAAAAAC7o/frm48_eCpSY/s400/Unit1.bmp" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Delegates:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;uses&lt;br /&gt;  Generics.Collections, Generics.Defaults;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  TProc&amp;lt;T&amp;gt; = procedure (n : T) of Object;&lt;br /&gt;  TProcList&amp;lt;T&amp;gt; = procedure (n : TList&amp;lt;T&amp;gt;) of Object;&lt;br /&gt;  TFunc&amp;lt;T&amp;gt; = reference to function() : T;&lt;br /&gt;  TFuncParam&amp;lt;T, TResult&amp;gt; = reference to function(param : T) : TResult;&lt;br /&gt;  TFuncList&amp;lt;T, TResult&amp;gt; = reference to function(n : TList&amp;lt;T&amp;gt;) : TResult;&lt;br /&gt;  TFuncListSelect&amp;lt;T, TResult&amp;gt; = reference to function(n : TList&amp;lt;T&amp;gt;) : TList&amp;lt;T&amp;gt;;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;IQueryList:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;IQueryList&amp;lt;T, TResult&amp;gt; = interface&lt;br /&gt;    function Where(const param : TFuncParam&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function OrderBy(const AComparer: IComparer&amp;lt;T&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function Select(const param : TFuncListSelect&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function FillList(const param : TFuncList&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function Distinct() : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function List() : TList&amp;lt;T&amp;gt;;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  TQueryList&amp;lt;T, TResult&amp;gt; = class(TInterfacedObject, IQueryList&amp;lt;T, TResult&amp;gt;)&lt;br /&gt;  private&lt;br /&gt;    FList : TList&amp;lt;T&amp;gt;;&lt;br /&gt;  protected&lt;br /&gt;    function Where(const param : TFuncParam&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function FillList(const param : TFuncList&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function Select(const param : TFuncListSelect&amp;lt;T, TResult&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function Distinct() : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;    function List() : TList&amp;lt;T&amp;gt;;&lt;br /&gt;    function OrderBy(const AComparer: IComparer&amp;lt;T&amp;gt;) : IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;  public&lt;br /&gt;    constructor Create();&lt;br /&gt;    destructor Destroy(); override;&lt;br /&gt;    class function New: IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;constructor TQueryList&amp;lt;T, TResult&amp;gt;.Create();&lt;br /&gt;begin&lt;br /&gt;  FList := TList&amp;lt;T&amp;gt;.Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;destructor TQueryList&amp;lt;T, TResult&amp;gt;.Destroy;&lt;br /&gt;begin&lt;br /&gt;  if Assigned(FList) then&lt;br /&gt;    FList.Free;&lt;br /&gt;  inherited;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.Distinct: IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;var&lt;br /&gt;  list : TList&amp;lt;T&amp;gt;;&lt;br /&gt;  i : integer;&lt;br /&gt;begin&lt;br /&gt;  list := TList&amp;lt;T&amp;gt;.Create();&lt;br /&gt;  for i := 0 to FList.Count-1 do&lt;br /&gt;  begin&lt;br /&gt;    if not list.Contains(FList[i]) then&lt;br /&gt;      list.Add(FList[i]);&lt;br /&gt;  end;&lt;br /&gt;  FList.Free;&lt;br /&gt;  FList := list;&lt;br /&gt;  result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.FillList(const param : TFuncList&amp;lt;T, TResult&amp;gt;): IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  param(FList);&lt;br /&gt;  Result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.List: TList&amp;lt;T&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  result := FList;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;class function TQueryList&amp;lt;T, TResult&amp;gt;.New: IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  result := Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.OrderBy(const AComparer: IComparer&amp;lt;T&amp;gt;): IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  FList.Sort(AComparer);&lt;br /&gt;  result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.Select(const param: TFuncListSelect&amp;lt;T, TResult&amp;gt;): IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  FList := param(FList);&lt;br /&gt;  result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TQueryList&amp;lt;T, TResult&amp;gt;.Where(const param: TFuncParam&amp;lt;T, TResult&amp;gt;): IQueryList&amp;lt;T, TResult&amp;gt;;&lt;br /&gt;var&lt;br /&gt;  list : TList&amp;lt;T&amp;gt;;&lt;br /&gt;  i: Integer;&lt;br /&gt;  Comparer: IEqualityComparer&amp;lt;TResult&amp;gt;;&lt;br /&gt;begin&lt;br /&gt;  list := TList&amp;lt;T&amp;gt;.Create();&lt;br /&gt;  for i := 0 to FList.Count-1 do&lt;br /&gt;  begin&lt;br /&gt;    Comparer := TEqualityComparer&amp;lt;TResult&amp;gt;.Default;&lt;br /&gt;    if not Comparer.Equals(Default(TResult), param(FList[i])) then&lt;br /&gt;      list.Add(FList[i]);&lt;br /&gt;  end;&lt;br /&gt;  FList.Free;&lt;br /&gt;  FList := list;&lt;br /&gt;  result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Example Implementation &amp;lt;Integer, Boolean&amp;gt;:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;procedure DisplayList();&lt;br /&gt;var&lt;br /&gt;  IqueryList : IQueryList&amp;lt;Integer, Boolean&amp;gt;;&lt;br /&gt;  item : integer;&lt;br /&gt;begin&lt;br /&gt;  //Create the list and fill it up with random values&lt;br /&gt;  IqueryList := TQueryList&amp;lt;Integer, Boolean&amp;gt;&lt;br /&gt;    .New()&lt;br /&gt;    .FillList(function ( list : TList&amp;lt;Integer&amp;gt; ) : Boolean&lt;br /&gt;              var k : integer;&lt;br /&gt;              begin&lt;br /&gt;                for k := 0 to 100 do&lt;br /&gt;                  list.Add(Random(100));&lt;br /&gt;                result := true;&lt;br /&gt;              end);&lt;br /&gt;&lt;br /&gt;  //Display filtered values&lt;br /&gt;  for item in IqueryList&lt;br /&gt;    .Select(function ( list : TList&amp;lt;Integer&amp;gt; ) : TList&amp;lt;Integer&amp;gt;&lt;br /&gt;              var&lt;br /&gt;                k : integer;&lt;br /&gt;                selectList : TList&amp;lt;Integer&amp;gt;;&lt;br /&gt;              begin&lt;br /&gt;                selectList := TList&amp;lt;Integer&amp;gt;.Create;&lt;br /&gt;                for k := 0 to list.Count-1 do&lt;br /&gt;                begin&lt;br /&gt;                  if Abs(list.items[k]) &amp;gt; 0 then&lt;br /&gt;                    selectList.Add(list.items[k]);&lt;br /&gt;                end;&lt;br /&gt;                list.Free;&lt;br /&gt;                result := selectList;&lt;br /&gt;              end)&lt;br /&gt;    .Where(function ( i : integer) : Boolean&lt;br /&gt;          begin&lt;br /&gt;            result := (i &amp;gt; 50);&lt;br /&gt;          end)&lt;br /&gt;    .Where(function ( i : integer) : Boolean&lt;br /&gt;          begin&lt;br /&gt;            result := (i &amp;lt; 75);&lt;br /&gt;          end)&lt;br /&gt;    .OrderBy(TComparer&amp;lt;integer&amp;gt;.Construct(&lt;br /&gt;         function (const L, R: integer): integer&lt;br /&gt;         begin&lt;br /&gt;           result := L - R; //Ascending&lt;br /&gt;         end&lt;br /&gt;     )).Distinct.List do&lt;br /&gt;          WriteLn(IntToStr(item));&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;This example fills up an initial list with 100 random numbers and then I query the list to give me all the values from the list which absolute value is greater than 0 and the values are between 50 and 75. From this list I want all the values ordered by value and I do not want repeated numbers (distinct method).&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Example Implementation &amp;lt;String, String&amp;gt;:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;procedure DisplayStrings();&lt;br /&gt;const&lt;br /&gt;   Chars = '1234567890ABCDEFGHJKLMNPQRSTUVWXYZ!';&lt;br /&gt;var&lt;br /&gt;  S: string;&lt;br /&gt;  IqueryList : IQueryList&amp;lt;String, String&amp;gt;;&lt;br /&gt;  item : String;&lt;br /&gt;begin&lt;br /&gt;  //Fill up the list with random strings&lt;br /&gt;  IqueryList := TQueryList&amp;lt;String, String&amp;gt;&lt;br /&gt;    .New&lt;br /&gt;    .FillList(function ( list : TList&amp;lt;String&amp;gt; ) : String&lt;br /&gt;              var&lt;br /&gt;                k : integer;&lt;br /&gt;                l : Integer;&lt;br /&gt;              begin&lt;br /&gt;                Randomize;&lt;br /&gt;                for k := 0 to 100 do&lt;br /&gt;                begin&lt;br /&gt;                  S := '';&lt;br /&gt;                  for l := 1 to 8 do&lt;br /&gt;                    S := S + Chars[(Random(Length(Chars)) + 1)];&lt;br /&gt;                  list.Add(S);&lt;br /&gt;                end;&lt;br /&gt;                result := '';&lt;br /&gt;              end);&lt;br /&gt;  //Query the list and retrieve all items which contains 'A'&lt;br /&gt;  for item in IqueryList.Where(function ( i : string) : string&lt;br /&gt;          begin&lt;br /&gt;            if AnsiPos('A', i) &amp;gt; 0 then&lt;br /&gt;              result := i;&lt;br /&gt;          end).List do&lt;br /&gt;    WriteLn(item);&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;The string example is quite similar, it fills up a list with 100 random string values and then it filters the list displaying only items which contains the character "A".&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Everything is based on interfaces so the garbage collector can step in and avoid memory leaks and you can find a sound widespread of generics, delegates and chaining methods all in once. This solution gives you control on the way data is treated and it can work with any type as it is using generics.&lt;br /&gt;&lt;br /&gt;Enjoy it!.&lt;br /&gt;&lt;br /&gt;I look forward to your comments.&lt;br /&gt;&lt;div style="text-align: right;"&gt;Jordi&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related Links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.msdn.microsoft.com/101-LINQ-Samples-3fb9811b"&gt;LINQ C# Examples&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://alex.ciobanu.org/?p=197"&gt;DeHL project&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2081492977282075589?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/PRxaoPw3JXg/fluent-interfaces-example-using-delphi.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-mv5eXSbGTX8/T2-GHobtetI/AAAAAAAAC7g/g2_Wo4bGazg/s72-c/chain200.jpg" height="72" width="72" /><thr:total>14</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/03/fluent-interfaces-example-using-delphi.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2597969485029664854</guid><pubDate>Sat, 25 Feb 2012 22:37:00 +0000</pubDate><atom:updated>2012-02-26T23:07:27.197+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Atom table</category><category domain="http://www.blogger.com/atom/ns#">API Windows</category><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Kernel</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>Monitoring Global Atom Table part III</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-y0TOh4Co-QM/T0fcl0kr0XI/AAAAAAAAC6k/kSK91NKID58/s1600/nums.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-y0TOh4Co-QM/T0fcl0kr0XI/AAAAAAAAC6k/kSK91NKID58/s1600/nums.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;New version &lt;b&gt;&lt;a href="http://code.google.com/p/atom-table-monitor/downloads/detail?name=ATOMTableMonitor%20v1.4.zip&amp;amp;can=2&amp;amp;q=#makechanges"&gt;v1.4&lt;/a&gt;&lt;/b&gt; has been released as there were few bugs detected. This version also includes a new and very interesting feature, inspecting atoms from &lt;b&gt;windows services&lt;/b&gt;. &lt;i&gt;&lt;span style="color: #444444;"&gt;"A Windows Service applications run in a different window station than the interactive station of the logged-on user. &lt;b&gt;&lt;u&gt;A window station is a secure object that contains a Clipboard, a set of global atoms, and a group of desktop objects.&lt;/u&gt;&lt;/b&gt; Because the station of the Windows service is not an interactive station, dialog boxes raised from within a Windows service application will not be seen and may cause your program to stop responding. Similarly, error messages should be logged in the Windows event log rather than raised in the user interface"&lt;/span&gt;&lt;/i&gt;.&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;Source :&lt;/b&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/d56de412(v=vs.80).aspx"&gt;Microsoft&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This actually means that a running service is using a &lt;b&gt;different set of global atoms&lt;/b&gt; than the current user. To display those atoms, &lt;a href="http://code.google.com/p/atom-table-monitor/"&gt;atom table monitor&lt;/a&gt; &lt;b&gt;v1.4&lt;/b&gt; includes an &lt;b&gt;Atom scanner service&lt;/b&gt; which uses the same core engine than &lt;b&gt;Atom monitor&lt;/b&gt; and retrieves the list of &lt;b&gt;Global atoms&lt;/b&gt; and &lt;b&gt;RWM atoms&lt;/b&gt; from the system under the &lt;b&gt;window station&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Current version contains: &lt;a href="http://code.google.com/p/atom-table-monitor/downloads/detail?name=ATOMTableMonitor%20v1.4.zip&amp;amp;can=2&amp;amp;q=#makechanges"&gt;Atom Table monitor v1.4&lt;/a&gt;.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;- Atom monitor win32 stand-alone tool.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;- List of common patterns.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;- Atom scanner win32 service.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;- Install / Unninstall service batch files.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Session selection screen:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-wMA0s0HxjXI/T0k1SI7ENjI/AAAAAAAAC6s/26_L_TuX8Ec/s1600/v1.4Service.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="231" src="http://3.bp.blogspot.com/-wMA0s0HxjXI/T0k1SI7ENjI/AAAAAAAAC6s/26_L_TuX8Ec/s400/v1.4Service.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;If the service is up and running, we can select the option to display the atoms from the service session. If the service is not detected the monitor will stop itself.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Service session monitoring &amp;nbsp;RWM atoms:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-RIsOXSEw4BU/T0k3K7DJ5tI/AAAAAAAAC60/ehV0fBX2RQ0/s1600/v1.4RWM.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://3.bp.blogspot.com/-RIsOXSEw4BU/T0k3K7DJ5tI/AAAAAAAAC60/ehV0fBX2RQ0/s400/v1.4RWM.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This screen is displaying the amount of atoms which are being monitored by the service session. You can play with that by creating a small tool to leak atoms and use different configurations from the service. Have a look at my previous post &lt;a href="http://thundaxsoftware.blogspot.com/2012/02/how-to-run-application-under-active.html"&gt;How to run an application under active session account from a windows service&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;User session monitoring RWM atoms:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-XTw_ohWnP-4/T0lhNkiU5CI/AAAAAAAAC7E/hWgPX5a7JSc/s1600/v1.4RWMUser.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://3.bp.blogspot.com/-XTw_ohWnP-4/T0lhNkiU5CI/AAAAAAAAC7E/hWgPX5a7JSc/s400/v1.4RWMUser.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Check out the amount of patterns which match an specific subset of atom strings. This will help you to rapidly identify which atoms are being created and which is the source.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Installing the service:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: justify;"&gt;Use the batch files to install / uninstall &lt;b&gt;ATOMScannerService.exe&lt;/b&gt;. Once installed, run it under local account.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-w04-lUHRDqA/T0qr0lNHjQI/AAAAAAAAC7M/rsg8OemiWc4/s1600/files.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-w04-lUHRDqA/T0qr0lNHjQI/AAAAAAAAC7M/rsg8OemiWc4/s1600/files.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-yTvk0TY6j3c/T0qsrhzKoGI/AAAAAAAAC7U/LpZJYFUSw88/s1600/service.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="25" src="http://4.bp.blogspot.com/-yTvk0TY6j3c/T0qsrhzKoGI/AAAAAAAAC7U/LpZJYFUSw88/s400/service.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;Once up and running, select "Monitor Atoms from service session" on Option's tab and press scan atom table.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-i.html"&gt;Monitoring Global Atom Table part I&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-ii.html"&gt;Monitoring Global Atom Table part II&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/atom-table-monitor/"&gt;atom table monitor google project&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2597969485029664854?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/_FnFVPqHayI/monitoring-global-atom-table-part-iii.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-y0TOh4Co-QM/T0fcl0kr0XI/AAAAAAAAC6k/kSK91NKID58/s72-c/nums.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-iii.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-6439163393985121530</guid><pubDate>Sat, 25 Feb 2012 17:22:00 +0000</pubDate><atom:updated>2012-02-25T18:22:16.118+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">API Windows</category><category domain="http://www.blogger.com/atom/ns#">JEDI</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">Services</category><title>How to run an application under active session account from a Windows service using Delphi</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-kn5_NfvGRxw/T0LZIObMvQI/AAAAAAAAC6c/tFuCrPB6Seo/s1600/images.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://2.bp.blogspot.com/-kn5_NfvGRxw/T0LZIObMvQI/AAAAAAAAC6c/tFuCrPB6Seo/s200/images.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To run an application from a service impersonating an user account, first we need to install "&lt;a href="http://sourceforge.net/projects/jedi-apilib/"&gt;JEDI API Library &amp;amp; Security Code Library&lt;/a&gt;" as it contains different interesting &lt;b&gt;OS callings&lt;/b&gt; 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:&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: bash"&gt;.\JEDI API 2.3 and JEDI WSCL 0.9.3\jwa\branches\2.3\Common&lt;br /&gt;.\JEDI API 2.3 and JEDI WSCL 0.9.3\jwa\branches\2.3\Win32API&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;Then instead of using &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682425(v=vs.85).aspx"&gt;CreateProcess&lt;/a&gt; function to execute an application, we need to use &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms682429(v=vs.85).aspx"&gt;CreateProcessAsUser&lt;/a&gt; function.&amp;nbsp;The new process runs in the security context of the user represented by the specified &lt;b&gt;token&lt;/b&gt;. The service must be run by the &amp;nbsp;&lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684190(v=vs.85).aspx"&gt;LocalSystem account&lt;/a&gt;&lt;/b&gt; 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&amp;nbsp;&lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383840(v=vs.85).aspx"&gt;WTSQueryUserToken&lt;/a&gt;&amp;nbsp;&lt;/b&gt;( &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383835(v=vs.85).aspx"&gt;WtsGetActiveConsoleSessionID&lt;/a&gt;, &lt;i&gt;hToken&lt;/i&gt; ) function. This function will only work under &lt;b&gt;LocalSystem account&lt;/b&gt; which has&amp;nbsp;&lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684190(v=vs.85).aspx"&gt;SE_TCB_NAME&lt;/a&gt;&lt;/b&gt; property &lt;b&gt;enabled&lt;/b&gt;, otherwise the query will be false.&lt;br /&gt;&lt;br /&gt;Use the following example within your service:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: delphi; highlight: [2, 34, 36]"&gt;uses&lt;br /&gt;  ComObj, ActiveX, JwaWinbase, JwaWtsApi32;&lt;br /&gt;&lt;br /&gt;{$R *.DFM}&lt;br /&gt;&lt;br /&gt;procedure ServiceController(CtrlCode: DWORD); stdcall;&lt;br /&gt;begin&lt;br /&gt;  ServiceExample.Controller(CtrlCode);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TServiceExample.GetServiceController: TServiceController;&lt;br /&gt;begin&lt;br /&gt;  Result := ServiceController;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceExecute(Sender: TService);&lt;br /&gt;begin&lt;br /&gt;  Timer1.Enabled := True;&lt;br /&gt;  while not Terminated do&lt;br /&gt;    ServiceThread.ProcessRequests(True); // wait for termination&lt;br /&gt;  Timer1.Enabled := False;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.Timer1Timer(Sender: TObject);&lt;br /&gt;const&lt;br /&gt;  ProgramName = 'C:\myTestproject1.exe';&lt;br /&gt;var&lt;br /&gt;  hToken: THandle;&lt;br /&gt;  StartupInfo: Windows.TStartupInfo;&lt;br /&gt;  ProcessInfo: Windows.TProcessInformation;&lt;br /&gt;  res: boolean;&lt;br /&gt;begin&lt;br /&gt;  Windows.GetStartupInfo(StartupInfo);&lt;br /&gt;  if WTSQueryUserToken(WtsGetActiveConsoleSessionID, hToken) then&lt;br /&gt;  begin&lt;br /&gt;    res := Windows.CreateProcessAsUser(hToken, ProgramName, nil, nil, nil, False, CREATE_NEW_CONSOLE, nil, nil, StartupInfo, ProcessInfo);&lt;br /&gt;    if res then&lt;br /&gt;      WaitForSingleObject(ProcessInfo.hProcess,INFINITE);&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.koders.com/delphi/fid5FD38445E2CB2A94256DF70ADAD6811E5DECB19C.aspx"&gt;JclMiscel.pas&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.delphipages.com/forum/showthread.php?t=197902"&gt;CreateProcessAsUser fast switching&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://developex.com/custom-software/devxexec.html"&gt;Run process from different credentials&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.remkoweijnen.nl/blog/2007/10/20/how-to-launch-a-process-in-a-terminal-session/"&gt;How to launch a process in a terminal session&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://embarcadero.newsgroups.archived.at/public.delphi.nativeapi/201003/1003252964.html"&gt;Calling CreateProcessAsUser from a Service&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.experts-exchange.com/Programming/Languages/Pascal/Delphi/Q_22718414.html"&gt;Delphi Services and Local System account&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms684190(v=vs.85).aspx"&gt;Local system account&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/aa383840(v=vs.85).aspx"&gt;WTSQueryUserToken&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-6439163393985121530?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/Ow_jEOP4k8E/how-to-run-application-under-active.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-kn5_NfvGRxw/T0LZIObMvQI/AAAAAAAAC6c/tFuCrPB6Seo/s72-c/images.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/02/how-to-run-application-under-active.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-8265302761613880816</guid><pubDate>Mon, 20 Feb 2012 22:25:00 +0000</pubDate><atom:updated>2012-02-20T23:35:15.489+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Atom table</category><category domain="http://www.blogger.com/atom/ns#">API Windows</category><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Kernel</category><title>Monitoring Global Atom Table part II</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-0MxUTgdRoE8/T0K8NrVA1RI/AAAAAAAAC5k/9kZU9be1hv8/s1600/nums.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-0MxUTgdRoE8/T0K8NrVA1RI/AAAAAAAAC5k/9kZU9be1hv8/s1600/nums.png" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a href="http://code.google.com/p/atom-table-monitor/"&gt;Atom table monitor&lt;/a&gt; is now available on &lt;a href="http://code.google.com/"&gt;google code&lt;/a&gt;. Atom table is an important resource to take into account when developing win32/win64 applications as if the table gets depleted a "&lt;b&gt;System Error. Code: 8. Not enough storage is available to process this command&lt;/b&gt;" would be returned leaving the system in an unresponsive / unstable state. This issue only happens under &lt;b&gt;Windows Vista / 7 / Server 2008&lt;/b&gt;, so it is crucial to avoid leaking atoms. There is a very&amp;nbsp;interesting&amp;nbsp;article (&lt;a href="http://blogs.msdn.com/b/ntdebugging/archive/2012/01/31/identifying-global-atom-table-leaks.aspx?"&gt;Identifying atom leaks&lt;/a&gt;) from Microsoft debug team which actually shows the way to monitor the atom entries by debugging the kernel. In the first part of this article (&lt;a href="http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-i.html"&gt;Monitoring Global Atom Table part I&lt;/a&gt;) I had delved into detail by debugging the kernel and explaining how to display different atom entries. In that post I released alpha version of "&lt;a href="http://www.4shared.com/rar/O45vzG21/DelphiATOMMonitor_v10.html"&gt;Atom table monitor&lt;/a&gt;" which I have seen it is wrong as it shares the same memory area for global atom table and registerwindowmessage table. In this new version (v1.2) both tables are displayed into separate memory grids:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Global atom table:&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-D6tRXUP7M0M/T0LAwZpBEWI/AAAAAAAAC5s/DxauJez7r3M/s1600/monitor1.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://4.bp.blogspot.com/-D6tRXUP7M0M/T0LAwZpBEWI/AAAAAAAAC5s/DxauJez7r3M/s400/monitor1.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;RegisterWindowMessage table:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ra7SgHtpfEk/T0LAyP_Tm4I/AAAAAAAAC50/t2P3rgKyNzw/s1600/monitor2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://4.bp.blogspot.com/-Ra7SgHtpfEk/T0LAyP_Tm4I/AAAAAAAAC50/t2P3rgKyNzw/s400/monitor2.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Display list of entries:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/--MXjyf2Uy64/T0LA0mwkGrI/AAAAAAAAC58/lQjr1O8WVNo/s1600/monitor3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://2.bp.blogspot.com/--MXjyf2Uy64/T0LA0mwkGrI/AAAAAAAAC58/lQjr1O8WVNo/s400/monitor3.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Matching string patterns:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-o8E5rBf5s4Y/T0LA2JJj0pI/AAAAAAAAC6E/jId5MN2Yq8U/s1600/monitor4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://4.bp.blogspot.com/-o8E5rBf5s4Y/T0LA2JJj0pI/AAAAAAAAC6E/jId5MN2Yq8U/s400/monitor4.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Counters:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-0w8YllG0ahk/T0LA3k-j-zI/AAAAAAAAC6M/YuVWBHP_eWc/s1600/monitor5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://1.bp.blogspot.com/-0w8YllG0ahk/T0LA3k-j-zI/AAAAAAAAC6M/YuVWBHP_eWc/s400/monitor5.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Testing screen:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-78qn1E24k1g/T0LA4_FeFvI/AAAAAAAAC6U/jAihiSGuF4Y/s1600/monitor6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="232" src="http://2.bp.blogspot.com/-78qn1E24k1g/T0LA4_FeFvI/AAAAAAAAC6U/jAihiSGuF4Y/s400/monitor6.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enjoy the tool!.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related articles:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://forums.devx.com/showthread.php?t=36978"&gt;How to list custom messages (RegisterWindowMessage)&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.windows-api.com/microsoft/VC-MFC/30695961/registered-window-message-string.aspx"&gt;RegisterWindowMessage string&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-8265302761613880816?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/hEwB7-HaHkI/monitoring-global-atom-table-part-ii.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-0MxUTgdRoE8/T0K8NrVA1RI/AAAAAAAAC5k/9kZU9be1hv8/s72-c/nums.png" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-ii.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-7640202013818888730</guid><pubDate>Sat, 18 Feb 2012 00:53:00 +0000</pubDate><atom:updated>2012-02-18T01:53:21.659+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><title>Use ADPlus to troubleshoot hangs and crashes in our Delphi applications</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-l3a7O1g5dkI/Tz7R-mwyQsI/AAAAAAAAC4c/6uvomMnkqG4/s1600/adplus.bmp" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-l3a7O1g5dkI/Tz7R-mwyQsI/AAAAAAAAC4c/6uvomMnkqG4/s1600/adplus.bmp" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;It's again debugging time and in this post I'm going to put forward how to use &lt;b&gt;ADPlus&lt;/b&gt; to troubleshoot &lt;b&gt;hangs&lt;/b&gt; or &lt;b&gt;crashes&lt;/b&gt; of our &lt;b&gt;Delphi&amp;nbsp;applications&lt;/b&gt;. 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 &lt;b&gt;&lt;u&gt;create the crash dump&lt;/u&gt;&lt;/b&gt; for its further analysis. Let's start with debugging time!.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Installing Debugging tools for windows:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This is the&amp;nbsp;Swiss&amp;nbsp;knife for any good developer. Bring it always with you as it is really helpful. You can download the library from &lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463009"&gt;here&lt;/a&gt;. Just install it and save it to and USB to be portable. Then spend time using it, not only using ADPlus but also with &lt;b&gt;Windbg&lt;/b&gt;, as it is crucial that you know about how to analyse the crash dump.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-JZCbZ2xqeOU/Tz7V2BHOY7I/AAAAAAAAC4k/OyZVv08Ly6w/s1600/adpluss.bmp" imageanchor="1"&gt;&lt;img border="0" height="247" src="http://3.bp.blogspot.com/-JZCbZ2xqeOU/Tz7V2BHOY7I/AAAAAAAAC4k/OyZVv08Ly6w/s1600/adpluss.bmp" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Setting up our Delphi Applications:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-LRFxAtcE4Zk/Tz7ejpVEynI/AAAAAAAAC40/NvVKnSAI0nM/s1600/delphi.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="222" src="http://4.bp.blogspot.com/-LRFxAtcE4Zk/Tz7ejpVEynI/AAAAAAAAC40/NvVKnSAI0nM/s400/delphi.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Edit in the project options to generate debug information and a detailed map file. Then using &lt;a href="http://code.google.com/p/map2dbg/"&gt;map2dbg&lt;/a&gt; we will transform the map file into debug symbols (.dbg files).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Once your project is correctly set up, build it and you will get the map file. Download the latest version of &lt;a href="http://code.google.com/p/map2dbg/downloads/detail?name=map2dbg%20v1.3.zip&amp;amp;can=2&amp;amp;q="&gt;map2dbg v1.3&lt;/a&gt; and copy map2dbg.exe where your project is located and run the following command line:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;i&gt;&lt;span style="color: red;"&gt;C:\testAdPlus&amp;gt;map2dbg.exe Project1.exe&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="color: red;"&gt;Converted 6882 symbols.&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You will now see a &lt;b&gt;.dbg&lt;/b&gt; file with all necessary information for ADPlus.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Setting up the Symbols:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Once again, if we run ADPlus without setting up the symbols, we will only see address of memory without descriptions:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: bash; highlight: [5]"&gt;Call stack below ---&lt;br /&gt;*** ERROR: Module load completed but symbols could not be loaded for C:\testAdPlus\Project1.exe&lt;br /&gt; # ChildEBP RetAddr  Args to Child              &lt;br /&gt;WARNING: Stack unwind information not available. Following frames may be wrong.&lt;br /&gt;00 0012f550 004832bd 01aba8c0 0045f20b 0012f700 Project1+0xb3295&lt;br /&gt;01 0012f698 00487615 0012f91c 01aba8c0 0012f9a8 Project1+0x832bd&lt;br /&gt;02 0012f6e4 0045eed1 01aba8c0 0012f91c 01aba8c0 Project1+0x87615&lt;br /&gt;03 0012f710 00487768 00050980 0012f9a8 01acb650 Project1+0x5eed1&lt;br /&gt;04 0012f86c 00487615 00000111 0012f91c 09010401 Project1+0x87768&lt;br /&gt;05 0012f8b8 004a7c25 0012f9a8 00000111 01acb650 Project1+0x87615&lt;br /&gt;06 0012f8e4 00486cb3 0012f8f8 00486ccb 0012f914 Project1+0xa7c25&lt;br /&gt;07 0012f914 0043fd4a 00000111 00000980 00050980 Project1+0x86cb3&lt;br /&gt;08 0012f92c 762cfd72 000209ae 00000111 00000980 Project1+0x3fd4a&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Setting up &lt;b&gt;_NT_SYMBOL_PATH&lt;/b&gt; environment variable:&lt;br /&gt;Create a new general environment variable with the following name: &lt;b&gt;_NT_SYMBOL_PATH&lt;/b&gt; and the following value:&lt;br /&gt;&lt;b&gt;symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols&lt;/b&gt;.&lt;br /&gt;Where C:\Symbols is the path to your symbols. This is the same parameter set in WinDbg which I explained in my previous post (&lt;a href="http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-i.html"&gt;monitoring atom table part I&lt;/a&gt;).&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Setting up ADPlus:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;We can either run ADPlus using a simple configuration or use the &lt;a href="http://lowleveldesign.codeplex.com/releases/view/80582"&gt;configuration file&lt;/a&gt; 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.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;C:\Program Files\Debugging Tools for Windows (x86)&amp;gt;adplus -crash -pmn Project1.exe -o C:\Adplus -mss c:\symbols&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This configuration will run ADPlus looking for crashes, waiting for &lt;b&gt;Project1.exe&lt;/b&gt; and it will output the results in &lt;b&gt;C:\ADPlus&lt;/b&gt; and it will use the symbols from &lt;b&gt;C:\Symbols&lt;/b&gt;.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-j2j6tYSmBdg/Tz7q1zyCohI/AAAAAAAAC5U/GiVBvjreQMk/s1600/adplus1z.bmp" imageanchor="1"&gt;&lt;img border="0" height="247" src="http://2.bp.blogspot.com/-j2j6tYSmBdg/Tz7q1zyCohI/AAAAAAAAC5U/GiVBvjreQMk/s1600/adplus1z.bmp" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;b&gt;Sample test:&lt;/b&gt;&lt;br /&gt;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.&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: delphi"&gt;procedure TForm1.Button1Click(Sender: TObject);&lt;br /&gt;begin&lt;br /&gt;  try&lt;br /&gt;    SimulateSystemException;&lt;br /&gt;  finally&lt;br /&gt;    Close;&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TForm1.SimulateSystemException;&lt;br /&gt;var&lt;br /&gt;  p: PChar;&lt;br /&gt;begin&lt;br /&gt;  p := PChar(5);&lt;br /&gt;  p^ := #9; //Access Violation here&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;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).&lt;br /&gt;&lt;br /&gt;You will get a new line in the cmd window telling you:&lt;br /&gt;&lt;i&gt;&lt;span style="color: red;"&gt;Attaching to 4812 - Project1 in crash mode 02/18/2012 00:16:00&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;Once it crashes, go to &lt;b&gt;C:\ADPlus&lt;/b&gt; folder and you will get a new folder with current date and the crash dump in it.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-AEbwmmdJQ9Q/Tz7uYpx2PPI/AAAAAAAAC5c/I2xKcauutDs/s1600/mindump.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="84" src="http://3.bp.blogspot.com/-AEbwmmdJQ9Q/Tz7uYpx2PPI/AAAAAAAAC5c/I2xKcauutDs/s1600/mindump.png" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Analysing crash dump with Windbg:&lt;/b&gt;&lt;br /&gt;Just open Windbg, load the first crash dump (FirstChance_Process_Shut_Down) and use the following commands:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [14]"&gt;0:000&amp;gt; !sym noisy&lt;br /&gt;noisy mode - symbol prompts on&lt;br /&gt;0:000&amp;gt; .reload Project1.exe&lt;br /&gt;0:000&amp;gt; !analyze -v&lt;br /&gt;ERROR: FindPlugIns 8007007b&lt;br /&gt;*******************************************************************************&lt;br /&gt;*                                                                             *&lt;br /&gt;*                        Exception Analysis                                   *&lt;br /&gt;*                                                                             *&lt;br /&gt;*******************************************************************************&lt;br /&gt;&lt;br /&gt;DBGHELP: kernel32 - public symbols  c:\symbols\kernel32.pdb\FCCF6FAC09804D49A4BB256A77F519572\kernel32.pdb&lt;br /&gt;DBGHELP: Project1.exe is stripped.  Searching for dbg file&lt;br /&gt;SYMSRV:  c:\symbols\Project1.dbg\4F3D9543457000\Project1.dbg not found&lt;br /&gt;SYMSRV:  http://msdl.microsoft.com/download/symbols/Project1.dbg/4F3D9543457000/Project1.dbg not found&lt;br /&gt;DBGHELP: .\Project1.dbg - file not found&lt;br /&gt;DBGHELP: .\exe\Project1.dbg - path not found&lt;br /&gt;DBGHELP: .\symbols\exe\Project1.dbg - path not found&lt;br /&gt;DBGHELP: Project1.exe missing debug info.  Searching for pdb anyway&lt;br /&gt;DBGHELP: Can't use symbol server for Project1.pdb - no header information available&lt;br /&gt;DBGHELP: Project1.pdb - file not found&lt;br /&gt;*** WARNING: Unable to verify checksum for Project1.exe&lt;br /&gt;*** ERROR: Module load completed but symbols could not be loaded for Project1.exe&lt;br /&gt;DBGHELP: Project1 - no symbols loaded&lt;br /&gt;DBGHELP: user32 - public symbols c:\symbols\user32.pdb\CFD2C4C8EB9C406D8B6DC29512EB176A2\user32.pdb&lt;br /&gt;DBGHELP: ole32 - public symbols c:\symbols\ole32.pdb\EDE30219D57144FAAC83675A6573D1982\ole32.pdb&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;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 -&amp;gt;&amp;nbsp;&lt;b&gt;c:\symbols\Project1.dbg\4F3D9543457000\Project1.dbg&lt;/b&gt;. Just copy your dbg file into defined location and try again reloading Project1.exe from Windbg command line.&lt;br /&gt;&lt;br /&gt;Now we can analyse again the crash dump and get all the information needed about the crash. This time with the correct symbols:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [4, 46]"&gt;Call stack below ---&lt;br /&gt;*** WARNING: Unable to verify checksum for C:\Users\jordi coll\Desktop\testAdPlus\Project1.exe&lt;br /&gt; # ChildEBP RetAddr  Args to Child              &lt;br /&gt;00 0012f550 00473c9d 008fa8c0 00455747 0012f700 Project1!Unit1.TForm1.SimulateSystemException+0x5&lt;br /&gt;01 0012f698 00477ff5 0012f91c 008fa8c0 0012f9a8 Project1!Controls.TControl.Click+0x75&lt;br /&gt;02 0012f6e4 0045540d 008fa8c0 0012f91c 008fa8c0 Project1!Controls.TWinControl.WndProc+0x56d&lt;br /&gt;03 0012f710 00478148 00010d2e 0012f9a8 0090b650 Project1!StdCtrls.TButtonControl.WndProc+0x71&lt;br /&gt;04 0012f86c 00477ff5 00000111 0012f91c 09010401 Project1!Controls.DoControlMsg+0x28&lt;br /&gt;05 0012f8b8 004984b1 0012f9a8 00000111 0090b650 Project1!Controls.TWinControl.WndProc+0x56d&lt;br /&gt;06 0012f8e4 00477693 0012f8f8 004776ab 0012f914 Project1!Forms.TCustomForm.WndProc+0x599&lt;br /&gt;07 0012f914 0043c146 00000111 00000d2e 00010d2e Project1!Controls.TWinControl.MainWndProc+0x2f&lt;br /&gt;08 0012f92c 762cfd72 00010d26 00000111 00000d2e Project1!Classes.StdWndProc+0x16&lt;br /&gt;09 0012f958 762cfe4a 00380fc8 00010d26 00000111 USER32!InternalCallWinProc+0x23&lt;br /&gt;0a 0012f9d0 762d0943 00000000 00380fc8 00010d26 USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])&lt;br /&gt;0b 0012fa10 762d0b36 00fd2450 00fd23e8 00000d2e USER32!SendMessageWorker+0x4b7 (FPO: [Non-Fpo])&lt;br /&gt;0c 0012fa30 74d1b4ba 00010d26 00000111 00000d2e USER32!SendMessageW+0x7c (FPO: [Non-Fpo])&lt;br /&gt;0d 0012fa50 74d1b51c 00a54518 00000000 00080032 comctl32!Button_NotifyParent+0x3d (FPO: [Non-Fpo])&lt;br /&gt;0e 0012fa6c 74d1b627 54010001 00000001 0012fb48 comctl32!Button_ReleaseCapture+0x112 (FPO: [Non-Fpo])&lt;br /&gt;0f 0012facc 762cfd72 00010d2e 00000202 00000000 comctl32!Button_WndProc+0xa98 (FPO: [Non-Fpo])&lt;br /&gt;10 0012faf8 762cfe4a 74cb70f8 00010d2e 00000202 USER32!InternalCallWinProc+0x23&lt;br /&gt;11 0012fb70 762d09d3 00000000 74cb70f8 00010d2e USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])&lt;br /&gt;12 0012fba0 762d0979 74cb70f8 00010d2e 00000202 USER32!CallWindowProcAorW+0x97 (FPO: [Non-Fpo])&lt;br /&gt;13 0012fbc0 004780f5 74cb70f8 00010d2e 00000202 USER32!CallWindowProcW+0x1b (FPO: [Non-Fpo])&lt;br /&gt;14 0012fd44 00477ff5 00000202 008fa8c0 0012fd80 Project1!Controls.TWinControl.DefaultHandler+0xdd&lt;br /&gt;15 0012fd90 0045540d 0012fe64 00000202 008fa8c0 Project1!Controls.TWinControl.WndProc+0x56d&lt;br /&gt;16 0012fdd0 0043c146 00000202 00000000 00080032 Project1!StdCtrls.TButtonControl.WndProc+0x71&lt;br /&gt;17 0012fde8 762cfd72 00010d2e 00000202 00000000 Project1!Classes.StdWndProc+0x16&lt;br /&gt;18 0012fe14 762cfe4a 00380fbb 00010d2e 00000202 USER32!InternalCallWinProc+0x23&lt;br /&gt;19 0012fe8c 762d018d 00000000 00380fbb 00010d2e USER32!UserCallWinProcCheckWow+0x14b (FPO: [Non-Fpo])&lt;br /&gt;1a 0012fef0 762d022b 00380fbb 00000000 00010d2e USER32!DispatchMessageWorker+0x322 (FPO: [Non-Fpo])&lt;br /&gt;1b 0012ff00 004a15d2 0012ff24 00010001 0012ff70 USER32!DispatchMessageW+0xf (FPO: [Non-Fpo])&lt;br /&gt;1c 0012ff1c 004a1617 00010d2e 00000202 00000000 Project1!Forms.TApplication.ProcessMessage+0x122&lt;br /&gt;1d 0012ff40 004a1942 0012ff54 004a194c 0012ff70 Project1!Forms.TApplication.HandleMessage+0xf&lt;br /&gt;1e 0012ff70 004a9c96 0012ffc4 00405a14 0012ff88 Project1!Forms.TApplication.Run+0xce&lt;br /&gt;1f 0012ff88 7610d0e9 7ffdd000 0012ffd4 77711603 Project1!Project1.Project1+0x4e&lt;br /&gt;20 0012ff94 77711603 7ffdd000 7736d39e 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])&lt;br /&gt;21 0012ffd4 777115d6 004a9c48 7ffdd000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])&lt;br /&gt;22 0012ffec 00000000 004a9c48 7ffdd000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])&lt;br /&gt;&lt;br /&gt;0:000&amp;gt; kvn&lt;br /&gt; # ChildEBP RetAddr  Args to Child              &lt;br /&gt;00 0012ff30 774a5370 7747b148 ffffffff 00000000 ntdll!KiFastSystemCallRet (FPO: [0,0,0])&lt;br /&gt;01 0012ff34 7747b148 ffffffff 00000000 0012ff58 ntdll!ZwTerminateProcess+0xc (FPO: [2,0,0])&lt;br /&gt;02 0012ff44 76f241ec 00000000 77e8f3b0 ffffffff ntdll!RtlExitUserProcess+0x7a (FPO: [Non-Fpo])&lt;br /&gt;03 0012ff58 00405f73 00000000 0012ff88 00000000 kernel32!ExitProcess+0x12 (FPO: [1,0,0])&lt;br /&gt;04 0012ff70 004a9c9b 0012ffc4 00405a14 0012ff88 Project1!System.Halt0+0xf3&lt;br /&gt;05 0012ff88 76f2d0e9 7ffd3000 0012ffd4 77481603 Project1!Project1.Project1+0x53&lt;br /&gt;06 0012ff94 77481603 7ffd3000 77aa9471 00000000 kernel32!BaseThreadInitThunk+0xe (FPO: [Non-Fpo])&lt;br /&gt;07 0012ffd4 774815d6 004a9c48 7ffd3000 00000000 ntdll!__RtlUserThreadStart+0x23 (FPO: [Non-Fpo])&lt;br /&gt;08 0012ffec 00000000 004a9c48 7ffd3000 00000000 ntdll!_RtlUserThreadStart+0x1b (FPO: [Non-Fpo])&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;The only remaining thing is to analyse the crash dump trying to identify which are the regions involved in the crash and tackle them!.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Happy ninja debugging!.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://support.microsoft.com/kb/286350"&gt;How to use ADPlus&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://lowleveldesign.wordpress.com/2012/01/16/adplus-managed-exceptions/"&gt;ADPlus Handling managed exceptions&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.logos.com/Creating_a_Crash_Dump_with_ADPlus"&gt;Creating Crash dump with ADPlus&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-7640202013818888730?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/z6_wfuVf-zI/use-adplus-to-troubleshoot-hangs-and.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-l3a7O1g5dkI/Tz7R-mwyQsI/AAAAAAAAC4c/6uvomMnkqG4/s72-c/adplus.bmp" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/02/use-adplus-to-troubleshoot-hangs-and.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-7219069316367307645</guid><pubDate>Wed, 08 Feb 2012 23:34:00 +0000</pubDate><atom:updated>2012-02-09T00:34:51.302+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Atom table</category><category domain="http://www.blogger.com/atom/ns#">API Windows</category><category domain="http://www.blogger.com/atom/ns#">Debug</category><category domain="http://www.blogger.com/atom/ns#">Kernel</category><title>Monitoring Global Atom Table part I</title><description>&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-m_q7lrq0pdc/TzF0nve_f7I/AAAAAAAAC34/wumg_gA0b0o/s1600/nums.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-m_q7lrq0pdc/TzF0nve_f7I/AAAAAAAAC34/wumg_gA0b0o/s1600/nums.png" /&gt;&lt;/a&gt;&lt;/div&gt;The aim of this article is to give a sound understanding about &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms649053(v=vs.85).aspx"&gt;Atoms&lt;/a&gt;, how to monitor them and check whether we have or have not any process that is potentially leaking atoms. As Microsoft very well defines:&lt;br /&gt;&lt;i&gt;&lt;span style="color: #666666;"&gt;"An atom table is a system-defined table that &lt;u&gt;stores strings and corresponding identifiers&lt;/u&gt;. An application places a string in an atom table and receives a 16-bit integer, called an &lt;b&gt;atom&lt;/b&gt;, that can be used to access the string. A string that has been placed in an atom table is called an atom name.&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="color: #666666;"&gt;The system provides a number of atom tables. Each atom table serves a different purpose.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;i&gt;&lt;span style="color: #666666;"&gt;Applications can use local atom tables to store their own item-name associations.&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;span style="color: #666666;"&gt;The system uses atom tables that are not directly accessible to applications. However, the application uses these atoms when calling a variety of functions. For example, &lt;u&gt;registered clipboard formats&lt;/u&gt; are stored in an internal atom table used by the system. &lt;u&gt;An application adds atoms to this atom table using&lt;/u&gt; the &lt;b&gt;RegisterClipboardFormat&lt;/b&gt; function. Also, registered classes are stored in an internal atom table used by the system. An application adds atoms to this atom table using the &lt;b&gt;RegisterClass&lt;/b&gt; or &lt;b&gt;RegisterClassEx&lt;/b&gt; function."&lt;/span&gt;&lt;/i&gt;&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;source:&lt;/b&gt; &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms649053(v=vs.85).aspx"&gt;Microsoft&lt;/a&gt;.&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Atoms&lt;/b&gt; are stored as two-byte integers&amp;nbsp;(uint16) and there can be &lt;i&gt;&lt;span style="color: #444444;"&gt;0xFFFF-0xC000=0x4000 (16384)&lt;/span&gt;&lt;/i&gt; entries maximum. If&amp;nbsp;&lt;i&gt;0xFFFF&lt;/i&gt; is reached &lt;b&gt;&lt;u&gt;ERROR 8&lt;/u&gt;&lt;/b&gt; is returned ("&lt;b&gt;System Error. Code: 8. Not enough storage is available to process this command"&lt;/b&gt;)&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Discovering Atom table:&lt;/b&gt;&lt;br /&gt;To display atom table we need to use&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463016.aspx"&gt;Debugging tools for Windows&lt;/a&gt;: &lt;a href="http://www.windbg.org/"&gt;Windbg&lt;/a&gt;&amp;nbsp;and debug the kernel to dump al registers.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;b&gt;First of all:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Install all necessary tools and then run &lt;b&gt;Windbg&lt;/b&gt; and configure all symbol parameters to correctly use &lt;b&gt;kernel debug mode&lt;/b&gt;(for windows 7/Server 2008 debug mode needs to be enforced using &lt;a href="http://msdn.microsoft.com/en-us/library/windows/hardware/ff542187(v=vs.85).aspx"&gt;bcdedit /debug on&lt;/a&gt; ). The most important module here is &lt;b&gt;win32k.sys&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-6HUDsOoiJTk/TzLXZ6touzI/AAAAAAAAC4Q/4okv_erDfSk/s1600/Dibujo1.PNG" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="227" src="http://3.bp.blogspot.com/-6HUDsOoiJTk/TzLXZ6touzI/AAAAAAAAC4Q/4okv_erDfSk/s400/Dibujo1.PNG" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Set Symbol file path (Menu File -&amp;gt; Symbol file path):&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;span style="color: red;"&gt;"symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols"&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As we need &lt;b&gt;win32k.sys&lt;/b&gt;, we need to generate the &lt;b&gt;pdb&lt;/b&gt; files with symbols information using &lt;b&gt;symchk&lt;/b&gt; tool from debugging directory:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;pre class="brush: bash; highlight: [1]"&gt;C:\Program Files\Debugging Tools for Windows (x86)&amp;gt;symchk C:\temp\bb\win32k.sys /v&lt;br /&gt;[SYMCHK] Searching for symbols to C:\temp\bb\win32k.sys in path symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols&lt;br /&gt;DBGHELP: Symbol Search Path: symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols&lt;br /&gt;[SYMCHK] Using search path "symsrv*symsrv.dll*C:\Symbols*http://msdl.microsoft.com/download/symbols"&lt;br /&gt;DBGHELP: No header for C:\temp\bb\win32k.sys.  Searching for image on disk&lt;br /&gt;DBGHELP: C:\temp\bb\win32k.sys - OK&lt;br /&gt;SYMSRV:  win32k.pdb from http://msdl.microsoft.com/download/symbols: 1170455 bytes - copied&lt;br /&gt;DBGHELP: win32k - public symbols&lt;br /&gt;         C:\Symbols\win32k.pdb\D8788E4736B34ED5B8516DBB9D45E9942\win32k.pdb&lt;br /&gt;[SYMCHK] MODULE64 Info ----------------------&lt;br /&gt;[SYMCHK] Struct size: 1680 bytes&lt;br /&gt;[SYMCHK] Base: 0xBF800000&lt;br /&gt;[SYMCHK] Image size: 1839616 bytes&lt;br /&gt;[SYMCHK] Date: 0x43446a58&lt;br /&gt;[SYMCHK] Checksum: 0x001ca511&lt;br /&gt;[SYMCHK] NumSyms: 0&lt;br /&gt;[SYMCHK] SymType: SymPDB&lt;br /&gt;[SYMCHK] ModName: win32k&lt;br /&gt;[SYMCHK] ImageName: C:\temp\bb\win32k.sys&lt;br /&gt;[SYMCHK] LoadedImage: C:\temp\bb\win32k.sys&lt;br /&gt;[SYMCHK] PDB: "C:\Symbols\win32k.pdb\D8788E4736B34ED5B8516DBB9D45E9942\win32k.pdb"&lt;br /&gt;[SYMCHK] CV: RSDS&lt;br /&gt;[SYMCHK] CV DWORD: 0x53445352&lt;br /&gt;[SYMCHK] CV Data:  win32k.pdb&lt;br /&gt;[SYMCHK] PDB Sig:  0&lt;br /&gt;[SYMCHK] PDB7 Sig: {D8788E47-36B3-4ED5-B851-6DBB9D45E994}&lt;br /&gt;[SYMCHK] Age: 2&lt;br /&gt;[SYMCHK] PDB Matched:  TRUE&lt;br /&gt;[SYMCHK] DBG Matched:  TRUE&lt;br /&gt;[SYMCHK] Line nubmers: FALSE&lt;br /&gt;[SYMCHK] Global syms:  FALSE&lt;br /&gt;[SYMCHK] Type Info:    TRUE&lt;br /&gt;[SYMCHK] ------------------------------------&lt;br /&gt;SymbolCheckVersion  0x00000002&lt;br /&gt;Result              0x00130001&lt;br /&gt;DbgFilename&lt;br /&gt;DbgTimeDateStamp    0x43446a58&lt;br /&gt;DbgSizeOfImage      0x001c1200&lt;br /&gt;DbgChecksum         0x001ca511&lt;br /&gt;PdbFilename         C:\Symbols\win32k.pdb\D8788E4736B34ED5B8516DBB9D45E9942\win32k.pdb&lt;br /&gt;PdbSignature        {D8788E47-36B3-4ED5-B851-6DBB9D45E994}&lt;br /&gt;PdbDbiAge           0x00000002&lt;br /&gt;[SYMCHK] [ 0x00000000 - 0x00130001 ] Checked "C:\temp\bb\win32k.sys"&lt;br /&gt;&lt;br /&gt;SYMCHK: FAILED files = 0&lt;br /&gt;SYMCHK: PASSED + IGNORED files = 1&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Once done, you will see the pdb file generated in &lt;b&gt;C:\Symbols&lt;/b&gt; folder and you would be able to load it from Windbg command line using the&amp;nbsp;WinDbg commands&amp;nbsp;&lt;a href="http://windbg.info/doc/1-common-cmds.html"&gt;http://windbg.info/doc/1-common-cmds.html&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: bash; highlight: [7]"&gt;kd&amp;gt; !sym noisy&lt;br /&gt;noisy mode - symbol prompts on&lt;br /&gt;kd&amp;gt; .reload win32k.sys&lt;br /&gt;kd&amp;gt; lm&lt;br /&gt;start    end        module name&lt;br /&gt;804d7000 806cdc00   nt         (export symbols)       ntkrnlpa.exe&lt;br /&gt;bf800000 bf9c1200   win32k     (deferred) &lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now we know that &lt;b&gt;win32k.sys&lt;/b&gt; it's loaded in address &lt;b&gt;bf800000&lt;/b&gt;&amp;nbsp;and the referenced memory can be displayed by using &lt;b&gt;dq&lt;/b&gt; command (using a 64-bit pointer) and only the first dword (L1):&lt;/div&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [4, 6, 15]"&gt;kd&amp;gt; dq win32k!UserAtomTableHandle L1&lt;br /&gt;DBGHELP: win32k - public symbols  &lt;br /&gt;         c:\symbols\win32k.pdb\D8788E4736B34ED5B8516DBB9D45E9942\win32k.pdb&lt;br /&gt;bf9a7c18  81b4a270`e1c47230&lt;br /&gt;&lt;br /&gt;kd&amp;gt; dq 81b4a270`e1c47230+10&lt;br /&gt;e1c47240  e1a841c0`e1ba3008 e15fb8f8`e19fae00&lt;br /&gt;e1c47250  e1ba3080`e1700738 e1546428`e1708f88&lt;br /&gt;e1c47260  e15f4e28`e15f4c78 e19e9058`e1a04278&lt;br /&gt;e1c47270  e15f9d20`e15fb878 e170eda8`e1704d90&lt;br /&gt;e1c47280  e1a0bea8`e1f71658 e1a841f0`e1a61550&lt;br /&gt;e1c47290  e15464a0`e1091388 e1b16bc8`e1542440&lt;br /&gt;e1c472a0  e1001d00`e1a014c0 e181efe0`e1c42118&lt;br /&gt;e1c472b0  e1bb9178`e16f33e0 e15fa858`e19e9078&lt;br /&gt;kd&amp;gt; dq&lt;br /&gt;e170076a  04080000`000081cc 04016d53`6d4d0001&lt;br /&gt;e170077a  00006156`4d430c07 00260012`6b76002c&lt;br /&gt;e170078a  0001007c`fec80000 7250ffff`00010000&lt;br /&gt;e170079a  6f724773`7365636f 7963696c`6f507075&lt;br /&gt;e17007aa  0407ffff`ffffffff d4987346`744e0c05&lt;br /&gt;e17007ba  00000000`0000e16e 4fcf0000`00000000&lt;br /&gt;e17007ca  29880003`00000000 04050000`0000e170&lt;br /&gt;e17007da  0401e24e`4d430001 f6886944`624f0c02&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;b&gt;Showing the content of the memory:&lt;/b&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;Now that we now where Global Atom table is allocated, we can start inspecting its elements by displaying&amp;nbsp;Unicode&amp;nbsp;characters from memory by using &lt;b&gt;du&lt;/b&gt; command:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [2, 4]"&gt;kd&amp;gt; du e1ba3080`e1700738+C&lt;br /&gt;e1700744  "DDEMLUnicodeClient"&lt;br /&gt;kd&amp;gt; du e1546428`e1708f88+C&lt;br /&gt;e1708f94  "ACTIVATESHELLWINDOW"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;We can dump the memory using 32-bit pointers (&lt;b&gt;dd &lt;/b&gt;command) and get the same results:&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [2, 9, 19, 21]"&gt;kd&amp;gt; dd e1c47240&lt;br /&gt;e1c47240  e1ba3008 e1a841c0 e19fae00 e15fb8f8&lt;br /&gt;e1c47250  e1700738 e1ba3080 e1708f88 e1546428&lt;br /&gt;e1c47260  e15f4c78 e15f4e28 e1a04278 e19e9058&lt;br /&gt;e1c47270  e15fb878 e15f9d20 e1704d90 e170eda8&lt;br /&gt;e1c47280  e1f71658 e1a0bea8 e1a61550 e1a841f0&lt;br /&gt;e1c47290  e1091388 e15464a0 e1542440 e1b16bc8&lt;br /&gt;e1c472a0  e1a014c0 e1001d00 e1c42118 e181efe0&lt;br /&gt;e1c472b0  e16f33e0 e1bb9178 e19e9078 e15fa858&lt;br /&gt;kd&amp;gt; dd e1c472b0&lt;br /&gt;e1c472b0  e16f33e0 e1bb9178 e19e9078 e15fa858&lt;br /&gt;e1c472c0  e1a84198 e1a61500 e195d558 e15ff980&lt;br /&gt;e1c472d0  e15424a0 00000000 00000000 00000000&lt;br /&gt;e1c472e0  00000000 00000000 00000000 00000000&lt;br /&gt;e1c472f0  00000000 00000000 00000000 00000000&lt;br /&gt;e1c47300  00000000 00000000 00000000 00000000&lt;br /&gt;e1c47310  00000000 00000000 00000000 00000000&lt;br /&gt;e1c47320  00000000 00000000 00000000 00000000&lt;br /&gt;kd&amp;gt; du e1ba3008+c&lt;br /&gt;e1ba3014  "Native"&lt;br /&gt;kd&amp;gt; du e15fa858+c&lt;br /&gt;e15fa864  "OleClipboardPersistOnFlush"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;To display the whole content we can use the following function to loop through all buckets, listing all atoms created:&amp;nbsp;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [1, 2]"&gt;kd&amp;gt; r $t0=poi(poi(win32k!UserAtomTableHandle)+C)&lt;br /&gt;kd&amp;gt; .for(r $t1=0; @$t1&amp;lt;@$t0; r $t1=@$t1+1) {du poi(poi(win32k!UserAtomTableHandle)+10+(@$t1*4))+C}&lt;br /&gt;e1ba3014  "Native"&lt;br /&gt;e1a841cc  "ObjectLink"&lt;br /&gt;e19fae0c  "6.0.2600.2180!tooltips_class32"&lt;br /&gt;e15fb904  "Static"&lt;br /&gt;e1700744  "DDEMLUnicodeClient"&lt;br /&gt;e1ba308c  "DataObject"&lt;br /&gt;e1708f94  "ACTIVATESHELLWINDOW"&lt;br /&gt;e1546434  "FlashWState"&lt;br /&gt;e15f4c84  "SysCH"&lt;br /&gt;e15f4e34  "PBrush"&lt;br /&gt;e1a04284  "6.0.2600.2180!msctls_progress32"&lt;br /&gt;e19e9064  "SysIC"&lt;br /&gt;e15fb884  "DDEMLEvent"&lt;br /&gt;e15f9d2c  "SHELLHOOK"&lt;br /&gt;e1704d9c  "Custom Link Source"&lt;br /&gt;e170edb4  "ControlOfsM*EVJK"&lt;br /&gt;e1f71664  "DesktopSFTBarHost"&lt;br /&gt;e1a0beb4  "SysDT"&lt;br /&gt;e1a6155c  "Link Source"&lt;br /&gt;e1a841fc  "FileName"&lt;br /&gt;e1091394  "ReBarWindow32"&lt;br /&gt;e15464ac  "SysWNDO"&lt;br /&gt;e154244c  "DDEMLAnsiServer"&lt;br /&gt;e1b16bd4  "SysLink"&lt;br /&gt;e1a014cc  "NetworkName"&lt;br /&gt;e1001d0c  "USER32"&lt;br /&gt;e1c42124  "OleDraw"&lt;br /&gt;e181efec  "FileNameW"&lt;br /&gt;e16f33ec  "MoreOlePrivateData"&lt;br /&gt;e1bb9184  "Edit"&lt;br /&gt;e19e9084  "Binary"&lt;br /&gt;e15fa864  "OleClipboardPersistOnFlush"&lt;br /&gt;e1a841a4  "OwnerLink"&lt;br /&gt;e1a6150c  "ListBox"&lt;br /&gt;e195d564  "Embed Source"&lt;br /&gt;e15ff98c  "SysIMEL"&lt;br /&gt;e15424ac  "ComboLBox"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: right;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;span style="text-align: right;"&gt;(Source code from&amp;nbsp;&lt;/span&gt;&lt;a href="http://blog.lordjeb.com/tag/debugging/" style="text-align: right;"&gt;http://blog.lordjeb.com/tag/debugging/&lt;/a&gt;&lt;span style="text-align: right;"&gt;)&lt;/span&gt;&lt;br /&gt;Another way of displaying the content of &lt;b&gt;Global Atom Table&lt;/b&gt; is by using &lt;span style="color: red;"&gt;&lt;b&gt;!gatom&lt;/b&gt;&lt;/span&gt; command from user session on &lt;b&gt;Windbg&lt;/b&gt;. (&lt;a href="http://msdn.microsoft.com/en-us/library/ff563166(v=vs.85).aspx"&gt;http://msdn.microsoft.com/en-us/library/ff563166(v=vs.85).aspx&lt;/a&gt;)&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [1, 2]"&gt;0:001&amp;gt; !gatom&lt;br /&gt;Global atom table c00c( 1) = Protocols (18) pinned&lt;br /&gt;c00d( 1) = Topics (12) pinned&lt;br /&gt;c00e( 1) = Formats (14) pinned&lt;br /&gt;c01f(36) = OleEndPointID (26)&lt;br /&gt;c026( 1) = AppProperties (26)&lt;br /&gt;c024( 1) = Delphi00000DB8 (28)&lt;br /&gt;c01e(94) = UxSubclassInfo (28)&lt;br /&gt;c010( 1) = EditEnvItems (24) pinned&lt;br /&gt;c022( 3) = CAddressComboEx_This (40)&lt;br /&gt;c01d( 6) = OleDropTargetMarshalHwnd (48)&lt;br /&gt;c028( 1) = Delphi000009C0 (28)&lt;br /&gt;c008( 1) = StdDoVerbItem (26) pinned&lt;br /&gt;c01c( 6) = OleDropTargetInterface (44)&lt;br /&gt;c02c( 1) = WndProcPtr0040000000000DC4 (52)&lt;br /&gt;c02b( 1) = ControlOfs0040000000000DC4 (52)&lt;br /&gt;c014( 1) = Save (8) pinned&lt;br /&gt;c016( 1) = MSDraw (12) pinned&lt;br /&gt;c02a( 1) = WndProcPtr0040000000000940 (52)&lt;br /&gt;c024( 1) = Delphi00000DB8 (28)&lt;br /&gt;c01e(94) = UxSubclassInfo (28)&lt;br /&gt;c023( 3) = CAutoComplete_This (36)&lt;br /&gt;c007( 1) = StdShowItem (22) pinned&lt;br /&gt;c011( 1) = True (8) pinned&lt;br /&gt;c010( 1) = EditEnvItems (24) pinned&lt;br /&gt;c019( 1) = PROGMAN (14)&lt;br /&gt;c012( 1) = False (10) pinned&lt;br /&gt;c015( 1) = Close (10) pinned&lt;br /&gt;c022( 3) = CAddressComboEx_This (40)&lt;br /&gt;c004( 1) = StdEditDocument (30) pinned&lt;br /&gt;c01d( 6) = OleDropTargetMarshalHwnd (48)&lt;br /&gt;c028( 1) = Delphi000009C0 (28)&lt;br /&gt;c008( 1) = StdDoVerbItem (26) pinned&lt;br /&gt;c01c( 6) = OleDropTargetInterface (44)&lt;br /&gt;c02c( 1) = WndProcPtr0040000000000DC4 (52)&lt;br /&gt;c005( 1) = StdNewfromTemplate (36) pinned&lt;br /&gt;c02b( 1) = ControlOfs0040000000000DC4 (52)&lt;br /&gt;c014( 1) = Save (8) pinned&lt;br /&gt;c016( 1) = MSDraw (12) pinned&lt;br /&gt;c02a( 1) = WndProcPtr0040000000000940 (52)&lt;br /&gt;c002( 1) = StdNewDocument (28) pinned&lt;br /&gt;c027( 1) = ddeconv (14)&lt;br /&gt;c029( 1) = ControlOfs0040000000000940 (52)&lt;br /&gt;c00f( 1) = Status (12) pinned&lt;br /&gt;c017(27) = ThemePropScrollBarCtl (42)&lt;br /&gt;c009( 1) = System (12) pinned&lt;br /&gt;c01b( 3) = AnimationID (22)&lt;br /&gt;c025( 1) = Folders (14)&lt;br /&gt;c00b( 1) = StdDocumentName (30) pinned&lt;br /&gt;c013( 1) = Change (12) pinned&lt;br /&gt;c001( 1) = StdExit (14) pinned&lt;br /&gt;c006( 1) = StdCloseDocument (32) pinned&lt;br /&gt;c01a( 6) = CAddressBand_This (34)&lt;br /&gt;c00a( 1) = OLEsystem (18) pinned&lt;br /&gt;c018( 3) = CC32SubclassInfo (32)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;But As we can see, we are not displaying all table completely as it is quite difficult to find the correct entry as the table contains atoms, registered clipboard formats, classes, etc. If we follow the steps from &lt;a href="http://blogs.msdn.com/b/ntdebugging/archive/2012/01/31/identifying-global-atom-table-leaks.aspx?"&gt;Microsoft debug team&lt;/a&gt;, the job is far way easy:&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: bash; highlight: [1, 3, 5, 20]"&gt;kd&amp;gt; dq win32k!UserAtomTableHandle l1&lt;br /&gt;bf9a7c18  81c58ce0`e1aa1da8&lt;br /&gt;lkd&amp;gt; dq 81c58ce0`e1aa1da8+10 l1&lt;br /&gt;e1aa1db8  e1929b00`e1423c58&lt;br /&gt;kd&amp;gt; dt nt!_HANDLE_TABLE e1929b00`e1423c58&lt;br /&gt;   +0x000 TableCode        : 0xe19012b8&lt;br /&gt;   +0x004 QuotaProcess     : 0xc0040004 _EPROCESS&lt;br /&gt;   +0x008 UniqueProcessId  : 0x06010001 Void&lt;br /&gt;   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK&lt;br /&gt;   +0x01c HandleTableList  : _LIST_ENTRY [ 0x4d4d49 - 0xc060405 ]&lt;br /&gt;   +0x024 HandleContentionEvent : _EX_PUSH_LOCK&lt;br /&gt;   +0x028 DebugInfo        : (null) &lt;br /&gt;   +0x02c ExtraInfoPages   : 0n4390977&lt;br /&gt;   +0x030 FirstFree        : 0x490050&lt;br /&gt;   +0x034 LastFree         : 0x50005c&lt;br /&gt;   +0x038 NextHandleNeedingPool : 0x50004e&lt;br /&gt;   +0x03c HandleCount      : 0n3473456&lt;br /&gt;   +0x040 Flags            : 0x310030&lt;br /&gt;   +0x040 StrictFIFO       : 0y0&lt;br /&gt;kd&amp;gt; !list "-t nt!_RTL_ATOM_TABLE_ENTRY.HashLink -e -x \"du @$extret+C\" e1929b00`e1423c58"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1423c64  "Native"&lt;br /&gt;du @$extret+C &lt;br /&gt;e19012c4  "Object Descriptor"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1905f14  "Link Source Descriptor"&lt;br /&gt;du @$extret+C &lt;br /&gt;e17e3fec  "Button"&lt;br /&gt;du @$extret+C &lt;br /&gt;e108d014  "msctls_updown32"&lt;br /&gt;du @$extret+C &lt;br /&gt;e108e224  "6.0.2600.2180!Static"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1c016f4  "MSIMEMouseOperation"&lt;br /&gt;du @$extret+C &lt;br /&gt;e112b32c  "WorkerW"&lt;br /&gt;du @$extret+C &lt;br /&gt;e167218c  "MSUIM.Msg.StubCleanUp"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1e6f12c  "Desktop More Programs Pane"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1e949fc  "FileContents"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1be4c1c  "CMBExecute"&lt;br /&gt;du @$extret+C &lt;br /&gt;e2218d8c  "C:\WINDOWS\system32\xpsp2res.dll"&lt;br /&gt;e2218dcc  ""&lt;br /&gt;du @$extret+C &lt;br /&gt;e222a80c  "C:\WINDOWS\WinSxS\x86_Microsoft."&lt;br /&gt;e222a84c  "Windows.Common-Controls_6595b641"&lt;br /&gt;e222a88c  "44ccf1df_6.0.2600.2180_x-ww_a84f"&lt;br /&gt;e222a8cc  "1ff9\comctl32.dll"&lt;br /&gt;du @$extret+C &lt;br /&gt;e16524dc  "ControlOfs0040000000000DC4"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1971964  "ControlOfs0040000000000940"&lt;br /&gt;du @$extret+C &lt;br /&gt;e214b4c4  "ControlOfs0040000000000EC4"&lt;br /&gt;du @$extret+C &lt;br /&gt;e162340c  "ControlOfs0040000000000274"&lt;br /&gt;du @$extret+C &lt;br /&gt;e1e7b7fc  "application/x-compressed"&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Using Atom table monitor v1.0:&lt;/b&gt;&lt;br /&gt;I have developed a small tool to visually monitor all atoms and look for different patterns on it using regular expressions and display the match with a different colour.&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-flrBc3-gV-Y/TzGlIsikzbI/AAAAAAAAC4I/2QB8h455k3M/s1600/Untitled1.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="226" src="http://4.bp.blogspot.com/-flrBc3-gV-Y/TzGlIsikzbI/AAAAAAAAC4I/2QB8h455k3M/s400/Untitled1.png" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;This small app will use&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms649063(v=vs.85).aspx"&gt;GlobalGetAtomName&lt;/a&gt;&amp;nbsp;(to get all atoms that have been added using GlobalAddAtom) and&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms649040(v=vs.85).aspx"&gt;GetClipboardFormatName&lt;/a&gt;&amp;nbsp;(to get all atoms that have been added using &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644947(v=vs.85).aspx"&gt;RegisterWindowMessage&lt;/a&gt;) functions to get all atoms and display them into a 128x128 memory grid using Delphi XE. It also keeps track of the amount of atoms through time plotting the results in a chart.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;&lt;pre class="brush: delphi"&gt;procedure ScanAtoms;&lt;br /&gt;var&lt;br /&gt;  index: WORD;&lt;br /&gt;  arrAtom, arrClipboard: array [0 .. 1024] of char;&lt;br /&gt;  AtomName, RWMName: string;&lt;br /&gt;  lenAtom, lenClipboard: integer;&lt;br /&gt;begin&lt;br /&gt;  for index := $C000 to $FFFF do&lt;br /&gt;  begin&lt;br /&gt;    lenAtom := GlobalGetAtomName(index, arrAtom, 1024);&lt;br /&gt;    lenClipboard := GetClipboardFormatName(index, arrClipboard, 1024);&lt;br /&gt;    if lenAtom &amp;gt; 0 then&lt;br /&gt;      FATomTable[index - $C000].atom := StrPas(arrAtom)&lt;br /&gt;    else if lenClipboard &amp;gt; 0 then&lt;br /&gt;      FATomTable[index - $C000].atom := StrPas(arrClipboard);&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Features:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Display global atom table from &lt;b&gt;0xC000&lt;/b&gt; to &lt;b&gt;0xFFFF&lt;/b&gt;.&lt;/li&gt;&lt;li&gt;Display atom string from table.&lt;/li&gt;&lt;li&gt;Look for patterns and match them with a specific colour&lt;/li&gt;&lt;li&gt;Counters detailing the matches.&lt;/li&gt;&lt;li&gt;Plotting amount of atoms.&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Testing:&lt;/b&gt;&lt;br /&gt;Tool can be tested by using &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms649060(v=vs.85).aspx"&gt;GlobalAddAtom&lt;/a&gt; or &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms644947(v=vs.85).aspx"&gt;RegisterWindowMessages&lt;/a&gt; functions and check out the monitor.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Download:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.4shared.com/rar/O45vzG21/DelphiATOMMonitor_v10.html"&gt;Atom table monitor v1.0&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;Jordi Corbilla&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/ntdebugging/archive/2012/01/31/identifying-global-atom-table-leaks.aspx?"&gt;Identifying Global Atom leaks&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/507853/system-error-code-8-not-enough-storage-is-available-to-process-this-command/9066509#9066509"&gt;System Error. Code 8. Not enough storage is available to process this command&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nynaeve.net/?p=114"&gt;Enable Kernel debugger on Windows Vista&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-7219069316367307645?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/TSixIDbAKks/monitoring-global-atom-table-part-i.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-m_q7lrq0pdc/TzF0nve_f7I/AAAAAAAAC34/wumg_gA0b0o/s72-c/nums.png" height="72" width="72" /><thr:total>2</thr:total><georss:featurename>London, UK</georss:featurename><georss:point>51.5081289 -0.128005</georss:point><georss:box>51.350006900000004 -0.443862 51.6662509 0.187852</georss:box><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/02/monitoring-global-atom-table-part-i.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-3790445274880099812</guid><pubDate>Tue, 31 Jan 2012 22:17:00 +0000</pubDate><atom:updated>2012-01-31T23:17:04.502+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Image processing</category><category domain="http://www.blogger.com/atom/ns#">Maths</category><category domain="http://www.blogger.com/atom/ns#">P-Zaggy</category><category domain="http://www.blogger.com/atom/ns#">VLO Framework</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">TCanvas</category><title>Projecting 3D points to a 2D screen coordinate system</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-vgyzSx6K7ls/TycFsTtRbSI/AAAAAAAAC24/0Vt3iKQ8yjw/s1600/figx01.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-vgyzSx6K7ls/TycFsTtRbSI/AAAAAAAAC24/0Vt3iKQ8yjw/s1600/figx01.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In this article I will put forward a small function to project 3D points to a 2D coordinate system. I have used &lt;a href="https://sourceforge.net/projects/vloframework/"&gt;VLO framework&lt;/a&gt; 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 &lt;a href="http://en.wikipedia.org/wiki/Viewport"&gt;viewport&lt;/a&gt; and then draw the 3D object projected into a 2D canvas from the viewport perspective. The following function will use &lt;a href="http://en.wikipedia.org/wiki/Rotation_matrix"&gt;rotation matrix&lt;/a&gt; to correctly position the points.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Sample code:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;procedure T3DMesh.CalcPoints();&lt;br /&gt;function d3Dto2D (viewport: T3DViewPort; point : T3DPoint; centre : T2DPoint; zoom : double) : T2DPoint;&lt;br /&gt;var&lt;br /&gt;  p : T3DPoint;&lt;br /&gt;  t : T3DPoint;&lt;br /&gt;  d2d : T2DPoint;&lt;br /&gt;begin&lt;br /&gt;  p.x := viewport.x + point.x;&lt;br /&gt;  p.y := viewport.y + point.y;&lt;br /&gt;  p.z := viewport.z + point.z;&lt;br /&gt;&lt;br /&gt;  t.x := (x * cos(viewport.roll)) - (z * sin(viewport.roll));&lt;br /&gt;  t.z := (x * sin(viewport.roll)) + (z * cos(viewport.roll));&lt;br /&gt;  t.y := (y * cos(viewport.pitch)) - (t.z * sin(viewport.pitch));&lt;br /&gt;  z := (t.y * cos(viewport.pitch)) - (t.z * sin(viewport.pitch));&lt;br /&gt;  x := (t.x * cos(viewport.yaw)) - (t.y * sin(viewport.yaw));&lt;br /&gt;  y := (t.x * sin(viewport.yaw)) + (t.y * cos(viewport.yaw));&lt;br /&gt;  d2d := nil;&lt;br /&gt;  if z &amp;gt; 0 then&lt;br /&gt;  begin&lt;br /&gt;      d2d := T2DPoint.Create(((x / z) * zoom) + centre.x, ((y / z) * zoom) + centre.y);&lt;br /&gt;  end;&lt;br /&gt;  result := d2d;&lt;br /&gt;end ;&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  listPoint : TObjectList;&lt;br /&gt;  i: Integer;&lt;br /&gt;  j: Integer;&lt;br /&gt;  x, y, z: Double;&lt;br /&gt;  d2dpoint : T2DPoint;&lt;br /&gt;begin&lt;br /&gt;  listPoint := TObjectList.Create;&lt;br /&gt;  listPoint2 := TObjectList.Create;&lt;br /&gt;&lt;br /&gt;  x :=-2.0;&lt;br /&gt;  y := -2.0;&lt;br /&gt;  z := 0.0;&lt;br /&gt;  for i := 0 to 40 do&lt;br /&gt;  begin&lt;br /&gt;    y := -2.0;&lt;br /&gt;    for j := 0 to 40 do&lt;br /&gt;    begin&lt;br /&gt;      z := cos((x * x + y * y) * 2) * exp(-1 * ((x * x) + (y * y)));&lt;br /&gt;      listPoint.Add(T3DPoint.Create(x,y,z));&lt;br /&gt;      y := y + 0.1;&lt;br /&gt;    end;&lt;br /&gt;    x := x + 0.1;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  for i := 0 to listPoint.count - 1 do&lt;br /&gt;  begin&lt;br /&gt;    d2dpoint := d3Dto2D(viewport, T3DPoint(listPoint[i]), centre, zoom);&lt;br /&gt;    if Assigned(d2dpoint) then&lt;br /&gt;      listPoint2.Add(d2dpoint);&lt;br /&gt;  end;&lt;br /&gt;  listPoint.Free;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Examples:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;z = sin(x) * cos (y):&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-hB0SRiVV884/Tyc0awXApyI/AAAAAAAAC3I/ntXOa1bETQM/s1600/plotsincos.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="171" src="http://3.bp.blogspot.com/-hB0SRiVV884/Tyc0awXApyI/AAAAAAAAC3I/ntXOa1bETQM/s400/plotsincos.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;z = cos((x^2+y^2)*2) * exp-(((x^2)+(y^2))):&lt;/b&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-HiWCdOfC_DI/TyhQ6YqrJRI/AAAAAAAAC3g/cVbGkH6-M1c/s1600/Dibujoxx.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="216" src="http://2.bp.blogspot.com/-HiWCdOfC_DI/TyhQ6YqrJRI/AAAAAAAAC3g/cVbGkH6-M1c/s320/Dibujoxx.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;z = x^2*exp(-x*x)*y^2*exp(-y*y):&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-V1xZZbZpYTk/TyhYzbaHDWI/AAAAAAAAC3o/ksdhHIqCb0E/s1600/Dibujox3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="46" src="http://4.bp.blogspot.com/-V1xZZbZpYTk/TyhYzbaHDWI/AAAAAAAAC3o/ksdhHIqCb0E/s400/Dibujox3.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-IAgAAlCi6bw/TyhcLfKt9RI/AAAAAAAAC3w/ESyND19g-EY/s1600/Dibujox4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="227" src="http://1.bp.blogspot.com/-IAgAAlCi6bw/TyhcLfKt9RI/AAAAAAAAC3w/ESyND19g-EY/s320/Dibujox4.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;With parameters:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-4btQRI1VPx0/Tyc1tn0lyGI/AAAAAAAAC3Y/73rbW0iyXuw/s1600/params.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://4.bp.blogspot.com/-4btQRI1VPx0/Tyc1tn0lyGI/AAAAAAAAC3Y/73rbW0iyXuw/s1600/params.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/519106/projecting-a-3d-point-to-a-2d-screen-coordinate"&gt;Projecting a 3D Point to a 2D coordinate&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/724219/how-to-convert-a-3d-point-into-2d-perspective-projection"&gt;Convert 3D Point into a 2D perspective projection&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://mathforum.org/library/drmath/view/51727.html"&gt;3D Projection Onto a 2D Plane&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://t16web.lanl.gov/Kawano/gnuplot/plot3d-e.html"&gt;Plotting 3D GnuPlot&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.arachnoid.com/sage/learning_sage.html"&gt;3D Graph&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-3790445274880099812?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/vf-aLTsejtE/projecting-3d-points-to-2d-screen.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-vgyzSx6K7ls/TycFsTtRbSI/AAAAAAAAC24/0Vt3iKQ8yjw/s72-c/figx01.jpg" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/01/projecting-3d-points-to-2d-screen.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-4185656162024732069</guid><pubDate>Sun, 15 Jan 2012 01:09:00 +0000</pubDate><atom:updated>2012-01-15T02:16:30.630+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Jflex</category><category domain="http://www.blogger.com/atom/ns#">Java</category><category domain="http://www.blogger.com/atom/ns#">Vijeo Citect</category><category domain="http://www.blogger.com/atom/ns#">Regular Expressions</category><category domain="http://www.blogger.com/atom/ns#">Compilers</category><category domain="http://www.blogger.com/atom/ns#">P-Zaggy</category><category domain="http://www.blogger.com/atom/ns#">VLO Framework</category><category domain="http://www.blogger.com/atom/ns#">CUP</category><category domain="http://www.blogger.com/atom/ns#">TCanvas</category><title>Scripting Language with Thundax P-Zaggy</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-RvvCFHPzwiQ/TxIOLAMXIdI/AAAAAAAAC2U/lQzAYBcBamA/s1600/scripting.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="115" src="http://2.bp.blogspot.com/-RvvCFHPzwiQ/TxIOLAMXIdI/AAAAAAAAC2U/lQzAYBcBamA/s200/scripting.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In this article I will show you the approach taken to solve a common problem: &lt;b&gt;Creating your own Scripting Language using a compiler&lt;/b&gt;. Sometimes we need to create our own language and to achieve that we either can create from scratch a lexical&amp;nbsp;analyser&amp;nbsp;in a high level language&amp;nbsp;or use an open source automatic generator of lexical analysers. As I do not want to spent too much time in this task, I obviously chose the second one using an easy approach using &lt;a href="http://jflex.de/"&gt;JFLEX&lt;/a&gt; and &lt;a href="http://www.cs.princeton.edu/~appel/modern/java/CUP/"&gt;CUP&lt;/a&gt;. There are many to choose from, e.g. &lt;a href="http://www.antlr.org/"&gt;Antlr&lt;/a&gt;, &lt;a href="http://javacc.java.net/"&gt;JavaCC&lt;/a&gt;, &lt;a href="http://sablecc.org/"&gt;SableCC&lt;/a&gt;, &lt;a href="http://ssw.jku.at/Coco/"&gt;Coco/R&lt;/a&gt;, &lt;a href="http://byaccj.sourceforge.net/"&gt;BYacc/J&lt;/a&gt;, &lt;a href="http://beaver.sourceforge.net/"&gt;Beaver&lt;/a&gt;, etc. but I like the way &lt;b&gt;Cup/Jflex&lt;/b&gt; work together. &lt;b&gt;Jflex&lt;/b&gt; will automatically generate the finite automata of the lexical&amp;nbsp;analyser&amp;nbsp;through the &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Regular_expression"&gt;regular expressions&lt;/a&gt;&lt;/b&gt; that define the tokens from a language. CUP is a system written in Java used to generate LALR syntax analysers. Cup file will contain the syntax definition of the language (&lt;a href="http://en.wikipedia.org/wiki/Formal_grammar"&gt;Grammar&lt;/a&gt;) using a notation similar to &lt;a href="http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form"&gt;BNF (Backus-Naur)&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This approach will allow me to create a small compiler which will contain a lexical analyser, a syntax analyser and a semantic analyser without having to add extra workload to my simple &lt;b&gt;Language builder&lt;/b&gt;. &lt;b&gt;Cup/Jflex&lt;/b&gt; compiler will handle whether the language is well defined or not and in my Delphi project I only have a dummy function that will run if the previous compiler &lt;b&gt;returns 0 errors&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I have also taken advantage of the &lt;a href="http://sourceforge.net/apps/mediawiki/synedit/index.php?title=SynEdit_Home_Page"&gt;SynEdit&lt;/a&gt; multi-line edit control to enhance the visualization of the simple Scripting Language. The exposed example is pretty basic and it will help to keep the grammar out of the Delphi code. I have tried other Delphi alternatives like &lt;a href="http://goldparser.org/"&gt;GOLD parser&lt;/a&gt; and &lt;b&gt;Coco/R&lt;/b&gt; but I did not get the expected results. &lt;b&gt;So, If you have any better idea, please do let me know!&lt;/b&gt;.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-50FVnqECX50/TxIfn4LNBgI/AAAAAAAAC2c/ecyFeOiPi34/s1600/parse.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="230" src="http://4.bp.blogspot.com/-50FVnqECX50/TxIfn4LNBgI/AAAAAAAAC2c/ecyFeOiPi34/s320/parse.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This example will allow the user to define the graph by calling the layout object and connecting one node from another using a numeric description. In left side figure you can actually see the basics of the language and its definition. It invokes the &lt;b&gt;layout&lt;/b&gt; object and then it generates a connection from the &lt;b&gt;node(1)&lt;/b&gt; to &lt;b&gt;node(2)&lt;/b&gt; and it ends the sentence with &lt;b&gt;";"&lt;/b&gt; character. There is no need to define the nodes as if a node does not exist it will be automatically created. The compiler created will manage all kind of errors and warnings and it will inform the user about them. Check that it will inform whether you are committing a lexical error (&lt;i&gt;non recognized symbols, etc&lt;/i&gt;) and syntax error (&lt;i&gt;bad composed expressions&lt;/i&gt;) through an &lt;b&gt;Error&lt;/b&gt; or a semantic error (&lt;i&gt;duplicated lines&lt;/i&gt;) through a &lt;b&gt;warning&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;A most developed example is shown in the following figure:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-dbLbrKqKtes/TxIikmpeiTI/AAAAAAAAC2k/pT6F5SEJx_o/s1600/error2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-dbLbrKqKtes/TxIikmpeiTI/AAAAAAAAC2k/pT6F5SEJx_o/s1600/error2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Once the language is free of errors, the generator is enabled and &lt;b&gt;P-Zaggy&lt;/b&gt; can build the graph using the instructions previously defined and analysed by the external compiler. Note that to be able to check the language you must have installed Java.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The following graph have been created using the basic language:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-9noGjDTWkqo/TxIjz8QV2mI/AAAAAAAAC2s/0QTMUpXwZbA/s1600/graph.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-9noGjDTWkqo/TxIjz8QV2mI/AAAAAAAAC2s/0QTMUpXwZbA/s1600/graph.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As you can see it is faster than placing all the objects with the mouse and we can use external tools to generate the script and then check them with the compiler.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Here you can get the latest version of the app:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/thundax-pzaggy/downloads/detail?name=ThundaxPZaggy%20v1.2.0%20build%20278.zip&amp;amp;can=2&amp;amp;q="&gt;Thundax P-Zaggy v1.2.0 build 278&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Jflex regular expressions:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: java"&gt;&amp;lt;YYINITIAL&amp;gt;layout {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.layout, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;node  {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.node, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;\( {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.OpenBracket, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;\)  {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.CloseBracket, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;tonode {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.tonode, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;parameters  {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.parameters, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;\. {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.dot, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;\; {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.endSentence, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&amp;lt;YYINITIAL&amp;gt;[0-9]+ {&lt;br /&gt;  if (CUP$parser$actions.verbose)&lt;br /&gt;    System.out.println(yytext());&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.INTEGER, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;[ \t\r\n]+  { pos = 1; }&lt;br /&gt;[a-z]+          {&lt;br /&gt;  System.out.println("ERROR at line "+(Integer.valueOf(yyline)+1) + ": '" +yytext() + "' not recognized");&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.ff, new sToken(pos - yytext().length(), yyline, yytext())); }&lt;br /&gt;.   {&lt;br /&gt;  System.out.println("ERROR at line "+(Integer.valueOf(yyline)+1) + ": '" +yytext() + "' not recognized");&lt;br /&gt;  pos += yytext().length();&lt;br /&gt;  return new Symbol(sym.ff, new sToken(pos - yytext().length(), yyline, yytext()));&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Cup grammar:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: java"&gt;terminal        sToken  layout, node, OpenBracket, CloseBracket, tonode, parameters, dot, endSentence, ff;&lt;br /&gt;&lt;br /&gt;terminal  sToken          INTEGER, ITEM, QUOTE;&lt;br /&gt;&lt;br /&gt;non terminal  scriptClass graphLine;&lt;br /&gt;non terminal    sToken          itemBracket, itemReturned;&lt;br /&gt;&lt;br /&gt;graphLine ::=  layout : t1&lt;br /&gt;   dot : t2&lt;br /&gt;   node : t3&lt;br /&gt;   itemBracket : e1&lt;br /&gt;   dot : t6&lt;br /&gt;   tonode : t7&lt;br /&gt;   itemBracket : e2&lt;br /&gt;          endSentence : t10&lt;br /&gt;          graphLine&lt;br /&gt;                        {:&lt;br /&gt;    scriptLines.AddTokens(e1, e2);&lt;br /&gt;    RESULT = scriptLines; :}&lt;br /&gt;          | error;&lt;br /&gt;&lt;br /&gt;itemBracket ::= OpenBracket : t4&lt;br /&gt;   itemReturned : e1&lt;br /&gt;   CloseBracket : t5 {: RESULT = (sToken)e1; :}&lt;br /&gt;                        | error;&lt;br /&gt;&lt;br /&gt;itemReturned ::= INTEGER : e1 {: RESULT = (sToken)e1; :}&lt;br /&gt;                 | error;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/LR_parser"&gt;LR Parser&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Parser"&gt;Parser&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/LALR_parser"&gt;LALR Parser&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-4185656162024732069?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/wFbT3D3wj9g/scripting-language-with-thundax-p-zaggy.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-RvvCFHPzwiQ/TxIOLAMXIdI/AAAAAAAAC2U/lQzAYBcBamA/s72-c/scripting.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/01/scripting-language-with-thundax-p-zaggy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-4268070973364719863</guid><pubDate>Mon, 02 Jan 2012 11:44:00 +0000</pubDate><atom:updated>2012-01-02T12:44:22.072+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">News</category><category domain="http://www.blogger.com/atom/ns#">Internet</category><title>The rules of a creator’s life (the secret formula)</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-hQ9V3mc0m6w/TwGXUUy8MHI/AAAAAAAAC2M/81VLkNK1gk0/s1600/rules-of-creators-life.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="640" src="http://3.bp.blogspot.com/-hQ9V3mc0m6w/TwGXUUy8MHI/AAAAAAAAC2M/81VLkNK1gk0/s640/rules-of-creators-life.png" width="481" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="color: #555555; font-size: 14px; line-height: 22px; margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px; padding-bottom: 20px; padding-left: 0px; padding-right: 0px; padding-top: 0px; text-align: justify; text-decoration: none;"&gt;&lt;span class="Apple-style-span" style="font-family: Arial, Helvetica, sans-serif;"&gt;(source&amp;nbsp;&lt;a href="http://www.creativesomething.net/post/14919213087" style="color: #3f9291; text-decoration: underline;" target="_blank"&gt;&lt;b&gt;creativesomething.net&lt;/b&gt;&lt;/a&gt;).&amp;nbsp;&lt;span class="Apple-style-span" style="color: #434343; font-weight: normal; line-height: 25px;"&gt;Rules created by&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; line-height: 25px;"&gt;&lt;a href="http://tannerchristensen.com/" style="border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; color: #0982df; text-decoration: none;"&gt;&lt;b&gt;Tanner Christensen&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; font-weight: normal; line-height: 25px;"&gt;&amp;nbsp;of&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; font-weight: normal; line-height: 25px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; line-height: 25px;"&gt;&lt;a href="http://www.creativesomething.net/post/14309368349" style="border-bottom-color: rgb(221, 221, 221); border-bottom-style: solid; border-bottom-width: 1px; color: #0982df; text-decoration: none;"&gt;&lt;b&gt;Creative Something&lt;/b&gt;&lt;/a&gt;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; font-weight: normal; line-height: 25px;"&gt;&amp;nbsp;&lt;/span&gt;&lt;span class="Apple-style-span" style="color: #434343; font-size: 14px; font-weight: normal; line-height: 25px;"&gt;showcases a&amp;nbsp;recipe&amp;nbsp;for success.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-4268070973364719863?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/E3-Jtpn23sQ/rules-of-creators-life-secret-formula.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-hQ9V3mc0m6w/TwGXUUy8MHI/AAAAAAAAC2M/81VLkNK1gk0/s72-c/rules-of-creators-life.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2012/01/rules-of-creators-life-secret-formula.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-627754865374463734</guid><pubDate>Fri, 30 Dec 2011 18:00:00 +0000</pubDate><atom:updated>2011-12-30T21:04:53.245+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Vijeo Citect</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Regular Expressions</category><category domain="http://www.blogger.com/atom/ns#">P-Zaggy</category><category domain="http://www.blogger.com/atom/ns#">VLO Framework</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">TCanvas</category><title>Finite automata to Regular Grammar with Thundax P-Zaggy</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-xvyBvoI3TD0/Tv3XJ8A6jFI/AAAAAAAAC1Q/q1IZAqnU64c/s1600/grammar.bmp" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-xvyBvoI3TD0/Tv3XJ8A6jFI/AAAAAAAAC1Q/q1IZAqnU64c/s1600/grammar.bmp" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Moving ahead with &lt;b&gt;&lt;a href="http://en.wikipedia.org/wiki/Finite-state_machine"&gt;FA&lt;/a&gt;&lt;/b&gt;, now we can generate the &lt;b&gt;right-linear grammar&lt;/b&gt; 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 (&lt;b&gt;&lt;i&gt;A → bC&lt;/i&gt;&lt;/b&gt;) using the info from the transition and both states.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a href="http://1.bp.blogspot.com/-YIttFPchPTQ/Tv3cU9ZAeJI/AAAAAAAAC1c/0_jNyokI8HM/s1600/example.bmp" imageanchor="1" style="clear: right; display: inline !important; float: right; margin-bottom: 1em; margin-left: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-YIttFPchPTQ/Tv3cU9ZAeJI/AAAAAAAAC1c/0_jNyokI8HM/s1600/example.bmp" /&gt;&lt;/a&gt;&lt;b&gt;P-Zaggy&lt;/b&gt; will use description text to assign unique variable names to each state. Each transition in the graph matches a production in the &lt;a href="http://en.wikipedia.org/wiki/Linear_grammar"&gt;right-linear grammar&lt;/a&gt;. For example (&lt;i&gt;right side image&lt;/i&gt;), the transition from &lt;b&gt;“A”&lt;/b&gt; to &lt;b&gt;“B”&lt;/b&gt; along the transition &lt;b&gt;“a”&lt;/b&gt; matches the production &lt;b&gt;&lt;i&gt;“A → aB”&lt;/i&gt;&lt;/b&gt;. This production will be automatically added into the production list in the "&lt;b&gt;Finite Automaton (simulation)&lt;/b&gt;" tab. To generate the full grammar, just open your finite automata and press "&lt;b&gt;&lt;i&gt;Get grammar&lt;/i&gt;&lt;/b&gt;" button to get the &lt;b&gt;linear grammar&lt;/b&gt;. Now as any final state carries the production to λ,&amp;nbsp;&lt;b&gt;λ symbol&lt;/b&gt; has been added to the system as&amp;nbsp;&lt;a href="http://en.wikipedia.org/wiki/Empty_string"&gt;empty string&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In the following image you will see a general example with the automatically generated grammar:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-v_NcF_WwCu0/Tv3jjqpGf0I/AAAAAAAAC10/TkotxKgwbDs/s1600/grammar3.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://3.bp.blogspot.com/-v_NcF_WwCu0/Tv3jjqpGf0I/AAAAAAAAC10/TkotxKgwbDs/s400/grammar3.bmp" width="271" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Example with&amp;nbsp;&lt;b&gt;λ string&lt;/b&gt;:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-lwiqPvEnbB0/Tv3n0LL2o8I/AAAAAAAAC2A/KLyEUHGFFD8/s1600/grammar4.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="186" src="http://1.bp.blogspot.com/-lwiqPvEnbB0/Tv3n0LL2o8I/AAAAAAAAC2A/KLyEUHGFFD8/s320/grammar4.bmp" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Demo video:&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/hYA9NB0OjpI" width="420"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Get the latest version from here:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/thundax-pzaggy/downloads/detail?name=ThundaxPZaggy%20v1.2.0%20build%20208.zip&amp;amp;can=2&amp;amp;q="&gt;Thundax P-Zaggy v1.20 build 208&lt;/a&gt;. (Executable)&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Looking back/ahead:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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!, &lt;b&gt;I am grateful for that!&lt;/b&gt;). 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.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Next year I will be implementing different algorithms and I will be focusing on &lt;b&gt;grammars&lt;/b&gt;, &lt;b&gt;compilers&lt;/b&gt; and &lt;b&gt;AI&lt;/b&gt; 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 &lt;b&gt;Delphi&lt;/b&gt;). I'm preparing a roadmap about different utilities I have in mind and stay tuned for new and very interesting stuff!.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Happy new year 2012!.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;Jordi Corbilla&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Finite-state_machine"&gt;Finite state machine&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Linear_grammar"&gt;Linear Grammar&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Regular_grammar"&gt;Regular Grammar&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Formal_language"&gt;Formal language&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Empty_string"&gt;Empty String&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/12/finite-automata-with-thundax-p-zaggy.html"&gt;Finite automata with Thundax P-Zaggy Part I&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/12/finite-automata-with-thundax-p-zaggy_29.html"&gt;Finite automata with Thundax P-Zaggy Part II&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cs.duke.edu/csed/jflap/"&gt;JFLAP (software for experimenting with formal languages)&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://delphi.about.com/od/objectpascalide/a/understanding-anonymous-methods-in-delphi.htm"&gt;Anonymous methods in Delphi&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://delphi.about.com/od/delphitips2009/qt/sort-generic.htm"&gt;Sort generic list&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-627754865374463734?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/v7kxPg5a48g/finite-automata-to-regular-grammar-with.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-xvyBvoI3TD0/Tv3XJ8A6jFI/AAAAAAAAC1Q/q1IZAqnU64c/s72-c/grammar.bmp" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/12/finite-automata-to-regular-grammar-with.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-9010409612027858432</guid><pubDate>Thu, 29 Dec 2011 18:53:00 +0000</pubDate><atom:updated>2011-12-29T19:53:45.184+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Vijeo Citect</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Regular Expressions</category><category domain="http://www.blogger.com/atom/ns#">P-Zaggy</category><category domain="http://www.blogger.com/atom/ns#">VLO Framework</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">TCanvas</category><title>Finite Automata with Thundax P-Zaggy part II</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-CbCxIpA62rc/TvykmFdaZaI/AAAAAAAAC0s/yfvQakRn_7I/s1600/DFA2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-CbCxIpA62rc/TvykmFdaZaI/AAAAAAAAC0s/yfvQakRn_7I/s1600/DFA2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Going on with the further enhancement of &lt;b&gt;P-Zaggy (&lt;a href="http://thundaxsoftware.blogspot.com/2011/12/finite-automata-with-thundax-p-zaggy.html"&gt;part I&lt;/a&gt;)&lt;/b&gt; to use its graph creation capability to run and simulate &lt;b&gt;DFA&lt;/b&gt;, I have released a new version (&lt;a href="http://code.google.com/p/thundax-pzaggy/downloads/detail?name=ThundaxPZaggy%20v1.2.0%20build%20180.zip&amp;amp;can=2&amp;amp;q="&gt;v1.2.0 build 180&lt;/a&gt;) 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 "&lt;b&gt;accepted/rejected&lt;/b&gt;" message. This version still only works with one char regular expressions &lt;b&gt;(^[A-Z]$)&lt;/b&gt; so more complex expressions &lt;b&gt;(^[A-Z]+$)&lt;/b&gt; will be used but not correctly adapted.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Examples:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-BZ5K9RAje98/TvyyuYH6q5I/AAAAAAAAC04/v54n5Rskfws/s1600/DFA.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="165" src="http://3.bp.blogspot.com/-BZ5K9RAje98/TvyyuYH6q5I/AAAAAAAAC04/v54n5Rskfws/s400/DFA.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-48ssLdTtleY/Tvyy9O9zyKI/AAAAAAAAC1E/ElaMDQvnh1Q/s1600/example.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="161" src="http://3.bp.blogspot.com/-48ssLdTtleY/Tvyy9O9zyKI/AAAAAAAAC1E/ElaMDQvnh1Q/s400/example.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/KuW5lTescD8" width="420"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://docwiki.embarcadero.com/VCL/en/RegularExpressionsCore.TPerlRegExList"&gt;Regular expressions&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-9010409612027858432?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/VLZwr0uj5mw/finite-automata-with-thundax-p-zaggy_29.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-CbCxIpA62rc/TvykmFdaZaI/AAAAAAAAC0s/yfvQakRn_7I/s72-c/DFA2.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/12/finite-automata-with-thundax-p-zaggy_29.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2906208331977365488</guid><pubDate>Thu, 29 Dec 2011 02:25:00 +0000</pubDate><atom:updated>2011-12-29T18:03:36.506+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Vijeo Citect</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Regular Expressions</category><category domain="http://www.blogger.com/atom/ns#">P-Zaggy</category><category domain="http://www.blogger.com/atom/ns#">VLO Framework</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">TCanvas</category><title>Finite Automata with Thundax P-Zaggy part I</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-7Y1QNO3PjPQ/TvvGlbQoB6I/AAAAAAAACzw/HGIAHRTrl4A/s1600/fm.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="138" src="http://1.bp.blogspot.com/-7Y1QNO3PjPQ/TvvGlbQoB6I/AAAAAAAACzw/HGIAHRTrl4A/s200/fm.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I have moved forward the development of &lt;a href="http://sourceforge.net/projects/vloframework/"&gt;Thundax P-Zaggy&lt;/a&gt; with the addition of a &lt;a href="http://en.wikipedia.org/wiki/Deterministic_finite_automaton"&gt;Finite Automata&lt;/a&gt; &lt;u&gt;builder and simulator&lt;/u&gt;. "A &lt;b&gt;deterministic finite automaton (DFA)&lt;/b&gt; also known as &lt;b&gt;deterministic finite state machine&amp;nbsp;&lt;/b&gt;is a finite state machine that &lt;b&gt;&lt;i&gt;accepts/rejects&lt;/i&gt;&lt;/b&gt; finite strings of symbols and only produces a unique computation (or run) of the automaton for each input string. (&lt;a href="http://en.wikipedia.org/wiki/Deterministic_finite_automaton"&gt;wikipedia&lt;/a&gt;)". Building the automata with &lt;b&gt;P-Zaggy&lt;/b&gt; is quite simple, so let's start by building a &lt;b&gt;DFA&lt;/b&gt; for the following language:&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;L = {ba | ab&lt;i&gt;&lt;sup&gt;n&lt;/sup&gt;&lt;/i&gt;a,&amp;nbsp;n &amp;gt;&amp;nbsp;0}.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As it is shown in the previous image, the DFA would be as follows:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-XL7E-4HFmSs/TvvKeRvPc1I/AAAAAAAACz8/nnRt7ZGJsQA/s1600/Dibujo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="212" src="http://2.bp.blogspot.com/-XL7E-4HFmSs/TvvKeRvPc1I/AAAAAAAACz8/nnRt7ZGJsQA/s400/Dibujo.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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 &lt;b&gt;transition string&lt;/b&gt; to change the ongoing state and &lt;u&gt;initial and final states need to be selected&lt;/u&gt; (using right click and selecting "&lt;b&gt;Mark as Start Node&lt;/b&gt;" for &lt;b&gt;Initial state&lt;/b&gt; and "&lt;b&gt;Mark as End Node&lt;/b&gt;" for &lt;b&gt;Final state&lt;/b&gt;).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-A2jlxfB1xJA/TvvMCrlp3-I/AAAAAAAAC0I/bdDZHmhOeR8/s1600/menu.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://1.bp.blogspot.com/-A2jlxfB1xJA/TvvMCrlp3-I/AAAAAAAAC0I/bdDZHmhOeR8/s320/menu.jpg" width="194" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;We can start the simulation with very simple steps. Firstly, select the tab called "&lt;b&gt;Finite Automaton (simulation)"&lt;/b&gt; and enter the &lt;i&gt;test input string&lt;/i&gt; to test. Then press start button to internally initialize the graph as a DFA and press &lt;b&gt;step&lt;/b&gt; 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 &lt;i&gt;accepted&lt;/i&gt; or &lt;i&gt;rejected&lt;/i&gt;. To set up a &lt;b&gt;single loop transition&lt;/b&gt;, select the &lt;b&gt;node&lt;/b&gt; and with right click select "&lt;b&gt;Set connector loop&lt;/b&gt;" and add text for the transition.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-zOhri3FTHKs/TvvN8ZQZaXI/AAAAAAAAC0U/4g8q7WacSlI/s1600/accept.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="217" src="http://2.bp.blogspot.com/-zOhri3FTHKs/TvvN8ZQZaXI/AAAAAAAAC0U/4g8q7WacSlI/s400/accept.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In this beta version, we can also use &lt;b&gt;Regular Expressions&lt;/b&gt; in our transitions thanks to the widespread use of regular expressions inside Delphi XE.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-4lGP6HjwLr8/TvxPeAlfoCI/AAAAAAAAC0g/trA3Xx5HJoQ/s1600/Dibujot.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="200" src="http://1.bp.blogspot.com/-4lGP6HjwLr8/TvxPeAlfoCI/AAAAAAAAC0g/trA3Xx5HJoQ/s400/Dibujot.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;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 "&lt;b&gt;empty string&lt;/b&gt;" and other considerations that I would be delving into detail in the following days. I am also working on a&amp;nbsp;&lt;b&gt;Layered-Tree-Draw Algorithm&lt;/b&gt; using&amp;nbsp;&lt;b&gt;&lt;a href="http://www.codeproject.com/KB/scripting/graphic_javascript_tree.aspx"&gt;Reingold-Tilford Algorithm&lt;/a&gt;&lt;/b&gt; and the enhancement of the better recognition of more &lt;b&gt;complex regular expressions&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Have a look at this preview of the functioning of the graph, it is really worth it:&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/r_O3ynhkXZg" width="420"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;Stay tuned and give &lt;b&gt;P-Zaggy&lt;/b&gt; a try from here:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/thundax-pzaggy/downloads/detail?name=ThundaxPZaggy%20v1.2.0%20build%20155.zip&amp;amp;can=2&amp;amp;q="&gt;Thundax P-Zaggy v1.2.0 build 155&lt;/a&gt;. (there are two examples included).&lt;/li&gt;&lt;/ul&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cs.wcupa.edu/~rkline/csc520/re-dfa-equiv.html"&gt;Regular language closure properties&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://sourceforge.net/projects/vloframework/"&gt;VLO Framework&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/06/thundax-p-zaggy-presentation.html"&gt;Thundax P-Zaggy presentation&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/02/thundax-p-zaggy-v12-beta.html"&gt;Thundax P-Zaggy 1.2 beta&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.regular-expressions.info/delphi.html"&gt;Regular Expressions&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2906208331977365488?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/TIw3_wyjHzs/finite-automata-with-thundax-p-zaggy.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-7Y1QNO3PjPQ/TvvGlbQoB6I/AAAAAAAACzw/HGIAHRTrl4A/s72-c/fm.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/12/finite-automata-with-thundax-p-zaggy.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-1451730767872273593</guid><pubDate>Sat, 10 Dec 2011 00:46:00 +0000</pubDate><atom:updated>2011-12-13T23:02:35.038+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">Services</category><title>Install multiple instances of the same Delphi application service</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-HW58BswO75M/TufDzU5xBbI/AAAAAAAACzM/hbFwTF9mOR4/s1600/Dibujo.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="170" src="http://1.bp.blogspot.com/-HW58BswO75M/TufDzU5xBbI/AAAAAAAACzM/hbFwTF9mOR4/s200/Dibujo.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;In this article you will find an example on &lt;i&gt;How to install multiple instances of the same Delphi application service&lt;/i&gt; under Windows. This topic was raised a few years ago in &lt;a href="http://stackoverflow.com/questions/612587/is-it-possible-to-install-multiple-instances-of-the-same-delphi-service-applicat"&gt;StackOverflow&lt;/a&gt; and I have decided to give more details about how to use multiple instances of the same service.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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 &amp;nbsp;executable. In this example I will identify the services when installing the service using the command line with the following instruction: &lt;b&gt;&lt;i&gt;"myService /install Param1"&lt;/i&gt;&lt;/b&gt;. &lt;b&gt;&lt;i&gt;Param1&lt;/i&gt;&lt;/b&gt; will be used to compose the internal service name as &lt;b&gt;myServiceParam1&lt;/b&gt;. If we want to use another instance, just install a second service with a different param name as:&amp;nbsp;&lt;b&gt;&lt;i&gt;myService /install Param2&lt;/i&gt;&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To achieve this is pretty simple, just create the service using your Delphi XE and then create the methods &lt;b&gt;ServiceBeforeUninstall&lt;/b&gt; and &lt;b&gt;ServiceCreate&lt;/b&gt;:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;unit uService;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, WinSvc;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  TServiceExample = class(TService)&lt;br /&gt;    procedure ServiceCreate(Sender: TObject);&lt;br /&gt;    procedure ServiceBeforeUninstall(Sender: TService);&lt;br /&gt;  private&lt;br /&gt;    FDescription: String;&lt;br /&gt;    FPreviousName: String;&lt;br /&gt;    FPreviusDisplayName: string;&lt;br /&gt;  public&lt;br /&gt;    function GetServiceController: TServiceController; override;&lt;br /&gt;    { Public declarations }&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  ServiceExample: TServiceExample;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  ComObj;&lt;br /&gt;&lt;br /&gt;{$R *.DFM}&lt;br /&gt;&lt;br /&gt;procedure ServiceController(CtrlCode: DWORD); stdcall;&lt;br /&gt;begin&lt;br /&gt;  ServiceExample.Controller(CtrlCode);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TServiceExample.GetServiceController: TServiceController;&lt;br /&gt;begin&lt;br /&gt;  Result := ServiceController;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceBeforeUninstall(Sender: TService);&lt;br /&gt;begin&lt;br /&gt;  Name := FPreviousName + FDescription;&lt;br /&gt;  DisplayName := FPreviusDisplayName + FDescription;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceCreate(Sender: TObject);&lt;br /&gt;begin&lt;br /&gt;  FDescription := System.ParamStr(2);&lt;br /&gt;  FPreviousName := Name;&lt;br /&gt;  FPreviusDisplayName := DisplayName;&lt;br /&gt;  Name := Name + FDescription;&lt;br /&gt;  DisplayName := DisplayName + FDescription;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Notice the &lt;b&gt;&lt;i&gt;System.ParamStr(2)&lt;/i&gt;&lt;/b&gt; that will use the second parameter which was input from the command line. The first parameter is the &lt;b&gt;/install&lt;/b&gt; command needed to install the service.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;After the execution of the following commands:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;myService /install Param1&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;myService /install Param2&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;You will see two installed services using the same executable:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-BnJTgWBFBjA/TufHgXnzg5I/AAAAAAAACzU/0vvtbHH11T8/s1600/Dibujo2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://3.bp.blogspot.com/-BnJTgWBFBjA/TufHgXnzg5I/AAAAAAAACzU/0vvtbHH11T8/s1600/Dibujo2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;To uninstall them, use the opposite command:&lt;br /&gt;&lt;b&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;myService /uninstall Param1&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;&lt;i&gt;myService /uninstall Param2&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;But this &lt;u&gt;is not ending here&lt;/u&gt;. Now the services are installed, but neither the &lt;b&gt;service name&lt;/b&gt; is set nor the &lt;b&gt;description&lt;/b&gt;. To achieve this, we need to use the &lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681987(v=vs.85).aspx"&gt;ChangeServiceConfig&lt;/a&gt; functions from &lt;b&gt;WinSvc - Service Control Manager unit&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Have a look at the complete source code:&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: delphi"&gt;unit uService;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  Windows, Messages, SysUtils, Classes, Graphics, Controls, SvcMgr, Dialogs, WinSvc;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  TServiceExample = class(TService)&lt;br /&gt;    procedure ServiceCreate(Sender: TObject);&lt;br /&gt;    procedure ServiceBeforeUninstall(Sender: TService);&lt;br /&gt;    procedure ServiceAfterInstall(Sender: TService);&lt;br /&gt;  private&lt;br /&gt;    FDescription: String;&lt;br /&gt;    FPreviousName: String;&lt;br /&gt;    FPreviusDisplayName: string;&lt;br /&gt;  public&lt;br /&gt;    function GetServiceController: TServiceController; override;&lt;br /&gt;    { Public declarations }&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;  SERVICE_DESCRIPTION = packed record&lt;br /&gt;    lpDescription: PChar;&lt;br /&gt;  end;&lt;br /&gt;&lt;br /&gt;  PSERVICE_DESCRIPTION = ^SERVICE_DESCRIPTION;&lt;br /&gt;&lt;br /&gt;var&lt;br /&gt;  ServiceExample: TServiceExample;&lt;br /&gt;&lt;br /&gt;const&lt;br /&gt;  SERVICE_CONFIG_DESCRIPTION = 1;&lt;br /&gt;&lt;br /&gt;function ChangeServiceConfig2(hService: SC_HANDLE; dwInfoLevel: DWORD; lpInfo: Pointer): BOOL; stdcall; external 'advapi32.dll' name 'ChangeServiceConfig2W';&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;  ComObj;&lt;br /&gt;{$R *.DFM}&lt;br /&gt;&lt;br /&gt;procedure ServiceController(CtrlCode: DWORD); stdcall;&lt;br /&gt;begin&lt;br /&gt;  ServiceExample.Controller(CtrlCode);&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TServiceExample.GetServiceController: TServiceController;&lt;br /&gt;begin&lt;br /&gt;  Result := ServiceController;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceAfterInstall(Sender: TService);&lt;br /&gt;var&lt;br /&gt;  SvcMgr, Svc: SC_HANDLE;&lt;br /&gt;  desc: SERVICE_DESCRIPTION;&lt;br /&gt;begin&lt;br /&gt;  SvcMgr := OpenSCManager(nil, nil, SC_MANAGER_ALL_ACCESS);&lt;br /&gt;  if SvcMgr = 0 then&lt;br /&gt;    Exit;&lt;br /&gt;  try&lt;br /&gt;    Svc := OpenService(SvcMgr, PChar(Name), SERVICE_ALL_ACCESS);&lt;br /&gt;    if Svc = 0 then&lt;br /&gt;      RaiseLastOSError;&lt;br /&gt;    try&lt;br /&gt;      desc.lpDescription := PWideChar(ParamStr(0) + ' ' + FDescription);&lt;br /&gt;      ChangeServiceConfig( Svc, SERVICE_NO_CHANGE, SERVICE_NO_CHANGE,SERVICE_NO_CHANGE, desc.lpDescription, nil, nil, nil, nil, nil, nil);&lt;br /&gt;      desc.lpDescription := PWideChar('Service Example with Params = ' + FDescription);&lt;br /&gt;      ChangeServiceConfig2(Svc, SERVICE_CONFIG_DESCRIPTION, @desc.lpDescription);&lt;br /&gt;    finally&lt;br /&gt;      CloseServiceHandle(Svc);&lt;br /&gt;    end;&lt;br /&gt;  finally&lt;br /&gt;    CloseServiceHandle(SvcMgr);&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceBeforeUninstall(Sender: TService);&lt;br /&gt;begin&lt;br /&gt;  Name := FPreviousName + FDescription;&lt;br /&gt;  DisplayName := FPreviusDisplayName + FDescription;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TServiceExample.ServiceCreate(Sender: TObject);&lt;br /&gt;begin&lt;br /&gt;  FDescription := System.ParamStr(2);&lt;br /&gt;  FPreviousName := Name;&lt;br /&gt;  FPreviusDisplayName := DisplayName;&lt;br /&gt;  Name := Name + FDescription;&lt;br /&gt;  DisplayName := DisplayName + FDescription;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;This solution is using the example provided by&amp;nbsp;&lt;a href="http://koochangmin.blogspot.com/2010/01/test.html"&gt;koochangmin&lt;/a&gt; on his Delphi blog. If you have a closer look at the &lt;b&gt;&lt;i&gt;ServiceAfterInstall&lt;/i&gt;&lt;/b&gt; method, you will find the composition of the name and description which will be used to populate the values in the service:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-25zjVsgx1nM/TufKL3V21vI/AAAAAAAACzc/bZSYx70cD50/s1600/Dibujo3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://2.bp.blogspot.com/-25zjVsgx1nM/TufKL3V21vI/AAAAAAAACzc/bZSYx70cD50/s400/Dibujo3.jpg" width="340" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;That is the way the service needs to be created in order to let the application use the parameters in runtime.&lt;br /&gt;&lt;br /&gt;If you have any problem uninstalling the services, just use the SC command to delete the service:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;sc delete ServiceExampleParam1&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://koochangmin.blogspot.com/2010/01/test.html"&gt;Windows Service Managing Unit&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/windows/desktop/ms681988(v=vs.85).aspx"&gt;ChangeServiceConfig2 function&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.tenouk.com/cddeefunction3.html"&gt;Another Windows Service: A&amp;nbsp;supplementary&amp;nbsp;note&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.astahost.com/info/tifsls-delete-service.html"&gt;How to delete a service&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-1451730767872273593?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/EvcTzzvd4mU/install-multiple-instances-of-same.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-HW58BswO75M/TufDzU5xBbI/AAAAAAAACzM/hbFwTF9mOR4/s72-c/Dibujo.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/12/install-multiple-instances-of-same.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2653887613547289591</guid><pubDate>Mon, 07 Nov 2011 18:38:00 +0000</pubDate><atom:updated>2011-11-07T19:48:03.694+01:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Facebook</category><category domain="http://www.blogger.com/atom/ns#">Videos</category><category domain="http://www.blogger.com/atom/ns#">Google</category><title>Google and Facebook "Secrets" unveiled</title><description>&lt;div style="text-align: justify;"&gt;Here you can see an interesting video from one of the TED talks this year in which we can see how the information is filtered and presented according to our surfing (using algorithmic and personalized filters). It gives interesting reflections.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/wGq3HWILr6k" width="560"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enjoy the video!.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2653887613547289591?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/kLiEpQ99NfA/google-and-facebook-secrets-unveiled.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/wGq3HWILr6k/default.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/11/google-and-facebook-secrets-unveiled.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-6299555966736956302</guid><pubDate>Mon, 17 Oct 2011 19:07:00 +0000</pubDate><atom:updated>2011-10-17T21:07:45.862+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Operating System</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>Monitoring Desktop Heap Memory and troubleshooting issues (part II)</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-afV1S9Ac0OM/TpxnjVC_lSI/AAAAAAAACyI/2lhrc38IwHY/s1600/heap.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em; text-align: justify;"&gt;&lt;img border="0" height="187" src="http://1.bp.blogspot.com/-afV1S9Ac0OM/TpxnjVC_lSI/AAAAAAAACyI/2lhrc38IwHY/s200/heap.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now that we know what &lt;i&gt;Desktop Heap Memory&lt;/i&gt; is and How works (&lt;a href="http://thundaxsoftware.blogspot.com/2011/10/monitoring-desktop-heap-memory-and.html"&gt;Monitoring Desktop Heap Memory and troubleshooting issues (part I)&lt;/a&gt;), we can extend this functionality and retrieve the &lt;b&gt;Heap size&lt;/b&gt; from our Delphi app and even better, create a new desktop with a&amp;nbsp;&lt;b&gt;specified heap size&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To achieve this I am going to use the public &lt;b&gt;API functions&lt;/b&gt; introduced in&amp;nbsp;Windows Vista: &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms682127.aspx"&gt;CreateDesktopEx&lt;/a&gt;&lt;/b&gt;, which allows the caller to specify the size of desktop heap.And, &lt;b&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms683238.aspx"&gt;GetUserObjectInformation&lt;/a&gt;&lt;/b&gt;&amp;nbsp;that includes a &amp;nbsp;flag for retrieving the desktop heap size (&lt;b&gt;UOI_HEAPSIZE&lt;/b&gt;).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Get Heap Size:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To get the heap size, we just need to invoke the &lt;b&gt;GetUserObjectInformation&lt;/b&gt; using the &lt;b&gt;UOI_HEAPSIZE&lt;/b&gt; flag:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;procedure GetHeapSizeClick();&lt;br /&gt;var&lt;br /&gt;  HDesktop: HDESK;&lt;br /&gt;  UHeapSize: ULong;&lt;br /&gt;  tempDword: DWORD;&lt;br /&gt;begin&lt;br /&gt;  HDesktop := OpenInputDesktop(0, False, DESKTOP_CREATEMENU or&lt;br /&gt;    DESKTOP_CREATEWINDOW or DESKTOP_ENUMERATE or DESKTOP_HOOKCONTROL or&lt;br /&gt;    DESKTOP_WRITEOBJECTS or DESKTOP_READOBJECTS or DESKTOP_SWITCHDESKTOP or&lt;br /&gt;    GENERIC_WRITE);&lt;br /&gt;&lt;br /&gt;  GetUserObjectInformation(HDesktop, UOI_HEAPSIZE, @UHeapSize, SizeOf(UHeapSize), tempDword);&lt;br /&gt;  OutputDebugString(PChar('UOI_HEAPSIZE ' + Inttostr(UHeapSize)));&lt;br /&gt;  CloseDesktop(HDesktop);&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;b&gt;The output of the string is as follows:&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Debug Output: UOI_HEAPSIZE &lt;b&gt;12288&lt;/b&gt; Process Project1.exe (4224)&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Where the value highlighted in bold, is the predefined size of your heap in the &lt;b&gt;SubSystems\Windows&lt;/b&gt; registry key.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Create a new desktop with a specific heap size:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Using the&amp;nbsp;&lt;a href="http://msdn.microsoft.com/en-us/library/ms682127.aspx"&gt;CreateDesktopEx&lt;/a&gt; or&amp;nbsp;&lt;b&gt;CreateDesktopExW&lt;/b&gt; (Unicode):&lt;br /&gt;&lt;br /&gt;&lt;pre class="brush: delphi"&gt;var&lt;br /&gt;  HDesktopglobal: HDESK;&lt;br /&gt;&lt;br /&gt;procedure CreateDesktop();&lt;br /&gt;var&lt;br /&gt;  UHeapSize: ULong;&lt;br /&gt;  tempDword: DWORD;&lt;br /&gt;begin&lt;br /&gt;  try&lt;br /&gt;    HDesktopglobal := CreateDesktopExW('Z', nil, nil, DF_ALLOWOTHERACCOUNTHOOK, GENERIC_ALL, nil, 3052, nil);&lt;br /&gt;  except&lt;br /&gt;    on e: exception do&lt;br /&gt;      ShowMessage(SysErrorMessage(GetLastError));&lt;br /&gt;  end;&lt;br /&gt;  if HDesktopglobal &amp;lt;&amp;gt; 0 then&lt;br /&gt;  begin&lt;br /&gt;    GetUserObjectInformation(HDesktopglobal, UOI_HEAPSIZE, @UHeapSize, SizeOf(UHeapSize), tempDword);&lt;br /&gt;    OutputDebugString(PChar('UOI_HEAPSIZE ' + Inttostr(UHeapSize)));&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure CloseDesk();&lt;br /&gt;begin&lt;br /&gt;  CloseDesktop(HDesktopglobal);&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;br /&gt;&lt;br /&gt;We can check the result with dheapmon tool:&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-8vUP03jkq78/Tpx7uToKJ2I/AAAAAAAACyQ/tdJ2yZxV_SU/s1600/heap2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="181" src="http://3.bp.blogspot.com/-8vUP03jkq78/Tpx7uToKJ2I/AAAAAAAACyQ/tdJ2yZxV_SU/s400/heap2.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: left;"&gt;With more details using &lt;b&gt;dheapmon -v&lt;/b&gt; and the looking for '&lt;b&gt;Z&lt;/b&gt;' desktop.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-TTUsjVjjhdE/Tpx8d-SSyEI/AAAAAAAACyY/XXS32mUouRY/s1600/heap3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="127" src="http://2.bp.blogspot.com/-TTUsjVjjhdE/Tpx8d-SSyEI/AAAAAAAACyY/XXS32mUouRY/s400/heap3.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;b&gt;The output of the string is as follows:&lt;/b&gt;&lt;/div&gt;&lt;div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"&gt;&lt;span class="Apple-style-span" style="color: red;"&gt;Debug Output: UOI_HEAPSIZE&amp;nbsp;&lt;b&gt;3052&lt;/b&gt;&amp;nbsp;Process Project1.exe (364)&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Remember that the Desktop needs to be &lt;b&gt;closed&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/ntdebugging/archive/2007/07/05/desktop-heap-part-2.aspx"&gt;Desktop heap&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms683238.aspx"&gt;GetUserObjectInformation&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms682127.aspx"&gt;CreateDesktopEx&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-6299555966736956302?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/E4uM--p8d28/monitoring-desktop-heap-memory-and_17.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-afV1S9Ac0OM/TpxnjVC_lSI/AAAAAAAACyI/2lhrc38IwHY/s72-c/heap.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/10/monitoring-desktop-heap-memory-and_17.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-5560064819427422938</guid><pubDate>Sun, 16 Oct 2011 01:05:00 +0000</pubDate><atom:updated>2011-10-16T03:05:26.736+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Utilities</category><category domain="http://www.blogger.com/atom/ns#">Extensions</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">Google Chrome</category><title>Open a list of URLs</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-8Nk-zgaEdRE/TposYo3lSHI/AAAAAAAACx4/oZZDz6oQssc/s1600/images.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="150" src="http://4.bp.blogspot.com/-8Nk-zgaEdRE/TposYo3lSHI/AAAAAAAACx4/oZZDz6oQssc/s200/images.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Going on with my previous entries, in this post I am releasing a little tool to open a web browser (in this case google chrome) and populate it with a list of stored URLs. This tool would be the culmination of the articles:&amp;nbsp;&lt;a href="http://thundaxsoftware.blogspot.com/2011/09/my-first-google-chrome-extension-get.html"&gt;My first Google Chrome extension (Get all URLs from Google Chrome tabs)&lt;/a&gt; and&amp;nbsp;&lt;a href="http://thundaxsoftware.blogspot.com/2011/09/get-chrome-active-tab-url-using-delphi.html"&gt;Get Chrome active tab URL using Delphi&lt;/a&gt;. And as you know, I love automating and when I am surfing the internet I like keeping track of my URLs and being able to retrieving and saving them easily.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;You can download the tool from &lt;a href="http://www.4shared.com/file/bL4lDO96/ThundaxDelphiURLBrowser.html?"&gt;here&lt;/a&gt;. The tool only needs the path to your browser (in my case google chrome) and a list of pre-saved &lt;b&gt;urls&lt;/b&gt; (for example the output list from my chrome extension).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The tool looks like this:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-1HwyCT6Wabc/TpotEZJzKyI/AAAAAAAACyA/uQOMwlC_gpY/s1600/chromee.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="261" src="http://4.bp.blogspot.com/-1HwyCT6Wabc/TpotEZJzKyI/AAAAAAAACyA/uQOMwlC_gpY/s400/chromee.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;And it uses the &lt;b&gt;ShellExecute&lt;/b&gt; function from &lt;b&gt;ShellAPI&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Enjoy it!.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related Links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://delphi.about.com/cs/adptips2004/a/bltip0504_4.htm"&gt;Open browser&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-5560064819427422938?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/5L4rZA8O7gg/open-list-of-urls.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-8Nk-zgaEdRE/TposYo3lSHI/AAAAAAAACx4/oZZDz6oQssc/s72-c/images.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/10/open-list-of-urls.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-6966213899184181351</guid><pubDate>Sun, 16 Oct 2011 00:48:00 +0000</pubDate><atom:updated>2011-10-18T18:45:05.073+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Operating System</category><category domain="http://www.blogger.com/atom/ns#">Windows</category><title>Monitoring Desktop Heap Memory and troubleshooting issues (part I)</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-Ot0ecbXaNYc/TpoEe0D_IdI/AAAAAAAACxY/PSTAZdLa4os/s1600/heap.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="187" src="http://4.bp.blogspot.com/-Ot0ecbXaNYc/TpoEe0D_IdI/AAAAAAAACxY/PSTAZdLa4os/s200/heap.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;This article wants to put together a series of interesting articles to monitor the &lt;i&gt;desktop&lt;/i&gt; &lt;a href="http://en.wikipedia.org/wiki/Heap_memory"&gt;heap memory&lt;/a&gt; and finally put forward a little in-house tool to monitor the output of &lt;a href="http://www.airesoft.co.uk/desktopheapmonitor"&gt;Desktop Heap Information Monitor Tool v8.1&lt;/a&gt;&amp;nbsp;from &lt;a href="http://www.airesoft.co.uk/"&gt;AireSoft&lt;/a&gt; using the algorithm from "&lt;a href="http://thundaxsoftware.blogspot.com/2011/07/capturing-console-output-with-delphi.html"&gt;capturing output capture&lt;/a&gt;" from one of my previous posts.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;b&gt;Installing "Desktop Heap Information Monitor Tool v8.1:&lt;/b&gt;&lt;br /&gt;To correctly install the &lt;a href="http://www.airesoft.co.uk/files/dheapdmp/dheapdmp.zip"&gt;tool&lt;/a&gt;&amp;nbsp;(&lt;b&gt;dheapdmp.zip&lt;/b&gt;), go to &lt;a href="http://www.airesoft.co.uk/desktopheapmonitor"&gt;AireSoft&lt;/a&gt; web page and follow the installation steps from the web. If an error pops up, follow the guidelines from the following links:&lt;br /&gt;- &lt;a href="http://www.eggheadcafe.com/microsoft/Windows-Debugging/31483162/dheapinst--driver-installation-error-occured-2.aspx"&gt;dheapInst - driver installation error occurred (2)&lt;/a&gt;.&lt;br /&gt;-&amp;nbsp;&lt;a href="http://blogs.msdn.com/b/alejacma/archive/2008/07/29/how-to-use-dheapmon-exe-to-troubleshoot-desktop-heap-issues.aspx"&gt;dheapinst - Driver Installation error occured (124)&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;If it helps, I got the error "&lt;b&gt;Driver Installation error occured (124)&lt;/b&gt;" and I fixed it by changing the compatibility of &lt;b&gt;dheapinst&lt;/b&gt; to &lt;b&gt;Windows Server 2003 SP1&lt;/b&gt;.&lt;br /&gt;&lt;br /&gt;Once installed, if we run &lt;b&gt;dheapmon -l&lt;/b&gt; to install the monitor and then again &lt;b&gt;dheapmon&lt;/b&gt;, we will see the heap memory information:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-eCEa6gjuXH4/TpoUGJl-LKI/AAAAAAAACxg/4xSXUKY6vUw/s1600/heap22.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="197" src="http://1.bp.blogspot.com/-eCEa6gjuXH4/TpoUGJl-LKI/AAAAAAAACxg/4xSXUKY6vUw/s400/heap22.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;More about "Desktop heap memory":&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;The Desktop Heap Monitor is a tool that examines usage of desktop heap.&amp;nbsp;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;WIN32 subsystem has internal heap area known as "&lt;b&gt;desktop heap&lt;/b&gt;." When you run a large number of Windows-based programs, "&lt;b&gt;Out Of Memory&lt;/b&gt;" error messages appear when you attempt to start new programs or try to use programs that are already running, even though &lt;u&gt;you still have plenty of physical and pagefile memory available&lt;/u&gt;.&amp;nbsp;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;This behavior can occur if the desktop heap in the WIN32 subsystem is &lt;b&gt;depleted&lt;/b&gt;&lt;/i&gt;. To fix this problem follow the next workaround :&lt;br /&gt;-&amp;nbsp;&lt;a href="http://support.microsoft.com/kb/126962/"&gt;http://support.microsoft.com/kb/126962/&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;source&lt;/b&gt;:&amp;nbsp;&lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=17782"&gt;Microsoft&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;&lt;br /&gt;&lt;/b&gt;&lt;br /&gt;&lt;b&gt;Increasing "Desktop heap memory":&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;To increase desktop heap memory, we can use the tool "&lt;a href="http://go.microsoft.com/?linkid=9743805"&gt;Microsoft Fix It 50496&lt;/a&gt;" that will increase the parameters automatically. If you want to fix it manually, you just need to go to the following registry path and tweak it:&lt;br /&gt;&lt;b&gt;- HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SubSystems&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-u2SchnYOq5U/Tpom5CNrATI/AAAAAAAACxo/KiYetQqjAfg/s1600/registry.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="202" src="http://1.bp.blogspot.com/-u2SchnYOq5U/Tpom5CNrATI/AAAAAAAACxo/KiYetQqjAfg/s400/registry.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Where the default values for my windows vista are:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;%SystemRoot%\system32\csrss.exe&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ObjectDirectory=\Windows&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;SharedSection=1024,12288,512&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Windows=On&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;SubSystemType=Windows&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ServerDll=basesrv,1&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ServerDll=winsrv:UserServerDllInitialization,3&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ServerDll=winsrv:ConServerDllInitialization,2&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;ProfileControl=Off&amp;nbsp;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;span class="Apple-style-span" style="color: #666666; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;MaxRequestThreads=16&lt;/span&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;i&gt;The first SharedSection value (1024) defines the heap size common to all desktops. This includes the global handle table.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;The second SharedSection value (12288) controls the size of the desktop heap that is associated with an interactive window station (used for Windows objects). This static value is used to prevent ill- behaved applications from consuming too many resources. Because the desktop heap is mapped into each process' address space, this value should not be set to an arbitrarily high value (as it would decrease performance), but should only be increased sufficiently to allow all the desired applications to run.&lt;/i&gt;&lt;br /&gt;&lt;i&gt;&lt;br /&gt;&lt;/i&gt;&lt;br /&gt;&lt;i&gt;The third SharedSection value (512) controls the size of the desktop heap for each desktop that is associated with a "non-interactive" window station.&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;source&lt;/b&gt; : &lt;a href="http://support.microsoft.com/kb/126962/"&gt;microsoft&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Monitoring Desktop Heap Memory:&lt;/b&gt;&lt;br /&gt;As it is quite difficult to monitor, I have developed a little tool that you can download from &lt;a href="http://www.4shared.com/file/MwRL_guJ/ThundaxHeapMonitorTool.html"&gt;here&lt;/a&gt;, to log every change on the table result.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-WEcNFh_xGJA/TpooUTpuJaI/AAAAAAAACxw/Fz5oNVO6zNg/s1600/Monitoring.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="377" src="http://2.bp.blogspot.com/-WEcNFh_xGJA/TpooUTpuJaI/AAAAAAAACxw/Fz5oNVO6zNg/s400/Monitoring.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Just point the tool to the &lt;b&gt;dheapmon&lt;/b&gt; executable and press start. Every &lt;b&gt;10s&lt;/b&gt; the output will be scanned and displayed into the component, taking into account the previous value, and if a change occurs it will be displayed in another colour.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;b&gt;Final notes:&lt;/b&gt;&lt;br /&gt;Desktop Heap memory is related to "&lt;b&gt;&lt;a href="http://support.microsoft.com/kb/126962"&gt;Out of Memory&lt;/a&gt;&lt;/b&gt;" issues and this article will help you to work with this parameter and how to deal with it and monitor it.&lt;br /&gt;&lt;br /&gt;Stay tuned for Part 2, where I will go further with Desktop heap memory using Delphi.&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;i&gt;Jordi Corbilla&lt;/i&gt;.&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blogs.msdn.com/b/ntdebugging/archive/2007/01/04/desktop-heap-overview.aspx"&gt;Desktop Heap Overview&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://blog.airesoft.co.uk/2009/10/desktop-heap-monitor-vista-7/"&gt;Desktop Heap Monitor for Windows Vista&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.airesoft.co.uk/desktopheapmonitor"&gt;Desktop Heap Memory for Windows Server 2008, Windows 7&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463028.aspx"&gt;Download Windows Symbol Packages&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;184802"&gt;User32.dll or Kernel32.dll fails to initialize&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://support.microsoft.com/default.aspx?scid=kb;EN-US;840342"&gt;Applications may not run correctly in a Terminal Services environment&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/windows/hardware/gg463016.aspx"&gt;Debugging tools for Windows 32 bits&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://forums.cnet.com/7723-19411_102-383701.html"&gt;"Not enough storage is available to process this command"&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://support.microsoft.com/kb/914216"&gt;Error message that is similar to the following when you try to install the Desktop Heap Monitor tool: "dheapinst - Win32k.sys symbol load error, correct symbol required"&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-6966213899184181351?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/bXRph5v6Deg/monitoring-desktop-heap-memory-and.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/-Ot0ecbXaNYc/TpoEe0D_IdI/AAAAAAAACxY/PSTAZdLa4os/s72-c/heap.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/10/monitoring-desktop-heap-memory-and.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2310236259155410968</guid><pubDate>Sat, 08 Oct 2011 21:59:00 +0000</pubDate><atom:updated>2011-10-08T23:59:38.481+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Steve Jobs</category><category domain="http://www.blogger.com/atom/ns#">Videos</category><title>My tribute to a man who was a unique genius, Steve Jobs</title><description>&lt;div style="text-align: center;"&gt;&lt;br /&gt;&lt;iframe allowfullscreen="" frameborder="0" height="315" src="http://www.youtube.com/embed/8rwsuXHA7RA" width="420"&gt;&lt;/iframe&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;i&gt;Steve Jobs was a unique creative genius whose life was far too brief&lt;/i&gt;. &lt;b&gt;Source&lt;/b&gt;: &lt;a href="http://www.macworld.co.uk/apple-business/news/index.cfm?newsid=3309222"&gt;macworld.co.uk&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2310236259155410968?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/dJWsKBSXdkQ/my-tribute-to-man-who-was-unique-genius.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://img.youtube.com/vi/8rwsuXHA7RA/default.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/10/my-tribute-to-man-who-was-unique-genius.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-4623470975708567912</guid><pubDate>Sun, 18 Sep 2011 14:17:00 +0000</pubDate><atom:updated>2011-09-18T16:17:06.437+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Extensions</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">Google Chrome</category><title>Get Chrome active tab URL using Delphi</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-r9g6hJk4hWo/TnXHOxOEkLI/AAAAAAAACww/wlMiz3xFQYw/s1600/log.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="53" src="http://3.bp.blogspot.com/-r9g6hJk4hWo/TnXHOxOEkLI/AAAAAAAACww/wlMiz3xFQYw/s200/log.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;After developing &lt;a href="http://thundaxsoftware.blogspot.com/2011/09/my-first-google-chrome-extension-get.html"&gt;my first Chrome extension&lt;/a&gt;&amp;nbsp;&lt;b&gt;to retrieve all URLs from Google chrome&lt;/b&gt;, I have been trying to reproduce the same behaviour using Delphi, but it was impossible. Chrome is still adding some new features and extending their extensions for developers. For example, others navigators such as Internet Explorer and Firefox they have a &lt;a href="http://en.wikipedia.org/wiki/Dynamic_Data_Exchange"&gt;DDE&lt;/a&gt; extension to retrieve some of the properties but not available for Chrome.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The best way I found was using FindWindow and SendMessage windows functions to get the text from the tab and get tue URL. It's not a win solution but will help you to retrieve the URL of the active page without copy-paste action, just by switching to the next tab and retrieving data from the tool.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The basic code to achieve this is the following one:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;function GetChromeActiveTabURL(Wnd: HWnd; Param: LParam): Bool; stdcall;&lt;br /&gt;var&lt;br /&gt;  urls: TStrings;&lt;br /&gt;  hWndMainWindow, hWndTab: HWND;&lt;br /&gt;  Buffer : array[0..255] of Char;&lt;br /&gt;  res : boolean;&lt;br /&gt;begin&lt;br /&gt;  res := true;&lt;br /&gt;  urls := TStrings(Param);&lt;br /&gt;  SendMessage(Wnd, WM_GETTEXT, Length(Buffer), integer(@Buffer[0]));&lt;br /&gt;  hWndMainWindow := FindWindow('Chrome_WidgetWin_0', Buffer);&lt;br /&gt;  application.ProcessMessages;&lt;br /&gt;  if hWndMainWindow &amp;lt;&amp;gt; 0 then&lt;br /&gt;  begin&lt;br /&gt;    hWndTab := FindWindowEx(hWndMainWindow, 0, 'Chrome_AutocompleteEditView', nil);&lt;br /&gt;    if hWndTab &amp;lt;&amp;gt; 0 then&lt;br /&gt;    begin&lt;br /&gt;      SendMessage(hWndTab, WM_GETTEXT, Length(Buffer), integer(@Buffer));&lt;br /&gt;      urls.Add(Buffer);&lt;br /&gt;      res := false;&lt;br /&gt;    end;&lt;br /&gt;  end;&lt;br /&gt;  Result := res;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;procedure TUrlChrome.GetUrl(Sender: TObject);&lt;br /&gt;var&lt;br /&gt;  Urls: TStringList;&lt;br /&gt;begin&lt;br /&gt;  Urls := TStringList.Create;&lt;br /&gt;  try&lt;br /&gt;    EnumWindows(@GetChromeActiveTabURL, LParam(Urls));&lt;br /&gt;    Memo1.Lines.AddStrings(Urls);&lt;br /&gt;  finally&lt;br /&gt;    FreeAndNil(Urls);&lt;br /&gt;  end;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To get the &lt;a href="http://msdn.microsoft.com/en-us/library/ms633499(v=VS.85).aspx"&gt;class name window&lt;/a&gt;, we can use &lt;a href="http://www.softpedia.com/get/Security/Security-Related/Winspector.shtml"&gt;Winspector&lt;/a&gt; to inspect chrome and get the names for the main window and for the tabs:&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Chrome_WidgetWin_0:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-3G0GN7d2OpM/TnX2fcmUbVI/AAAAAAAACw8/qUeUzWcwTS4/s1600/win.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="278" src="http://3.bp.blogspot.com/-3G0GN7d2OpM/TnX2fcmUbVI/AAAAAAAACw8/qUeUzWcwTS4/s400/win.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;b&gt;Chrome_AutocompleteEditView:&lt;/b&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-_DJrjSgOTbg/TnX2eGVzuSI/AAAAAAAACw4/2b3SWO1UBPY/s1600/tab.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="247" src="http://3.bp.blogspot.com/-_DJrjSgOTbg/TnX2eGVzuSI/AAAAAAAACw4/2b3SWO1UBPY/s400/tab.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;And you can get the tool from here: &lt;a href="http://www.4shared.com/file/K4J67vnt/ThundaxChromeURL.html"&gt;ThundaxChromeURL&lt;/a&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-hZkPlbxhFGU/TnXrbS2XBRI/AAAAAAAACw0/kKKPSDFJodU/s1600/chrom.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="242" src="http://4.bp.blogspot.com/-hZkPlbxhFGU/TnXrbS2XBRI/AAAAAAAACw0/kKKPSDFJodU/s400/chrom.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;I'm not proud of this solution, but at least it will work for current versions of Chrome. I also recommend to give a go to my &lt;a href="http://thundaxsoftware.blogspot.com/2011/09/my-first-google-chrome-extension-get.html"&gt;chrome extension&lt;/a&gt;&amp;nbsp;(It's not been published into Chrome market, it turns out that you have to pay a $5.00 fee), that is much better than the tool as it's able to get all urls.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/5222301/how-to-get-the-url-from-chrome-using-delphi"&gt;How to get url from chrome&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.softpedia.com/progDownload/Winspector-Download-117157.html"&gt;WinsPector Download&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms633497(v=vs.85).aspx"&gt;EnumWindows function&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.delphipages.com/forum/showthread.php?t=115353"&gt;Get list opened windows&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.swissdelphicenter.ch/torry/showcode.php?id=198"&gt;Get url instances internet explorer&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms633500(v=VS.85).aspx"&gt;FindWindowEx function&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/147929/c-sending-messages-to-google-chrome-from-c-application"&gt;Sending messages to Chrome&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms633515(v=VS.85).aspx"&gt;GetWindow function&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.swissdelphicenter.ch/torry/showcode.php?id=410"&gt;Enumerate windows and child windows&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/5086582/enumchildwindows-over-tabcontroller-items-in-the-untouched-tabs-are-not-captured"&gt;Enum child windows&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/6002044/enumwindows-and-enumchildwindows-to-keep-my-treeview-updated"&gt;Enum child windows treeview&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/Answers/246371/How-to-get-handles-of-tabs.aspx#answer1"&gt;Get handles of tabs&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-US/Library/ms633494.aspx"&gt;EnumChildWindows function&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-4623470975708567912?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/jMqdP3oSthY/get-chrome-active-tab-url-using-delphi.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/-r9g6hJk4hWo/TnXHOxOEkLI/AAAAAAAACww/wlMiz3xFQYw/s72-c/log.png" height="72" width="72" /><thr:total>7</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/09/get-chrome-active-tab-url-using-delphi.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-8894917063926777233</guid><pubDate>Sat, 17 Sep 2011 19:45:00 +0000</pubDate><atom:updated>2011-09-18T12:18:10.662+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Extensions</category><category domain="http://www.blogger.com/atom/ns#">Google Chrome</category><title>My first Google Chrome extension (Get all URLs from Google Chrome tabs)</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-3w-bxqSD9OU/TnTxjo9xONI/AAAAAAAACwg/_lozgENiXoc/s1600/images.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="149" src="http://2.bp.blogspot.com/-3w-bxqSD9OU/TnTxjo9xONI/AAAAAAAACwg/_lozgENiXoc/s200/images.jpg" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As a good internet researcher I always have hundreds of tabs opened in my &lt;a href="http://www.google.com/chrome/?installdataindex=nosearch&amp;amp;hl=en-GB&amp;amp;brand=CHMA&amp;amp;utm_campaign=en-GB&amp;amp;utm_source=en-GB-ha-emea-uk-bk&amp;amp;utm_medium=ha"&gt;Chrome&lt;/a&gt; navigator and sometimes I find a bit of chore to copy and paste all the URL that I have done a research on and that any other day &lt;b&gt;I would be using again&lt;/b&gt;. So, that's my extension about, to display in a pop up window all the url's from all tabs to then copy them without problems (the correct name would be [search purposes] -&amp;gt; &lt;b&gt;&lt;i&gt;Get all URLs from Google Chrome tabs&lt;/i&gt;&lt;/b&gt;).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I have been struggling to write a little tool using Delphi, but it only works with &lt;b&gt;Internet explorer&lt;/b&gt; and &lt;b&gt;Mozilla firefox&lt;/b&gt;, so I thought it could be great to give &lt;a href="http://code.google.com/chrome/extensions/getstarted.html"&gt;chrome extensions&lt;/a&gt; a try.&amp;nbsp;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;It is quite easy to develop and debug using all the development tools available from the navigator itself. As in the following example, I have opened 3 new tabs with the &lt;b&gt;&lt;a href="http://www.google.es/"&gt;www.google.es&lt;/a&gt;&lt;/b&gt; URL, and if we click the extension button, will get a pop up list with the URLs from all tabs:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-aHgPh--Xck4/TnT0867SjhI/AAAAAAAACwk/9wzgiTQeEa4/s1600/result.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="82" src="http://3.bp.blogspot.com/-aHgPh--Xck4/TnT0867SjhI/AAAAAAAACwk/9wzgiTQeEa4/s400/result.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The source code is as follows:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;manifest.json:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: jscript"&gt;{&lt;br /&gt;  "name": "Get All URL's Extension by Jordi Corbilla",&lt;br /&gt;  "version": "1.0",&lt;br /&gt;  "description": "Extension to display all the URL's from all TABs.",&lt;br /&gt;  "browser_action": {&lt;br /&gt;    "default_icon": "icon.ico",&lt;br /&gt;    "popup": "urlList.html"&lt;br /&gt;  },&lt;br /&gt;  "permissions": [&lt;br /&gt;    "tabs"&lt;br /&gt;  ],&lt;br /&gt;  "icons" : {&lt;br /&gt;&lt;br /&gt;    "48" : "icon.ico",&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    "128" : "icon.ico"&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;  }&lt;br /&gt;}&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;urlList.html:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: jscript"&gt;&amp;lt;!DOCTYPE&amp;gt;&lt;br /&gt;&amp;lt;!--&lt;br /&gt; * Copyright (c) 2011 Jordi Corbilla. All rights reserved.  &lt;br /&gt;--&amp;gt;&lt;br /&gt;&amp;lt;html&amp;gt;&lt;br /&gt;  &amp;lt;head&amp;gt;&lt;br /&gt;    &amp;lt;script&amp;gt;&lt;br /&gt;      chrome.tabs.getAllInWindow(null, function(tabs) {&lt;br /&gt;        tabs.forEach(function(tab){&lt;br /&gt;          myFunction(tab.url);	&lt;br /&gt;        });&lt;br /&gt;      });&lt;br /&gt;&lt;br /&gt;      function myFunction(tablink) {&lt;br /&gt;        console.log(tablink);&lt;br /&gt;        var oNewNode = document.createElement("LI");&lt;br /&gt;        urlList.appendChild(oNewNode);&lt;br /&gt;        oNewNode.innerText=tablink;  &lt;br /&gt;      }&lt;br /&gt;&amp;lt;/script&amp;gt;&lt;br /&gt;&amp;lt;/head&amp;gt;&lt;br /&gt;  &amp;lt;body&amp;gt;&lt;br /&gt;    &amp;lt;div&amp;gt;URL List&amp;lt;/div&amp;gt;&lt;br /&gt;    &amp;lt;ul ID = urlList&amp;gt;&lt;br /&gt;    &amp;lt;/ul&amp;gt;&lt;br /&gt;  &amp;lt;/body&amp;gt;&lt;br /&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;You can download the extension from here: &lt;a href="http://www.4shared.com/file/DvLoNsdE/URLJCExtension.html"&gt;URLJCExtension.zip&lt;/a&gt;. To install, you only need to unzip the file and then go to&amp;nbsp;&lt;a href="chrome://extensions/"&gt;chrome://extensions/&lt;/a&gt;, expand developer mode and load my extension (from the unzipped folder):&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-gwlRISgabb0/TnT349cLCLI/AAAAAAAACwo/IwLv5LPW2Bw/s1600/extension.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="120" src="http://3.bp.blogspot.com/-gwlRISgabb0/TnT349cLCLI/AAAAAAAACwo/IwLv5LPW2Bw/s400/extension.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As the extension uses the console log method, you can see all the links in the console (just for debug purposes, but it's really good to have a go on it).&lt;br /&gt;&lt;br /&gt;Just right click on the extension icon and then "Inspect Pop-up" and you'll see the following window with the current list of urls:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-ywAPi1Ud5OM/TnXFTg7c64I/AAAAAAAACws/XJszlqh8MFg/s1600/debug.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="400" src="http://1.bp.blogspot.com/-ywAPi1Ud5OM/TnXFTg7c64I/AAAAAAAACws/XJszlqh8MFg/s400/debug.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Enjoy the extension!.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/217957/how-to-print-debug-messages-in-the-google-chrome-javascript-console"&gt;Print debug messages chrome console&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/6453860/how-to-match-a-url-from-a-tab-with-an-array-of-urls-google-chrome-extension"&gt;Array of URLs&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://supercollider.dk/2010/04/chrome-extensions-for-web-hackers-part-%E2%85%A1-background-pages-255"&gt;Chrome Extensions Hacking Part 2&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://msdn.microsoft.com/en-us/library/ms535934(v=vs.85).aspx"&gt;appendChild method&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://stackoverflow.com/questions/1979583/how-can-i-get-the-url-for-a-google-chrome-tab"&gt;Get URL from chrome tab&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-8894917063926777233?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/ithzsrTmFy4/my-first-google-chrome-extension-get.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-3w-bxqSD9OU/TnTxjo9xONI/AAAAAAAACwg/_lozgENiXoc/s72-c/images.jpg" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/09/my-first-google-chrome-extension-get.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-2640753993764039382</guid><pubDate>Fri, 26 Aug 2011 16:14:00 +0000</pubDate><atom:updated>2012-03-25T22:15:37.992+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Chaining Method</category><category domain="http://www.blogger.com/atom/ns#">Aspect oriented programming</category><category domain="http://www.blogger.com/atom/ns#">Dependency Injection</category><title>Fluent Interfaces example using Delphi part I</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-vu--nNY_6xo/Tle-M2RuTxI/AAAAAAAACwQ/WZssyPOclS8/s1600/chain200.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://1.bp.blogspot.com/-vu--nNY_6xo/Tle-M2RuTxI/AAAAAAAACwQ/WZssyPOclS8/s1600/chain200.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I was introduced to &lt;a href="http://en.wikipedia.org/wiki/Fluent_interface"&gt;Fluent interfaces&lt;/a&gt; when I was developing with Java using &lt;a href="http://en.wikipedia.org/wiki/Dependency_injection"&gt;Dependency Injection&lt;/a&gt;&amp;nbsp;and somebody told me that it could be really interesting if I post an example using &lt;b&gt;Delphi&lt;/b&gt; and chaining method, and here I am!. I have developed a simple example that uses &lt;a href="http://en.wikipedia.org/wiki/Method_chaining"&gt;chaining methods&lt;/a&gt; to populate a &lt;i&gt;THouse&lt;/i&gt; object with &lt;i&gt;TDoors&lt;/i&gt; and &lt;i&gt;TWindows&lt;/i&gt; objects with the hope it will make it easy to understand the concept. There are several examples on the net, but I couldn't find any interesting enough. So this simple example will try to introduce you to "how to develop fluent interfaces using method chaining" with the aim of writing more readable code. The overview of the architecture is the following one, using &lt;b&gt;UML&lt;/b&gt; notation:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-Z6eJforpTOQ/TlfDX616MtI/AAAAAAAACwU/-GSfsh0M0hM/s1600/uFI.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="256" src="http://1.bp.blogspot.com/-Z6eJforpTOQ/TlfDX616MtI/AAAAAAAACwU/-GSfsh0M0hM/s400/uFI.bmp" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;The Fluent Interface unit example is as follows (uFI.pas) using generics and interfaces:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;// ***********************************************&lt;br /&gt;// @author  jordi corbilla&lt;br /&gt;// @comment Fluent interface composition example&lt;br /&gt;//&lt;br /&gt;// ***********************************************&lt;br /&gt;&lt;br /&gt;unit uFI;&lt;br /&gt;&lt;br /&gt;interface&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;    Graphics, Contnrs, Generics.Collections, Classes;&lt;br /&gt;&lt;br /&gt;type&lt;br /&gt;    TWindow = class;&lt;br /&gt;&lt;br /&gt;    IWindow = interface&lt;br /&gt;        function SetColor(color: TColor): TWindow;&lt;br /&gt;        function ToString(): string;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    TWindow = class(TInterfacedObject, IWindow)&lt;br /&gt;    private&lt;br /&gt;        FColor: TColor;&lt;br /&gt;    public&lt;br /&gt;        function SetColor(color: TColor): TWindow;&lt;br /&gt;        function ToString(): string; override;&lt;br /&gt;        class function New: TWindow;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    TDoor = class;&lt;br /&gt;&lt;br /&gt;    IDoor = interface&lt;br /&gt;        function SetColor(color: TColor): TDoor;&lt;br /&gt;        function ToString(): string;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    TDoor = class(TInterfacedObject, IDoor)&lt;br /&gt;    private&lt;br /&gt;        FColor: TColor;&lt;br /&gt;    public&lt;br /&gt;        function SetColor(color: TColor): TDoor;&lt;br /&gt;        function ToString(): string; override;&lt;br /&gt;        class function New: TDoor;&lt;br /&gt;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    IHouse = interface&lt;br /&gt;        function AddWindow(window: TWindow): IHouse;&lt;br /&gt;        function AddDoor(door: TDoor): IHouse;&lt;br /&gt;        function ToString(): String;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    THouseItemsList&amp;lt;T&amp;gt; = class(TObjectList)&lt;br /&gt;        function ToString(): string; override;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    TDoorList = class(THouseItemsList&amp;lt;IDoor&amp;gt;)&lt;br /&gt;        function ToString(): string; override;&lt;br /&gt;    public&lt;br /&gt;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    TWindowList = class(THouseItemsList&amp;lt;IWindow&amp;gt;)&lt;br /&gt;        function ToString(): string; override;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;    THouse = class(TInterfacedObject, IHouse)&lt;br /&gt;    private&lt;br /&gt;        FDoorList: TDoorList;&lt;br /&gt;        FWindowList: TWindowList;&lt;br /&gt;    protected&lt;br /&gt;        function AddWindow(window: TWindow): IHouse;&lt;br /&gt;        function AddDoor(door: TDoor): IHouse;&lt;br /&gt;    public&lt;br /&gt;        property WindowList: TWindowList read FWindowList;&lt;br /&gt;        property DoorList: TDoorList read FDoorList;&lt;br /&gt;        class function New: IHouse;&lt;br /&gt;        function ToString(): String; override;&lt;br /&gt;        constructor Create();&lt;br /&gt;        destructor Destroy(); override;&lt;br /&gt;    end;&lt;br /&gt;&lt;br /&gt;implementation&lt;br /&gt;&lt;br /&gt;uses&lt;br /&gt;    SysUtils;&lt;br /&gt;&lt;br /&gt;{ THouse }&lt;br /&gt;&lt;br /&gt;function THouse.AddDoor(door: TDoor): IHouse;&lt;br /&gt;begin&lt;br /&gt;    Self.FDoorList.Add(door);&lt;br /&gt;    result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function THouse.AddWindow(window: TWindow): IHouse;&lt;br /&gt;begin&lt;br /&gt;    Self.FWindowList.Add(window);&lt;br /&gt;    result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;constructor THouse.Create;&lt;br /&gt;begin&lt;br /&gt;    FDoorList := TDoorList.Create;&lt;br /&gt;    FWindowList := TWindowList.Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;destructor THouse.Destroy;&lt;br /&gt;begin&lt;br /&gt;    FreeAndNil(FDoorList);&lt;br /&gt;    FreeAndNil(FWindowList);&lt;br /&gt;    inherited;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;class function THouse.New: IHouse;&lt;br /&gt;begin&lt;br /&gt;    result := Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function THouse.ToString: String;&lt;br /&gt;var&lt;br /&gt;    description: TStringList;&lt;br /&gt;begin&lt;br /&gt;    description := TStringList.Create;&lt;br /&gt;    try&lt;br /&gt;        description.Add(Self.FDoorList.ToString);&lt;br /&gt;        description.Add(Self.FWindowList.ToString);&lt;br /&gt;    finally&lt;br /&gt;        result := description.Text;&lt;br /&gt;        description.Free;&lt;br /&gt;    end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TWindow }&lt;br /&gt;&lt;br /&gt;class function TWindow.New: TWindow;&lt;br /&gt;begin&lt;br /&gt;    result := Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TWindow.SetColor(color: TColor): TWindow;&lt;br /&gt;begin&lt;br /&gt;    Self.FColor := color;&lt;br /&gt;    result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TWindow.ToString: string;&lt;br /&gt;begin&lt;br /&gt;    result := 'Window color ' + ColorToString(FColor) + sLineBreak;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TDoor }&lt;br /&gt;&lt;br /&gt;class function TDoor.New: TDoor;&lt;br /&gt;begin&lt;br /&gt;    result := Create;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TDoor.SetColor(color: TColor): TDoor;&lt;br /&gt;begin&lt;br /&gt;    Self.FColor := color;&lt;br /&gt;    result := Self;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;function TDoor.ToString: string;&lt;br /&gt;begin&lt;br /&gt;    result := 'Door color ' + ColorToString(FColor) + sLineBreak;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ THouseItemsList }&lt;br /&gt;&lt;br /&gt;function THouseItemsList&amp;lt;T&amp;gt;.ToString: string;&lt;br /&gt;var&lt;br /&gt;    i: Integer;&lt;br /&gt;    description: String;&lt;br /&gt;begin&lt;br /&gt;    for i := 0 to Self.count - 1 do&lt;br /&gt;        description := description + ' ' + Self[i].ToString;&lt;br /&gt;    result := description;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TDoorList }&lt;br /&gt;&lt;br /&gt;function TDoorList.ToString: string;&lt;br /&gt;var&lt;br /&gt;    description: TStringList;&lt;br /&gt;begin&lt;br /&gt;    description := TStringList.Create;&lt;br /&gt;    try&lt;br /&gt;        description.Add('Number of doors: ' + inttostr(Self.count));&lt;br /&gt;        description.Add('Descriptions: ');&lt;br /&gt;        description.Add( inherited ToString);&lt;br /&gt;    finally&lt;br /&gt;        result := description.Text;&lt;br /&gt;        FreeAndNil(description);&lt;br /&gt;    end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;{ TWindowList }&lt;br /&gt;&lt;br /&gt;function TWindowList.ToString: string;&lt;br /&gt;var&lt;br /&gt;    description: TStringList;&lt;br /&gt;begin&lt;br /&gt;    description := TStringList.Create;&lt;br /&gt;    try&lt;br /&gt;        description.Add('Number of Windows: ' + inttostr(Self.count));&lt;br /&gt;        description.Add('Descriptions: ');&lt;br /&gt;        description.Add( inherited ToString);&lt;br /&gt;    finally&lt;br /&gt;        result := description.Text;&lt;br /&gt;        FreeAndNil(description);&lt;br /&gt;    end;&lt;br /&gt;end;&lt;br /&gt;&lt;br /&gt;end.&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now it comes when we can use the object using &lt;b&gt;FI notation&lt;/b&gt; in a more readable way:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;var&lt;br /&gt;    House: IHouse;&lt;br /&gt;begin&lt;br /&gt;    House := THouse.New.AddWindow(TWindow.New.SetColor(clFuchsia)).AddDoor(TDoor.New.SetColor(clWhite))&lt;br /&gt;        .AddWindow(TWindow.New.SetColor(clRed)).AddDoor(TDoor.New.SetColor(clGreen));&lt;br /&gt;    Memo1.Lines.Add(House.ToString);&lt;br /&gt;    House := nil;&lt;br /&gt;&lt;br /&gt;    House := THouse.New;&lt;br /&gt;    House.AddWindow(TWindow.New.SetColor(clRed)).AddWindow(TWindow.New.SetColor(clBlue)).AddWindow(TWindow.New.SetColor(clGreen));&lt;br /&gt;    House.AddDoor(TDoor.New.SetColor(clRed)).AddDoor(TDoor.New.SetColor(clBlue)).AddDoor(TDoor.New.SetColor(clGreen));&lt;br /&gt;    Memo1.Lines.Add(House.ToString);&lt;br /&gt;    House := nil;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Notice that now, we can chain our objects, composing the structure of the House by using the &lt;b&gt;AddWindow&lt;/b&gt; and &lt;b&gt;AddDoor&lt;/b&gt; method. To display the result I'm using the &lt;b&gt;ToString&lt;/b&gt; method that will do the job for my purpose.&lt;br /&gt;&lt;br /&gt;And the result of the previous execution:&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Number of doors: 2&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Descriptions:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Door color clWhite&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Door color clGreen&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Number of Windows: 2&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Descriptions:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Window color clFuchsia&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Window color clRed&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Number of doors: 3&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Descriptions:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Door color clRed&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Door color clBlue&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Door color clGreen&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Number of Windows: 3&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;Descriptions:&amp;nbsp;&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Window color clRed&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Window color clBlue&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="color: blue; font-family: 'Courier New', Courier, monospace; font-size: x-small;"&gt;&amp;nbsp;Window color clGreen&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Just play with it and you'll experience the powerfulness of this method. I hope you like it.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;I'm looking forward to your comments.&lt;br /&gt;&lt;div style="text-align: right;"&gt;&lt;b&gt;Jordi&lt;/b&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-2640753993764039382?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/5reeBe2Qg7Q/fluent-interfaces-example-using-delphi.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-vu--nNY_6xo/Tle-M2RuTxI/AAAAAAAACwQ/WZssyPOclS8/s72-c/chain200.jpg" height="72" width="72" /><thr:total>16</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/08/fluent-interfaces-example-using-delphi.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-7164906712504454754</guid><pubDate>Mon, 22 Aug 2011 20:08:00 +0000</pubDate><atom:updated>2011-08-22T22:14:00.740+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Maths</category><category domain="http://www.blogger.com/atom/ns#">Direct2D</category><category domain="http://www.blogger.com/atom/ns#">Physics</category><category domain="http://www.blogger.com/atom/ns#">Computational geometry</category><title>Building my own Delphi Physics Engine part IX</title><description>&lt;div style="text-align: justify;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-jHBJ5jwI4dc/TlF9AQkbBrI/AAAAAAAACwI/Du6WP16S9EU/s1600/Direct2d.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="168" src="http://2.bp.blogspot.com/-jHBJ5jwI4dc/TlF9AQkbBrI/AAAAAAAACwI/Du6WP16S9EU/s200/Direct2d.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;I'm quite familiar with &lt;a href="http://en.wikipedia.org/wiki/Graphics_Device_Interface"&gt;&lt;b&gt;GDI&lt;/b&gt;&lt;/a&gt;, the graphics provided under &lt;b&gt;Microsoft&lt;/b&gt; and which is widely used in Windows applications. &lt;a href="http://code.google.com/p/thundax-delphi-physics-engine/"&gt;TDPE&lt;/a&gt; is now ready to use &lt;a href="http://www.google.co.uk/url?sa=t&amp;amp;source=web&amp;amp;cd=1&amp;amp;ved=0CCoQFjAA&amp;amp;url=http%3A%2F%2Fmsdn.microsoft.com%2Fen-us%2Flibrary%2Fdd370990(v%3Dvs.85).aspx&amp;amp;ei=JYdRTr-mNY-DhQez_a3XBg&amp;amp;usg=AFQjCNHH9HLdxPoq3pJWm5RTGR77oPJQ4Q&amp;amp;sig2=1C6vNAUfUqoN9xoG9Nbr-A"&gt;Direct2D&lt;/a&gt; as now it's fully supported by &lt;b&gt;Delphi 2010&lt;/b&gt; and &lt;b&gt;XE&lt;/b&gt;. According to MSDN, &lt;b&gt;Direct2D&lt;/b&gt; is:&amp;nbsp;&lt;i&gt;&lt;span class="Apple-style-span" style="color: purple;"&gt;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.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As I'm testing this under &lt;b&gt;Windows Vista&lt;/b&gt;, I've had to upgrade my windows version to &lt;b&gt;Service Pack 2&lt;/b&gt; and then I've installed the following update (&lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=3274"&gt;KB971512&lt;/a&gt; - &lt;i&gt;The Windows Graphics, Imaging, and XPS Library contain the latest advancements in modern graphics technologies for gaming, multimedia, imaging and printing applications&lt;/i&gt;.). Direct2D is already installed in Windows 7.&lt;br /&gt;&lt;br /&gt;We can use the same methods from &lt;b&gt;&lt;a href="http://docwiki.embarcadero.com/VCL/en/Graphics.TCanvas"&gt;TCanvas&lt;/a&gt;&lt;/b&gt; for our &lt;b&gt;&lt;a href="http://docwiki.embarcadero.com/VCL/en/Direct2D.TDirect2DCanvas"&gt;TDirect2DCanvas&lt;/a&gt;&lt;/b&gt; as they derive from the same ancestor &lt;b&gt;&lt;a href="http://docwiki.embarcadero.com/VCL/en/Graphics.TCustomCanvas"&gt;TCustomCanvas&lt;/a&gt;&lt;/b&gt;. But you need to check the documentation for differences in the way they work.&lt;br /&gt;&lt;br /&gt;A simple way to use &lt;b&gt;Direct2D&lt;/b&gt; is as follows:&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;pre class="brush: delphi"&gt;uses&lt;br /&gt;    Direct2D, D2D1;&lt;br /&gt;&lt;br /&gt;procedure Paint();&lt;br /&gt;begin&lt;br /&gt;    if TDirect2DCanvas.Supported then&lt;br /&gt;    begin&lt;br /&gt;        d2dCanvas := TDirect2DCanvas.Create(Canvas, ClientRect);&lt;br /&gt;        try&lt;br /&gt;            d2dCanvas.RenderTarget.beginDraw;&lt;br /&gt;            d2dCanvas.RenderTarget.Clear(D2D1ColorF(clBlack));&lt;br /&gt;            d2dCanvas.RenderTarget.SetAntialiasMode(D2D1_ANTIALIAS_MODE_PER_PRIMITIVE);&lt;br /&gt;            // drawing goes here&lt;br /&gt;            Paint(d2dCanvas);&lt;br /&gt;            d2dCanvas.RenderTarget.EndDraw;&lt;br /&gt;        finally&lt;br /&gt;            FreeAndNil(d2dCanvas);&lt;br /&gt;        end;&lt;br /&gt;    end;&lt;br /&gt;end;&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;Here is the result of the Physics Engine using a &lt;b&gt;Direct2D Render&lt;/b&gt; and a &lt;b&gt;GDI Render&lt;/b&gt;:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-hwDhE4gZTJ8/TlK4XOrQcUI/AAAAAAAACwM/qKLsgqbfu7k/s1600/Dibujo.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="131" src="http://4.bp.blogspot.com/-hwDhE4gZTJ8/TlK4XOrQcUI/AAAAAAAACwM/qKLsgqbfu7k/s400/Dibujo.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/_l9DLteBUtc?hl=en&amp;amp;fs=1" width="425"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;You will see the difference when switching from &lt;b&gt;GDI&lt;/b&gt; to &lt;b&gt;Direct2D&lt;/b&gt; 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.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: #444444;"&gt;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.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: #444444;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: #444444;"&gt;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 &lt;a href="http://en.wikipedia.org/wiki/Graphics_processing_unit"&gt;GPU&lt;/a&gt;.&amp;nbsp;&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: right;"&gt;&lt;i&gt;&lt;span class="Apple-style-span" style="color: #444444;"&gt;Source : &lt;a href="http://www.codeproject.com/Articles/95054/Programming-Direct2D-Part-1"&gt;Programming Direct2D&lt;/a&gt;.&lt;/span&gt;&lt;/i&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Get the latest version here: &lt;a href="http://www.4shared.com/file/gc8ltW55/ThundaxBallsDemo_v1584.html"&gt;ThundaxBallDemo v1.584&lt;/a&gt;.&lt;br /&gt;&lt;b&gt;Interaction:&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'d'&lt;/b&gt; will drop a box with a random colour and a constant angular velocity.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'f'&lt;/b&gt; will drop a circle with a random colour and a constant angular velocity.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'mouse interaction'&lt;/b&gt; mouse is able to grab items.&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'q'&lt;/b&gt; Enable/Disable &lt;b&gt;GDI&lt;/b&gt; or &lt;b&gt;Direct2D&lt;/b&gt; rendering.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Note:&lt;/b&gt; You need to have installed Direct2D to run the app using Direct2D, otherwise GDI will be used.&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://docwiki.embarcadero.com/RADStudio/en/Using_the_Direct2D_Canvas"&gt;Using Direct2D&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.codeproject.com/Articles/95054/Programming-Direct2D-Part-1"&gt;Programming Direct2D&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.infoq.com/news/2009/06/Windows-7-Graphics"&gt;Windows 7 Graphic Engine&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/08/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part VIII&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/06/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part VII&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/05/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part VI&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine_05.html"&gt;Building my own Delphi Physics Engine part V&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine_04.html"&gt;Building my own Delphi Physics Engine part IV&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part III&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/12/building-my-own-delphi-physics-engine_10.html"&gt;Building my own Delphi Physics Engine part II&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/12/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part I&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-7164906712504454754?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/uw36_IpW9N4/building-my-own-delphi-physics-engine_22.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-jHBJ5jwI4dc/TlF9AQkbBrI/AAAAAAAACwI/Du6WP16S9EU/s72-c/Direct2d.png" height="72" width="72" /><thr:total>2</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/08/building-my-own-delphi-physics-engine_22.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-4186519833830600707</guid><pubDate>Wed, 10 Aug 2011 21:04:00 +0000</pubDate><atom:updated>2011-08-10T23:05:02.208+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Maths</category><category domain="http://www.blogger.com/atom/ns#">Physics</category><category domain="http://www.blogger.com/atom/ns#">Computational geometry</category><title>Building my own Delphi Physics Engine part VIII</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-XgLtjjG_2nI/TkLhUc0r8fI/AAAAAAAACwA/70vjSJhP-d8/s1600/TDPE2.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" src="http://2.bp.blogspot.com/-XgLtjjG_2nI/TkLhUc0r8fI/AAAAAAAACwA/70vjSJhP-d8/s1600/TDPE2.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;a href="http://code.google.com/p/thundax-delphi-physics-engine/"&gt;TDPE&lt;/a&gt; is almost ready and it will not take long to release the first&amp;nbsp;stable&amp;nbsp;library!. I am eager to continue working on the project trying to sort out different physic&amp;nbsp;scenarios&amp;nbsp;&amp;nbsp;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 &lt;a href="http://en.wikipedia.org/wiki/Code_refactoring"&gt;refactor&lt;/a&gt; all the code to cope with a &lt;a href="http://en.wikipedia.org/wiki/Multilayered_architecture"&gt;layer architecture&lt;/a&gt;. 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.&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-ids4c--FLLw/TkLrAIQAEMI/AAAAAAAACwE/Eo8w1mkaAGQ/s1600/Dibujo.bmp" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="185" src="http://3.bp.blogspot.com/-ids4c--FLLw/TkLrAIQAEMI/AAAAAAAACwE/Eo8w1mkaAGQ/s320/Dibujo.bmp" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: justify;"&gt;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.&lt;/div&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;iframe allowfullscreen="" frameborder="0" height="349" src="http://www.youtube.com/embed/zhmr2xmExZ8?hl=en&amp;amp;fs=1" width="425"&gt;&lt;/iframe&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;&lt;i&gt;Enjoy the video!.&lt;/i&gt;&lt;/b&gt;&lt;br /&gt;&lt;br /&gt;Get the latest executable here: &lt;a href="http://www.4shared.com/file/bffzSTBq/ThundaxBallsDemo_v1504.html"&gt;ThundaxBallDemo v1.504&lt;/a&gt;.&lt;br /&gt;&lt;b&gt;Interaction:&lt;/b&gt;&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'d'&lt;/b&gt; will drop a box with a random color and a constant angular velocity&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'f'&lt;/b&gt; will drop a circle with a random color and a constant angular velocity&lt;br /&gt;&lt;span class="Apple-tab-span" style="white-space: pre;"&gt;	&lt;/span&gt;&lt;b&gt;'mouse interaction'&lt;/b&gt; mouse is able to grab items&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Related links:&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.edenwaith.com/products/pige/tutorials/collision.php"&gt;Collision Detection&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.essentialmath.com/CollisionDetection.pps"&gt;Collision Detection. Essential maths for programmers&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/06/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part VII&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/05/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part VI&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine_05.html"&gt;Building my own Delphi Physics Engine part V&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine_04.html"&gt;Building my own Delphi Physics Engine part IV&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2011/02/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part III&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/12/building-my-own-delphi-physics-engine_10.html"&gt;Building my own Delphi Physics Engine part II&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://thundaxsoftware.blogspot.com/2010/12/building-my-own-delphi-physics-engine.html"&gt;Building my own Delphi Physics Engine part I&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-4186519833830600707?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/JMXmCxRr_VA/building-my-own-delphi-physics-engine.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-XgLtjjG_2nI/TkLhUc0r8fI/AAAAAAAACwA/70vjSJhP-d8/s72-c/TDPE2.jpg" height="72" width="72" /><thr:total>6</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/08/building-my-own-delphi-physics-engine.html</feedburner:origLink></item><item><guid isPermaLink="false">tag:blogger.com,1999:blog-7022755517551007355.post-8450646618639274651</guid><pubDate>Sun, 10 Jul 2011 20:07:00 +0000</pubDate><atom:updated>2011-07-20T23:38:50.781+02:00</atom:updated><category domain="http://www.blogger.com/atom/ns#">Delphi</category><category domain="http://www.blogger.com/atom/ns#">Jenkins</category><category domain="http://www.blogger.com/atom/ns#">Delphi 2010</category><category domain="http://www.blogger.com/atom/ns#">Delphi XE</category><category domain="http://www.blogger.com/atom/ns#">Continuous Integration</category><title>Continuous Integration for your Delphi projects using Jenkins CI</title><description>&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-YZUFnYXo9gQ/Thn4ktXyuMI/AAAAAAAACvI/vjHFnmFt4ag/s1600/jenkins_logo.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="63" src="http://1.bp.blogspot.com/-YZUFnYXo9gQ/Thn4ktXyuMI/AAAAAAAACvI/vjHFnmFt4ag/s200/jenkins_logo.png" width="200" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Going on with the utilization of &lt;a href="http://thundaxsoftware.blogspot.com/2011/07/delphi-msbuild.html"&gt;Msbuild&lt;/a&gt;, I'm putting forward this post using &lt;a href="http://en.wikipedia.org/wiki/Jenkins_(software)"&gt;Jenkins CI&lt;/a&gt; (&lt;a href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous Integration&lt;/a&gt;) &lt;i&gt;previously known as &lt;a href="http://en.wikipedia.org/wiki/Hudson_(software)"&gt;Hudson&lt;/a&gt;&lt;/i&gt;, for your&amp;nbsp;Delphi&amp;nbsp;projects under Windows Vista.&amp;nbsp;&lt;i&gt;&lt;span class="Apple-style-span" style="color: #444444;"&gt;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.&lt;/span&gt;&lt;/i&gt;&amp;nbsp;(Source: &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Meet+Jenkins"&gt;What is Jenkins?&lt;/a&gt;). With these simple steps I'll lead you&amp;nbsp;throughout the whole installation and configuration of your first &lt;b&gt;Delphi built project&lt;/b&gt; using &lt;b&gt;Jenkins CI&lt;/b&gt; and &lt;b&gt;MsBuild&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;1 . Download the latest version of Jenkins CI.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Use the following &lt;a href="http://mirrors.jenkins-ci.org/windows/latest"&gt;link&lt;/a&gt; to download the latest &lt;b&gt;windows installer&lt;/b&gt;, in my case &lt;b&gt;v1.419&lt;/b&gt;. The default installation path is&amp;nbsp;&lt;b&gt;C:\Program Files\Jenkins&lt;/b&gt; and there you'll find the service wrapper &lt;b&gt;jenkins.exe&lt;/b&gt; and the&amp;nbsp;Java&amp;nbsp;web archive (&lt;b&gt;jenkins.war&lt;/b&gt;) that is very useful to start the Jenkins if you have difficulties&amp;nbsp;installing&amp;nbsp;it with a container. It's very easy to run&amp;nbsp;Jenkins&amp;nbsp;by itself using the command: &lt;b&gt;java -jar jenkins.war&lt;/b&gt; (which uses &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Winstone"&gt;Winstone&lt;/a&gt; as a container).&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-1Pd8jGf86jA/Thn8toD_Q4I/AAAAAAAACvM/fHG4ZB66NkE/s1600/jen3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="246" src="http://3.bp.blogspot.com/-1Pd8jGf86jA/Thn8toD_Q4I/AAAAAAAACvM/fHG4ZB66NkE/s320/jen3.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;2. Setting up environment variables.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;To make sure that Jenkins runs perfectly, we need to set up the &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Administering+Jenkins"&gt;JENKINS_HOME&lt;/a&gt; environment variable:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-gWIXuYzz_jU/Thn9ZMv6sNI/AAAAAAAACvQ/AY4Xkw6rGGU/s1600/jen4.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="27" src="http://3.bp.blogspot.com/-gWIXuYzz_jU/Thn9ZMv6sNI/AAAAAAAACvQ/AY4Xkw6rGGU/s320/jen4.jpg" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;3. Adding administrator privileges to Jenkins windows service.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;We need to be sure that the service has enough permissions to be running. To do this, go to console and type down&amp;nbsp;&lt;b&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;&lt;b&gt;"&lt;/b&gt;&lt;/span&gt;services.msc"&lt;/b&gt;. Then look for &lt;b&gt;Jenkins&lt;/b&gt; service and add the log on information using an administrator account.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-dmGZ897VaEM/Thn_UsXk53I/AAAAAAAACvU/Wr8v2ZxvDUc/s1600/jen5.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="183" src="http://3.bp.blogspot.com/-dmGZ897VaEM/Thn_UsXk53I/AAAAAAAACvU/Wr8v2ZxvDUc/s400/jen5.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;i&gt;I had a lot of troubles trying to execute MSBuild from Jenkins until I realised that the service didn't have enough permissions.&lt;/i&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;4. Installing Jenkins CI plug-ins.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Once&amp;nbsp;everything&amp;nbsp;is done, we can go on with Jenkins and open a web explorer and type &lt;b&gt;&lt;a href="http://localhost:8080/"&gt;http://localhost:8080&lt;/a&gt;&lt;/b&gt;. Now we need to add the following&amp;nbsp;plug-ins:&amp;nbsp;&lt;b&gt;&lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/MSBuild+Plugin"&gt;Jenkins MSBuild Plugin&lt;/a&gt;&lt;/b&gt; and&amp;nbsp;&lt;b&gt;&lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Setenv+Plugin"&gt;Hudson Setenv Plugin&lt;/a&gt;&lt;/b&gt;. To install them go to "&lt;b&gt;Manage Jenkins&lt;/b&gt;"-&amp;gt; "&lt;a href="http://localhost:8080/pluginManager/"&gt;Manage Pluggins&lt;/a&gt;" -&amp;gt; &lt;a href="http://localhost:8080/pluginManager/available"&gt;Available&lt;/a&gt; and look for them. Then, save the changes at the end of the page and &lt;a href="https://wiki.jenkins-ci.org/display/JENKINS/Administering+Jenkins"&gt;reload&lt;/a&gt; Jenkins.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Once installed, you'll find them under the &lt;b&gt;Installed section&lt;/b&gt;:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-hvHZMn3_ei8/ThoBQBuGejI/AAAAAAAACvY/eod2OEisivE/s1600/jen6.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="145" src="http://1.bp.blogspot.com/-hvHZMn3_ei8/ThoBQBuGejI/AAAAAAAACvY/eod2OEisivE/s400/jen6.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;5. Configure MSBuild.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now the&amp;nbsp;plug-in is ready, and we need to&amp;nbsp;supply the path of our MSBuild. Go to "Manage Jenkins" -&amp;gt; "&lt;a href="http://localhost:8080/configure"&gt;Configure Jenkins&lt;/a&gt;" and add the Msbuild information in the MSbuild section:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-dw736B6VA3E/ThoCE2OtSGI/AAAAAAAACvc/AiVjviYFSSM/s1600/jen7.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="133" src="http://3.bp.blogspot.com/-dw736B6VA3E/ThoCE2OtSGI/AAAAAAAACvc/AiVjviYFSSM/s400/jen7.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;6. Adding environment variables.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;As we are trying to build Delphi projects we need to set up Jenkins with the same environment variables included in &lt;b&gt;rsvars.bat&lt;/b&gt; batch file.&amp;nbsp;Go to "Manage Jenkins" -&amp;gt; "&lt;a href="http://localhost:8080/configure"&gt;Configure Jenkins&lt;/a&gt;" and add the following environment variables according to your Delphi version:&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9VY_8G8G2KE/ThoC18QegrI/AAAAAAAACvg/z2n6Bx_NCZg/s1600/jen8.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="242" src="http://4.bp.blogspot.com/-9VY_8G8G2KE/ThoC18QegrI/AAAAAAAACvg/z2n6Bx_NCZg/s400/jen8.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;7. Setting up your project.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Start a new job with your project description and choose the "&lt;b&gt;Build a free-style software project&lt;/b&gt;" type. And add the following MSbuild information to build your project (&lt;b&gt;dproj&lt;/b&gt; file):&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-TkIImoT-O9I/ThoEF_PupsI/AAAAAAAACvk/aHqw93Zt7jo/s1600/jen9.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="141" src="http://4.bp.blogspot.com/-TkIImoT-O9I/ThoEF_PupsI/AAAAAAAACvk/aHqw93Zt7jo/s400/jen9.jpg" width="400" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;8. Build your Project.&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;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.&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-2bi4J1IVyyo/ThoEtwno8VI/AAAAAAAACvo/u-1lBgSqukA/s1600/jen10.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320" src="http://2.bp.blogspot.com/-2bi4J1IVyyo/ThoEtwno8VI/AAAAAAAACvo/u-1lBgSqukA/s320/jen10.jpg" width="286" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;Now, you can add your Delphi projects and improve the &lt;b&gt;quality of your software&lt;/b&gt;.&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;b&gt;Related Links:&lt;/b&gt;&lt;/div&gt;&lt;div style="text-align: justify;"&gt;&lt;/div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://blog.mgm-tp.com/2010/04/hudson-continuous-integration-part1/"&gt;Hudson continuous integration&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://wiki.hudson-ci.org/display/HUDSON/Installing+Hudson+as+a+Windows+service"&gt;Installing Hudson as a service&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://christerblog.wordpress.com/2010/04/25/using-hudson-to-build-delphi-projects/"&gt;Using hudson to build delphi projects&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.nickhodges.com/post/Getting-Hudson-set-up-to-compile-Delphi-Projects.aspx"&gt;Getting hudson set up to compile delphi projects&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://unxutils.sourceforge.net/"&gt;Unxutils&lt;/a&gt;.&lt;/li&gt;&lt;/ul&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7022755517551007355-8450646618639274651?l=thundaxsoftware.blogspot.com' alt='' /&gt;&lt;/div&gt;</description><link>http://feedproxy.google.com/~r/RandomThoughtsOnCodingTechnology/~3/qgXJTMvZyG4/continuous-integration-for-your-delphi.html</link><author>noreply@blogger.com (Jordi Corbilla)</author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://1.bp.blogspot.com/-YZUFnYXo9gQ/Thn4ktXyuMI/AAAAAAAACvI/vjHFnmFt4ag/s72-c/jenkins_logo.png" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://thundaxsoftware.blogspot.com/2011/07/continuous-integration-for-your-delphi.html</feedburner:origLink></item></channel></rss>

