Sunday, July 30, 2006

FoxPro and the Windows API…


I’ve known for a long time that I ‘could’ leverage the Windows API (as can just about anyone) from within FoxPro, VB.Net and a score of other languages.

I just really haven’t done much with it until the past couple of weeks.

I’ve managed to pull together enough API functions to actually accomplish some things on the job that have been not only a problem, but a roadblock to progress as well!

One of the tasks, that has t take place monthly is the download of several files, some from FTP locations, and some from websites, these files are then parsed, massaged and utilized to produce the monthly supplements to the publications I’ve mentioned before.

At one time, a previous programmer had employed the object model from a mainframe connectivity product called “Extra!” to do some of this.

Unfortunately for me, and the users, somewhere else in IS the decision was made to switch to another product as the corporate standard.

Not that this is a bad thing, but, as part of the rollout each PC that had the new product installed, also had the old one removed. A very efficient, very common, practice, but it can also lead to some dependency issues. What I found was that with each of these changes, the application would cease to run on yet one more desktop.

So, I first looked for the manuals on the object model for the new product. Turns out the version in common use was no longer supported… I was however able to download a trial of the newer version, and began changing the code sections that involved communicating with, and downloading files from, the Mainframe.

In the middle of that I discover that the ‘trial’ version I’m using is being replaced by a new release… great! Now I’ll be building for the latest and greatest version!

Not so great, all of the functions did not work in exactly the same way, and required that I determine the version involved, and shift between now two separate sections of code to use the same product.

Needless to say, I got fairly frustrated.

For the most part I’ve automated the process to run on one PC from my “Automation Console” and have relieved the users of the responsibility.

Then about two weeks ago (around when I vanished from blog-land) I had a new problem.

We purchase a subscription to postal code databases. These are updated monthly and to retrieve the updates requires navigating to a website, logging in and starting the download process, individually, for each of the three files.

Now, in and of itself, this is not that big a deal, it only takes about 15 minutes in all to do so.

The bigger problem however is dependency. Several jobs, both on the Mainframe, and on the network, as well as the company’s interactions with an industry depend on the postal updates.

So, it’s either find a way to automate the process, or never be away from the office on the 1st of the month.

Necessity they say, is the mother of invention, and in this case at least it’s true!

I started doing a little research, and became very interested in a couple of Windows DLL’s called WinINet.dll and kernal32.dll.

A little more research and I found this site, which besides having a ton of free information on correctly using the Windows API from within FoxPro (well Visual FoxPro to be more specific), there’s also a membership (yes there’s a fee) option that opens a much wider group of code examples and ideas.

The best thing about it is that the code I received from them, was 100% royalty free, and I’m free to use it as I see fit. My mention of them here is one way for me to ‘give back’ a little, as their set up covers some very technical ground very nicely, and for a very reasonable price!

Now, on to the good stuff.

The problem:

I knew I could use the Internet Explorer object to navigate to the website in code, and possibly pass the username and password, but, when you do that you do not get an opportunity to pass a ‘local’ destination. As a result the “Save As” dialog box pops up, once again requiring user intervention to continue.

What I needed was a way to bypass that step and allow this process to be 100% automated.

The other issue was that the particular files I question are also “Zipped” and require “UnZipping” before the subsequent processes can utilize them.

I also needed an easy, and free, method of unpacking these files

The Solution

I employed functions from the WinINet.DLL to resolve the first issue. I’ve included a piece of sample code for those of you who aren’t completely bored with all of this, and might actually like to try something similar.

The second issue was a bit more difficult, I found a nice, free, unzip utility that runs from the command line. The problem was knowing when each process finished. A timer could be employed, but it’s fairly inaccurate, and the amount of ‘time’ would have to adhere to a ‘worst case’ scenario… Not something I like to do.

So, to solve that issue I turned again to the API kernal32.dll and a 32bit CreateProcess function that allows monitoring for the processes completion.

*---The sample for the HTTP download process---


*--WinINet FoxPro Option example
#DEFINE INTERNET_OPEN_TYPE_DIRECT 1
#DEFINE INTERNET_FLAG_NEED_FILE 16

DO DECL && declare external functions

PRIVATE hOpen
*--Make sure WinINet is available
hOpen = InternetOpen ("w32vfp=110", ;
INTERNET_OPEN_TYPE_DIRECT, 0, 0, 0)
IF hOpen = 0
? "GetLastError:", GetLastError()
? "WinInet is not available on this computer"
RETURN
ENDIF

