Jump to content
Sign in to follow this  
pdanes

Detect DOS app waiting for KB input

Recommended Posts

pdanes

I have written an Access database that uses the AutoITX3 DLL to send text to a DOS application. It is a legacy text editor that a client is unwilling to give up - the database reads text files from this editor and indexes the contents. The database is read-only, so when the user wants to repair something, he presses a button to activate the editor. The editor runs inside DOSBox and I use the AutoITX3 Send function to give the editor a few initial commands. The problem is timing - running under Windows, the editor's start-up time is highly variable - sometimes almost instant, sometimes five to six seconds, depending on what else is going on (virus scan, memory full of junk that has to be swapped out, etc.). A long enough sleep time to insure the editor is ready for input results in unnecessary wait time for the user, a shorter time means the sent text sometimes gets shoveled into the text file, because the editor is not ready for the commands yet.

Is there a call that will tell me when the --**-> DOS application INSIDE the DOSBox window <-**-- has run out of things to do and is waiting for keyboard input?

Pete

Share this post


Link to post
Share on other sites
Sunaj

Is there a call that will tell me when the --**-> DOS application INSIDE the DOSBox window <-**-- has run out of things to do and is waiting for keyboard input?

Maybe monitor the CPU usage of DOSBox? Or is there any visual indicators you could go on? If possible I think the latter would be better for reliable(ish, sorry but) results. Interesting little hack you got going btw! ;)

Share this post


Link to post
Share on other sites
Richard Robertson

There's no way to tell for sure. Technically it can accept input and give output at the same time.

Nothing will work reliably.

Share this post


Link to post
Share on other sites
pdanes

> Maybe monitor the CPU usage of DOSBox?

The CPU usage would probably do it. Do you know how to test that? I don't.

> Or is there any visual indicators you could go on?

There is a visual indication, but I have no idea how the VBA code in the Access database would recognize it. The editor is called with a command parameter, the filename, which it opens just fine. The editor then takes a little time to settle down while it attends to some routine start-up tasks, like any editor, and only then is it ready to accept command input. I feed it that in the from of an F10 key, followed by two capital Ns, followed by the text which I want it to locate (F10, N, N is the command sequence to search for something in this old editor). The problem is in the start-up time - if I send it this sequence while it's still busy waking up, the F10 is lost, then part way through the text sequence which I want it to find, the editor starts accepting input and what's left of the search text gets inserted at the beginning of the text, as if the user had simply typed it into the existing text.

> Interesting little hack you got going btw! :)

Thank you; I was pretty pleased to find AutoIT, which is what allowed me to do it. It turned out to be incredibly useful. The database I wrote replaces an older DOS version, which was still functional but got sidelined due to inadequate capacity. I wrote mine with much more detailed error reporting than the old one, so the user suddenly discovered huge amounts of errors in the source text, which the old database had simply ignored (missing text, duplicate text, incorrect sequencing commands, improperly formatted dates,...). Since the old database made no mention of these things, the user had no indication that they even existed, so they accumulated. Now suddenly, the user was faced with literally tens of thousands of error messages. Many were systematic and the user could repair large quantities of them with macros, but some were individual, unique things, like simple typos. This hack made the corrections much easier, since the user did not have to manually start the editor, get the correct file and search for the offending text. I rigged my database so that all he has to do is double-click on an error message and Access will start a DOSBox process, within it call the old DOS editor, tell it which file to open and go directly to the text that caused the error message. Reduces an annoying amount of repetitive typing and task-switching to one double-click. It works probably 95% of the time, so it's not a huge issue, and the errors have mostly been eliminated by now anyway, but I can see uses for such a technique in future applications and would like to get the timing resolved.

Edited by pdanes

Share this post


Link to post
Share on other sites
Sunaj

> The CPU usage would probably do it. Do you know how to test that? I don't.

