I can not figure out how to use Shell correctly.

Some things are confusing.

lpfilename name is declared as a DWORD when it really is a byte value.

Thanks.

   
Shell PROTO :DWORD, :DWORD

.data

lpfilename      DWORD  "E:\Bat\bak1.bat",0 ; bat file to execute
dwTimeOut      DWORD  15000  ; Allow 15 seconds before timing out

.code

start:

main proc

invoke Shell,ADDR lpfilename, ADDR dwTimeOut
 
invoke  ExitProcess,NULL

main endp

;----------------------------------------------------------------------------;
; This is a translation of a shell script originally written by Edgar Hansen;
; in GoASM code. Translation by Paul E. Brennick  <pebrennick@verizon.net>  ;
;                                                                          ;
; Shell:      This function will run an executable and wait until it has    ;
;            finished before continuing. The function provides for a time  ;
;            out for a maximum wait period.                                ;
; Parameters: lpfilename = The fully qualified path to an executable to run ;
;            dwTimeOut = The amount of time in milliseconds to wait, -1 for;
;            no timeout                                                    ;
; Returns:    0 if successful, STATUS_TIMEOUT if the timeout has elapsed    ;
;            -1 if there was an error creating the process                ;
;                                                                          ;
;----------------------------------------------------------------------------;
Shell PROC lpfilename:DWORD, dwTimeOut:DWORD

  LOCAL  Sh_st_info :STARTUPINFO
  LOCAL  Sh_pr_info :PROCESS_INFORMATION

  mov    DWORD PTR , SIZEOF STARTUPINFO
  invoke  GetStartupInfoA, ADDR Sh_st_info
  mov    DWORD PTR , 0
  invoke  CreateProcessA, 0, , 0, 0, 0, 0, 0, 0, \
          ADDR Sh_st_info, ADDR Sh_pr_info
  test    eax, eax ;ObjectToWaitOn
  jz ERROR
  invoke  WaitForSingleObject, ,
  push    eax
  invoke  CloseHandle,
  invoke  CloseHandle,
  pop    eax
  test    eax, eax
  RET
ERROR:
  xor    eax, eax
  sub    eax, 1
  RET
Shell ENDP

end    start
Posted on 2007-09-20 06:40:05 by skywalker
I just glanced at the code and I believe the DWORD value for the "lpfilename" parameter is the DWORD memory pointer to the string representing the null-terminated name of the program to be executed by the "Shell" procedure. That means you could also prototype it in C/C++ as void*.

One more thing to note is that the "WaitForSingleObject" locks the calling thread until the event object's state is changed to "signalled". Instead of that, I think, depending on your needs, it is better to create an event object using the "CreateEvent" Win32 API. Then create a thread using the "CreateThread" Win32 API and check the state of that event with the "WaitForSingleObject" with really small values for its time-out. Then you will have a running program while the other process is running.
Posted on 2007-09-20 07:34:25 by XCHG

I just glanced at the code and I believe the DWORD value for the "lpfilename" parameter is the DWORD memory pointer to the string representing the null-terminated name of the program to be executed by the "Shell" procedure. That means you could also prototype it in C/C++ as void*.

One more thing to note is that the "WaitForSingleObject" locks the calling thread until the event object's state is changed to "signalled". Instead of that, I think, depending on your needs, it is better to create an event object using the "CreateEvent" Win32 API. Then create a thread using the "CreateThread" Win32 API and check the state of that event with the "WaitForSingleObject" with really small values for its time-out. Then you will have a running program while the other process is running.


Thanks for your ideas.

The process to follow execution of the bat file is a shutdown.

I made some changes and here is what I got.

Assembling: E:\masm32\Source\WaitForSingleObject.asm
E:\masm32\Source\WaitForSingleObject.asm(99) : error A2005: symbol redefinition
: lpfilename
E:\masm32\Source\WaitForSingleObject.asm(99) : error A2111: conflicting paramete
r definition
E:\masm32\Source\WaitForSingleObject.asm(70) : error A2084: constant value too l
arge

   
Shell PROTO :DWORD, :DWORD

