I want to close the program from anywhere, but not use HALT

I ran into an issue using Halt. Is there an alternative?

do you mean a remote close? Nettalk allows that.
Or do you mean the current user?

Or is it just that the Halt window mucked up the close?
Capesoft Messagebox has a replacement with many options, including logging.

I have used TaskKill.exe to terminate the current or all the WinPreview Exe’s (made by the Window Designer). This happens inside the Preview program itself, so it does kill the EXE that ran it.

See the CBWndPreview.clw file on GitHub line 4899 the TaskKillRtn ROUTINE. Just do a Find on ā€œTaskKillā€ … It’s not much code so I’ll paste it:

TaskKillRtn ROUTINE
  DATA    
BatFN   PSTRING(48)
Tm8     STRING(8)
CRLF    STRING('<13,10>') !Tests show max length below 350 chars so below PUTINIs safe from 1024 limit
FI_Filter   PSTRING(256)
Title   STRING(32)
  CODE
  IF ~GLO:IsPreviewEXE THEN
      IF 1=Message(COMMAND('0')&'||This is NOT a Preview EXE.||Do you really want to Halt It?','HALT',ICON:Hand,'Let Run|Halt It') THEN EXIT.
  END
  Tm8 = FORMAT(CLOCK(),@t05) &'00'
  BatFN='.\WinPreviewKill' & Tm8[1:4] &'-'& Tm8[5:8] &'.BAT'
  REMOVE(BatFN)     
  FI_Filter = '/FI "IMAGENAME eq WinPreview*"'
  IF SMCmd_wParam=SMCmd_HaltCapt THEN
     Title=GloT:Caption
     IF Title[1]='"' THEN Title=LEFT(Title[2:32]).
     X=INSTRING('"',Title) ; IF X THEN Title=SUB(Title,1,X-1).
     FI_Filter=CLIP(FI_Filter) & ' /FI "WINDOWTITLE eq ' & CLIP(Title) &'*"' 
  END  
  PUTINI('BAT', 'REM 1 ', |
    CRLF & 'TITLE Halt Window Previews' & CHOOSE(~Title,'',' of "' & CLIP(Title) &'*"' ) & |
    CRLF & 'ECHO OFF' & |   
    CRLF & 'COLOR 1E' & |   
    CRLF & 'CLS' & |   
    CRLF & 'REM /v slowwww: TASKLIST /v /FO LIST ' & FI_Filter & |     !Verbose List above table so can see more details
             ' | Findstr /ivb /C:"Session" /C:"Mem" /C:"Status" /C:"User" /C:"CPU"' & |
    CRLF & 'ECHO+ ' & |               !CRLF &'ECHO ={80}' &| !too slow--> 
    CRLF & 'ECHO+ ' & CRLF , BatFN ) 
  PUTINI('BAT','REM 2 ','Confirm Kill List' & |
    CRLF & 'ECHO TASKLIST ' & FI_Filter & |
    CRLF & 'TASKLIST ' & FI_Filter & |
    CRLF & 'REM ECHO ErrorLevel %ErrorLevel%' & |
    CRLF & 'ECHO+' & |
    CRLF & 'CHOICE /C:YN /N /T 99 /D N /M "Halt the above Window Previews? (Y/N)" ' & |
    CRLF & 'IF %ERRORLEVEL% EQU 2 EXIT /B 666' & |
    CRLF & 'ECHO+ ' & CRLF , BatFN )
  PUTINI('BAT','REM 3 ','Kill Previews ' & |
    CRLF & 'ECHO+' & |   
    CRLF & 'ECHO TASKKILL ' & FI_Filter & |
    CRLF & 'TASKKILL ' & FI_Filter & |
    CRLF & '' & |
    CRLF & 'REM ECHO ErrorLevel %ErrorLevel% & PAUSE' & |
    CRLF & ':EndIt' & |
    CRLF & 'DEL %0 ' & CRLF, BatFN )

  !if 2=message('BatFN=' & BatFN &'||Path=' & LongPath() &'||' & FI_Filter,,,'Run|Close' ) THEN EXIT. 

   RUN(BatFN,1) 
   REMOVE(BatFN) 
   IF RUNCODE()<>666 THEN HALT().  !User Says NO then BAT does EXIT /B 666

Interesting code trick. I run TaskKill from a BAT file that I create using a PUTINI. It has one bad line [BAT] that errors, but a CLS fixes that.

The above Kill filters on Image Name (EXE Name) WinPreview* with wildcard *. If I just wanted to Kill My Running EXE I would use the /PID # switch that takes the Process ID from GetCurrentProcessId() so there is zero risk of killing the wrong one.

Halt probably calls Windows ExitProcess that tries to shutdown cleanly, but can deadlock (read the notes).

TerminateProcess will ā€œunconditionally cause a process to exitā€ so is what you could try. I used TaskKill because I wanted to kill multiple EXEs

