<?xml version="1.0" encoding="UTF-8" ?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en-US"><title type="html">Kok Kiet's Blog</title><subtitle type="html">About Programming, Visual FoxPro, .NET.</subtitle><id>http://weblogs.foxite.com/kkchan/atom.aspx</id><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/default.aspx" /><link rel="self" type="application/atom+xml" href="http://weblogs.foxite.com/kkchan/atom.aspx" /><generator uri="http://communityserver.org" version="2.0.60217.2664">Community Server</generator><updated>2007-08-28T16:54:01Z</updated><entry><title>ThemedButton Prototype</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/07/03/6367.aspx" /><link rel="enclosure" type="application/zip" length="3757" href="http://weblogs.foxite.com/kkchan/attachment/6367.ashx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/07/03/6367.aspx</id><published>2008-07-03T08:19:00Z</published><updated>2008-07-03T08:19:00Z</updated><content type="html">&lt;p&gt;I just created themedbutton, by referring code of ThemedControls project in VFPX. It is quite easy to follow.&lt;/p&gt; &lt;table cellspacing="0" cellpadding="2"&gt;  &lt;tr&gt; &lt;td&gt; &lt;div class="wlWriterSmartContent" id="scid:6960CE03-38FC-44df-87D4-FA4540212B06:9306b5c3-a500-4d66-94af-3119ebee49f7"&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/6363/original.aspx" alt="" /&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt; &lt;div class="wlWriterSmartContent" id="scid:6960CE03-38FC-44df-87D4-FA4540212B06:290dd968-afe5-4754-86ab-81fe22422247"&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/6364/original.aspx" alt="" /&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt;&lt;img src="/photos/kkchan/images/6366/original.aspx"&gt;&lt;/td&gt;&lt;/tr&gt; &lt;tr&gt; &lt;td&gt; &lt;p align="center"&gt;Normal&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Hover&lt;/p&gt;&lt;/td&gt; &lt;td&gt; &lt;p align="center"&gt;Focused&lt;/p&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;However, it is not completed. There are some limitation/enhancements required:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Anchoring is not yet supported. (VFP doesn't anchor internal controls if parent container is adjusted during design time)  &lt;li&gt;Only Click event is supported.  &lt;li&gt;It is based on control base class. Native command button property such as picture margin, spacing and position is not yet implemented.  &lt;li&gt;Only picture with size 16X16 pixels is supported. &lt;li&gt;That are "ugly" parts at four corners.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:2bf3126b-ea5d-4d5f-8ed6-7aed1d56d679"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/VFPX" rel="tag"&gt;VFPX&lt;/a&gt;, &lt;a href="http://technorati.com/tags/GDI+" rel="tag"&gt;GDI+&lt;/a&gt;, &lt;a href="http://technorati.com/tags/ThemedControls" rel="tag"&gt;ThemedControls&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6367" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Resize image in .NET</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/29/6349.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/29/6349.aspx</id><published>2008-06-29T09:48:58Z</published><updated>2008-06-29T09:48:58Z</updated><content type="html">&lt;p&gt;I need to resize user provided image using picturebox with size 48X48 pixels. I "googled" and found the following sample code:&lt;/p&gt; &lt;p&gt;&lt;u&gt;&lt;strong&gt;Using DrawImage&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;&lt;pre&gt;FileStream loFileStream = &lt;span&gt;new&lt;/span&gt; FileStream(@"&lt;span&gt;.\RefreshCL.png&lt;/span&gt;", FileMode.Open, FileAccess.Read);
Image loOriginalImage = Bitmap.FromStream(loFileStream);           
Bitmap loBitmap = &lt;span&gt;new&lt;/span&gt; Bitmap(48, 48);

&lt;span&gt;using&lt;/span&gt; (Graphics g = Graphics.FromImage((Image)loBitmap))
{
    g.DrawImage(loOriginalImage, 0,0, 48,48);
    pictureEdit1.Image = loBitmap;
}&lt;/pre&gt;
&lt;div class="wlWriterSmartContent" id="scid:6960CE03-38FC-44df-87D4-FA4540212B06:8c4c92d6-61c7-4de8-90a4-05e0faca9f9e"&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/6348/original.aspx" alt="" /&gt;&lt;/div&gt;As we can see the result as above, it is not good. The image is broken 
&lt;p&gt;&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I "googled" again and get this code&lt;/p&gt;
&lt;p&gt;&lt;u&gt;&lt;strong&gt;Using GetThumbnailImage&lt;/strong&gt;&lt;/u&gt;&lt;/p&gt;&lt;pre&gt;FileStream loFileStream = &lt;span&gt;new&lt;/span&gt; FileStream(@"&lt;span&gt;.\RefreshCL.png&lt;/span&gt;", FileMode.Open, FileAccess.Read);
            
Image loOriginalImage = Bitmap.FromStream(loFileStream);

loOriginalImage = loOriginalImage.GetThumbnailImage(48, 48, &lt;span&gt;new&lt;/span&gt; Image.GetThumbnailImageAbort(ThumbnailCallback), IntPtr.Zero);

pictureEdit1.Image = loOriginalImage;