.data

lpfilename      DWORD  "E:\Bat\bak1.bat",0
dwTimeOut      DWORD  15000  ; Allow 15 seconds before timing out

.code

start:

main proc

invoke Shell,ADDR , ADDR
 
invoke  ExitProcess,NULL

main endp

;----------------------------------------------------------------------------;
; This is a translation of a shell script originally written by Edgar Hansen;
; in GoASM code. Translation by Paul E. Brennick  <pebrennick@verizon.net>  ;
;                                                                          ;
; Shell:      This function will run an executable and wait until it has    ;
;            finished before continuing. The function provides for a time  ;
;            out for a maximum wait period.                                ;
; Parameters: lpfilename = The fully qualified path to an executable to run ;
;            dwTimeOut = The amount of time in milliseconds to wait, -1 for;
;            no timeout                                                    ;
; Returns:    0 if successful, STATUS_TIMEOUT if the timeout has elapsed    ;
;            -1 if there was an error creating the process                ;
;                                                                          ;
;----------------------------------------------------------------------------;
Shell PROC lpfilename:DWORD, dwTimeOut:DWORD

  LOCAL  Sh_st_info :STARTUPINFO
  LOCAL  Sh_pr_info :PROCESS_INFORMATION

  mov    DWORD PTR , SIZEOF STARTUPINFO
  invoke  GetStartupInfoA, ADDR Sh_st_info
  mov    DWORD PTR , 0
  invoke  CreateProcessA, 0, , 0, 0, 0, 0, 0, 0, \
          ADDR Sh_st_info, ADDR Sh_pr_info
  test    eax, eax ;ObjectToWaitOn
  jz ERROR
  invoke  WaitForSingleObject, ,
  push    eax
  invoke  CloseHandle,
  invoke  CloseHandle,
  pop    eax
  test    eax, eax
  RET
ERROR:
  xor    eax, eax
  sub    eax, 1
  RET
Shell ENDP

end    start





Posted on 2007-09-20 08:08:18 by skywalker
I got the problem solved.(File Attachment)

CreateProcess has to be used a little differently when running a batch file.

Maybe you know why double quotes are necessary for the szCommandLine.

Attachments:
Posted on 2007-09-20 09:58:33 by skywalker
skywalker: instead of hardcoding the cmd.exe path, you should use GetEnvironmentVariable to get the COMSPEC variable, which points to the system's shell/command interpreter. More robust code, and should work on both 9x and NT that way as well.

And btw, an alternate way of getting double quotes in your string:

szCommandLine  BYTE  '"/C E:\Bat\bakit.bat"',0

Posted on 2007-09-20 16:37:30 by f0dder

skywalker: instead of hardcoding the cmd.exe path, you should use GetEnvironmentVariable to get the COMSPEC variable, which points to the system's shell/command interpreter. More robust code, and should work on both 9x and NT that way as well.

And btw, an alternate way of getting double quotes in your string:

szCommandLine  BYTE  '"/C E:\Bat\bakit.bat"',0




Thanks FOdder,

Ok, I will study GetEnvironmentVariable. Only 499 more APIs to study, :-)

Windows is pretty intuitive or observant.

I renamed my batch file that was in the startup list to test my prog and windows "found it." and ran it. bak.bat -> bak1.bat  Should I be worried. :-) Just kidding.

Non-programming riff raff below
--------------------------------------------------------
I was at a job fair looking for a technical writer position.

They had programming positions using C ++ or C Sharp.
I'll stick with assembly.

I am still doing home and commercial remodeling/repair. I hope to find a job soon,
the ole unemployment will be history in a month.

Outta here.