LOCAL lcUrlBase,lcFileName, lcPathDst, lcFileDst, ;
lnCaSize, lnUaSize, lnMxSize, lcUserName, lcPWord

lcUserName = "Your User Name"
lcPWord = "password"
*--Basic URL
lcUrlBase = "http://www.SiteName.com/"
*-- remote file with UserName and password
lcFileName = "download.asp?file=114&login=" + ;
lcUserName + ;
"&password=" + lcPWord
*-- assign a destination directory
lcPathDst = "F:\DownLoads\"
*--&& assign a destination FileName
lcFileDst = ALLTRIM(STR(YEAR(DATE())))+CMONTH(DATE()) + ;
"CanadaPostalFile.zip"
lnCaSize = GetPostalData(lcUrlBase,lcFileName, ;
lcPathDst, lcFileDst, ;
"DownLoading Canadian Postal " + ;
"Codes File. . .", 20)

*--release Session handle and library
= InternetCloseHandle (hOpen)

*--Now Extract Downloaded File
=Run32Bit("F:\UnzipUtility\7za e F:\Downloads\" + ;
ALLTRIM(STR(YEAR(DATE())))+CMONTH(DATE()) + ;
"CanadaPostalFile.zip -of:\Railinc Postal*.* -y")

RETURN

*--------------------------------------------------------

FUNCTION GetPostalData (lcBaseUrl, lcFile, lcDstPath, ;
lcDstFile, lcProgMess, lnProgMax)

* get a handle of the remote file
hFile = InternetOpenUrl (hOpen,;
lcBaseUrl + lcFile, "", 0,;
INTERNET_FLAG_NEED_FILE, 0)

IF hFile <> 0
* even if there is no such file, the most evidence
* you will get is an ASCII file in response
* (404 error page)
lnFileSize = 0
lnProgVal = 0
lnByteCount = http2local (hFile, ;
lcDstPath + lcDstFile, ;
lcProgMess, lnProgMax)
= InternetCloseHandle (hFile)
ELSE
? "Unable to open source file"
? "GetLastError:", GetLastError()
ENDIF

RETURN lnByteCount

*------------------------------------------------------

FUNCTION http2local (hSource, lcTarget, lcMess, lnMax)
* reads data from a remote file
#DEFINE TransferBuffer 4096

*-- Progress Status Bar ------------
*---Note, if you have your own insert it here
* If you'd like this one, drop me an email
*--If you don't want one, comment this out
DO FORM cpsProgstat NAME wlStatBar
wlStatBar.Label1.CAPTION = lcMess

*--as we don't know the exact file size, we'll
* use what was passed or, if nothing default
* to 40K and reset as required
IF VARTYPE(lnMax) = 'N'
wlStatBar.ocxProgressBar.MAX = lnMax
ELSE
wlStatBar.ocxProgressBar.MAX = 40
ENDIF
*-------end progress/stat init

* create the target file
hTarget = FCREATE (lcTarget)
IF (hTarget = -1)
?? "invalid target file name"
RETURN -1
ENDIF

LOCAL lnTotalBytesRead, lnBytesRead
lnTotalBytesRead = 0

DO WHILE .T.
lcBuffer = REPLI (CHR(0), TransferBuffer)
lnBytesRead = 0

IF InternetReadFile (hSource, @lcBuffer,;
TransferBuffer, @lnBytesRead) = 1

= FWRITE (hTarget, lcBuffer, lnBytesRead)
IF lnBytesRead = 0
EXIT
ENDIF

lnTotalBytesRead = lnTotalBytesRead + lnBytesRead
IF MOD(lnTotalBytesRead,1000) = 0
lnProgVal = lnProgVal+1
*--Reset bar if required
* Comment this section out if not using
* a progress bar
IF lnProgVal > wlStatBar.ocxProgressBar.MAX
lnProgVal = 0
ENDIF
wlStatBar.ocxProgressBar.VALUE = lnProgVal
*-- end progress bar
ENDIF
ELSE
EXIT
ENDIF
ENDDO

= FCLOSE (hTarget)

*-- More Satus/Progress Bar updates
wlStatBar.Label1.CAPTION=LTRIM(STR(lnTotalBytesRead))+ ;
" bytes Ok"
wlStatBar.RELEASE