&lt;span&gt;public&lt;/span&gt; &lt;span&gt;bool&lt;/span&gt; ThumbnailCallback()
{
    &lt;span&gt;return&lt;/span&gt; &lt;span&gt;true&lt;/span&gt;;
}&lt;/pre&gt;&lt;br&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/6347/original.aspx"&gt; As this is much better.&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6349" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Sync Provider for SQL Express</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/25/6334.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/25/6334.aspx</id><published>2008-06-25T03:00:34Z</published><updated>2008-06-25T03:00:34Z</updated><content type="html">&lt;p&gt;Microsoft has released Sync Framework couple months ago, enable offline data collection applications to synchronize local data back to another/centralized database. &lt;/p&gt; &lt;p&gt;Eventually, this feature is already available in SQL Server (Data Replication) since long time ago. However, it is not so easy for developers as it required certain level of knowledge of SQL Server. Deployment is not so straight forward as well. At least, it is not by "Developer" way. Sync framework introduced is something that really helps in my opinion.&lt;/p&gt; &lt;p&gt;SQL Server Express is a lightweight edition of SQL Server. Most importantly, it is free! Therefore, It is always the best choose as database server used at branches. Then, data would be sync back to main database intervally.&lt;/p&gt; &lt;p&gt;Nevertheless, Sync framework is more focus on SQL Server CE, mobile devices. More and more providers are released for these few months but not yet any provider for SQL Server Express. Sync provider for SQL Express has been requested at least for six months. And finally, Microsoft has released Sync &lt;a href="https://code.msdn.microsoft.com/Release/ProjectReleases.aspx?ProjectName=sync&amp;amp;ReleaseId=1200" target="_blank"&gt;Provider for SQL Express as sample&lt;/a&gt; at Code Gallery. &lt;em&gt;&lt;strong&gt;In the future Microsoft certainly plan of including a fully supported version of a SQL Express client provider within a future release of Sync Services for ADO.NET.&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Source: &lt;a title="Sample - SQL Express Client Synchronization using Sync Services for ADO.NET" href="http://blogs.msdn.com/sync/archive/2008/06/24/sample-sql-express-client-synchronization-using-sync-services-for-ado-net.aspx"&gt;Sample - SQL Express Client Synchronization using Sync Services for ADO.NET&lt;/a&gt;&lt;/p&gt; &lt;p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:20e334de-1b41-4cdb-a24e-858fa943287c"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Sync%20Services%20for%20ADO.NET" rel="tag"&gt;Sync Services for ADO.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tags/SQL%20Server" rel="tag"&gt;SQL Server&lt;/a&gt;&lt;/div&gt;&lt;/p&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6334" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>FoxCharts is Rock!</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/24/6316.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/24/6316.aspx</id><published>2008-06-24T06:32:22Z</published><updated>2008-06-24T06:32:22Z</updated><content type="html">&lt;p&gt;Well, it might not any latest news. But it is really rock!&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;font color="#ff0000"&gt;(Updated) &lt;/font&gt;&lt;/em&gt;Source: &lt;/p&gt; &lt;p&gt;&lt;a href="http://weblogs.foxite.com/vfpimaging/archive/2008/05/21/6080.aspx"&gt;http://weblogs.foxite.com/vfpimaging/archive/2008/05/21/6080.aspx&lt;/a&gt;&lt;br&gt;&lt;a href="http://weblogs.foxite.com/vfpimaging/archive/2008/04/24/6040.aspx"&gt;http://weblogs.foxite.com/vfpimaging/archive/2008/04/24/6040.aspx&lt;/a&gt;&lt;br&gt;&lt;a href="http://weblogs.foxite.com/vfpimaging/archive/2008/04/04/5919.aspx"&gt;http://weblogs.foxite.com/vfpimaging/archive/2008/04/04/5919.aspx&lt;/a&gt; &lt;p&gt;VFPX: &lt;a title="http://www.codeplex.com/VFPX/Wiki/View.aspx?title=FoxCharts&amp;amp;referringTitle=Home" href="http://www.codeplex.com/VFPX/Wiki/View.aspx?title=FoxCharts&amp;amp;referringTitle=Home"&gt;http://www.codeplex.com/VFPX/Wiki/View.aspx?title=FoxCharts&amp;amp;referringTitle=Home&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt;&lt;img src="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=VFPX&amp;amp;DownloadId=33098"&gt; &lt;/p&gt; &lt;p&gt;&lt;img src="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=VFPX&amp;amp;DownloadId=33094"&gt; &lt;/p&gt; &lt;p&gt;&lt;img src="http://www.codeplex.com/Project/Download/FileDownload.aspx?ProjectName=VFPX&amp;amp;DownloadId=33101"&gt; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:8d4eaf50-b06a-452b-9138-0cf443784da6"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/VFP" rel="tag"&gt;VFP&lt;/a&gt;, &lt;a href="http://technorati.com/tags/VFPX" rel="tag"&gt;VFPX&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxCharts" rel="tag"&gt;FoxCharts&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6316" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>IIS Unexpected error 0x8ffe2740 occurred</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/24/6315.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/24/6315.aspx</id><published>2008-06-24T06:24:00Z</published><updated>2008-06-24T06:24:00Z</updated><content type="html">&lt;p&gt;That day I hit error as above when I want to access my localhost IIS. Luckily I could get it fixed very soon. It is caused by Skype.&lt;/p&gt; &lt;p&gt;&lt;a title="http://blog.jtbworld.com/2007/01/skype-behind-iis-error.html" href="http://blog.jtbworld.com/2007/01/skype-behind-iis-error.html"&gt;http://blog.jtbworld.com/2007/01/skype-behind-iis-error.html&lt;/a&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:0e2cb8e9-8e7e-4cf5-aab9-46d5b436a5df"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/IIS" rel="tag"&gt;IIS&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Skype" rel="tag"&gt;Skype&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6315" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Add DataEnvironment class to form</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/24/6314.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/24/6314.aspx</id><published>2008-06-24T06:08:25Z</published><updated>2008-06-24T06:08:25Z</updated><content type="html">&lt;p&gt;DataEnvironment class has been introduced since VFP8. We could get more info from VFP help.&lt;/p&gt; &lt;p&gt;mk:@MSITStore:C:\Program%20Files\Microsoft%20Visual%20FoxPro%208\dv_foxhelp.chm::/html/ctlDataEnvironment_Object.htm&lt;/p&gt; &lt;p&gt;Last few days, we tried to migrate some of the form's DataEnvironment to class for customization purpose. we then dynamically assign DEClass and DEClassLibrary property at form to have dynamic DataEnvironment.&lt;/p&gt; &lt;p&gt;However, we just hit error complaint that object "DataEnvironment" is not found. After some troubleshooting, we found that our application framework (VPME8) requires to access DE property values of DataEnvironment during form initialization. No matter what, the framework require DE's name to be DataEnvironment. In fact, DE's naming convention is DE's name + nth.&lt;/p&gt; &lt;p&gt;We found two workarounds:&lt;/p&gt; &lt;p&gt;&lt;u&gt;Using AddObject()&lt;/u&gt;&lt;/p&gt;&lt;pre&gt;&lt;span&gt;SET&lt;/span&gt; &lt;span&gt;CLASSLIB&lt;/span&gt; &lt;span&gt;TO&lt;/span&gt; &amp;lt;DELib&amp;gt; &lt;span&gt;ADDITIVE&lt;/span&gt;

&lt;span&gt;THISFORM&lt;/span&gt;.&lt;span&gt;RemoveObject&lt;/span&gt;("&lt;span&gt;DataEnvironment&lt;/span&gt;")
&lt;span&gt;THISFORM&lt;/span&gt;.&lt;span&gt;AddObject&lt;/span&gt;("&lt;span&gt;DataEnvironment&lt;/span&gt;", "&lt;span&gt;&amp;lt;DE&amp;gt;&lt;/span&gt;")&lt;/pre&gt;
&lt;p&gt;&lt;u&gt;Using Property&lt;/u&gt;&lt;/p&gt;&lt;pre&gt;&lt;span&gt;THISFORM&lt;/span&gt;.&lt;span&gt;RemoveObject&lt;/span&gt;("&lt;span&gt;DataEnvironment&lt;/span&gt;")

