Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations SkipVought on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Testing if a command was successful via custom confirmation message

Status
Not open for further replies.

breezett93

Technical User
Jun 24, 2015
128
0
16
US
Hello,

I am writing a small program to take a file, convert it, perform a small task in the file, then send it off to a final destination.

I'm looking for a way to output a "Transaction successful/failed" message. I read about MessageBox(). Is this the best solution?

If so, how can I "test" to make sure the program worked?

For example,

if(program successfully manipulated file/file transfered)
Output("Transaction Successful")​
else
Output("Transaction Failed")​
 
[pre]if (program successfully manipulated file)
Messagebox("Transaction Successful")
else
Messagebox("Transaction Failed")
Endif[/pre]
 
Assuming that your program takes the form of a PRG file, you need to include a RETURN command in that file.

The RETURN command will terminate the execution of the program, and return a value to the calling program. It is that value that you use to determine success or otherwise. The caller can then test the value, and use it to decide whether to display the message.

So, in very broad terms, your called program will look like this:

Code:
* MyProg.PRG
* Do the process
IF <the process worked>
  RETURN .T.
ELSE
  RETURN .F.
ENDIF

And the caller:

Code:
IF MyProg()
  MESSAGEBOX("Success")
ELSE
  MESSAGEBOX("Failure")
ENDIF

For more information, see the VFP Help for RETURN.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
Thanks for the info! So MessageBox() is the way to go.

 
MessageBox is, well, a message box, a dialog displaying a message. You might roll your own form displaying whatever you like, graphics, video, but for a simple text message the Messagebox is fine.
In the general case where you do batch processing of some tasks, you would only store the success/failure status with the job data for the batch or create a queue of messages or simply log error data. A messagebox needs attention of someone and you wouldn't like to click OK 10s or even 100s of times, if things fail for always the same reason, eg you send a batch of mails and each mail isn't sent, because your internet connection is currently down.

So it surely depends if this is just a single job the user starts and wants to see a confirmation of the job done or information about the failure - or if this is an unattended batch process, where you might want a summary of overall success or exceptions. There is no general rule of what to do, what's right or wrong, you have to know what you do and want.

Bye, Olaf.
 
So MessageBox() is the way to go.

You've slightly missed the point.

You asked how to test if the program worked. The message box doesn't do that. The message box is simply a way of displaying the result of that test. Whether it is the best way is an entirely different question.

In general, a message box is most useful if you need to be sure that the user has seen the message. That's because it requires the user to acknowledge it, either with a keypress or a mouse click - unlike, say, a Wait window, which might disappear before the user has noticed it.

If the process is particularly long - more than, say, half a minute or so - it is a good idea to display some sort of progress report while it is in progress. A simple percentage completion figure is adequate for that. But that doesn't obviate the need for a success or failure message.

One other point: If the process fails, for goodness sake tell the user why it failed and what they can do about it. I feel particularly strongly about this at the moment because last week I spent 20 minutes downloading and installing a certain component from Microsost, only to see a message box right at the end of the process, which simplly said "Error: Installation failed". I've no idea idea what the error was or what I could do to put it right. I hope you won't inflict that sort of thing on your own users.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
I don't think the process would take longer than 30 seconds. It's just adding a leading 0 to every entry in one column and then converting the file to a dbf.

Would a Try/Catch be best for determining if the program was successful or not at each step?

 
It depends what you expect might go wrong. If you think you might have a condition in your data that you can't otherwise check for, a TRY/CATCH/ENDTRY might possibly be appropriate. But in general you would use that construct as a form of error-trapping - a bit like ON ERROR, but more local in its scope.

For example, if you need to delete a file, but you are worried that the file might be open in another application (and therefore Windows prevents it from being deleted), TRY/CATCH/ENDTRY would be a good way of trapping that situation. But if you need to use a file and you are worried that the file might not exist, it would be better to check for that condition using the FILE() function.

Nor should you use TRY/CATCH to check for program errors, such as bad syntax or data-type mismatches. That sort of error (which ideally would be dealt with during program testing) should invoke your global error-handler, which should then shut down the whole application.

Mike



__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips and downloads
 