I use remote close to shut down my software that is running on workstations. I’ve been using Halt for a long time, but all of a sudden it’s causing an error. I have a small procedure I call to check if the ā€˜code’ that allows the program to run is good, if it is, it just returns. If it isn’t, it halts. It’s only called at the beginning of running the program. On other areas, I just call the procedure on the same thread, so I get a variable back which then if true, it closes the window, which is the main screen. If there’s no easy way, I’ll just rewrite the check code in a procedure that is not handwritten so I can just call it and return. I tried setting a global variable, but the variable isn’t set yet because I’m starting the procedure. I think I’ll just rewrite it. I wrote this procedure like 20 years ago. But you’d think Clarion would have a simple way to shut down the program. It even says in the docs that Halt shouldn’t be used on multi-dll programs. All of a sudden, I’m getting a really ugly error with a bunch of stuff that would scare the crap out of my customers. Before, it would just cleanly exit. I thought there was a program close in one of the tools I have… I think I have them all… not messagebox though, I had a ton of trouble with it years ago. But I’ll look into it.
Thanks

I think there’s a Clean Close Down Template, you might look into that.
MessageBox hooks the dialogs and Halt and allows you to replace them with your own procedures, so you have lots of control.

I have a feeling that Halt doesn’t necessarily close and remove everything properly, it just stops and exits.