loDE = &lt;span&gt;NEWOBJECT&lt;/span&gt;("&lt;span&gt;&amp;lt;DE&amp;gt;&lt;/span&gt;", "&lt;span&gt;&amp;lt;DELib&amp;gt;&lt;/span&gt;")
&lt;span&gt;THISFORM&lt;/span&gt;.&lt;span&gt;AddProperty&lt;/span&gt;("&lt;span&gt;DataEnvironment&lt;/span&gt;", loDE)&lt;/pre&gt;&lt;br&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:822567a7-cc92-4456-8d37-9ada8ed41b40"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/VFP" rel="tag"&gt;VFP&lt;/a&gt;, &lt;a href="http://technorati.com/tags/DataEnvironment" rel="tag"&gt;DataEnvironment&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6314" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Source code analysis tool for C#</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/23/6313.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/23/6313.aspx</id><published>2008-06-23T09:34:42Z</published><updated>2008-06-23T09:34:42Z</updated><content type="html">&lt;p&gt;My team is moving to a new web product which would be developed in .NET C#. We are currently 9 developers and going to grown to 12. This is not the first .NET application. In fact, there are couple of them already. One of the problems we are having is not strong in SOP (Standard Operation Procedure). Very simple guideline such coding standard.&lt;/p&gt; &lt;p&gt;Even though we have coding standard documentation downloaded online, most of them are not followed. &lt;/p&gt; &lt;ul&gt; &lt;li&gt;The document is too long to read.&lt;/li&gt; &lt;li&gt;Developers might confuse with so many guidelines.&lt;/li&gt; &lt;li&gt;Manual code review required even for simple thing such as naming convention. Very time consumed.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;Recently, I am researching on any tool that able to help us to:-&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Detect any violations.&lt;/li&gt; &lt;li&gt;Suggest and auto correct violations.&lt;/li&gt; &lt;li&gt;Ability to be integrated with any CI (Continuous Integration) tool.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;And I found two tools as below:-&lt;/p&gt; &lt;ol&gt; &lt;li&gt;StyleCop&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Enforce a common set of best practices for layout, readability, maintainability, and documentation of C# source code.&lt;/li&gt; &lt;li&gt;Has been used for many years now internally at Microsoft.&lt;/li&gt; &lt;li&gt;Analysis source code instead of compiled binary.&lt;/li&gt; &lt;li&gt;It is &lt;strong&gt;free&lt;/strong&gt;&lt;/li&gt; &lt;li&gt;&lt;em&gt;It contains 200 best practice rules covered the following:-&lt;/em&gt;&lt;/li&gt; &lt;ul&gt; &lt;li&gt;&lt;em&gt;Layout of elements, statements, expressions, and query clauses &lt;/em&gt; &lt;li&gt;&lt;em&gt;Placement of curly brackets, parenthesis, square brackets, etc &lt;/em&gt; &lt;li&gt;&lt;em&gt;Spacing around keywords and operator symbols &lt;/em&gt; &lt;li&gt;&lt;em&gt;Line spacing &lt;/em&gt; &lt;li&gt;&lt;em&gt;Placement of method parameters within method declarations or method calls &lt;/em&gt; &lt;li&gt;&lt;em&gt;Standard ordering of elements within a class &lt;/em&gt; &lt;li&gt;&lt;em&gt;Formatting of documentation within element headers and file headers &lt;/em&gt; &lt;li&gt;&lt;em&gt;Naming of elements, fields and variables &lt;/em&gt; &lt;li&gt;&lt;em&gt;Use of the built-in types &lt;/em&gt; &lt;li&gt;&lt;em&gt;Use of access modifiers &lt;/em&gt; &lt;li&gt;&lt;em&gt;Allowed contents of files &lt;/em&gt; &lt;li&gt;&lt;em&gt;Debugging text&lt;/em&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Integrated with Visual Studio IDE, and also MSBuild-based command line builds.&lt;/li&gt; &lt;li&gt;Ability to analysis code per file basis.&lt;/li&gt; &lt;li&gt;FxCop vs StyleCop&lt;/li&gt; &lt;ul&gt; &lt;li&gt;StyleCop - focuses on layout, readability and documentation&lt;/li&gt; &lt;li&gt;FxCop - focuses on design of the code&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Limitations&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Does not allow its rules to be very configurable.&lt;/li&gt; &lt;li&gt;Does not provides auto correction actions. Manual correction is required.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Downloadable: &lt;a title="http://code.msdn.microsoft.com/sourceanalysis/Release/ProjectReleases.aspx?ReleaseId=1047" href="http://code.msdn.microsoft.com/sourceanalysis/Release/ProjectReleases.aspx?ReleaseId=1047"&gt;http://code.msdn.microsoft.com/sourceanalysis/Release/ProjectReleases.aspx?ReleaseId=1047&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Blog: &lt;a title="http://blogs.msdn.com/sourceanalysis/" href="http://blogs.msdn.com/sourceanalysis/"&gt;http://blogs.msdn.com/sourceanalysis/&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;CodeIt.Right&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Combines static code analysis and automatic refactoring to best practices in one application. But there is more - CodeIt.Right will &lt;i&gt;&lt;strong&gt;automatically&lt;/strong&gt;&lt;/i&gt; correct code errors and violations (e.g. naming conventions, incorrectly implemented coding patterns, etc)!&lt;/li&gt; &lt;li&gt;Comprehensive rule set based on &lt;b&gt;Microsoft .NET Guidelines&lt;/b&gt;, &lt;b&gt;Framework Design Guidelines&lt;/b&gt; and &lt;b&gt;best practices&lt;/b&gt; - right out of the box&lt;/li&gt; &lt;li&gt;Integrated with Visual Studio IDE, and also MSBuild-based command line builds.&lt;/li&gt; &lt;li&gt;Ability configure rules and create custom rules based on existing base rule.&lt;/li&gt; &lt;li&gt;&lt;strong&gt;SDK&lt;/strong&gt; available to allow creating of new complex custom rules.&lt;/li&gt; &lt;li&gt;It contains 100+ best practice rules.&lt;/li&gt; &lt;li&gt;Rule Library &lt;strong&gt;Auto-update&lt;/strong&gt;.&lt;/li&gt; &lt;li&gt;Multiple profiles - group rules the way you want and quickly switch between profiles.&lt;/li&gt; &lt;li&gt;Safely &lt;b&gt;Undo/Redo&lt;/b&gt; the changes - multi-file Visual Studio undo/redo.&lt;/li&gt; &lt;li&gt;Ability to analysis code in solution or per project basis.&lt;/li&gt; &lt;li&gt;Contains two editions&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Standard Edition - Rules authoring, machine basis.&lt;/li&gt; &lt;li&gt;Enterprise Edition - Standard creation is separated into a separate module, allowing a Team Lead or an Architect create the team guidelines and then enforce them to the rest of the team. Also it comes with two modules included into the package - the Analysis Module and the Team Configuration Module. The latter besides tweaking the guidelines to the team standards is also responsible for publishing and pushing the end result to the developer workstations. (is currently in the works and will be out end of the summer 2008)&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Commercial: &lt;a title="http://submain.com/order.aspx" href="http://submain.com/order.aspx"&gt;http://submain.com/order.aspx&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Trial version available: &lt;a title="http://submain.com/?nav=download&amp;amp;" href="http://submain.com/?nav=download&amp;amp;"&gt;http://submain.com/?nav=download&amp;amp;&lt;/a&gt; (30 days evaluation)&lt;/li&gt; &lt;li&gt;Blog: &lt;a title="http://community.submain.com/blogs/default.aspx" href="http://community.submain.com/blogs/default.aspx"&gt;http://community.submain.com/blogs/default.aspx&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Tutorial available: &lt;a title="http://community.submain.com/content/Tutorials.aspx" href="http://community.submain.com/content/Tutorials.aspx"&gt;http://community.submain.com/content/Tutorials.aspx&lt;/a&gt;&lt;/li&gt; &lt;li&gt;More details: &lt;a title="http://submain.com/?nav=products.cir" href="http://submain.com/?nav=products.cir"&gt;http://submain.com/?nav=products.cir&lt;/a&gt;&lt;/li&gt; &lt;li&gt;Limitations&lt;/li&gt; &lt;ul&gt; &lt;li&gt;Rule list are not "complete" enough, but many rules to be released every week.&lt;/li&gt;&lt;/ul&gt; &lt;li&gt;Time saving to standardize existing source code since auto correction feature built-in.&lt;/li&gt;&lt;/ul&gt;&lt;/ol&gt; &lt;p&gt;Personally, I feel that StyleCop is very good because it contains quite complete rule list. It is suitable for whom:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Do not mind to correct violations manually. &lt;/li&gt; &lt;li&gt;Apply on new project only since any corrections could be done immediately without long violation list prompted. Apply to existing project would require more resources to correct violations.&lt;/li&gt; &lt;li&gt;Willing to follow Microsoft internal coding standard.&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;On the other hand, CodeIt.Right would be suitable for whom:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Would like to apply coding standard to existing "legacy" project. Auto correction would save a lot of time.&lt;/li&gt; &lt;li&gt;Do not wish to follow Microsoft internal coding standard exactly.&lt;/li&gt; &lt;li&gt;Would like to have additional rules or develop own custom rules.&lt;/li&gt; &lt;li&gt;Do not want to correct violations manually.&lt;/li&gt; &lt;li&gt;Would like to automate violations correction process during CI (Continuous Integration).&lt;/li&gt;&lt;/ul&gt; &lt;p&gt;No matter which tool to be used, it would really help because no manual code review is required.&lt;/p&gt; &lt;p&gt;Happy coding!&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:259b8fa8-be76-4c90-a1d4-f21219a95f8e"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/.NET" rel="tag"&gt;.NET&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Continuous%20Integration" rel="tag"&gt;Continuous Integration&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Coding%20Guideline" rel="tag"&gt;Coding Guideline&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6313" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Enumerate all resource name from external assembly</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/06/22/6307.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/06/22/6307.aspx</id><published>2008-06-22T11:31:00Z</published><updated>2008-06-22T11:31:00Z</updated><content type="html">&lt;p&gt;Sometime we might want to re-use resources such as image that already exist in external assembly. We need to know what resource exist.&lt;/p&gt; &lt;p&gt;Here is sample code that iterate all DLL files and display its resource name.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;pre&gt;&lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;string&lt;/span&gt; filename &lt;span&gt;in&lt;/span&gt; System.IO.Directory.GetFiles(@"&lt;span&gt;C:\Documents and Settings\chankk\My Documents\Visual Studio 2008\Projects\ClassLibrary1\bin\debug&lt;/span&gt;", "&lt;span&gt;*.dll&lt;/span&gt;"))
{
    Assembly loAss = Assembly.LoadFrom(filename);

    &lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;string&lt;/span&gt; resname &lt;span&gt;in&lt;/span&gt; loAss.GetManifestResourceNames())
    {
        &lt;span&gt;if&lt;/span&gt; (resname.EndsWith("&lt;span&gt;.resources&lt;/span&gt;"))
        {
            Stream stream = loAss.GetManifestResourceStream(resname);

            ResourceReader rreader = &lt;span&gt;new&lt;/span&gt; ResourceReader(stream);

            IDictionaryEnumerator ie = rreader.GetEnumerator();

            &lt;span&gt;while&lt;/span&gt; (ie.MoveNext())
            {
                textBox1.Text += ie.Key + Environment.NewLine;
            }
        }
    }
}&lt;/pre&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=6307" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Run application and wait (RunAs)</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/03/07/5688.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/03/07/5688.aspx</id><published>2008-03-07T11:41:40Z</published><updated>2008-03-07T11:41:40Z</updated><content type="html">&lt;p&gt;I am changing my application to be Vista compatible. I need to run an external EXE and wait for until it terminate. Beside, I also need to run this EXE with Admin privilege under certain condition.&lt;/p&gt; &lt;p&gt;To run external application and wait till it terminate, I found the code as below.&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;loShell = &lt;span&gt;CREATEOBJECT&lt;/span&gt;("&lt;span&gt;WScript.Shell&lt;/span&gt;")
loShell.&lt;span&gt;Run&lt;/span&gt;("&lt;span&gt;C:\MyApp\MyApp.exe&lt;/span&gt;", 1, 1)&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;However, it doesn't support elevation.&lt;/p&gt;
&lt;p&gt;To run application via elevation process, I can&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span&gt;DECLARE&lt;/span&gt; &lt;span&gt;INTEGER&lt;/span&gt; ShellExecute &lt;span&gt;IN&lt;/span&gt; "&lt;span&gt;Shell32.dll&lt;/span&gt;" ;
	&lt;span&gt;INTEGER&lt;/span&gt; &lt;span&gt;hwnd&lt;/span&gt;, &lt;span&gt;STRING&lt;/span&gt; lpVerb, &lt;span&gt;STRING&lt;/span&gt; lpFile, &lt;span&gt;STRING&lt;/span&gt; lpParameters, ;
	&lt;span&gt;STRING&lt;/span&gt; lpDirectory, &lt;span&gt;LONG&lt;/span&gt; nShowCmd