RETURN lnTotalBytesRead

*--------------------------------------------------------

PROCEDURE DECL
DECLARE INTEGER GetLastError IN kernel32

DECLARE INTEGER InternetOpen IN wininet;
STRING sAgent, INTEGER lAccessTypem,;
STRING sProxyName, ;
STRING ProxyBypass, STRING lFlags

DECLARE INTEGER InternetCloseHandle IN wininet ;
INTEGER hInet

DECLARE INTEGER InternetOpenUrl IN wininet;
INTEGER hInternet, STRING lpszUrl, ;
STRING lpszHeaders,;
INTEGER dwHeadersLength, ;
INTEGER dwFlags,;
INTEGER dwContext

DECLARE INTEGER InternetReadFile IN wininet;
INTEGER hFile, STRING @lpBuffer,;
INTEGER dwNumberOfBytesToRead,;
INTEGER @lpdwNumberOfBytesRead

DECLARE ;
INTEGER InternetQueryDataAvailable IN wininet;
INTEGER hFile,;
INTEGER @ lpdwBytesAvailable,;
INTEGER dwFlags,;
INTEGER dwContext
.
----------------------------

Last, but certainly not least the 32bit comand line process to allow us to know when each process completes, and return control to VFP when it does.

----------------------------


* Function Run32Bit
PARAMETERS pcFile2Run, plShowDone
#DEFINE NORMAL_PRIORITY_CLASS 32
#DEFINE IDLE_PRIORITY_CLASS 64
#DEFINE HIGH_PRIORITY_CLASS 128
#DEFINE REALTIME_PRIORITY_CLASS 1600

*-- Return code from WaitForSingleObject() if
* it timed out.
#DEFINE WAIT_TIMEOUT 0x00000102

*-- This controls how long, in milli secconds,
* WaitForSingleObject()
* waits before it times out. Change this to
* suit your preferences.
#DEFINE WAIT_INTERVAL 200

*--Declare the required kernal32 items
DECLARE INTEGER CreateProcess IN kernel32.DLL ;
INTEGER lpApplicationName, ;
STRING lpCommandLine, ;
INTEGER lpProcessAttributes, ;
INTEGER lpThreadAttributes, ;
INTEGER bInheritHandles, ;
INTEGER dwCreationFlags, ;
INTEGER lpEnvironment, ;
INTEGER lpCurrentDirectory, ;
STRING @lpStartupInfo, ;
STRING @lpProcessInformation

DECLARE INTEGER WaitForSingleObject IN kernel32.DLL ;
INTEGER hHandle, INTEGER dwMilliseconds

DECLARE INTEGER CloseHandle IN kernel32.DLL ;
INTEGER hObject

DECLARE INTEGER GetLastError IN kernel32.DLL
*---------------------------------------------

*-- STARTUPINFO is 68 bytes, of which we need to
* initially populate the 'cb' or Count of Bytes
* member with the overall length of the structure.
* The remainder should be 0-filled
START = long2str(68) + REPLICATE(CHR(0), 64)

*-- PROCESS_INFORMATION structure is 4 longs,
* or 4*4 bytes = 16 bytes, which we'll fill with nulls.
process_info = REPLICATE(CHR(0), 16)

*-- Start the program that was passed in
* (EXE name must be null-terminated)
File2Run = pcFile2Run + CHR(0)

*-- Call CreateProcess, obtain a process handle.
* Treat the application to run as the
* 'command line' argument, accept all other
* defaults. Important to pass the start and
* process_info by reference.
RetCode = CreateProcess(0, File2Run, 0, 0, 1, ;
NORMAL_PRIORITY_CLASS, 0, 0, @START, @process_info)

*-- Unable to run, exit now.
IF RetCode = 0
=MESSAGEBOX("Error occurred. Error code: ", ;
GetLastError())
ELSE
*-- Extract the process handle from the
* PROCESS_INFORMATION structure.
hProcess = str2long(SUBSTR(process_info, 1, 4))

DO WHILE .T.
*-- Use timeout of TIMEOUT_INTERVAL msec
* so the display will be updated.
* Otherwise, the VFP window never repaints until
* the loop is exited.
IF WaitForSingleObject(hProcess, ;
WAIT_INTERVAL) != WAIT_TIMEOUT
EXIT
ELSE
DOEVENTS
ENDIF
ENDDO

