You are here

Batch file launcher in assembler

15 posts / 0 new
Last post
musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
Batch file launcher in assembler

I'm aware that my problem is only loosely connected with PortableApps but since the germ of the idea started here, I'm hoping that at least I can be pointed to a forum somewhere that might help me with an assembly language program.

It started with wanting to launch a specific batch program from the PortableApps Menu. I found a solution for that, several actually.

I noticed that many, if not all of the so called batch file compilers were simply a wrapper for the original batch file. I also noticed that the overhead to launch the batch file took as much as 90K to accomplish that task, which seemed pretty excessive.

I thought I could write a launcher in assembler which would probably take only a few hundred bytes. So I tried it and sure enough. I accomplished the basic task in about 400 bytes ,exclusive of the batch file.

The problem is this. It works in WinXp, in WinWFW, in DOS 6.2. It does NOT work in win98 or win95. I've spent countless hours with Google trying to find an answer without success.

Then I thought of this forum. I hope my problem can fit under the "General" umbrella.

Can you help in any way? Even if only a link to a relevant forum?

Thanks

(I left out the details until I know whether this is the proper place to discuss them)

John Bentley
John Bentley's picture
Offline
Last seen: 15 years 5 months ago
Developer
Joined: 2006-01-24 13:26
I'm pretty sure that Win 9x

I'm pretty sure that Win 9x doesn't support command line applications.

cowsay Moo
cowthink 'Dude, why are you staring at me.'

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
Actually it does.

Thanks for taking the time and having the interest to respond.

I've been using the DOS window in Win9x since the win95 days, so I'm pretty sure that's not the problem. How it supports 16 bit applications might be, tho.

Thanks again for the interest, it's appreciated.

Joble
Joble's picture
Offline
Last seen: 16 years 4 months ago
Joined: 2007-05-03 12:46
MASM Batch Run File

https://portableapps.com/node/6715#comment-34211

There are also several posts about running batch commands through NSIS and/or calling a .bat from an NSIS launcher.

I've never been able to test in Win9x, wish I could be more help.

But Wait! Didn't Win9x use .pif files? Try making a .pif file and call it instead, or from within your .asm call cmd [commands]. Just a thought, hope it helps.

My launcher is 12.5 KB with its icon. What assembler are you using? I just dabble with MASM and really like it, but not really good at it, would you post your code? I'd be interested in seeing how you kept it so small. My code is contained in the linked post above.

Have an Awesome Day!

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
Thanks for your Interest

I found some of those posts you mention in the course of my search. Didn't see yours at the time, wasn't looking in that forum. Thanks for the link!

Hadn't thought about .pif files, I'll look into that.

I'm using WASM, a 16 bit assembler that dates back many years. Produces .com files. About as close as you can get to actual machine code. (I know the object is an .exe file, but .com files can be renamed as .exe files and run. Command interpreter ignores the extension name, looks at the code to tell which type it is.)

Your MASM32 assembler looks to be a lot more high level. I may have to acquire that or some other 32 bit assembler to solve the puzzle I've set for myself.

To clarify what my problem actually is:

I actually wrote two different routines. One just runs an external pre-existing batch file. That works just fine in all Windows versions that I have including win9x.

Then I set out to write another that would generate the batch file, execute it, and then delete it. I can create it and run it in XP. In Win9x I can create it, but when I try to run it I get a repetitive "sharing violation" message that I have to CTL-C out of.

The same batch file (created from within the routine) that cannot be run from inside the routine, can be run without error from the command line. This is my puzzle.

I would be happy to "post" my code for either or both programs. How do I do that? I'm new at this forum stuff.

Joble
Joble's picture
Offline
Last seen: 16 years 4 months ago
Joined: 2007-05-03 12:46
Cut and Paste

MASM32 is a free download with tons of examples and tutorials. Google should find it. And it is all self contained so runs portably. In fact I made the launcher just for it because it's default setup is to run in the root directory, and it looked like a pain to change it from the default, hence the launcher.

Rather than create run and delete the batch file, can you run the shell command from inside your .asm using shellexecute or some similar function?

you can separate your code from your comments 
by using the pre, code, or cite tags

Is it possible your app is creating the batch, running it, but then not waiting for it to finish before attempting to delete it, thus the sharing violation? Trying to delete it while it's still open or in use?

Have an Awesome Day!

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
Good point, but...

"Is it possible your app is creating the batch, running it, but then not waiting for it to finish before attempting to delete it, thus the sharing violation?

Good point, but no. This being a work in process, I haven't actually written the delete file routine yet. The program just creates and (attempts) to run the batch file right now.

But it might be a timing issue between creation and trying to execute before creation is complete. Shouldn't work that way, but this is a 32 bit environment pretending it's 16 bit. Maybe it's just not doing it right. Hmmm...

"Rather than create run and delete the batch file, can you run the shell command from inside your .asm using shellexecute or some similar function?"

Short answer, yes. Actually, the first program I wrote, just as a proof of concept of running a child process, does just that very thing. It calls a copy of %COMSPEC% which then executes what's on the calling routine's command tail. It would be simple to incorporate the command tail into the body of the program, this eliminating any need for the calling routine to specify information.