ShellExecute(0, "&lt;span&gt;runas&lt;/span&gt;", "&lt;span&gt;C:\MyApp\MyApp.exe&lt;/span&gt;", "&lt;span&gt;&lt;/span&gt;", "&lt;span&gt;&lt;/span&gt;", 1)&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;Unfortunately, ShellExecute() doesn't wait but return control back to calling program immediately.&lt;/p&gt;
&lt;p&gt;In order to have both features, I found ShellExecute&lt;strong&gt;&lt;em&gt;EX&lt;/em&gt;&lt;/strong&gt; ...&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;span&gt;DECLARE&lt;/span&gt; &lt;span&gt;LONG&lt;/span&gt; ShellExecuteEx &lt;span&gt;IN&lt;/span&gt; &lt;span&gt;Shell&lt;/span&gt;32 &lt;span&gt;STRING&lt;/span&gt; @SHELLEXECUTEINFO

&lt;span&gt;DECLARE&lt;/span&gt; &lt;span&gt;INTEGER&lt;/span&gt; WaitForSingleObject &lt;span&gt;IN&lt;/span&gt; kernel32;
	&lt;span&gt;INTEGER&lt;/span&gt; hHandle, &lt;span&gt;INTEGER&lt;/span&gt; dwMilliseconds

&lt;span&gt;LOCAL&lt;/span&gt; loSHELLEXECUTEINFO &lt;span&gt;AS&lt;/span&gt; SHELLEXECUTEINFO &lt;span&gt;OF&lt;/span&gt; SHELLEXECUTEINFO.prg, ;
		lcStructure &lt;span&gt;AS&lt;/span&gt; &lt;span&gt;String&lt;/span&gt;

loSHELLEXECUTEINFO = &lt;span&gt;NEWOBJECT&lt;/span&gt;("&lt;span&gt;SHELLEXECUTEINFO&lt;/span&gt;", "&lt;span&gt;SHELLEXECUTEINFO.prg&lt;/span&gt;")
loSHELLEXECUTEINFO.fld("&lt;span&gt;lpVerb&lt;/span&gt;") = "&lt;span&gt;runas&lt;/span&gt;" + &lt;span&gt;CHR&lt;/span&gt;(0)
loSHELLEXECUTEINFO.fld("&lt;span&gt;lpFile&lt;/span&gt;") = "&lt;span&gt;C:\MyApp\MyApp.exe&lt;/span&gt;" + &lt;span&gt;CHR&lt;/span&gt;(0)
loSHELLEXECUTEINFO.fld("&lt;span&gt;nShow&lt;/span&gt;") = 1
loSHELLEXECUTEINFO.fld("&lt;span&gt;lpParameters&lt;/span&gt;") = &lt;span&gt;CHR&lt;/span&gt;(0)

&lt;span&gt;**********************************************&lt;/span&gt;
&lt;span&gt;* Required in order to get process id returned&lt;/span&gt;
&lt;span&gt;**********************************************&lt;/span&gt;
loSHELLEXECUTEINFO.fld("&lt;span&gt;fMask&lt;/span&gt;") = SEE_MASK_NOCLOSEPROCESS

lcStructure = loSHELLEXECUTEINFO.&lt;span&gt;Structure&lt;/span&gt; 

ShellExecuteEx(@lcStructure)&lt;/pre&gt;&lt;pre&gt;loSHELLEXECUTEINFO.&lt;span&gt;Structure&lt;/span&gt; = lcStructure

&lt;span&gt;***********************************************************&lt;/span&gt;
&lt;span&gt;* Wait for application termination (-1)&lt;/span&gt;
&lt;span&gt;***********************************************************&lt;/span&gt;
WaitForSingleObject(loSHELLEXECUTEINFO.fld("&lt;span&gt;hProcess&lt;/span&gt;"), -1)