*-- Show a message box when we're done,
* If desired
IF plShowDone
=MESSAGEBOX ("Process completed")
ENDIF

* Close the process handle afterwards.
RetCode = CloseHandle(hProcess)
ENDIF

RETURN


********************
FUNCTION long2str
********************
* Passed : 32-bit non-negative numeric value (pnLongVal)
* Returns : ASCII character representation of passed
* value in low-high format (lnretstr)
* Example :
* m.longval = 999999
* lnLongStr = long2str(m.long)

PARAMETERS pnLongVal

PRIVATE i, lnretstr

lnretstr = ""
FOR i = 24 TO 0 STEP -8
lnretstr = CHR(INT(pnLongVal/(2^i))) + lnretstr
pnLongVal = MOD(pnLongVal, (2^i))
NEXT
RETURN lnretstr


*******************
FUNCTION str2long
*******************
* Passed: 4-byte character string (lnLongStr)
* in low-high ASCII format
* returns: long integer value
* example:
* lcLongStr = "1111"
* lnLongVal = str2long(lcLongStr)

PARAMETERS lcLongStr

PRIVATE i, lnRetVal

lnRetVal = 0
FOR i = 0 TO 24 STEP 8
lnRetVal = lnRetVal + (ASC(lcLongStr) * (2^i))
lcLongStr = RIGHT(lcLongStr, LEN(lcLongStr) - 1)
NEXT
RETURN lnRetVal
.
----------------------------

Well, I hope that helps you with a problem you might have in the future. Again, if you really want to get a 'handle' on integrating API funtions into your VFP applications, check out News2News!! They've got the goods!!



Technorati Tags: - - -
-IceRocket Tags: - - -

Saturday, July 29, 2006

Time just slips away…

I know it’s been forever since I’ve blogged anything. My wife even commented yesterday that it’s been nearly a month!

I know, at least part of, the reason is that much of what I’ve been thinking, feeling and therefore tempted to write about, is geopolitical in nature, and I’ve tried, for the most part to leave that out of my blog posts.

In my mind, the last thing the blog world needs is another amateur geopolitical analyst, lord knows there’s no shortage of them.

Today however I found myself sitting in amazement as some guy on the news was talking about how Israel is ‘over-reacting’… That the war in Iraq and elsewhere in the middle east is primarily George Bush’s fault and the US’s “Cowboy Diplomacy”.

So if you’d rather not read a geopolitical rant from me, you should stop here.

Is the memory span of these “news” folks really that short? That not even five years after the September 11th attack, they’ve managed, in the interim, to rewrite history such that the events on that day were somehow *our* fault? Was I the only person who clearly saw that a “Global War on Terror” would not stop in Afghanistan, or Iraq, for that matter?

Do they really think that if we just go up to the likes of Hezbollah, Hamas and Al Qaeda folks and give them a hug they’ll stop hating us? Have they forgotten that to these folks we’re ‘non-believers’ and that it’s their duty to rid the planet of any, and all, non-believers?

Is it clear only to me that this wave of Islam inspired terrorism, that hides behind calling it a “Jihad” or holy war, is a fanatical splinter of the Islamic faith, and that no amount of reasoning, or rational discourse is about to sway their beliefs?

Sometimes I wonder if folks are just so obsessed with their lawns, cars and the next trip to Starbuck’s that they just can’t see past their own little private reality.

Do I think that Bush, or Israel for that matter has done everything right so far? No I don’t. Do I have a better feasible, workable solution? No, I don’t. Thankfully, it’s not my job to do those things. I promise you I’d be far more aggressive than anyone has been so far!

I know people are dying, on all sides, and in my heart I wish that wasn’t happening. But as my grandmother used to say, “Wishing don’t make it so”.

The sad reality is, when wars are waged, good people die. Civilians, and military alike, the fact remains, people die. There’s no such thing as a ‘clean’ war where only combatants, or even enemy combatants, die. Non-combatants have been dying as battles are fought since the beginnings of time and it’s not likely to change in our lifetime.

These terrorists don't want to convert or to rule us. We are a vile infestation of Allah's paradise. They don't care how "progressive" we are, how peace-loving we might be, or how much you sympathize, and/or empathize, with their cause.They want you (and I) dead, and think it is God's (or more precisely Allah’s) will for them to do it, and, that they’ll be rewarded in the afterlife for giving up their life to do so.