What helps you decide if something was successful or failed is very specific o what you do. As Mike already said TRY..CATCH..FINALLY only is one answer. If you save buffered changes of a table with TABLEUPDATE() it has a return value .T. or .F. stating success or failure/conflicts, if you use SQLExec() it has a return value meaning a status.

Not all failures create an error trapped by CATCH or ON ERROR, so also your own code should verify its own success and report it back in one or the other way. Whatever suits best. You might even use ERROR to cause an error, if some needed precondition isn't met.

There is no general way of doing things, just very many good principles. Mike already mentioned one: To give progress feedback in case something takes long. Processing any DBF can be short or long, depends on how much data there is in it. 2GB is not processed fast, for example.

In the task you describe sufficient code would do

Code:
Local lcStep, llSucess
TRY
   llSucess = .T. && assume we'll have no problem
   lcStep = "Retreiving data"
   SELECT something FROM somewhere INTO CURSOR csrPreresult READWRITE
   lcStep = "Transforming data"
   UPDATE crsPreresult SET somecolumn = "0"+somecolumn
   lcStep = "Creating dbf"
   COPY TO somefilename.dbf
   USE crsPreresult
   Messagebox("The output dbf was created")
CATCH
   llSucess = .F.
   Messagebox("The output dbf was not created. Failing at "+lcStep)
ENDTRY

RETURN llSuccess

This is putting the message in a somewhat user friendly manner, though most users won't know the single steps involved in creating the output dbf file, would they?

You can have more detailed and valuable info on what did go wrong for you as developer, by CATCH TO loException. This Exception object then tells more, eg an error number, message, line number of the failing line etc., for example the SELECT query can fail on "somewhere" not existing, "somewhere" not being accessible to the user or the query creating a too large crsPreresult cursor or network errors or, or, or.., as a developer you would want to know and the CATCH TO loException would tell more. In the same manner the routine triggered by any error can get info via AERROR(), LINENO() and more functions.

You can't be prepared for any thinkable failure of other software, hardware or administrative circumstances.

Using lcStep to give the user a hint what exactly failed doesn't need to be done for each line of code, often enough not at all, knowing you fail at this block of code might be sufficient.

Bye, Olaf.
 
breezett93 said:
take a file, convert it
Convert it to WHAT?
* A VFP Data Table/Cursor?

breezett93 said:
then adding a leading 0 to every entry in one column and then converting the file to a dbf.

If your utility was making this change from the outset in a VFP table/cursor, then no additional 'conversion' to a DBF is necessary.

Good Luck,
JRB-Bldr







 
I don't think the process would take longer than 30 seconds. It's just adding a leading 0 to every entry in one column and then converting the file to a dbf.

Would a Try/Catch be best for determining if the program was successful or not at each step?

It depends what you want to do.

Your original request was to display the result.

You COULD use Try/Catch:

Code:
Try
   <do something>
Catch
   Messagebox("there was an error")
Endtry

It's a rather tortured use of Try/Catch, which is intended to be a more focused exception handler. A more usual use would be to trap success of a specific operation and branch code appropriately:

Code:
llErrorOpening = .f.
Try
   Use MyTable
Catch
   llErrorOpening = .t.
Entry

If llErrorOpening
   MessageBox("Could not open...")
Else
   * other processing
Endif

Don't conflate trapping an error with reporting an error. They're very different conditions and actions.
 
Good point, Dan.

As the Messagebox is user interface it should not be put inside a (business) process doing something nonvisual (data manipulations of any nature). As I said earlier:
myself said:
you would only store the success/failure status with the job data for the batch or create a queue of messages or simply log error data.

As you can never know when a routine is called in batch actually any non visual process should just have a way of returning feedback to the calling program and only the code concerned with user interface should display messages to the user. The process itself might need attention and a decision of the user, but if itself is asking a yes/no/cancel decision that's breaking oop rules of the separation of concerns.

So you could also take my code example and just let it store the message it would report in something ike a nessages queue, which the UI layer of the application looks into and displays. The code can signal the success .T. or .F. and the calling code receiving success=.f. (failure) would look out for any messages to be displayed in that queue, it might be one, it might be more messages.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top