The puzzle I wanted to solve was to create a "wrapper" for the original batch file that would contain the batch file, launch it and then delete leaving nothing behind, with minimal overhead.

I assume you're saying I can just cut and paste my code into this message window, so I'll do that. I want to clean it up a little bit first tho, so that it's more understandable, so it might be a few hours before I get back to you.

Thanks for the info about MASM32, it's always good to have new toys to play with!

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
Program assembler code

As promised here is the code for the program that launches an external batch file, followed by the test batch file.

I've tried to comment copiously so as to indicate what going on. This is very low level stuff, so even thought there are a lot of lines it compiles at 332 bytes.

I posted this because it comes close to what you did in MASM32 and would be of interest to you to compare. This one works and just needs some polishing up.

It is, however NOT the one that is giving me trouble and is the reason for my original post. Before posting that listing, however, I'm going to work with it a little bit more. I got a couple of ideas from our discussion that I want to try out first.

We'll see how that works out. Thanks for your help thus far!

Here's the listings:

-----------------  RUNBATCH  CODE ---------------------------

;;;;;;;; RUNBATCH
                    ;WARNING!!! THIS IS NOT A FINISHED PRODUCT!
                    ;
                    ;A routine to run a child process.
                    ;Done as a "proof of concept", not as a working program.
                    ;Uses INT2Eh to run the child process
                    ;invokes a copy of %COMSPEC% to execute the
                    ;data in the calling routine command tail.
                    ;NOTE: to work properly in winXP, the batch file
                    ;  executed must determine if the OS is WinXP
                    ;  and if so call CMD.EXE /C to execute another
                    ;  iteration of itself.
                    ;  The reason is that this routine returns
                    ;  COMMAND.COM as the COMSPEC value even though
                    ;  the correct value is CMD.EXE.  If this were
                    ;  an actual working program the identification of
                    ;  OS would be done here instead of the batch file.
         org   100h
;change memory allocation        ;make memory available for child process
         mov   ah, 4Ah
         mov   bx, offset endpgm
         shr   bx                ;change to paragraphs
         shr   bx                ;by dividing by 16 (dec)
         shr   bx                
         shr   bx
         inc   bx
         int   21h
;
;setup prog name (COMSPEC) by looking in environment block for COMSPEC=
         mov   ES, [2Ch]
         mov   DI, 0               ;look in environment segment
cmploop
         mov   SI, offset DblZer   ;look for End Of Environment marker 
         mov   cx, 2
         push  DI
         repe
         cmpsb
         pop   DI
         je    NF                  ;EOE reached w/ no match for COMSPEC.
                                   ;Failed. End search.

         mov   SI, offset comspec  ;look for COMSPEC
         mov   cx, 8
         push  DI
         repe
         cmpsb
         pop   DI
         je    found
contsch
         inc   DI
         jmp   cmploop

NF    
         ;if COMSPEC not found
         mov   ah, 09h
         mov   dx, offset NoComMsg
         int   21h
         mov   al, 2
         jmp   EXIT
found                       ;COMSPEC found in environment block
         cmp   DI, 0
         je    skipzck
         cmp   byte [DI-1], 0
         jne   contsch      ;not beg of arg. must be x..COMSPEC=
                            ;resume search

skipzck                     ;retrieve %COMSPEC% value
         push  ES           ;point DS to environment, ES to local
         push  DS
         pop   ES
         pop   DS
         xchg  DI,SI
         add   SI, 8
         mov   DI, offset progname
         mov   cx, 0
mov_val                             ;retrieve value for COMSPEC
         cmp   byte [SI], 0
         je    end_mov_val          ;and move to "progname"
         movsb
         inc   cx
         jmp   mov_val
end_mov_val
         push  ES                   ;restore ES to local value
         pop   DS 
;
;setup cmdtail
         xor   cx, cx               ;move calling routine cmd tail to
         mov   cl, [80h]            ;area for child process cmd tail
         add   cx, 1
         mov   SI, 81h
                          ;DI = value for offset cmdtail
         repnz
         movsb
         mov   cx, DI,
         sub   cx, offset cmdLINE
         dec   cx
         mov   cmdLine, cl
;
         ;EXEC the program
EXEC
         mov   SI, offset cmdline
         push  CS
         pop   DS            ;make sure DS points to Code Segment 
         int   2Eh
                             ;if any code follows betwwen INT 2E and "EXIT"
                             ;must add coding to save and restore
                             ;registers, SS,SP, DS,ES, ax,bx,cx,dx SI,DI.

         ;(this is where the "delete file" code would go)

EXIT     mov   ah, 4Ch       ;exit with return code. 
         int   21h
;
         db    'Begin data area',0         ;marker for beginning data area
;
comspec  db    'COMSPEC=',0                ;search argument for COMSPEC
dblzer   db    0,0                         ;END marker for environment area
NoComMsg db    '"COMSPEC" not found!', 24h        
         db    'progname follows',0