In that way, these folks are not all that different from the ‘Crusaders’ of times past, where wars were waged simply because one group believed differently from another, each staunchly believing theirs was the true, and proper religion. The only thing that’s really changed is the ability to kill on a broader scale and from greater distances. The reasons however, remain the same.

There will be no peace, not as long as these folks have access to weapons, explosives and other “war resources”. Those resources will always be available as long as there are nation states, sympathetic to their cause.

I do know this, the solution is not to stick our heads in the sand and ‘wish’ it all away.

We live in an ‘accepting’ society, one where our right to worship is protected and I know, that for some, it’s difficult to imagine a world where those rights don’t exist. But, that world exists, and we see it everyday on CNN, Fox and MSNBC. Yes, they’re killing American soldiers, but if you look at the numbers, they’re killing far more of their own countrymen (and women and children). Why? Simply because they’re Shiite instead of Sunni, Sunni instead of Shiite, or that some other, similar difference exists between them.

I fear that the only way this will ever ‘end’ is when folks like Al Qaeda, Hamas and Hezbollah no longer exist, or when they’ve succeeded in eliminating those of us they view as the ‘infidels’ are gone.

God forgive me, I pray it’s us, and not them, who survive.

A writer who I’ve found to have both a historical, well read, and a very balanced perspective on all of this can be found here.

A couple of the articles I really enjoyed were his strategic overview of the war on terror and his essential library.

If you’ve managed to stay with me this far, thank you, I appreciate it. Hopefully, getting this written will free up my mind for some other, less serious thoughts to emerge!

As always, your thoughts, comments and ideas are welcomed!
----------------------

Technorati Tags: - - -
-IceRocket Tags: - - -

Sunday, July 09, 2006

Hurry up and wait. . .

I think the first time I ever heard the phrase was shortly after I hit the ‘Boot Camp’ in 1971, I may have heard it before that, but I don’t recall it that way.

The Navy seemed famous for demanding we be somewhere, at some particular time, usually under threat of disciplinary action if we were not there at the assigned time. We’d go through whatever was necessary to get there, on time, and nearly always would end up standing around, waiting for who ever ‘demanded’ we be there to show up and let us know ‘why’ we were there.

It’s funny, I don’t recall ever having to be anywhere before that, except to work, at a specific time, and for me anyway, when I got to work, there was no waiting around, there was always something to start right in on. The concept of hurrying, to later wait, never even crossed my mind until my stint in the military.

It’s returned intermittently over the years, but lately it seems to have invaded everything I end up involved in!

The latest was a series of interviews I did, through a recruiter, for a company looking for a FoxPro expert. Prior to the first interview, there was a lot of discussion about ‘how fast can you start’, ‘the client isn’t going to want to wait’, etc… as there often is, but this time things progressed past that stage and on to the second interview.

In the first interview the call was within a minute of the time they’d agreed to call, the second was 15 minutes after the agreed upon time…. The interview went well, and I got a sense that the manager was looking at me for a broader role than the one I’d originally started interviewing for… after the fact, the recruiter confirmed that the person interviewing me had actually indicated exactly that in her summary of our interview.

Again there was a ‘you will be ready to move on this’ type of discussion, and again I’d confirmed my timeframes.

It’s been two weeks today since that interview, last week the company said we’d all talk on Wednesday, then on Wednesday moved that discussion to this morning… and today, it’s been moved off until next week.

I’m not quite sure what to make of all of this, initial urgent, pressing needs talk…. Followed by a rather lengthy ‘lull’ period post interview… the recruiter assures me I’m still in the game… that it’s not a matter of if, but when… If that’s true, I’m wondering now how ‘urgently’ I should be willing to transition… 2 weeks? 3 weeks? 4?

It’s not just this one incident; by the way, it seems life has taken that course over the years.

Doctor’s offices complain if you’re late, but if you’re on time, they have no problem letting you sit for an hour or more because the “Dr is running late”… if they expect a call from me, if *I’m running late, shouldn’t they extend the same courtesy to the Doc’s patients? After all we *are the ones paying the bill… and their salaries, the office rent etc…. Hell, if my cable company is running late, not only do they call, they give me a $10 credit on my account for my inconvenience!!

