Sunday, December 14, 2008

Just the other day I got burned by what I consider a rookie mistake. I was working with a Visual FoxPro application (compiled as a multi-threaded DLL) that records application events to a Visual FoxPro table. To limit the size of the log table, the application re-used records after 500,000 events by updating the oldest record instead of adding new records.

As a general rule I know that I should always use a SELECT command before performing any command or function that processes a work area. For example, in the following sample code the SCATTER command is used to copy data from the current record to an array. Because this command processes the current work area only, I should always select the desired work area first.

* create a cursor with a single record
CREATE CURSOR "CURSOR01" (character1 C(10))
INSERT INTO "CURSOR01" (character1) VALUES("VALUE01")

* create another cursor with a single record
CREATE CURSOR "CURSOR02" (character1 C(10))
INSERT INTO "CURSOR02" (character1) VALUES("VALUE02")

* before calling the SCATTER command, select the work area
SELECT("CURSOR01")
SCATTER NAME loValues

* this should display "VALUE01"
WAIT WINDOW loValues.character1

The exception to this rule is any command that has an IN clause or alias parameter. For example, in the following sample code the REPLACE command can safely be used without selecting the desired work area first.

* create a cursor with a single record
CREATE CURSOR "CURSOR01" (character1 C(10))
INSERT INTO "CURSOR01" (character1) VALUES("VALUE01")

* create another cursor with a single record
CREATE CURSOR "CURSOR02" (character1 C(10))
INSERT INTO "CURSOR02" (character1) VALUES("VALUE02")

* this should display "CURSOR02"
WAIT WINDOW ALIAS()

* change the value in CURSOR01 cursor
REPLACE character1 WITH "NEWVALUE" IN "CURSOR01"

* this should display "NEWVALUE"
WAIT WINDOW CURSOR01.character1

In this particular situation, I was using a LOCATE command without specifically selecting the work area first. In an application compiled into an EXE, executing the LOCATE command when the current work area is blank would cause an Open File Dialog similar to the one below to appear.