&lt;span&gt;**************************************************************&lt;/span&gt;
&lt;span&gt;* Define SHELLEXECUTEINFO strucuture using class Struct&lt;/span&gt;
&lt;span&gt;* from http://fox.wikis.com/wc.dll?Wiki~ApiStructureClass~VFP&lt;/span&gt;
&lt;span&gt;**************************************************************&lt;/span&gt;

&lt;span&gt;DEFINE&lt;/span&gt; &lt;span&gt;CLASS&lt;/span&gt; SHELLEXECUTEINFO &lt;span&gt;AS&lt;/span&gt; Struct &lt;span&gt;OF&lt;/span&gt; Struct.prg

	#&lt;span&gt;IF&lt;/span&gt; .F.
		&lt;span&gt;LOCAL&lt;/span&gt; &lt;span&gt;THIS&lt;/span&gt; &lt;span&gt;AS&lt;/span&gt; SHELLEXECUTEINFO &lt;span&gt;OF&lt;/span&gt; SHELLEXECUTEINFO.prg
	#&lt;span&gt;ENDIF&lt;/span&gt;

	&lt;span&gt;PROCEDURE&lt;/span&gt; &lt;span&gt;INIT&lt;/span&gt;()
	
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;cbSize&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 60)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;fMask&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;hwnd&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpVerb&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpFile&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpParameters&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpDirectory&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))

		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;nShow&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;hInstApp&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpIDList&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;lpClass&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;hkeyClass&lt;/span&gt;", "&lt;span&gt;@STRING&lt;/span&gt;", &lt;span&gt;CHR&lt;/span&gt;(0))
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;dwHotKey&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;hIcon&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)
		&lt;span&gt;THIS&lt;/span&gt;.AddField("&lt;span&gt;hProcess&lt;/span&gt;", "&lt;span&gt;LONG&lt;/span&gt;", 0)

	&lt;span&gt;ENDPROC&lt;/span&gt;	

&lt;span&gt;ENDDEFINE&lt;/span&gt;&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;I used &lt;a href="http://fox.wikis.com/wc.dll?Wiki~ApiStructureClass~VFP" target="_blank"&gt;ApiStructureClass&lt;/a&gt; to create structure that required by ShellExecuteEx. It makes job much easier.&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:77f4db10-5359-42df-8e46-178e2af64085"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxWikis" rel="tag"&gt;FoxWikis&lt;/a&gt;, &lt;a href="http://technorati.com/tags/WinAPI" rel="tag"&gt;WinAPI&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Vista" rel="tag"&gt;Vista&lt;/a&gt;, &lt;a href="http://technorati.com/tags/RunAs" rel="tag"&gt;RunAs&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5688" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Use NEWOBJECT() function with care</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/02/25/5669.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/02/25/5669.aspx</id><published>2008-02-25T07:43:23Z</published><updated>2008-02-25T07:43:23Z</updated><content type="html">&lt;p&gt;I like to use NEWOVBJECT() to initiate object so that I don't have to care about SET PROCEDURE TO / SET CLASSLIB TO. &lt;/p&gt; &lt;p&gt;Recently, I am re-writing my company application update program. That is a method that loop thru all the necessary directory and files and store the file info (as per array content returned by ADIR()) into collection. The file details are stored as object based (I have class called FileInfo). FileInfo object is created using NEWOBJECT("FileInfo", "FileInfo.prg") function.&lt;/p&gt; &lt;p&gt;During the testing, I found the program takes 6.6 secs to check for 1200 files. The code of NEWOBJECT("FileInfo", "FileInfo.prg") was hit 2400 times due to the same function being called for source and target file. Each hit take average 0.0027 secs. That meant program spent 6.47 secs just to create FileInfo objects. This is unacceptable.&lt;/p&gt; &lt;p&gt;I changed my code SET PROCEDURE TO FileInfo.prg ADDITIVE at program startup and replace NEWOBJECT() with CREATEIBJECT(). Hey, the program now only take 1.5 secs to do the same thing. Therefore, we got to use NEWOBJECT() with care otherwise it might kill your application.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:42880c33-678f-4670-b8d3-c7ed88a87d53"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5669" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>VFP Studio - Code Editor Screencast</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2008/02/23/5662.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2008/02/23/5662.aspx</id><published>2008-02-23T03:40:03Z</published><updated>2008-02-23T03:40:03Z</updated><content type="html">&lt;p&gt;Craig has posted a &lt;a href="http://www.sweetpotatosoftware.com/SPSBlog/ct.ashx?id=b71ea97e-8fb8-4401-ace4-b5a536fe0a37&amp;amp;url=http%3a%2f%2fwww.sweetpotatosoftware.com%2fVFPStudio%2fVFPStudioCodeEditor.htm" target="_blank"&gt;screencast&lt;/a&gt; that demonstrate his current work to use &lt;a href="http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,b71ea97e-8fb8-4401-ace4-b5a536fe0a37.aspx" target="_blank"&gt;Visual Studio IDE for VFP code editing&lt;/a&gt;.&lt;/p&gt; &lt;p&gt;It is amazing. Once again, thank Craig.&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:1ab5dbd9-35e4-4315-abe7-11a8ee0153fa"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Craig%20Boyd" rel="tag"&gt;Craig Boyd&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5662" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Run VFP code from non-VFP environment</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2007/09/27/5032.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2007/09/27/5032.aspx</id><published>2007-09-27T08:01:49Z</published><updated>2007-09-27T08:01:49Z</updated><content type="html">&lt;p&gt;As I am automating VFP build process as mentioned, I always need to execute VFP code from non-VFP environment. In order to have "full" power of VFP, I choose to use OLE automation using VBscript.&lt;/p&gt; &lt;p&gt;There are two ways to run VFP code from VBScript which I use frequently:&lt;/p&gt; &lt;ul&gt; &lt;li&gt;Writing some code in prg. This is a very straight forward appraoch&lt;/li&gt;&lt;/ul&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span&gt;Set&lt;/span&gt; oFox = &lt;span&gt;CreateObject&lt;/span&gt;("&lt;span&gt;VisualFoxPro.Application&lt;/span&gt;")
oFox.DoCmd("&lt;span&gt;DO myPrg WITH '&lt;/span&gt;" &amp;amp; MyParameter &amp;amp; "&lt;span&gt;'&lt;/span&gt;")&lt;/pre&gt;&lt;/blockquote&gt;
&lt;ul&gt;
&lt;li&gt;Pass VFP code string&lt;/li&gt;&lt;/ul&gt;
&lt;blockquote&gt;&lt;pre&gt;&lt;font color="#008040"&gt;'USE myTable
'SCAN
'    IF myField = 'A'
'        ?myField
'    ENIDF
'ENDSCAN&lt;/font&gt;

