<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://weblogs.foxite.com/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Kok Kiet's Blog</title><link>http://weblogs.foxite.com/kkchan/default.aspx</link><description>About Programming, Visual FoxPro, .NET.</description><dc:language>en-US</dc:language><generator>CommunityServer 2.0 (Build: 60217.2664)</generator><item><title>Run application and wait (RunAs)</title><link>http://weblogs.foxite.com/kkchan/archive/2008/03/07/5688.aspx</link><pubDate>Fri, 07 Mar 2008 18:41:40 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5688</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5688.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5688</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5688.aspx</wfw:comment><description>&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;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>Use NEWOBJECT() function with care</title><link>http://weblogs.foxite.com/kkchan/archive/2008/02/25/5669.aspx</link><pubDate>Mon, 25 Feb 2008 14:43:23 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5669</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5669.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5669</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5669.aspx</wfw:comment><description>&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;</description></item><item><title>VFP Studio - Code Editor Screencast</title><link>http://weblogs.foxite.com/kkchan/archive/2008/02/23/5662.aspx</link><pubDate>Sat, 23 Feb 2008 10:40:03 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5662</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5662.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5662</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5662.aspx</wfw:comment><description>&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;</description></item><item><title>Run VFP code from non-VFP environment</title><link>http://weblogs.foxite.com/kkchan/archive/2007/09/27/5032.aspx</link><pubDate>Thu, 27 Sep 2007 15:01:49 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5032</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5032.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5032</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5032.aspx</wfw:comment><description>&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;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category></item><item><title>Find and Replace &amp;quot;\&amp;quot; in VFP</title><link>http://weblogs.foxite.com/kkchan/archive/2007/09/27/5030.aspx</link><pubDate>Thu, 27 Sep 2007 13:48:48 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5030</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5030.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5030</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5030.aspx</wfw:comment><description>&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;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category></item><item><title>Edit project version info</title><link>http://weblogs.foxite.com/kkchan/archive/2007/09/26/5021.aspx</link><pubDate>Wed, 26 Sep 2007 18:12:23 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:5021</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/5021.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=5021</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/5021.aspx</wfw:comment><description>&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;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category></item><item><title>Experience in Automate VFP Project Build</title><link>http://weblogs.foxite.com/kkchan/archive/2007/08/28/4763.aspx</link><pubDate>Tue, 28 Aug 2007 14:54:01 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:4763</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/4763.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=4763</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/4763.aspx</wfw:comment><description>&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;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>FoxPro control with design time support</title><link>http://weblogs.foxite.com/kkchan/archive/2007/08/20/4568.aspx</link><pubDate>Mon, 20 Aug 2007 21:26:15 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:4568</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/4568.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=4568</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/4568.aspx</wfw:comment><description>&lt;p&gt;Amazing!!! Craig Boyd shown us a simple way to implement FoxPro control design time support. IOW, you can execute any custom code if any changes to control's property, size and etc. Craig also posted screencast to show it live, and source code is available!&lt;/p&gt; &lt;p&gt;&lt;a href="http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,cbe94fe8-cf6b-4600-9a05-b23b0adff749.aspx" target="_blank"&gt;Visual FoxPro - Designer Ideas and a Screencast&lt;/a&gt;&lt;/p&gt; &lt;p&gt;Thank you, Craig.&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:7ee3f623-bab0-444f-9767-870ce98b32b3"&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=4568" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category></item><item><title>Show images in grid (Update)</title><link>http://weblogs.foxite.com/kkchan/archive/2007/06/08/3936.aspx</link><pubDate>Fri, 08 Jun 2007 09:33:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3936</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3936.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3936</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3936.aspx</wfw:comment><description>&lt;p&gt;I posted blog entry about how to &lt;a href="/kkchan/archive/2007/05/16/3790.aspx"&gt;show image in grid&lt;/a&gt; based on control source in last month. I received few comments/emails and inform me that my sample is not working.&lt;/p&gt; &lt;p&gt;First of all, thank you for your interest&amp;nbsp;of reading my blog. OK, I read&amp;nbsp;my previous blog again and agree that my explanation is not clear enough. I miss out some steps to mention. I repost it here with &lt;a href="http://weblogs.foxite.com/kkchan/attachment/3936.ashx"&gt;sample&lt;/a&gt; attached.&lt;/p&gt; &lt;p&gt;1. Create new class (CREATE CLASS ?)&lt;/p&gt; &lt;p&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/3951/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;2. Place an image control on the container class. Adjust image position accordingly. (Set Image.anchor = 15 if using VFP9). Set mycontainer.backstyle = 0 - Transparent, mycontainer.borderwidth = 0, myimage.backstyle = 0 - Transparent.&lt;/p&gt; &lt;p&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/3952/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;3. Select container object, select “Edit Property/Method …” from menu as shown below.&lt;/p&gt; &lt;p&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/3953/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;4. Edit Property/Method dialog form will be shown. Select BackStyle from the list and check “Assign Method” and “Access Method” checkbox and click Apply.&lt;/p&gt; &lt;p&gt;&lt;img src="/photos/kkchan/images/3784/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;5. Open mycontainer.backstyle_access method and put your code.&lt;/p&gt; &lt;p&gt;&lt;img src="/photos/kkchan/images/3933/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;6. Save your class.&lt;/p&gt; &lt;p&gt;7. Create a form, place your grid control and place mycontainer class into column. (Remember to delete the existing column.textbox control).&lt;/p&gt; &lt;p&gt;&lt;img src="/photos/kkchan/images/3932/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;8. Set column.sparse = .F.&lt;/p&gt; &lt;p&gt;9. Add your code to open table/create cursor.&lt;/p&gt; &lt;p&gt;&lt;img src="/photos/kkchan/images/3934/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;10. Set "mycursor.cimage" to grid.column1.controlsource; "mycursor.cdescr" to grid.column2.controlsource.&lt;/p&gt; &lt;p&gt;11. Save your form and run it.&lt;/p&gt; &lt;p&gt;&lt;img src="/photos/kkchan/images/3935/original.aspx"&gt; &lt;/p&gt; &lt;p&gt;Do you get the same result?&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:4fd807f0-3967-42d2-919d-721cbf868cef"&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;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3936" width="1" height="1"&gt;</description><enclosure url="http://weblogs.foxite.com/kkchan/attachment/3936.ashx" length="15518" type="application/zip" /></item><item><title>A simple way to retrieve web page content</title><link>http://weblogs.foxite.com/kkchan/archive/2007/05/26/3856.aspx</link><pubDate>Fri, 25 May 2007 22:02:13 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3856</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3856.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3856</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3856.aspx</wfw:comment><description>&lt;p&gt;I was asked how to GET rss feed from a web site. During research, I found couple of ways to do it in .NET. Below is the simplest way as I can get.&lt;/p&gt; &lt;blockquote&gt;&lt;pre&gt;&lt;span&gt;///Sample using System.Net&lt;/span&gt;