I find myself wondering when this shift occurred. When everyone, especially business folks, became so ‘all important’? I know it wasn’t always this way.

When I was a sales rep, my customers would almost always apologize if they’d kept me waiting when we had an appointment. I know that if I was running at all late, I would find a pay phone (remember those?) and call in, even if it meant I’d be a few minutes later. If for no other reason, than to let them know I respected their time at least as much as they respected mine.

When my wife was in the hospital recently, and she’d been instructed to not get out of bed without one of the nursing staff present, I went out to the nurse’s station (after pressing the call button and waiting 5 minutes) to request someone come to assist her to the bathroom… when I made my request I was told, and I quote

“Someone will be there as soon as we finish our reports”

I looked at the nurse who said that to me and replied

“I’m sorry, I must not have made myself clear, someone, will come with me, right frickin NOW, or I’ll have the hospital administrator up here explaining to me why reports are more important than you caring for my wife!”

Amazingly enough, ‘someone’, came right to the room with me.

Why were those reports more important than the patient? How many other calls were going unanswered? When did it become acceptable to provide care when it was convenient? I know it hasn’t always been that way.

Have we all become so disconnected in our electronic ‘space’ that we’re forgetting those intrapersonal skills we learned as kids? Do kids today learn those skills? Have video games, the internet, email, cell phones, text messages and the like so disconnected us from being human that we fail to see the ‘human side’ any more?

If so, then the promise of a smaller world as the result of ‘connectivity’ is a long way from fruition… the world may be ‘smaller’ in that we can reach out and touch folks around the globe almost effortlessly… if we lose sight of who’s on the other end of that contact though… what’s the point?

I’m waiting patiently to hear about the gig… patiently because I’m working… if I wasn’t I’d be snatching up the first gig that came my way. I wouldn’t be telling the other client to ‘hurry up’ though; I’d just take the first solid offer that came my way.

I remember the day I came to this gig, earlier in the day, I’d had another interview. At the close of the interview the fellow said:

“You should be aware I’ll be interviewing other candidates”

To which I replied:

“Thanks for making me aware of that, you should also be aware I’ll be interviewing other clients as well”

When they called me back in 10 days, I told them I’d already taken an assignment. The client (as well as the recruiter) was pretty upset, inferring that I should have ‘waited’ while they made up their mind. I remember thinking that had I waited, they might have never called back. They were, after all, interviewing others.

I don’t really have any answers, just more questions about this issue. I’ve thought about it quite a bit lately, but no clear, “ah-hah!!” has come to me… maybe it’s the general continuation of the *me generation sliding into more of the fabric of daily life… maybe it’s just the over all pace of life in general… I just don’t know.

I do know, I don’t like the trend though!

What do you think?


Technorati Tags: - - -
-IceRocket Tags: - - -

Thursday, July 06, 2006

They say the first step is admitting you have a problem….

So I’ll admit it, I’m addicted… hopelessly, utterly and completely under its spell… from the way it sounds, to the way it smells… I’m flat out a horsepower junkie.

Cars, trucks, motorcycles and outdoor power equipment… tillers, mowers, blowers, chain saws, weed eaters, generators, splitters, tractors, chippers… beg, borrowed, purchased or rented… I just love using gasoline powered equipment.

I know, the price of gas is close to $3/gallon, and we’re “running out” of oil… (Except there seems to be no shortage once the price goes up… ever wonder about that?)… and folks seem to think that electric powered stuff is ‘cleaner’ more environmentally ‘friendly’… which of course means the polluting is being done in someone else’s backyard…

But, folks, the hum of an electric motor does absolutely nothing for me.

There’s no thrill of that first ‘cough’ as the motor tries to fire on the first pull… no satisfaction in the way it settles in at speed… or the sweet smell of the two cycle engine on a chain saw or weed eater as you fire it up first thing in the morning…

Then there’s the difference in raw power… the shear volume of work, the right small engine, paired with the right pulleys and belts, or better yet the perfect hydraulic pump, can do is astounding… Despite having owned, rented, and borrowed all sorts of equipment over the years, I never cease to marvel at what can be accomplished by one man with one of these tools.

I mean I’m amazed at what *I* can do… but seriously, I’m amazed at what someone truly talented can do as it’s always three to four times what I get done.

I’ve tried to quit, go cold turkey, those were not happy times….