However, in an application compiled into a DLL, the LOCATE command appears to be ignored if the current work area is blank. An error does not get thrown and the program simply executes the next line of code. :(

Fortunately, I was able to track down and fix the problem quickly. I'm sure that this is one of those mistakes that we all make at one time or another. I'm just hoping that by blogging about it, I will be less likely to make it again {g}.

posted on Sunday, December 14, 2008 8:35:47 PM UTC  #    Comments [0]
 Tuesday, April 15, 2008

Ever since I decided to post the Beyond Compare add-on utility, VFP2Text, it was always my intention to also release the source code. The reason I waited was to allow some time for any bug reports or major enhancement ideas. I figured initially it would be easier for me to handle them.

Well, it's been over a month since I first blogged about the add-on and so far no problems reported and the enhancement requests have been about minor changes. So, in keeping with my original plan, I have posted the source code for the utility on my web site here.

In return, I ask that you please share with me any cool enhancements or bugs you find. Thanks.

posted on Tuesday, April 15, 2008 11:03:32 AM UTC  #    Comments [0]
 Friday, April 11, 2008

Last night Mike Feltman, of F1 Technologies, did a presentation called "Collections". He discussed the basics of collections and arrays, and very some cool utilities he wrote for working with both.

One of cool things I learned had to do with the FOXOBJ clause of the FOR EACH ... ENDFOR command. For example, in the following code sample "loObject" is not a Visual FoxPro object, but is re-casted as a COM object.

loCollection = CREATEOBJECT("Collection")
loCollection.Add(CREATEOBJECT("Custom"))
FOR EACH loObject IN loCollection
   && loObject is a COM object, AMEMBERS() returns 0.
ENDFOR

Starting with Visual FoxPro 9, we can add the FOXOBJ clause so that loObject is a Visual FoxPro object. This is an important distinction, because functions like AMEMBERS() and COMOBJ() would produce unexpected results.

loCollection = CREATEOBJECT("Collection")
loCollection.Add(CREATEOBJECT("Custom"))
FOR EACH loObject IN loCollection FOXOBJECT
   && loObject is a Visual FoxPro object, AMEMBERS() returns 18.
ENDFOR

The FOXOBJ clause was not new to me. However, what I did not know was that using the FOXOBJ clause made the FOR EACH ... ENDFOR command almost 2x faster than the FOR ... ENDFOR equivalent.

* create a collection with 10,000 items
loCollection = CREATEOBJECT("Collection")
FOR m.lnX = 1 TO 10000
   loCollection.Add(CREATEOBJECT("Custom"))
ENDFOR

* test the performance using FOR EACH
m.lnStartTime = SECONDS()
FOR EACH loObject IN loCollection
   * do nothing, we already have an object reference
ENDFOR
? "FOR EACH: " + TRANSFORM(SECONDS() - m.lnStartTime) && 0.156 seconds

* test the performance using FOR EACH with FOXOBJ
m.lnStartTime = SECONDS()
FOR EACH loObject IN loCollection FOXOBJ
   * do nothing, we already have an object reference
ENDFOR
? "FOR EACH with FOXOBJ: " + TRANSFORM(SECONDS() - m.lnStartTime) && 0.016 seconds

* test the performance using simple FOR
m.lnStartTime = SECONDS()
FOR m.lnX = 1 TO loCollection.COUNT
   * get an object reference to the item
   loObject = loCollection.ITEM(m.lnX)
ENDFOR
? "FOR: " + TRANSFORM(SECONDS() - m.lnStartTime) && 0.031 seconds

Little gems like this are one of the benefits of attending local FoxPro user groups meetings. The opportunity to learn something new, meet new people, and the comradery are all valuable benefits.

If you missed this presentation, I heard that Mike will be presenting it again at the Grand Rapids Area FoxPro User Group on May 10th, 2008.


Links:
DAFUG http://dafug.org
GRAFUG http://www.grafug.com
F1 Technologies http://www.f1tech.com

posted on Friday, April 11, 2008 10:43:36 PM UTC  #    Comments [0]
 Wednesday, April 09, 2008

I downloaded my first issue of FoxRockX and I have to say that I like it. The format reminds me of the old FoxTalk issues. There is a good amount of content; twenty-four pages with out any advertisements. And of course, source code was included.

Out of the five articles in this issue, Doug Hennig's "Deep Dive: A Generic Import Utility" is my favorite. This article is part one of a two-part series that will demonstrate how to add a generic import utility to your application. In this issue he discusses the overall design and engine code. The next issue will be about the user interface.

Articles like this are a major reason why I subscribe to technical publications. Maybe I don't have a need for this today. But, I know that there is a good chance I will someday. And when that time comes I will more than likely use this article and sample code as inspiration for designing and writing my own.


Links:
FoxRockX http://www.foxrockx.com
Subscription in America & Asia http://www.hentzenwerke.com
Subscriptions in Europe http://shop.dfpug.com

posted on Wednesday, April 09, 2008 10:27:24 PM UTC  #    Comments [0]
 Tuesday, April 08, 2008

Last year we let our subscription to FoxTalk lapse for several reasons. For starters, there was the marketing tactics of Eli Journals. Then there was the matter where the archive issues, published before Eli Journals took over, were no longer available on the web site. But most of all, I felt that the content was not what it used to be.

So when I heard that Rainer Becker was starting a new on-line magazine called FoxRockX, I was like "hey that's cool". Then I heard that one of my favorite columns, the KitBox, would be coming back along with the always entertaining Marcia Atkins and Andy Kramek...and I thought "that's awesome". But when I found that a FoxRockX subscription included on-line access to the complete archives of FoxTalk issues...I was sold.

It is going to be so cool to have the old FoxTalk issues available in a searchable format. I don't know how many times I've been able to get a head start on a problem by taking advantage of something in one of those articles. Plus, I can't wait to see the new stuff.


Links:
FoxRockX http://www.foxrockx.com
Subscription in America & Asia http://www.hentzenwerke.com
Subscriptions in Europe http://shop.dfpug.com

posted on Tuesday, April 08, 2008 10:21:43 PM UTC  #    Comments [0]
 Saturday, March 08, 2008

Beyond Compare is one of my favorite developer utilities.  It's a tool for comparing folders, files, and folder like things such as ZIP and CAB files.  It can detect differences using several methods, such as the timestamp, size, CRC, attributes, and more.


Once two files are identified as not identical, you can drill down into the contents and see exactly what is different line by line using Beyond Compare's File Viewer.


This feature is cool, however the native file viewer only supports text files such as HTML, TXT, XML, and so on.  If you try to compare a binary file, you get something that looks like this.


I checked Beyond Compare's web site and found several plug-ins for viewing other binary files like BMP, GIF, JPG, and MP3.  Hmm, not what I was looking for, but could be a handy thing to have in the future.


I looked around a little more and I found some file viewer rules for handling binary files like DOC, XLS, and PDF.  Once again, not what I needed, but I would probably need some day.

So I decided to download a few of these and what I found is that the file viewer rules use Beyond Compare's capability to launch an external conversion program before a file is passed to it's native file viewer.  For example, the DOC rule uses a Visual Basic Script (VBS) to automate Microsoft Word, open the passed DOC file, and then save a copy of it to a temporary text file.  This temporary file is then passed to Beyond Compare's internal File Viewer for the line by line comparison.


Bingo!  If Beyond Compare can call an external conversion program, why not write something that converts FoxPro files to plain text files.  And thus VFP2TEXT was created.

Here's how it works.  I created a file viewer rule in Beyond Compare for all FoxPro related file types (CDX, DBC, DBF, DCT, DCX, FPT, FRT, FRX, FXP, H, LBT, LBX, MNT, MNX, MPR, MPX, PJT, PJX, PRG, QPR, SCT, SCX, VCT, VCX).  This rule calls executes VFP2TEXT.EXE passing both the original file name and a temporary file name.


Based on the file type, the VFP2TEXT.EXE program converts the passed file to a text file using one of the following methods:

  • Index (CDX, DCX): retrieve the index tag information only.
  • Table (DBF, DBC, FRX, SCX, etc): use the CURSORTOXML() function to generate an XML file.
  • Text (H, MPR, PRG, etc): no conversion.
  • Visual Class Library (VCX): use the Class Browser View Code feature to generate a PRG file.


If you would like a copy of this utility, you can download the latest version from my web site here.  When using it, there are a couple of things to keep in mind:

  • Beyond Compare will execute the conversion program twice, once for the file on the left and once for the file on the right.
  • Be careful about doing a Rules-Based Comparison on a large directory.  I prefer to use the Binary Comparison first, and then use a Rules-Based Comparison on the results.


Links:
Beyond Compare http://www.scootersoftware.com/

posted on Saturday, March 08, 2008 12:48:52 PM UTC  #    Comments [4]
 Friday, December 14, 2007

Last night Paul Mrozowski did a presentation called "Lucene.NET as a Document Search Engine".  He began by explaining that Lucene.NET is an open source indexing and search library written in C#.  It is not a traditional application.  Instead it is a tool developers can use to index and search documents, such as CHM, DOC, HLP, PDF, RTF, and TXT files. 

Paul first demonstrated how easy it is to install Lucene.NET, some of the configuration settings, and how to set it up to run as a background service in Microsoft Windows.  Next he showed us a COM wrapper class that he created in order to use Lucene.NET from Visual FoxPro.

The wrapper class could be used to index the source files and perform some pretty complex searches.  I liked the way it could include the surrounding portions of text with the search results.  For example, if you searched for the phrase "fox" in "Visual FoxPro Rocks", you could include a variable amount of the original characters found before and after the search phrase.

In addition to indexing document files, he also demonstrated how the wrapper class could be used to build your own index entries with meta data.  For example, you could index the contents of a memo field and then store the table name and record identification in the meta data.  Later, this information could be searched the same as document file.

Although the wrapper class did not have the complete functionality of Lucene.NET, it did fill the most basic needs.  He mentioned the idea of either posting the sample code to his web site or better yet making it a VFPX project.  All in all, it was a very cool presentation.


Links:
DAFUG http://dafug.org
Paul Mrozowski http://www.rcs-solutions.com

posted on Friday, December 14, 2007 7:06:16 PM UTC  #    Comments [0]
 Sunday, October 21, 2007

I started today with Doug Hennig's session Best Practices for Vertical Application Development.  Although I had attended this same session previously at the 2006 Great Lakes Great Database Workshop conference, I still managed to learn some new things.  If you missed this session I have a couple of book recommendations of my own.  Check out "Eric Sink on the Business of Software" by none other than Eric Sink.  And finally "Micro-ISV: From Vision to Reality" by Bob Walsh.

My last session was Marcia Akins QuickBooks Automation.  Marcia did an amazing job of demonstrating of how to get started with the QuickBooks COM component.  I especially liked all of the "gotcha" warnings.

In summary, I had a really good time at Southwest Fox this year.  It was good to see some old friends, make some new ones, and learn new ways to use my favorite development tool - Visual FoxPro.

posted on Sunday, October 21, 2007 10:27:01 PM UTC  #    Comments [0]
 Saturday, October 20, 2007

My first session of the day was Christof Wollenhaupt's Using CVS and Subversion with VFP.  Since I have only used Microsoft's Visual Source Safe and Sourcegear's Fortress, I was curious as to how CVS compared.  It is definitely something I would consider using in the future.  Christof also showed a utility he wrote to convert Visual FoxPro files into XML files before checking them into Source Code Control.  The utility also has the ability to convert the XML files back to binary files - very cool!  For those who are interested, you can download the TwoFox utility from his website at http://foxpert.com.

The next session was Craig Boyd's The Power of Regular Expressions.  I must admit that I never tried Regular Expressions before because they looked so complicated.  However, after Craig's presentation I've come to realize that they really are not that bad once you know the basics.  Of course it helps that Craig did an awesome job of explaining what how to read and write regular expressions, how to use them, and provided plenty of good real world examples.

Following lunch I attended Steve Sawyer's Basic Marketing for Custom Business Software Services session.  Steve had some very interesting ideas on marketing and networking.  He also recommended another book for the reading list - Rain Making: The Professional's Guide to Attracting New Clients by Ford Harding.

After that I went to Whil Hentzen's So You've Inherited an Application. Now What?  A lot of this session was geared towards custom software development shops with some good general programming ideas mixed in.  For example, when you are working on a project - don't end your day by stopping at the end of the module/class you were working on.  Try to stop somewhere in the middle and document what you had left to do.  The next day you'll find that you are able to get into the zone much faster.

posted on Saturday, October 20, 2007 9:59:12 PM UTC  #    Comments [0]
 Friday, October 19, 2007

Day 2 began with Steve Sawyer presenting a session on Software Project Management.  During the past couple of years I've taken more of an interest in the business side of software development, therefore this session was something I was really looking forward to.  Steve did a good job of explaining what a project manager is, and just as important, is not.  One key point that I got from the session was that project management requires a lot of diplomacy when they take the role of a liaison between customers and technical people.  Steve also recommended a book by Thomas Friedman, "The World is Flat".  I'll have to add that to my reading list.

My next session was Michael Hogan's 254 Fields in that Table?  This presentation addressed the problem where you need to store different fields for each record in a table.  For example, an Items table contains a record for Shoes and a record for Blenders.  Each Shoe item has a Brand, Color, and Size attribute.  Whereas each Blender item has a Brand, Motor Speed, and Watts attribute.  He demonstrated several common solutions such as a single flat table, many related tables, a generic attribute table, and using embedded XML.  Michael discussed the pros and cons of each solution, with last one being the best overall solution.

My third session was Christof Wollenhaupt's Introduction to COM.  This session discussed the history COM, what makes it so cool.  He also offered an excellent rebuttal to the argument that COM is dead and went on to provide evidence to the contrary.  A real highlight of this session is a function he wrote that can be used to load DLLs without registering them first!

After lunch, I attended Whil Hentzen's session Introduction to Client-Server Using VFP and MySQL.  One of the topics he discusses is the problem of loading MySQL on a development machine.  It is easy to be misled by the performance since the data is "local".  I though about this and wondered if running MySQL in a virtual environment, such as VirtualPC or VMWare, would address that issue.  If this topic was something you missed, I would suggest checking out Whil's book "MySQL Client-Server Apps with Visual FoxPro" at Hentzenwerke.  Having read the book and attended the session, I would say that the book covers what he presented and more.

Following that I went to Christof Wollenhaupt's session On the Dark Side of FoxPro.  This session explained a lot about how Visual FoxPro works internally.  He discussed data sessions, object creation, variables, memory management, tables and indexes, Rushmore optimization, and so much more.  This is one of those times when you don't want the presentation to end because you are learning so much.

My last session of the day was Doug Hennig's Developing Visual FoxPro Applications for Windows Vista.  Doug did an excellent job of explaining what has changed in Vista, how it affects application development and deployment, and what we need to do for our applications to run on Vista.  One of Doug's comments was something to the effect that Vista is not going to go away anytime soon - so we might as well get used to it.

posted on Friday, October 19, 2007 8:54:47 PM UTC  #    Comments [0]
 Thursday, October 18, 2007

Day 1 began with Michael Hogan's pre-conference session No Boundaries: Visual FoxPro Web Applications.  Michael did a great job of explaining the differences between web applications and desktop applications; and the advantages/disadvantages of both.  I especially liked the way he demonstrated "statelessness" using audience participation.  In addition he showed us some of his deployed solutions and took us for a tour behind the scenes.  If you want to get started in web applications, this session was a great way to begin.

After a quick dinner break, it was time for the Keynote.  I'll skip most of the details and jump straight to the cool stuff.

First, Christof Wollenhaupt demonstrated his Guineu project.  Guineu is an alternative runtime that allows a Visual FoxPro application to run on multiple platforms (Windows, Pocket PC, and Linux) without any modifications to the code.  Guineu is currently in development, but it still looks very promising.

Next, Toni Feltman demonstrated a couple of eTechnologia's developer tools.  The first tool was .NET Extender.  It provides the ability to use any of the .NET classes (including controls) in Visual FoxPro.  The second item was VFPCompiler for .NET.  This tool compiles Visual FoxPro forms and classes (SCX, VCX, and PRG) into pure .NET IL Managed Code.  Both of these tools are currently in alpha stage.

Finally, Alan Stevens and Craig Boyd demonstrated something they called "VFP Studio 2008".  It uses something that will be new in Visual Studio called the "isolated shell".  I wish I could explain more, however due to the time constraints they were not able to provide a whole of details.  So, I'm just going to leave it at that for now.  Hopefully Craig will be able to talk more about it on his blog at Sweet Potato Software.

posted on Thursday, October 18, 2007 6:38:30 PM UTC  #    Comments [0]