Here you go :) -adapted from [http://www.autoitscript.com/forum/index.php?showtopic=60458&view=findpost&p=454767]

Global $wbemFlagReturnImmediately = 0x10 
Global $wbemFlagForwardOnly = 0x20 
Global $wbemFlags = $wbemFlagReturnImmediately + $wbemFlagForwardOnly 
Global $strComputer = @ComputerName  
While 1     
 Global $colItems = $objWMIService.ExecQuery("SELECT * FROM Win32_Processor", "WQL", $wbemFlags)    
 $n = 0     
 $sMsg = ""     
 For $objItem In $colItems      
  $sMsg &= $n & ":  LoadPercentage: " & $objItem.LoadPercentage & @CRLF         
  $n += 1   
 Next   
 Sleep(100)     
 ConsoleWrite("CPU Load: " & $sMsg & @CRLF) 
Wend

> There is a visual indication, but I have no idea how the VBA code in the Access database would recognize it [...]

Ok, you could search these forums for a pixel search routine or look into doing your own - this is perhaps the best possibility.

Also, thanks for your further explanation of what your hack has achieved for your client - is often these real-world examples that makes me think about possible novel uses of AutoIt.

Cheers,

Sunaj

Share this post


Link to post
Share on other sites
pdanes

Hi Sunaj,

thanks for the CPU code. I tried it and it works, but since it gives me total CPU load, rather than load for a particular process, it doesn't really do what I need. I would be unable to tell the difference between a busy editor and, for instance, a running virus scan.

The PixelSearch method seems more promising. It looks complicated and I've never done anything quite like that, so I'm probably facing a bit of a learning curve, but it looks interesting. I'll give it a whirl. If you like, I can let you know how it works out. If so, what would you prefer - continue this post (it may be a while), start another post, email, something else?

Pete

Share this post


Link to post
Share on other sites
MadBoy

Hi Sunaj,

thanks for the CPU code. I tried it and it works, but since it gives me total CPU load, rather than load for a particular process, it doesn't really do what I need. I would be unable to tell the difference between a busy editor and, for instance, a running virus scan.

The PixelSearch method seems more promising. It looks complicated and I've never done anything quite like that, so I'm probably facing a bit of a learning curve, but it looks interesting. I'll give it a whirl. If you like, I can let you know how it works out. If so, what would you prefer - continue this post (it may be a while), start another post, email, something else?

Pete

I am not sure whether this would be possible on your app but i used to read what 'devcon.exe' was saying on cmd window when started. Small cut out of my code. Run and StdoutRead and you could probably try that (if it's a graphic based app i am not sure how it would 'work' if at all but worth a try).

$DevicesStatus = Run(@ComSpec & " /c " & $devcon & " status *", '', @SW_HIDE, 2)
    While 1
        $DevicesStatusData = StdoutRead($DevicesStatus)
        If @error Then ExitLoop
        If $DevicesStatusData Then
            $DevicesStatusOutput &= $DevicesStatusData
        Else
            Sleep(10)
        EndIf
    WEnd
    $DevicesStatusOutput = StringStripWS($DevicesStatusOutput, 6) ; Remove spaces from output
    $DevicesStatusOutput = StringSplit($DevicesStatusOutput, @CRLF) ; Split output of devcon into array
    ;_ArrayDisplay($DevicesStatusOutput, "DUPA")
    $DevicesLastLine = $DevicesStatusOutput[$DevicesStatusOutput[0]] ; Output of last DEVCON line
    $DevicesLastLineSplit = StringSplit($DevicesLastLine, "matching", 1)
    _AddLineBox("Detecting number of devices in system.")

Edit:

I guess stdout from help file has better example :)

Edited by MadBoy

My little company: Evotec (PL version: Evotec)

Share this post


Link to post
Share on other sites
pdanes

Thanks for the code. Unfortunately, I wasn't able to get hold of the text in the editor. It's an oddball and doesn't even use the DOS calls, but rather does most of the display work itself, which makes its output pretty much invisible to any normal code. But I got it working with the PixelSearch function, since that sees what happens in the window, regardless of how it happens. The editor displays boxes and I can see when they appear and that's enough to let me know what I need, namely when the editor has responded and is ready for another command.

Pete

I am not sure whether this would be possible on your app but i used to read what 'devcon.exe' was saying on cmd window when started. Small cut out of my code. Run and StdoutRead and you could probably try that (if it's a graphic based app i am not sure how it would 'work' if at all but worth a try).

$DevicesStatus = Run(@ComSpec & " /c " & $devcon & " status *", '', @SW_HIDE, 2)
    While 1
        $DevicesStatusData = StdoutRead($DevicesStatus)
        If @error Then ExitLoop
        If $DevicesStatusData Then
            $DevicesStatusOutput &= $DevicesStatusData
        Else
            Sleep(10)
        EndIf
    WEnd
    $DevicesStatusOutput = StringStripWS($DevicesStatusOutput, 6) ; Remove spaces from output
    $DevicesStatusOutput = StringSplit($DevicesStatusOutput, @CRLF) ; Split output of devcon into array
    ;_ArrayDisplay($DevicesStatusOutput, "DUPA")
    $DevicesLastLine = $DevicesStatusOutput[$DevicesStatusOutput[0]] ; Output of last DEVCON line
    $DevicesLastLineSplit = StringSplit($DevicesLastLine, "matching", 1)
    _AddLineBox("Detecting number of devices in system.")

Edit:

I guess stdout from help file has better example :)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  

×