I sold my 18Hp, 3 cyl diesel tractor, along with the 50” mower deck, 48” roto-tiller and rear blade… got rid of the big Toro weedeater (brush cutter actually)… the lawn mower, almost everything actually… even went so far as to hire a ‘service’ to come in and take care of my lawn…

Those were dark days indeed… I’d find myself in the garage looking over the new models in catalogs from Stihl, Troy-bilt, John Deere, Homelite, etc… hiding the catalogs so my secret wouldn’t be discovered….

It was all in vain… the first time I fired up the chain saw here (which was the one piece I didn’t sell… hey, you never know, I might have needed it for protection)… the ‘thirst’ was back…. And I’ve been battling, albeit losing, with it ever since.

Maybe if I'd sold the chain saw... a Stihl 041-Farm Boss... I bought it nearly 30 years ago this year... after a lawn mower it was the first, "just for me" piece of outdoor power equipment... Since then it's cut at least 200 *full*, not face, cords of wood... trimmed untold limbs and help clean up dozens of yards, and a couple of roads after bad storms... A true friend in need.... how could I sell it?

I get my ‘fix’ every so often by renting something… but the real juice is in buying, loading up and bringing home a new piece of power equipment!! Saturday… I fell totally off the wagon… and bought a new Troy-bilt Chipper/Shredder… 6.5Hp of pure gasoline fired Intek power… RR…RRRR….RRRRRRRR!!!

Can you guess what I’ll be doing next? Well, as time and temperatures permit anyway… that’s right…. making mulch of the read falls, low hanging limbs and other ‘yard waste’!!

Hey, I know, I’m being eco-sound… after all isn’t it better to make my own mulch than to send this stuff off to a land fill?

As always I’ll post some before and after pics in the albums as I progress… I’m sailing now… cruising on that gasoline fumed crest … and all is right with the world… What I fear though… is what it will take to feel this way the ‘next’ time…

If you ever see a bearded old fart, on the street, and begging for spare tractor parts… take pity on me, throw me a spark plug or something… I tried.. I really, really tried… but the jones is back… with a vengeance!
------------------------

Note: I hope my attempt at humor isn’t lost… while I do confess to a long standing love affair with gasoline powered anything… and it does border on an addiction… it really is under control.. honest!!


Technorati Tags: - - -
-IceRocket Tags: - - -

Tuesday, July 04, 2006

FoxPro Moves to 12th… No, Stays in 13th!

See the actual chart here

It moved up one more spot in the past month, although temporarily to 12th, but as of today, it’s in 13th again.

That said, at this time last year it was in 35th!! That’s right, it moved up 22 spots over one year ago. In contrast, VB.Net was in 16h at this time last year, and is now in 19th.

Visual FoxPro is now listed as an ‘A’ language, VB.Net, a ‘B’.

Java remains at number one again this month, moving up one spot from the #2 slot it had last year.

I remain exited about FoxPro’s climb this year. I know part of it is due to the number of us out here posting about our success stories as well as doing a bit of ‘evangelizing’ about the product. I also know that a good part of it is also due to the fact that it remains a solid business tool.

FoxPro was one of, if not the, first of the MS languages with the ability to consume web services. It’s got an extremely versatile language that’s been tuned over 20+ years to provide incredible data manipulation capabilities.

Couple that with the ability to work easily with Oracle, DB2, MS-SQL or the native VFP database container (DBC) and you have a tool that exceeds TOAD, or Squirrel in not only working with ‘raw data’, but as a front end to those stores as well.

I know Microsoft will never give the press to FoxPro it gives to Access or SQL Server, as they see it as competing with both of them (something it does very well by the way), and as the pricing model does not separate the ‘data engine’ from the language, and provides the developer the ability to distribute their application without the end user needing a copy of VFP there’s just no profit motive for them to start doing so.

I am seeing a growing community of FoxPro ‘bloggers’ though… and some talented ones as well. I read a discussion this morning about some of us creating a site that showcases Visual FoxPro success stories. I think that’s an excellent idea, and one I think I’ll incorporate into the revamp of one of my sites I’m currently working on.

For those of you who are not ‘techies’ or programmer types, think about it this way. Imagine you spent 10, or 20 years of your life, learning how to use a tool, or better yet a ‘set’ of tools to do your job. Then, one day, you’re told the ‘tool set’ you’ve invested time, and money, to become expert at…. Is no longer an acceptable tool set for you to use.