&lt;span&gt;Set&lt;/span&gt; oFox = &lt;span&gt;CreateObject&lt;/span&gt;("&lt;span&gt;VisualFoxPro.Application&lt;/span&gt;") 
oFox.DoCmd("&lt;span&gt;EXECSCRIPT('&lt;/span&gt;" &amp;amp; sCommand &amp;amp; "&lt;span&gt;')&lt;/span&gt;")&lt;/pre&gt;&lt;/blockquote&gt;
&lt;p&gt;This approach is very useful if we allow other user to enter VFP code in UI which involve multiple lines of code, without need of VFP IDE.It seem very simple, right? Yes, it is. However,&amp;nbsp;I just hit one error "Runtime Error" when we try to run the code above. It is because the VFP code string contains CRLF. The workaround I found is:&lt;/p&gt;
&lt;blockquote&gt;&lt;pre&gt;oFox.SetVar "&lt;span&gt;lcCode&lt;/span&gt;", sCommnad
oFox.DoCmd("&lt;span&gt;EXECSCRIPT(lcCode)&lt;/span&gt;")&lt;/pre&gt;&lt;/blockquote&gt;&lt;pre&gt;Do you have any other way to do this?&lt;/pre&gt;&lt;pre&gt;&amp;nbsp;&lt;/pre&gt;
&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:38a5085d-1a89-4a74-9cc1-0d04e8d7cd49"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5032" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Find and Replace &amp;quot;\&amp;quot; in VFP</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2007/09/27/5030.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2007/09/27/5030.aspx</id><published>2007-09-27T06:48:48Z</published><updated>2007-09-27T06:48:48Z</updated><content type="html">&lt;p&gt;I just found that is "&lt;strong&gt;really"&lt;/strong&gt; written in C/C++. When I try to replace string from "myfolder\" to "myfolder\trunk" using Find and Replace dialog, VFP would replace my text as below&lt;/p&gt; &lt;blockquote&gt; &lt;p&gt;..\myfolder\myfile.prg ==&amp;gt; ..\myfolder\&lt;font color="#ff0000"&gt;&lt;strong&gt;{TAB}&lt;/strong&gt;&lt;/font&gt;runk\myfile.prg&lt;/p&gt;&lt;/blockquote&gt; &lt;p&gt;VFP treat "\t" is tab identifier with is normally used in C/C++ type of language. For workaround, just put one more "\" in replace string column, "myfolder\\trunk".&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:14fb9281-1be9-4c99-94de-0f34711d0f56"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5030" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Edit project version info</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2007/09/26/5021.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2007/09/26/5021.aspx</id><published>2007-09-26T11:12:23Z</published><updated>2007-09-26T11:12:23Z</updated><content type="html">&lt;p&gt;VFP allow us to edit project version info from build dialog.&lt;/p&gt; &lt;p&gt;&lt;img src="http://farm2.static.flickr.com/1387/1441737659_45a9963de1.jpg?v=0"&gt; &lt;/p&gt; &lt;p&gt;We also can edit it programmatically as below.&lt;/p&gt; &lt;p&gt;&lt;img src="http://farm2.static.flickr.com/1428/1441737797_3a61de624d.jpg?v=0"&gt; &lt;/p&gt; &lt;p&gt;Both ways is working fine, except VFP IDE is required.&lt;/p&gt; &lt;p&gt;I have written a simple class to enable Project and Version Info edition programmatically without need of VFP IDE. This class would open pjx file, read/write content to DevInfo column.&lt;/p&gt;&lt;pre&gt;&lt;span&gt;USE&lt;/span&gt; myProj.pjx

loDevInfo = &lt;span&gt;NEWOBJECT&lt;/span&gt;("&lt;span&gt;DevInfo&lt;/span&gt;", "&lt;span&gt;DevInfo.prg&lt;/span&gt;")
loDevInfo.VersionMajor = &lt;span&gt;TRANSFORM&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Major)
loDevInfo.VersionMinor = &lt;span&gt;TRANSFORM&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Minor)
loDevInfo.VersionRevision = &lt;span&gt;TRANSFORM&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Revision)

&lt;span&gt;LOCATE&lt;/span&gt; &lt;span&gt;FOR&lt;/span&gt; &lt;span&gt;type&lt;/span&gt; = "&lt;span&gt;H&lt;/span&gt;"
&lt;span&gt;REPLACE&lt;/span&gt; DevInfo &lt;span&gt;WITH&lt;/span&gt; loDevInfo.GetDevInfo()

&lt;span&gt;** Author	0x00-0x2D&lt;/span&gt;
&lt;span&gt;** Company	0x2E-0x5B&lt;/span&gt;
&lt;span&gt;** Address	0x5C-0x89&lt;/span&gt;
&lt;span&gt;** City		0x8A-0x9E&lt;/span&gt;
&lt;span&gt;** State		0x9F-0xA4&lt;/span&gt;
&lt;span&gt;** Postcode	0xA5-0xAF&lt;/span&gt;
&lt;span&gt;** Country	0xB0-0xDD&lt;/span&gt;
&lt;span&gt;** Comment	0xDE-0x1DC&lt;/span&gt;
&lt;span&gt;** Company	0x1DD-0x2DB&lt;/span&gt;
&lt;span&gt;** Descr		0x2DC-0x3DA&lt;/span&gt;
&lt;span&gt;** (C)		0x3DB-0x4D9&lt;/span&gt;
&lt;span&gt;** Trade		0x4DA-0x5D8&lt;/span&gt;
&lt;span&gt;** Product	0x5d9-0x6D7&lt;/span&gt;
&lt;span&gt;** Major		0x6D8-0X6DC&lt;/span&gt;
&lt;span&gt;** Minor		0x6DD-0x6E1&lt;/span&gt;
&lt;span&gt;** Revision	0x6E2-0x6E6&lt;/span&gt;
&lt;span&gt;** Language	0x6E7-0x702&lt;/span&gt;

#&lt;span&gt;DEFINE&lt;/span&gt;	AUTHOR_LENGTH				0X2D - 0X00 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMPANY_LENGTH				0X5B - 0X2E + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	ADDRESS_LENGTH				0X89 - 0X5C + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	CITY_LENGTH					0X9E - 0X8A + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	STATE_LENGTH				0XA4 - 0X9F + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	POSTCODE_LENGTH			0XAF - 0XA5 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COUNTRY_LENGTH				0XDD - 0XB0 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMMENTS_LENGTH			0X1DC - 0XDE + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMPANYNAME_LENGTH		0X2DB - 0X1DE + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	FILEDESCRIPTION_LENGTH	0X3DA - 0X2DD + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COPYRIGHT_LENGTH			0X4D9 - 0X3DB + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	TRADEMARKS_LENGTH			0X5D8 - 0X4DA + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	PRODUCTNAME_LENGTH		0X6D7 - 0X5DA + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONMAJOR_LENGTH		0X6DC - 0X6D8 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONMINOR_LENGTH		0X6E1 - 0X6DD + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONREVISION_LENGTH	0X6E6 - 0X6E2 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	LANGUAGEID_LENGTH			0X702 - 0X6E7 + 1

#&lt;span&gt;DEFINE&lt;/span&gt;	AUTHOR_POSITION	 			1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMPANY_POSITION	 			0X2E + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	ADDRESS_POSITION	 			0X5C + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	CITY_POSITION	 				0X8A + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	STATE_POSITION	 				0X9F + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	POSTCODE_POSITION	 			0XA5 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COUNTRY_POSITION	 			0XB0 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMMENTS_POSITION	 			0XDE + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COMPANYNAME_POSITION	 		0X1DE + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	FILEDESCRIPTION_POSITION	0X2DD + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	COPYRIGHT_POSITION	 		0X3DB + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	TRADEMARKS_POSITION	 		0X4DA + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	PRODUCTNAME_POSITION	 		0X5DA + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONMAJOR_POSITION	 	0X6D8 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONMINOR_POSITION	 	0X6DD + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	VERSIONREVISION_POSITION	0X6E2 + 1
#&lt;span&gt;DEFINE&lt;/span&gt;	LANGUAGEID_POSITION	 		0X6E7 + 1