post(event:closedown,1) turns out to work well. In this particular procedure, I close the one file I manually opened, and post to the main thread, which is 1. ChatGPT gave me the answer… it gave me a lot of other answers too, this one was at the bottom and worked perfectly for my circumstance.
Thanks for everyones help, it led me in the right direction. (Its actually 2 commas in the post(event:closedown) above. Must be some kind of html thing in this board?

Hi Ray,

That’s an interesting problem, and you can definitely hit edge cases (for example, a third party template hooking HALT and changing the expected behavior).

I just added two new shutdown helpers to vuFileTools that are aimed at your exact scenario.

vuCloseApp(Mode) gives you three behaviors:

  • Mode 0: cooperative close request (normal shutdown). Windows get a chance to close cleanly, but users may still see ā€œsave changesā€ prompts.
  • Mode 1: cooperative close first, plus a safety net. It requests a normal shutdown, then forces termination after a short delay if the app is still running.
  • Mode 2: immediate hard kill. No prompts and no cleanup, so unsaved work can be lost.

The other new function, vuCloseAppEx(Mode, KillDelayMS, WarnSeconds), adds two things: you can set the Mode 1 safety net delay, and you can optionally warn users and wait (for example, 30 seconds) before initiating the close so they can save work.

That might be a good fit for you because you can kick people out of the program, but still give them a warning that it is about to happen. If they are at the machine, they can save and close normally. If they walk away from a save prompt, it still exits.

This should work well for situations like ā€œclients launched from a server share and I need everybody out so I can update the EXEā€ because you can warn them, attempt a clean close, and still guarantee the app exits.

If anyone reading this is not familiar with vuFileTools, the main site is clarionproseries.com and the online function reference is here: https://clarionproseries.github.io/docs/vuFileTools/

I am building the installer now and it should be available soon.

(edit)

The new build is up and you can read about the new functions here:

I hope this helps everyone who needs this sort of functionality!

Charles

You can wrap your Clarion code in two backticks and it will look better and format correctly:

POST(EVENT:CloseDown,,1)

:slight_smile:

One more thing about the code you used.

POST(EVENT:CloseDown,,1) works fine as long as you are not sitting in a dirty FORM.

In my testing, if a FORM is open and has unsaved changes, posting CloseDown does trigger the usual ā€œsave changesā€ prompt, but it may not actually close the application frame afterward.

The reason is that once that prompt is up, the event processing has effectively shifted into the FORM thread/window, so the frame does not necessarily complete its own shutdown sequence.

This is exactly the kind of edge case where a safety net close mode like I just implemented in vuFileTools is useful, because it still attempts a clean shutdown, but guarantees the process exits even if the app gets stuck behind a save prompt.

That’s also the case that’s handled by MessageBox with a countdown timer.
I’ve been using Nettalk remote shutdown with massagebox for years and it works very well.

If you want to kill program and send an exit code, you can use ExitProcess.

The API is called in this repo, but building a procedure to call it and have the app use this shutdown procedure requires a bit of thinking and changes to the app in general, like Form’s to be aborted or saved.

CHAIN with an empty string will terminate the program.

CHAIN(ā€˜ā€™)

CHAIN('')

Docs says:

CHAIN terminates the current program, closing all files and returning its memory to the operating system, and executes another program.

Hi Ray,

What error are you getting from HALT()? Is it a compile error or a runtime error?

Best regards,

In this particular instance there’s no danger of that, but in many other cases, your code will work much better (and safer). I appreciate it, and others will to. I’ve had vufile tools forever and use it all the time. I’m glad you took over and glad you’re adding new tools.

Thanks Ray!

It’s a good library of functions and now that I have it in a new build system it is a lot easier to extend and document so I’m sure there will be more goodies added as we go along.

I replaced the closedown with the vuCloseApp(0). It works well. I know it’s closing normally because I have a little POP sound when my app closes. Nettalk has a way of shutting down the app over the lan, but I warn people to shut it down manually because I’m not sure if it shuts down correctly on the workstations. I’ll look into that… and see if I can replace the shutdown with this.
I think I used mailslot years ago. I built something like a kiosk display where it would show the transaction as it is being processed to the customer on a 2nd screen. In between, it would show ads for the store, which were created by flash files. Too bad they’re gone. I use the vuMail tool as well.
Thanks for all of your work.

I’m glad it helped out Ray.

Like anything there are multiple ways to get there sometimes and it is usually about finding the one that works best for your needs.

The vuMail template is long in the tooth now since Microsoft deprecated the underlying API and as a result it never got updated to modern security standards. As a result it won’t connect to many of the more secure servers these days.

But the good news is that we’re almost ready to release a new product that is a drop in replacement for the code called vuMailKit. It is built on modern subsystems that Microsoft recommends for email.

It works with all modern secure servers and even handles OAuth security with ease so it makes your customer’s experience easy in that regard too.

We’d hoped to have it out a while back, but decided to take a different approach in making it backwards compatible for vuMail users so we duplicated all 70+ functions in the new code (and added some more for the new features).

We’re working on the docs and such now and should have the Basic version out in a day or so.

There will also be a Pro version a bit later that gives you IMAP capability as well as an email client that you can rebrand and sell to your customers.

We’re also working on a Back Office edition that will make it easy to run and manage an email campaign, handle bounces, unsubscribes and mailing lists.

Looking forward to it. I use VuMail almost exclusively. The problem of course, most of our customers use Gmail… so we have to help those that need hand holding to create an app password in Gmail and use that. Then if they change their password or change their computer, it has to be redone sometimes because the data is stored in the system registry. I’m hoping there will be an (easy for me) way to use gmail without the whole app password thing. Is that what Oauth is for?
By the way, I’m using your vutools to test for internet connection before I use my FTP all over the place now so I can see if they’re expired for my subscription users. Works flawlessly so far. Testing it on customers computers now.

Hi Ray,

I’m glad to hear you are getting mileage out of the vuFileTools internet connection check. That sort of use case (fail fast before FTP, avoid support calls) is why it is there.

We’ve had a lot of positive feedback from developers about the new features we added. We have more in the works and are always glad to get suggestions from developers about things they need.

On OAuth, yes that is exactly what it is for.

With Gmail, the ā€œapp passwordā€ approach is basically a workaround for ā€œno modern authā€.

OAuth lets the user sign in to Google normally (including 2FA), grant consent, and then your app uses tokens instead of storing their Gmail password or an app password. So when they change their Google password, your app does not break, because you are not depending on the password in the first place.

On vuMailKit compatibility and storage:

  • Drop in compatible: vuMailKit is being built so your existing vuMail code can stay the same (same call patterns and behavior), so upgrading is meant to be ā€œswap the engine, keep the codeā€.

You literally remove the vuMail template from your app, add the one for vuMailKit and that’s it. There are optional features and settings of course that vuMail doesn’t have, but for developers that don’t need or care about them, the migration from the old tool to the new one is just that easy.

  • Registry settings: if your app already uses the vuMail Registry settings, vuMailKit can continue to honor them so you do not have to rewrite your configuration logic. If you do not use the Registry today, you will not be forced to start.

  • Secure OAuth storage: OAuth needs a refresh token (and related metadata) stored locally so the user does not have to re-auth every run. vuMailKit will store those secrets in secure storage on Windows (not plain Registry values). Specifically, we will store the OAuth secrets in Windows Credential Manager, protected by Windows DPAPI encryption under the current Windows user account. That means it is encrypted at rest, and it is not sitting in the Registry in a form that can be copied around.

  • Clean migration option: if you have existing installs where ā€œless secureā€ values are in the Registry, vuMailKit will provide an easy migration path: read the existing Registry values, write them into the secure store, and (your choice) either stop using the Registry after migration or keep Registry support enabled for backward compatibility. The default direction is ā€œmigrate then stop relying on Registry for secretsā€, but you stay in control.

The net result is that your customers no longer need the ā€œhand holding to create an app passwordā€ routine for Gmail. They sign in once through the OAuth flow, and it stays working across password changes. If they move to a new computer, the fix is a clean ā€œsign in againā€ instead of ā€œhunt down the right app password and hope the Registry values are correctā€.