Posted on 2007-09-20 17:15:51 by skywalker
Stuff about the scheduler has been moved here, to avoid thread pollution and because imho it's worthy of a separate topic.
Posted on 2007-09-21 06:46:48 by f0dder
the quotes thing is due to the ability to pass the commandline
"exename.exe" blah blah blah

similar to createprocess...
where for 32 bit programs, you pass everything on the lpApplicationName portion, for 16 bit progs, you use lpCommandLine portion too...

Posted on 2007-09-22 05:15:46 by evlncrn8
It's filling the buffer with the correct path, but  CreateProcess isn't working.


szCommandLine  BYTE  QM,"/C E:\Bat\bakit.bat",QM,0
Spec                BYTE  "ComSpec",0                  ; find where cmd.exe resides
buffer             BYTE  128 dup(0)

.code

start:

INVOKE GetEnvironmentVariable, ADDR Spec, ADDR buffer,128

  INVOKE CreateProcess,ADDR buffer,ADDR szCommandLine, NULL, NULL, FALSE, \
      NORMAL_PRIORITY_CLASS, NULL, NULL, ADDR SystemInfo, ADDR ProcessInfo

int 3
  .IF (eax !=0)

    INVOKE WaitForSingleObject,ProcessInfo.hProcess,15000 ; timeout after 15 seconds


Posted on 2007-09-23 16:03:37 by skywalker
Here's a (full) working sample - blank lines removed for brevity.

.586p
.model flat,stdcall
option casemap:none
option proc:private
incAPI MACRO files:VARARG
FOR file, <files>
include file&.inc
includelib file&.lib
ENDM
ENDM
CTEXT MACRO y:VARARG
LOCAL sym

CONST segment
IFIDNI <y>,<>
sym db 0
ELSE
sym db y,0
ENDIF
CONST ends

EXITM <OFFSET sym>
ENDM
include <windows.inc>
incAPI <kernel32,user32>
.data?
szComspec byte MAX_PATH dup(?)
szAppname byte MAX_PATH dup(?)
ProcessInfo PROCESS_INFORMATION<?>
StartupInfo STARTUPINFO<?>
.code
ENTRY:
invoke GetStartupInfo, addr StartupInfo
invoke GetEnvironmentVariable, CTEXT('ComSpec'), addr szComspec, sizeof szComspec
invoke wsprintf, addr szAppname, CTEXT('"%s" /c "c:\test.bat"'), addr szComspec
invoke CreateProcess, 0, addr szAppname, 0, 0, FALSE, \
NORMAL_PRIORITY_CLASS, 0, 0, addr StartupInfo, addr ProcessInfo
invoke WaitForSingleObject, ProcessInfo.hProcess, INFINITE
invoke ExitProcess, 0
END ENTRY

Posted on 2007-09-23 17:25:54 by f0dder
yup, startup info not filled... you need to read msdn/docs skywalker :) use the force heheh
Posted on 2007-09-23 22:10:13 by evlncrn8

Here's a (full) working sample - blank lines removed for brevity.

.586p
.model flat,stdcall
option casemap:none
option proc:private
incAPI MACRO files:VARARG
FOR file, <files>
include file&.inc
includelib file&.lib
ENDM
ENDM
CTEXT MACRO y:VARARG
LOCAL sym

CONST segment
IFIDNI <y>,<>
sym db 0
ELSE
sym db y,0
ENDIF
CONST ends

EXITM <OFFSET sym>
ENDM




Thanks for the help. The code looks a "tad" discombobulated, but I will burn the midnight oil examing it.

Aren't those includes in a file. :-)

f0dder edit: moved non-quote stuff outside quote
Posted on 2007-09-24 17:01:37 by skywalker
You don't have to understand those two macros to use them ;), but they're pretty useful. Not mine, btw, snatched from the board - original author is probably bitRAKE, but I forgot to take note :/

And yeah, those would usually be in my macros.inc file :)
Posted on 2007-09-24 19:01:21 by f0dder
You are a good man.





Posted on 2007-09-24 19:33:55 by skywalker