&lt;span&gt;DEFINE&lt;/span&gt; &lt;span&gt;CLASS&lt;/span&gt; DevInfo &lt;span&gt;AS&lt;/span&gt; &lt;span&gt;Line&lt;/span&gt;

	#&lt;span&gt;IF&lt;/span&gt; .F.
		&lt;span&gt;LOCAL&lt;/span&gt; &lt;span&gt;THIS&lt;/span&gt; &lt;span&gt;AS&lt;/span&gt; DevInfo &lt;span&gt;OF&lt;/span&gt; DevInfo.prg
	#&lt;span&gt;ENDIF&lt;/span&gt;

	Author = "&lt;span&gt;&lt;/span&gt;"
	Company = "&lt;span&gt;&lt;/span&gt;"
	Address = "&lt;span&gt;&lt;/span&gt;"
	City = "&lt;span&gt;&lt;/span&gt;"
	State = "&lt;span&gt;&lt;/span&gt;"
	Postcode = "&lt;span&gt;&lt;/span&gt;"
	Country = "&lt;span&gt;&lt;/span&gt;"
	Comments = "&lt;span&gt;&lt;/span&gt;"
	CompanyName = "&lt;span&gt;&lt;/span&gt;"
	FileDescription = "&lt;span&gt;&lt;/span&gt;"
	Copyright = "&lt;span&gt;&lt;/span&gt;"
	Trademarks = "&lt;span&gt;&lt;/span&gt;"
	ProductName = "&lt;span&gt;&lt;/span&gt;"
	VersionMajor = "&lt;span&gt;&lt;/span&gt;"
	VersionMinor = "&lt;span&gt;&lt;/span&gt;"
	VersionRevision = "&lt;span&gt;&lt;/span&gt;"
	LanguageID = "&lt;span&gt;&lt;/span&gt;"

	&lt;span&gt;PROCEDURE&lt;/span&gt; Parse(tcDevInfo &lt;span&gt;AS&lt;/span&gt; &lt;span&gt;String&lt;/span&gt;)
	
		&lt;span&gt;THIS&lt;/span&gt;.Author = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, AUTHOR_POSITION, AUTHOR_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Company = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, COMPANY_POSITION, COMPANY_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Address = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, ADDRESS_POSITION, ADDRESS_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.City = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, CITY_POSITION, CITY_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.State = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, STATE_POSITION, STATE_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Postcode = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, POSTCODE_POSITION, POSTCODE_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Country = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, COUNTRY_POSITION, COUNTRY_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Comments = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, COMMENTS_POSITION, COMMENTS_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.CompanyName = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, COMPANYNAME_POSITION, COMPANYNAME_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.FileDescription = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, FILEDESCRIPTION_POSITION, FILEDESCRIPTION_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Copyright = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, COPYRIGHT_POSITION, COPYRIGHT_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.Trademarks = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, TRADEMARKS_POSITION, TRADEMARKS_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.ProductName = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, PRODUCTNAME_POSITION, PRODUCTNAME_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.VersionMajor = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, VERSIONMAJOR_POSITION, VERSIONMAJOR_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.VersionMinor = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, VERSIONMINOR_POSITION, VERSIONMINOR_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.VersionRevision = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, VERSIONREVISION_POSITION, VERSIONREVISION_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		&lt;span&gt;THIS&lt;/span&gt;.LanguageID = &lt;span&gt;STRTRAN&lt;/span&gt;(&lt;span&gt;SUBSTR&lt;/span&gt;(tcDevInfo, LANGUAGEID_POSITION, LANGUAGEID_LENGTH), &lt;span&gt;CHR&lt;/span&gt;(0), "&lt;span&gt;&lt;/span&gt;")
		
	&lt;span&gt;ENDPROC&lt;/span&gt;
	
	&lt;span&gt;PROCEDURE&lt;/span&gt; GetDevInfo() &lt;span&gt;AS&lt;/span&gt; &lt;span&gt;String&lt;/span&gt;
	
		&lt;span&gt;LOCAL&lt;/span&gt; lcDevInfo &lt;span&gt;AS&lt;/span&gt; &lt;span&gt;String&lt;/span&gt;
		
		lcDevInfo = "&lt;span&gt;&lt;/span&gt;" 

		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Author, AUTHOR_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Company, COMPANY_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Address, ADDRESS_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.City, CITY_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.State, STATE_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Postcode, POSTCODE_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Country, COUNTRY_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Comments, COMMENTS_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0)) + &lt;span&gt;CHR&lt;/span&gt;(0x20)
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.CompanyName, COMPANYNAME_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0)) + &lt;span&gt;CHR&lt;/span&gt;(0x20)
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.FileDescription, FILEDESCRIPTION_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Copyright, COPYRIGHT_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.Trademarks, TRADEMARKS_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0)) + &lt;span&gt;CHR&lt;/span&gt;(0x20)
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.ProductName, PRODUCTNAME_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.VersionMajor, VERSIONMAJOR_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.VersionMinor, VERSIONMINOR_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.VersionRevision, VERSIONREVISION_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
		lcDevInfo = lcDevInfo + &lt;span&gt;PADR&lt;/span&gt;(&lt;span&gt;THIS&lt;/span&gt;.LanguageID, LANGUAGEID_LENGTH, &lt;span&gt;CHR&lt;/span&gt;(0))
	
		&lt;span&gt;RETURN&lt;/span&gt; lcDevInfo
		 
	&lt;span&gt;ENDPROC&lt;/span&gt;
	