WebRequest wr = HttpWebRequest.Create(@"&lt;span&gt;http://msdn.microsoft.com/globalrss/en-us/global-msdn-en-us.xml&lt;/span&gt;");
WebResponse ws = wr.GetResponse();

StreamReader sr = &lt;span&gt;new&lt;/span&gt; StreamReader(ws.GetResponseStream());
&lt;span&gt;string&lt;/span&gt; str = sr.ReadToEnd();
&lt;span&gt;this&lt;/span&gt;.textBox1.Text = str;

&lt;span&gt;///Sample using System.Data&lt;/span&gt;

DataSet ds = &lt;span&gt;new&lt;/span&gt; DataSet()
ds.ReadXml(@"&lt;span&gt;http://msdn.microsoft.com/globalrss/en-us/global-msdn-en-us.xml&lt;/span&gt;");&lt;/pre&gt;&lt;pre&gt;&lt;span&gt;string&lt;/span&gt; str = ds.GetXml()
&lt;span&gt;this&lt;/span&gt;.textBox1.Text = str;&lt;/pre&gt;&lt;/blockquote&gt;I feel so excited when I found that I can read web content using DataSet. Amazing!!&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3856" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1016.aspx">.NET</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>WebConfig Updater</title><link>http://weblogs.foxite.com/kkchan/archive/2007/05/24/3852.aspx</link><pubDate>Thu, 24 May 2007 21:11:17 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3852</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3852.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3852</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3852.aspx</wfw:comment><description>&lt;p&gt;I&amp;nbsp;has couple of .NET 1.1 web applications use web.config to store most of the application settings.&amp;nbsp;While releasing new version, I need to ship new settings&amp;nbsp;with default value (with comments), and also retain&amp;nbsp;existing customer settings.&lt;/p&gt; &lt;p&gt;Below is my prototype code&amp;nbsp;to update web.config from another. &lt;/p&gt;&lt;pre&gt;&lt;span&gt;using&lt;/span&gt; System;
&lt;span&gt;using&lt;/span&gt; System.Collections.Generic;
&lt;span&gt;using&lt;/span&gt; System.Text;
&lt;span&gt;using&lt;/span&gt; System.Xml;
&lt;span&gt;using&lt;/span&gt; System.Collections.Specialized;