To me, it’s similar to telling a mechanic, who’s managed to become proficient, and make a living with, sockets, ratchets, screwdriver and hammers, being told those tools can no longer be used, and they now have to use an ‘new and improved’ tool set. Never mind that most of the new tools don’t look, feel or work like the old ones, but in many cases require more time, money and effort to not only use, but to master as well.

I’ve made a fairly big investment in .Net, and while I’m far from the expert I am in FoxPro, with .Net, I’m certainly proficient.

Unfortunately, even if I was to purport .Net expertise, the going rate for .Net programmers is about half what I’d earn on a similar project in VFP. Like that mechanic, I still need to feed and provide for my family, so I’m going to take the work that will allow me to do so, all other things being equal.

In addition, in the right hands, VFP is still one of the fastest development platforms around allowing a VFP guy like me to model, and present an interface to the customer, complete with a basic data model, in days, not weeks or months.

I’m taking steps to get my blog ‘googlized’ so it’s included in the “Tiobe Index” calculations… the way I see it, FoxPro needs all the free press it can get.


Technorati Tags: - - -
-IceRocket Tags: - - -

Monday, July 03, 2006

A Little Manual Labor Is Good For The Soul. . .

Or in this case, a lot of manual labor!

I took the concept of ‘Labor Day’ and decided to embark on another labor intense weekend project.

About half of our lot is ‘overgrown’… I’m sorry, it’s a “Natural Area”.. in current landscape speak.

One of the reasons I believe it was being kept as a natural area, instead of as lawn, is that much of it is so steeply sloped as to make it difficult to mow. One of the reasons I’ve let it stay ‘Natural’ is that I liked the fact that from the street, it’s very difficult to even see our house.

Why, well from the house, it’s also very difficult to see the street, or most of the neighboring homes, so, despite living ‘in the city’ it can feel like we’re ‘in the country’.

Unfortunately, as anyone who lives in or around wooded areas can attest, these areas also are a breeding ground for all sorts of summer insects, and I decided that this year I was going to attempt to reclaim some of that land. While I want to keep it ‘natural’, I also want to be able to walk around on it and not have to fight my way through brush, mosquitoes and all other sorts of annoying insects.

Also, in the center of this area is a drainage conduit (otherwise known as a “ditch”) that needs some attention. There are some washed out areas and one ‘hole that needs to be filled in. Last year when I’d rented the tractor I tried to get back in there with it, but the undergrowth was so thick, and there were so many deadfalls that it was close to impossible to find a direct route in.

So, as phase 1 of my reclamation project I decided to see what I could accomplish with a day and a half and a walk behind brush cutter. I’m sure you’ve seen them advertised, the most common is the DR field and Brush Mower, and there are other, similar ones as well. The one I rented was made by Murray, who makes most of the Lawn and Garden equipment you see with a ‘store’ brand on it.

It was 15HP, had 4 forward speeds, and one reverse speed. Al I ever used was 1st, and reverse… and often I was wishing 1st was even slower than it was. This area was very, very overgrown, and while the going was slow, this little machine did (what I think) is an amazing job.

I had to enlist the chainsaw, and a pair of heavy duty loppers to help get though some of the thickest stuff, but over a day and a half I managed to really make some headway.

I’ve posted some before and after pics here and as you can see I knocked down a lot of brush.

One of the things I liked best was that the machine essentially mulched everything up into fairly small pieces, leaving the area looking like I’d actually mulched it (I didn’t).

It was tough work though, and with the temps here in the 90’s and the humidity fairly high as well, it was hard on this old body of mine. It’s much tougher work than it looks on TV, when working through the heavy stuff. On the other hand in the couple of small areas where I had mostly tall grass and ivy, it was about the same work as mowing the lawn.

It cost about $80 to rent the machine for Saturday afternoon and Sunday, considering one of the machines costs about $2,000 to buy, it was a bargain in my book. I would only use one once, maybe twice a year, so owning one doesn’t make much sense to me.

Oh, if you plan on renting one, a tilt bed, or ramped trailer is the way to go… it’s far to heavy to lift in and out of a pickup bed!!

I’m off today and tomorrow as well, but I think I’m going to find something less, labor intensive to do!!

Enjoy the 4th!!!


Technorati Tags: - - -
-IceRocket Tags: - - -