&lt;span&gt;ENDDEFINE&lt;/span&gt;&lt;/pre&gt;
&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:ed8ebe8d-f2d1-4941-b6ef-b922b793c671"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=5021" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry><entry><title>Experience in Automate VFP Project Build</title><link rel="alternate" type="text/html" href="http://weblogs.foxite.com/kkchan/archive/2007/08/28/4763.aspx" /><id>http://weblogs.foxite.com/kkchan/archive/2007/08/28/4763.aspx</id><published>2007-08-28T07:54:01Z</published><updated>2007-08-28T07:54:01Z</updated><content type="html">&lt;p&gt;I was setting up Automate Build for my VFP project. I get a copy of &lt;a href="http://www.finalbuilder.com/" target="_blank"&gt;FinalBuilder&lt;/a&gt;&amp;nbsp;and use it as my starting point for Daily Build and &lt;a href="http://www.theserverside.net/news/thread.tss?thread_id=46610" target="_blank"&gt;Continuous Integration&lt;/a&gt;. I choose FinalBuilder is because it is easy use, good support and&amp;nbsp;easy installation. FYI, &lt;em&gt;&lt;strong&gt;FinalBuilder&lt;/strong&gt; is an automated build and release management solution (ABRM)&amp;nbsp;for Windows software developers and SCM professionals. &lt;/em&gt;It is just one of the automate build&amp;nbsp;tools&amp;nbsp;in market. Other&amp;nbsp;product like MS Build, NAnt, VSTS Team System and many more.&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;Automate Build&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;By using automate build tool, we could define, debug, maintain, run and schedule&amp;nbsp;reliable and repeatable build processes with minimal coding required.&amp;nbsp;Build process doesn't meant only compile project, it also include activities like Get Latest Source File, run database script, copy files to deployment server, package deployment files, run&amp;nbsp;automated testing&amp;nbsp;and etc Once build process is automated, we only need to have single mouse click to establish build process.&amp;nbsp;After this implementation, I have shorten time spent to deploy new version of application &lt;strong&gt;from two hours to ten minutes&lt;/strong&gt;.&lt;/p&gt; &lt;p&gt;Before we start to automate our build process, it is recommended to sit down, take some papers to draft out current manual build process, just like writing program. The draft could be in pseudo code, flow chart, point form or whatever format. It would definitely help and save our time without keep revising the automated build process during implementation. I wasted a lot of time to revise my Build Process.&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;Automated Build Management Solution - FinalBuilder&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;FinalBuilder, as other&amp;nbsp;ABRM tool, provides a lot of predefined common &lt;em&gt;actions&lt;/em&gt; to perform varies tasks&amp;nbsp;such as get latest source files, compile projects, execute setup scripts, copy files, FTP&amp;nbsp;and etc. We could use each of action by simple configuration. Below is the IDE screenshot of FinalBuilder and&amp;nbsp;overview of my automate build process.&lt;/p&gt; &lt;p&gt;&lt;img height="768" src="http://www.visualsolutions.com.my/blog/chankk/FinalBuilder.jpg" width="1280"&gt; &lt;/p&gt; &lt;p&gt;&lt;font size="2"&gt;Figure 1 Screenshot of Build Process defined in FinalBuilder&lt;/font&gt;&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;Automate Build for VFP Project&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;During this implementation, I was facing some issues. The main&amp;nbsp;issue is, FinalBuilder doesn't natively support VFP (as&amp;nbsp;most vendors). That is no VFP compiler available. No VFP Compiler, are you kididng? This is the main tasks for automate build! Yes, you didn't hear wrongly.&lt;/p&gt; &lt;p&gt;Fortunately , FinalBuilder come with Action Studio, allow us to create custom actions for any specific usage via ActiveX Script (VB Script/JScript), .NET interop&amp;nbsp;and COM.&lt;/p&gt; &lt;h4&gt;&lt;strong&gt;VFP Compiler Custom Action&lt;/strong&gt;&lt;/h4&gt; &lt;p&gt;To write custom action, I did some researches and&amp;nbsp;found&amp;nbsp;article posted in&amp;nbsp;&lt;a href="http://codemag.com" target="_blank"&gt;CODE&lt;/a&gt; magazine titled&amp;nbsp;&lt;a href="http://www.code-magazine.com/Article.aspx?quickid=0703102"&gt;Integrating VFP into VSTS Team Projects&lt;/a&gt;&amp;nbsp;by &lt;b&gt;John Miller&lt;/b&gt;. &amp;nbsp;John shared his code to rebuild VFP project file (PJX) from PJM file and BUILD EXE from project. I copied, customized posted code to create my&amp;nbsp;"VFP Compiler" action, called from FinalBuilder. I added feature to explicitly compile all .prg files excluded from project, since I found that don't know why excluded .prg files&amp;nbsp;are not compiled&amp;nbsp;using BUILD EXE command.&lt;/p&gt; &lt;p&gt;At the beginning, I tried to use COM to wrapper my build project code, however, as you might already known &lt;strong&gt;BUILD&lt;/strong&gt; command is not supported&amp;nbsp;during run-time. VFP doesn't&amp;nbsp;complain for this exception either. I spent a lot of time to troubleshoot this, as it is not documented in Help file (as least I&amp;nbsp;couldn't find&amp;nbsp;it :'(). The workaround is either call VFP via command line or OLE Automation. I choose the 2nd way, automate VFP IDE using VB Script.&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span&gt;Set&lt;/span&gt; oFox = &lt;span&gt;CreateObject&lt;/span&gt;("&lt;span&gt;VisualFoxPro.Application&lt;/span&gt;")
oFox.DoCmd("&lt;span&gt;*** BUILD EXE&lt;/span&gt;")

&lt;span&gt;&lt;font color="#008000"&gt;'Do some other things&lt;/font&gt;&lt;/span&gt;

oFox.Quit&lt;/pre&gt;&lt;/blockquote&gt;&lt;font size="2"&gt;&lt;/font&gt;
&lt;p&gt;&lt;font size="2"&gt;The "VFP Compiler" Custom Action created and allowed us to do configuration, and currently it only&amp;nbsp;accept settings&amp;nbsp;such as project to be built, output destination, runtime version, SET PATH list and&amp;nbsp;strict date level. &lt;/font&gt;&lt;/p&gt;
&lt;table cellspacing="5" cellpadding="2"&gt;

&lt;tr&gt;
&lt;td&gt;
&lt;h4&gt;&lt;font size="2"&gt;&lt;strong&gt;Steps to setup&lt;/strong&gt;&lt;/font&gt;&lt;/h4&gt;
&lt;ol&gt;
&lt;li&gt;&lt;font size="2"&gt;Download the custom action &lt;/font&gt;&lt;a href="http://www.visualsolutions.com.my/blog/chankk/FoxProFBCustomActions.zip" target="_blank"&gt;&lt;font size="2"&gt;here&lt;/font&gt;&lt;/a&gt;&lt;font size="2"&gt;. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Extract it, and copy FoxProFBCustomActions.fbp5&amp;nbsp;to "&amp;lt;Final Builder Path&amp;gt;\ActionDefs" folder. Copy ProjectBuilder.prg to&amp;nbsp;any folder. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Launch Final Builder IDE.&amp;nbsp;&amp;nbsp;Action "Build Project and EXE" would be shown in&amp;nbsp;Action Types List under category Visual FoxPro (Figure 2). &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Drag and drop action from action types list to action list (Figure 3). &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Action property page is shown. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Specify any name as Build Name. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Specify Project Name (PJM), with path. PJM extension could be omitted. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Specify output destination and&amp;nbsp;file name&amp;nbsp;of project executable file. EXE extension could be omitted. If this field left blank, EXE would be built and store at same location and name of project file (PJM), with EXE extension &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Select runtime version to build the EXE and project (Figure 4). &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Specify search path list. Remember to include location that stored the ProjectBuilder.prg (Figure 5). &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Specify environment settings. Currently only support Strict Date Level (Figure 6). &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Click OK to confirm. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;New action would be added to action list (Figure 7).&lt;/font&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;p&gt;&lt;strong&gt;Possible Enhancements&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Some future enhancements I can think of :&lt;/font&gt;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;font size="2"&gt;Ability to type VFP code in action property page, and run it at Before/After Compile event; either full VFP code or just a function call. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Full set of environment settings available in VFP option dialog. &lt;/font&gt;
&lt;li&gt;&lt;font size="2"&gt;Ability to VFP related actions global settings such as common library path list in FinalBuilder options page.&lt;/font&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/td&gt;
&lt;td&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/VFPActions.jpg"&gt;&lt;br&gt;&lt;font size="2"&gt;Figure 2 Some VFP Custom Actions&lt;br&gt;&lt;br&gt;&lt;/font&gt;&lt;br&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/VFPActions_Drag.jpg"&gt;&lt;br&gt;&lt;font size="2"&gt;Figure 3&amp;nbsp; Drag action to action list&lt;/font&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;p&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/VFPActions_Build.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Figure&amp;nbsp;4 Build Project Settings&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/VFPActions_SetPath.jpg"&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Figure 5 Set Path Settings&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/VFPActions_ENV.jpg"&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;&lt;font size="2"&gt;Figure 6 Environment Settings&lt;/font&gt;&lt;/font&gt;&lt;/p&gt;
&lt;p&gt;&lt;img src="http://www.visualsolutions.com.my/blog/chankk/BuildHRMSEXE.jpg"&gt;&lt;/p&gt;
&lt;p&gt;&lt;font size="2"&gt;Figure 7&amp;nbsp;Action to Compile Projects&lt;/font&gt;&lt;/p&gt;
&lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:d19d576b-8906-45df-94a6-bb9ad81bdf76"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/Visual%20FoxPro" rel="tag"&gt;Visual FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FoxPro" rel="tag"&gt;FoxPro&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Software%20Development" rel="tag"&gt;Software Development&lt;/a&gt;, &lt;a href="http://technorati.com/tags/FinalBuilder" rel="tag"&gt;FinalBuilder&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Daily%20Build" rel="tag"&gt;Daily Build&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=4763" width="1" height="1"&gt;</content><author><name>kkchan</name><uri>http://weblogs.foxite.com/members/kkchan.aspx</uri></author></entry></feed>