cmdline  db    0                           ;command tail for child process
progname ds    7Fh, 0                      ;%COMSPEC% value
endpgm   dw    offset endpgm               ;marker for EOP

---------------- END RUNBATCH ---------------------------------------------

Begin listing of NTEMP2.BAT:  Test file for above

@echo off
REM for testing to verify that it's loaded and running

if NOT %1!==! goto %1
if NOT %OS%!==Windows_NT! goto STARTBAT
   CMD /C %0 STARTBAT
   goto EXIT

:STARTBAT
@echo off
prompt Running %0$_$P$G
echo   Running %0 %1
echo COMSPEC=%COMSPEC%
rem see if long file name is recognized.
C:
CD "C:\Program Files"
CD
pause
rem before running place a CD to original directory on the next line
rem CD (return to original directory, don't forget remove the "rem"!)
:EXIT 

Joble
Joble's picture
Offline
Last seen: 16 years 4 months ago
Joined: 2007-05-03 12:46
Wow

You're in deep. I like it, I'll use it as a tutorial for myself. Mine is 32 bit, will be a learning experience to compare the use of the registers.

MASM is an assembler but the M in Masm stands for Macro so I don't have to worry as much about the low level stuff, but it does allow for it, it is at its core an assembler, with Macros added, basically just pre-written assembler routines, like a code library. It has examples of text editors, that save and delete documents!

From the look of your code it wouldn't be much of a learning curve and you could probably solve your problem in no time at all by looking at the sample code and tutorials. That's where your extensive experience with cut & paste will come in handy. If you plan on using this code commercially there may be some copyrites on some of the tutorial code, each author is different, they are explained in the program, or in the code itself. But you can freely cut and paste for non-commercial purposes. Enjoy and I look forward to your next post.

Just add a new comment to your original post so we can get rid of the indent and use the whole page Wink

Have an Awesome Day!

rab040ma
Offline
Last seen: 7 months 1 week ago
Joined: 2007-08-27 13:35
16bit
But it might be a timing issue between creation and 
trying to execute before creation is complete. Shouldn't 
work that way, but this is a 32 bit environment pretending 
it's 16 bit. Maybe it's just not doing it right. Hmmm...

Are you using a 16-bit assembler on purpose?

MC

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
It's what I have. (short answer)

(long answer)
I acquired it many years ago and use it mainly to create small things to enhance my batch files Sort of thing they used to call "external DOS commands". It works well for that environment.

For "real" programs I use Visual Basic.

This whole thing started as an experiment to see if I could create a routine using standard DOS calls that theoretically are supported in all flavors of Windows, that would work in all DOS and Windows environments.

Jury's still out.

It's interesting that this one particular routine works in an XP command window, but not win9x...?

I'll probably acquire a copy of MASM32. It might be good for writing standalone programs (my preferred type) and still be compatible with the 32 bit environment.

Joble
Joble's picture
Offline
Last seen: 16 years 4 months ago
Joined: 2007-05-03 12:46
Batch Attack!

I don't know what the final goal, or outcome is to be, but, one batch file can create, run, and delete another batch file, being it's own wrapper.

I haven't tested this, but it would be something like this:

@echo dir > test.bat
@echo dir *.exe >> test.bat
test
pause
del test.bat

Have an Awesome Day!

m2
Offline
Last seen: 13 years 11 months ago
Joined: 2006-12-12 12:00
http://www.internals.com/arti

http://www.internals.com/articles/protmode/interrupts.htm says:
"Windows 95 and 98 use a similar technique to hop between user and kernel mode, but rely upon INT 30h instead of using INT 2Eh."

"Those people who think they know everything are a great annoyance to those of us who do." Asimov

musicman
Offline
Last seen: 12 years 10 months ago
Joined: 2007-09-20 19:09
http://www.internals.com/arti

Thank you! Thank you! This is precisely the kind of information I was looking for on my original post!

My DOS functions manual, which was written when DOS 3.x was current, doesn't show an INT 30h. Maybe this interrupt was added later, maybe for DOS 7?

I'm going to check out this int30H and see what it is and what it does.

In the meantime, I devised a "work around", still using int 2Eh. The routine seems to work on everything I have installed. DOS 6.2, WFWG running on top of DOS 6.2, win95, win98 and winXP.

The problem was that I was getting a sharing violation (in Win9x only) when trying to execute the just created batch file. I used a batch file trick, calling another copy of the program with a command line parameter to just create the batch file and then exit back to the original copy, which then was able to execute the batch file without a problem.

Seems to work OK far. I'm now cleaning up the code. When I'm done if anyone is interested in seeing a copy, I'd be happy to send them the code. Nothing original, it creates a batch file included in the program as data, executes it and then deletes it. AS noted seems to work in all flavors of DOS/Windows that I've been able to try it on. It is written in pure assembler, and is pretty small, the code part right now is about 1100 bytes.

Thanks to all who offered help!

Joble
Joble's picture
Offline
Last seen: 16 years 4 months ago
Joined: 2007-05-03 12:46
Glad

to be of service! Wink

Have an Awesome Day!

Log in or register to post comments