&lt;span&gt;namespace&lt;/span&gt; ConsoleApplication1
{
    &lt;span&gt;class&lt;/span&gt; Program
    {
        &lt;span&gt;static&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; Main(&lt;span&gt;string&lt;/span&gt;[] args)
        {
            ConfigManager loConfig = &lt;span&gt;new&lt;/span&gt; ConfigManager();
            ConfigManager loConfig2 = &lt;span&gt;new&lt;/span&gt; ConfigManager();

            loConfig.ReadKeysFromConfig(@"&lt;span&gt;c:\Web.config&lt;/span&gt;");
            loConfig2.ReadKeysFromConfig(@"&lt;span&gt;c:\web1.config&lt;/span&gt;");

            &lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;string&lt;/span&gt; lo &lt;span&gt;in&lt;/span&gt; loConfig2.AppSettings.Keys)
            {
                &lt;span&gt;string&lt;/span&gt; lcvalue = loConfig2.AppSettings[lo];

                &lt;span&gt;if&lt;/span&gt; (lcvalue != "&lt;span&gt;&lt;/span&gt;")
                {
                    loConfig.AppSettings[lo] = lcvalue;
                }

                Console.WriteLine("&lt;span&gt;Key=&lt;/span&gt;" + lo + "&lt;span&gt; value=&lt;/span&gt;" + loConfig.AppSettings[lo]);
            }

            loConfig.WriteKeysToConfig(@"&lt;span&gt;c:\Web.config&lt;/span&gt;");

            Console.ReadLine();
        }
    }

    &lt;span&gt;public&lt;/span&gt; &lt;span&gt;class&lt;/span&gt; ConfigManager
    {
        NameValueCollection _ConfigKeys = &lt;span&gt;new&lt;/span&gt; NameValueCollection();

        &lt;span&gt;public&lt;/span&gt; NameValueCollection AppSettings
        {
            &lt;span&gt;get&lt;/span&gt;
            {
                &lt;span&gt;return&lt;/span&gt; _ConfigKeys;
            }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; ReadKeysFromConfig(&lt;span&gt;string&lt;/span&gt; tcConfigFile)
        {
            &lt;span&gt;string&lt;/span&gt; lcKey = "&lt;span&gt;&lt;/span&gt;";
            &lt;span&gt;string&lt;/span&gt; lcValue = "&lt;span&gt;&lt;/span&gt;";

            &lt;span&gt;try&lt;/span&gt;
            {
                XmlDocument _xdoc = &lt;span&gt;new&lt;/span&gt; XmlDocument();
                _xdoc.Load(tcConfigFile);
                XmlNode xmlnode = _xdoc.SelectSingleNode("&lt;span&gt;/configuration/appSettings&lt;/span&gt;");

                &lt;span&gt;foreach&lt;/span&gt; (XmlNode loNode &lt;span&gt;in&lt;/span&gt; xmlnode.ChildNodes)
                {
                    &lt;span&gt;if&lt;/span&gt; (loNode.Name != "&lt;span&gt;#comment&lt;/span&gt;")
                    {
                        &lt;span&gt;try&lt;/span&gt;
                        {
                            lcKey = loNode.Attributes["&lt;span&gt;key&lt;/span&gt;"].InnerText;
                            lcValue = loNode.Attributes["&lt;span&gt;value&lt;/span&gt;"].InnerText;

                            _ConfigKeys.Add(lcKey, lcValue);
                        }
                        &lt;span&gt;catch&lt;/span&gt; (XmlException ex)
                        {
                            &lt;span&gt;throw&lt;/span&gt; ex;
                        }
                    }
                }
            }
            &lt;span&gt;catch&lt;/span&gt; (XmlException ex)
            {
                &lt;span&gt;throw&lt;/span&gt; ex;
            }
        }

        &lt;span&gt;public&lt;/span&gt; &lt;span&gt;void&lt;/span&gt; WriteKeysToConfig(&lt;span&gt;string&lt;/span&gt; tcConfigFile)
        {
            XmlNode xmlnode = &lt;span&gt;null&lt;/span&gt;;

            &lt;span&gt;try&lt;/span&gt;
            {
                XmlDocument _xdoc = &lt;span&gt;new&lt;/span&gt; XmlDocument();
                _xdoc.Load(tcConfigFile);

                &lt;span&gt;foreach&lt;/span&gt; (&lt;span&gt;string&lt;/span&gt; lckey &lt;span&gt;in&lt;/span&gt; _ConfigKeys.Keys)
                {
                    xmlnode = _xdoc.SelectSingleNode(@"&lt;span&gt;/configuration/appSettings/add[@key='&lt;/span&gt;" + lckey + "&lt;span&gt;']&lt;/span&gt;");

                    &lt;span&gt;if&lt;/span&gt; (xmlnode == &lt;span&gt;null&lt;/span&gt;)
                    {
                        xmlnode = _xdoc.CreateNode(XmlNodeType.Element, "&lt;span&gt;add&lt;/span&gt;", &lt;span&gt;null&lt;/span&gt;);
                        XmlAttribute xmlkeyattr = _xdoc.CreateAttribute("&lt;span&gt;key&lt;/span&gt;");
                        xmlkeyattr.Value = lckey;
                        XmlAttribute xmlvalueattr = _xdoc.CreateAttribute("&lt;span&gt;value&lt;/span&gt;");
                        xmlvalueattr.Value = _ConfigKeys[lckey];

                        xmlnode.Attributes.Append(xmlkeyattr);
                        xmlnode.Attributes.Append(xmlvalueattr);

                        XmlNode xmlparent = _xdoc.SelectSingleNode(@"&lt;span&gt;/configuration/appSettings&lt;/span&gt;");

                        &lt;span&gt;if&lt;/span&gt; (xmlparent == &lt;span&gt;null&lt;/span&gt;)
                        {
                            XmlNode AppSettingNode = _xdoc.CreateNode(XmlNodeType.Element, "&lt;span&gt;appSettings&lt;/span&gt;", &lt;span&gt;null&lt;/span&gt;);
                            xmlparent.AppendChild(AppSettingNode);
                        }

                        xmlparent.AppendChild(xmlnode);
                    }
                    &lt;span&gt;else&lt;/span&gt;
                    {
                        xmlnode.Attributes.GetNamedItem("&lt;span&gt;value&lt;/span&gt;").Value = _ConfigKeys[lckey];
                    }
                }

                _xdoc.Save(tcConfigFile);
            }
            &lt;span&gt;catch&lt;/span&gt; (XmlException ex)
            {
                &lt;span&gt;throw&lt;/span&gt; ex;
            }
        }
    }
}&lt;/pre&gt;
&lt;p&gt;It is my first touch to XMLDocument. It looks complex, but actually not that difficult :)&lt;/p&gt;
&lt;p&gt;Reference:&lt;/p&gt;
&lt;p&gt;&lt;a href="http://www.west-wind.com/presentations/configurationclass/configurationclass.asp"&gt;West-wind Configuration Class&lt;/a&gt;&lt;/p&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3852" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1016.aspx">.NET</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>Won book titled Refactoring Database</title><link>http://weblogs.foxite.com/kkchan/archive/2007/05/17/3801.aspx</link><pubDate>Thu, 17 May 2007 15:58:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3801</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3801.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3801</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3801.aspx</wfw:comment><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;A month ago, I attended &lt;a href="http://www.iasahome.org/web/malaysia/symposium"&gt;IASA synbosium&lt;/a&gt; which held at Kuala Lumpur, Malaysia. It is an event&amp;nbsp;that talk about&amp;nbsp;enterprise architecture. I was so lucky to win a book titled "Refactoring Database" from IBM lucky draw and got chance to have photo with the author, Scott W.Ambler. :D&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:26aedecb-86f9-4d2e-903a-f4ee900d4998"&gt;&lt;img src="/photos/kkchan/images/3800/original.aspx" alt=""&gt;&lt;br&gt;&lt;br&gt;Signature from Scott: &lt;b&gt;&lt;i&gt;Data doesn't have to be in "Four Letters" words anymore!&lt;br&gt;&lt;br&gt;&lt;font color="#ff0000"&gt;Updated:&lt;br&gt;&lt;/font&gt;&lt;/i&gt;&lt;/b&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="/photos/kkchan/images/3813/original.aspx" border="0"&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3801" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1015.aspx">General</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>TechEd SEA 2007 is coming back!</title><link>http://weblogs.foxite.com/kkchan/archive/2007/05/16/3797.aspx</link><pubDate>Wed, 16 May 2007 17:02:08 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3797</guid><dc:creator>kkchan</dc:creator><slash:comments>0</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3797.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3797</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3797.aspx</wfw:comment><description>&lt;p&gt;&lt;a href="http://www.microsoft.com/malaysia/techedsea2007"&gt;TechEd2007&lt;/a&gt; is one of the must attend event. Mark your calander to attend this event on 10-13 Sept 2007 at KLCC convention center, Kuala Lumpur, Malaysia. See you there!&lt;/p&gt; &lt;table&gt;  &lt;tr&gt; &lt;td&gt; &lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:36d4b727-9035-4876-a5e1-5bb6cb1627f2"&gt;&lt;img src="http://weblogs.foxite.com/photos/kkchan/images/3796/original.aspx" alt=""&gt;&lt;/div&gt;&lt;/td&gt; &lt;td&gt; &lt;blockquote&gt; &lt;p&gt;&lt;em&gt;Tech•Ed SEA 2007, Microsoft’s premier &amp;amp; largest annual conference in the South East Asia region, focuses on newly released products such as of Microsoft Office along with content about upcoming releases such as Windows Server code name "Longhorn". For four days in September, you can get technical training, information and resources to help you build, deploy, secure, mobilize, and manage solutions.&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;&lt;/em&gt; &lt;p&gt;&lt;em&gt;Tech•Ed SEA 2007 features:&lt;/em&gt;  &lt;p&gt;&lt;em&gt;&lt;/em&gt; &lt;p&gt;&lt;u&gt;&lt;em&gt;More than 120 breakout sessions&lt;/em&gt;&lt;/u&gt;&lt;br&gt;&lt;em&gt;This year’s event will feature even more speakers from Microsoft Corporation allowing you to hear about your favorite technologies from the sources who develop them. Create a personal learning program from 6 technical tracks with more than 120 breakout sessions.&lt;/em&gt;  &lt;p&gt;&lt;u&gt;&lt;em&gt;Hands-on experiences&lt;/em&gt;&lt;/u&gt;&lt;br&gt;&lt;em&gt;Tech•Ed offers opportunities to evaluate products both from Microsoft and from 250 of our most important industry partners. Additionally, based on attendee feedback from last year, we will be more than doubling the number of Instructor Led Lab sessions as well as introducing a whole host of new self-paced Hands On Lab content.&lt;/em&gt;  &lt;p&gt;&lt;em&gt;&amp;nbsp;&lt;u&gt;Networking with your peers&lt;/u&gt;&lt;/em&gt;&lt;br&gt;&lt;em&gt;Walking around Tech•Ed are more than 2,000 minds just like yours. 2,000 IT pros and developers to meet. 2,000 opinions to consider. Add to the mix Microsoft product team members and industry gurus and you will immediately see why a Tech•Ed crowd is like no other. &lt;/em&gt; &lt;p&gt;&lt;em&gt;Tech•Ed is a one-of-a-kind experience!&lt;/em&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:d4c68962-d3b1-4291-9c21-e5242ac44fac"&gt;Technorati tags: &lt;a href="http://technorati.com/tags/TechEd" rel="tag"&gt;TechEd&lt;/a&gt;, &lt;a href="http://technorati.com/tags/Conference" rel="tag"&gt;Conference&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3797" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1015.aspx">General</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1016.aspx">.NET</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1020.aspx">SQL Server</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1021.aspx">Software Development</category></item><item><title>Show images in grid</title><link>http://weblogs.foxite.com/kkchan/archive/2007/05/16/3790.aspx</link><pubDate>Wed, 16 May 2007 12:56:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3790</guid><dc:creator>kkchan</dc:creator><slash:comments>3</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3790.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3790</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3790.aspx</wfw:comment><description>&lt;p&gt;&lt;/p&gt; &lt;p&gt;Few days ago, my friend called me. He said that he has a field stored the path of some images. He want to&amp;nbsp;show these images in grid.&amp;nbsp;I followed Craig Boyd &lt;a href="http://www.sweetpotatosoftware.com/SPSBlog/PermaLink,guid,74d1b7b9-ae11-4c0c-b284-d1cb4b2f94b0.aspx"&gt;tip&lt;/a&gt; and posted the intructions which I sent to my friend at here if anyone might interested. &lt;/p&gt;&lt;p&gt;1. Create new class (CREATE CLASS ?) &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:21e2a179-3791-4f97-9d2c-bf344d3390ff"&gt;&lt;img src="/photos/kkchan/images/3787/original.aspx" alt=""&gt;&lt;/div&gt; &lt;p&gt;2. Place an image control on the container class. (Set Image.anchor = 15 if using VFP9)&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:91ceee6a-58b2-40b8-8940-64e9e9eabfe7"&gt;&lt;img src="/photos/kkchan/images/3788/original.aspx" alt=""&gt;&lt;/div&gt; &lt;p&gt;3. Select container object, select “Edit Property/Method …” from menu as shown below. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:18a4c2e5-5dcf-4ec8-8132-019849487b5e"&gt;&lt;img src="/photos/kkchan/images/3786/original.aspx" alt=""&gt;&lt;/div&gt; &lt;p&gt;4. Edit Property/Method dialog form will be shown. Select BackStyle from the list and check “Assign Method” and “Access Method” checkbox and click Apply. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:9bc5f144-5e38-4cfe-b5c8-b2e1ade637e2"&gt;&lt;img src="/photos/kkchan/images/3784/original.aspx" alt=""&gt;&lt;/div&gt; &lt;p&gt;5. Open backstyle_access method and put your code. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:e8d873cd-538c-438d-ad1a-03f06377ce77"&gt;&lt;img src="/photos/kkchan/images/3785/original.aspx" alt=""&gt;&lt;/div&gt; &lt;p&gt;6. Save your class. &lt;/p&gt;&lt;p&gt;7. Create a form, place your grid control and place your container class into column. (Remember to delete the existing column.textbox control). &lt;/p&gt;&lt;p&gt;8. Set controlsource to your column. &lt;/p&gt;&lt;p&gt;Below is the screenshot to show images in grid I received from him. &lt;/p&gt;&lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:7c8ce66c-bdbe-4965-ac73-dff991cfcbba"&gt;&lt;img src="/photos/kkchan/images/3789/original.aspx" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3790" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category></item><item><title>Anchoring behavour of VFP and .NET</title><link>http://weblogs.foxite.com/kkchan/archive/2007/04/19/3714.aspx</link><pubDate>Thu, 19 Apr 2007 10:41:00 GMT</pubDate><guid isPermaLink="false">8827bd1c-7596-4a8f-b0de-f59ce9ede522:3714</guid><dc:creator>kkchan</dc:creator><slash:comments>2</slash:comments><comments>http://weblogs.foxite.com/kkchan/comments/3714.aspx</comments><wfw:commentRss>http://weblogs.foxite.com/kkchan/commentrss.aspx?PostID=3714</wfw:commentRss><wfw:comment>http://weblogs.foxite.com/rsscomments/3714.aspx</wfw:comment><description>&lt;p&gt;Recently, I play around with anchoring feature in .NET. I found that .NET anchoring is more "accurate" in this scenario compare to VFP.&lt;/p&gt; &lt;p&gt;Let assume we have&amp;nbsp;few controls&amp;nbsp;placed at the center of form. There may be some situations we don't want to have anchoring at all because it make our screen look ugly, combobox become too long and etc.&amp;nbsp;We want these controls retain at the center with same size even though the form is maimized.&amp;nbsp;&lt;/p&gt; &lt;p&gt;Lets turn off anchor for all controls - set 0 (ZERO) to anchor property (VFP); set None to anchor property (.NET).&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:1c9006a3-25d5-4f77-bcdb-24f993b8d430"&gt;&lt;img src="/photos/kkchan/images/3712/original.aspx" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Figure 1 VFP Form at design time&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:a44dd6de-1233-4683-87a0-5301acfc93bc"&gt;&lt;img src="/photos/kkchan/images/3713/original.aspx" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Figure 2 .NET Form at design time&lt;/em&gt;&lt;/p&gt; &lt;p&gt;Let resize the form and see what will happen.&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:57ccc058-c117-4903-aeb8-4f7a7080cb20"&gt;&lt;img src="/photos/kkchan/images/3710/original.aspx" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Figure 3 VFP Form at runtime&lt;/em&gt;&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;p&gt; &lt;/p&gt;&lt;div class="wlWriterSmartContent" id="6960CE03-38FC-44df-87D4-FA4540212B06:2148f457-0581-4b76-a6b1-9e3f7912b471"&gt;&lt;img src="/photos/kkchan/images/3711/original.aspx" alt=""&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt; &lt;p&gt;&lt;em&gt;Figure 4 .NET Form at runtime&lt;/em&gt;&lt;/p&gt; &lt;p&gt;As we can see here, VFP controls retain at the same position. However, .NET controls's has been moved to center of form. From this testing, we can say that, VFP always use &lt;strong&gt;"Left, Top"&lt;/strong&gt; anchoring if we set anchoring off. Do you agree?&lt;/p&gt; &lt;p&gt;&amp;nbsp;&lt;/p&gt; &lt;div class="wlWriterSmartContent" id="0767317B-992E-4b12-91E0-4F059A8CECA8:0e899e46-f819-4d66-91e9-8cc81bdba7cb"&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/.NET" rel="tag"&gt;.NET&lt;/a&gt;&lt;/div&gt;&lt;img src="http://weblogs.foxite.com/aggbug.aspx?PostID=3714" width="1" height="1"&gt;</description><category domain="http://weblogs.foxite.com/kkchan/archive/category/1014.aspx">Visual FoxPro</category><category domain="http://weblogs.foxite.com/kkchan/archive/category/1016.aspx">.NET</category></item></channel></rss>