I know this code is bigger than it needs to be.
I don't know quite how to exit it if Netscape is running.

Could someone help reduce it's size as well.

Thanks.




; merge.asm Run another program(batch file for now)
but only if Netscape isn't running.
; Add code later to show message box


.486
.model flat, stdcall ; 32 bit memory model
option casemap :none ; case sensitive


include \masm32\include\windows.inc
include \masm32\include\masm32.inc
include \masm32\include\gdi32.inc
include \masm32\include\user32.inc
include \masm32\include\kernel32.inc
include \masm32\include\Comctl32.inc
include \masm32\include\comdlg32.inc
include \masm32\include\shell32.inc
include \masm32\include\oleaut32.inc
include \masm32\macros\macros.asm

includelib \masm32\lib\masm32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\Comctl32.lib
includelib \masm32\lib\comdlg32.lib
includelib \masm32\lib\shell32.lib
includelib \masm32\lib\oleaut32.lib

.data

ProcessNameToSearchFor BYTE "C:\PROGRAM FILES\NETSCAPE\NETSCAPE\NETSCP.EXE", 0
ProcessNameLength DWORD 45 ; length not including null-termination

.code

start:

main proc

LOCAL buffer[260]:BYTE

call TestAppRunning ; see if Netscape is running, if so exit

invoke GetCL,1,ADDR buffer

fn ShellExecute,0,"open",ADDR buffer,NULL,NULL,SW_SHOWNORMAL

invoke ExitProcess,0

main endp

align 4

TestAppRunning proc syscall
LOCAL Process:PROCESSENTRY32, SnapShot:DWORD

comment * -----------------------------------------------------------------------------
Test if application is already running. App name wanted and its length are
coded in the .data section.

On exit:
EAX = 0 if not running or unsuccessful, else nonzero
EBX/EBP/EDI/ESI are preserved.
----------------------------------------------------------------------------- *

push ebx
push edi
push esi

invoke CreateToolhelp32Snapshot, TH32CS_SNAPPROCESS, 0
test eax, eax
jz AppNotRunning ; unable to create SnapShot

mov SnapShot, eax
mov Process.dwSize, (SIZEOF PROCESSENTRY32)
invoke Process32First, SnapShot, ADDR Process ; return first process handle

TestValidHandle:
test eax, eax
jz CloseSnapHandle

TestProcessName:
xor eax, eax ; counter for name length
lea esi, Process.szExeFile
lea edi, ProcessNameToSearchFor
@@:
add eax, 1
cmp BYTE PTR [esi+eax-1], 0
je @F
cmp BYTE PTR [esi+eax-1], "a"
jb @B
cmp BYTE PTR [esi+eax-1], "z"
ja @B
sub BYTE PTR [esi+eax-1], 32
jmp @B
@@:
sub eax, ProcessNameLength
jbe GetNextProcess ; exit if process name not long enough

mov cl, [edi] ; get 1st char in pattern
add esi, eax ; add source length
neg eax ; invert sign

ScanProcess:
cmp cl, [esi+eax] ; scan for 1st byte of pattern
je PreMatchProcess ; test if it matches

NextScanPosition:
add eax, 1
js ScanProcess ; exit on sign inversion

GetNextProcess:
invoke Process32Next, SnapShot, ADDR Process ; return next process handle
jmp TestValidHandle

PreMatchProcess:
mov edx, ProcessNameLength ; put pattern length into EDX
lea ebx, [esi+eax] ; put current scan address in EBX

TestMatchProcess:
mov ch, [edi+edx-1] ; load last byte of pattern length
cmp ch, [ebx+edx-1] ; compare it with last byte in main string
jne NextScanPosition ; jump back on mismatch

sub edx, 1
jnz TestMatchProcess ; 0 = match, fall through on match

invoke CloseHandle, SnapShot ; returns non-zero if process exists
jmp AppIsRunning

CloseSnapHandle:
invoke CloseHandle, SnapShot

AppNotRunning:
xor eax, eax ; returns zero if unsuccessful
; or process does not exist

AppIsRunning:
pop esi

cmp eax,0 ; if eax isn't zero, don't proceed
;jnz dont_runbat ; execute portion of program
; that runs the batch file
pop edi
pop ebx
ret

TestAppRunning endp


end start
Posted on 2004-11-08 18:57:30 by skywalker
SkyWalker,

Here is a very simple way to do what you are after IF Netscape is the only browser to use the Mozilla engine.


; ?????????????????????????????????????????????????????????????????????????

main proc

LOCAL hNetscape :DWORD
LOCAL buffer[128]:BYTE

invoke GetCL,1,ADDR buffer

mov hNetscape, FUNC(FindWindow,chr$("MozillaWindowClass"),NULL)

.if eax == 0 ; if windows cannot be found
invoke WinExec,ADDR buffer, 1 ; start it
.else ; otherwise
invoke SetForegroundWindow,hNetscape ; set it to the forground
.endif

ret

main endp

; ?????????????????????????????????????????????????????????????????????????


Tested and works fine but if you also have Firefox or K-Melion that use the Mozilla engine, it can work on them as well without distinguishing which is which.

A slightly more complicated version is to enumerate all of the running windows in the system and test if the word "Netscape" is in the window title.
Posted on 2004-11-09 03:25:06 by hutch--
SkyWalker,

Here is a very simple way to do what you are after IF Netscape is the only browser to use the Mozilla engine.


; ?????????????????????????????????????????????????????????????????????????

main proc

LOCAL hNetscape :DWORD
LOCAL buffer[128]:BYTE

invoke GetCL,1,ADDR buffer

mov hNetscape, FUNC(FindWindow,chr$("MozillaWindowClass"),NULL)

.if eax == 0 ; if windows cannot be found
invoke WinExec,ADDR buffer, 1 ; start it
.else ; otherwise
invoke SetForegroundWindow,hNetscape ; set it to the forground
.endif

ret

main endp

What exactiy is the SetForegroundWindow statement doing.

I have gotten this feedback from someone else about my code.
Is it a lot more code to have it work on XP.

That's a nice attempt there. You could keep it as is but bear in mind 2 things. First,the Toolhelp32 API does not run on all windows distributions.Second,there's not really a need to search for all processes to find a a particular one,just call FindWindow to get it's window handle back.
Posted on 2004-11-09 06:38:13 by skywalker
SetForgroundWindow does exactly what it says, it sets the window that you set as the handle parameter as the forground window which means if it was covered up, it comes up to the top. The API changes what is called the Z order which is the x, y, Z axis.

The logic of the small test piece is display the browser if its already running otherwise start it.
Posted on 2004-11-09 08:02:03 by hutch--
SetForgroundWindow does exactly what it says, it sets the window that you set as the handle parameter as the forground window which means if it was covered up, it comes up to the top. The API changes what is called the Z order which is the x, y, Z axis.

The logic of the small test piece is display the browser if its already running otherwise start it.


I don't want the browser started. My batch file zips up and deletes files the browser uses, thus I want to exit out if it's running. Later as I get more familiar I can maybe show an error message.
Posted on 2004-11-09 16:15:05 by skywalker
Hi skywalker.

You can start by declaring ProcessNameLength as a constant. an immediate value.
that way you dont waste space on data. and your mov and sub dont refer to a memory address, but an immediate value. making it twice as fast.


ProcessNameToSearchFor BYTE "C:\PROGRAM FILES\NETSCAPE\NETSCAPE\NETSCP.EXE", 0

ProcessNameLength equ $ - ProcessNameToSearchFor ; length including null-termination!
ProcessNameLength2 equ $ - ProcessNameToSearchFor-1 ; length not including null-termination!

..


mov SnapShot, eax
mov Process.dwSize, (SIZEOF PROCESSENTRY32)
invoke Process32First, SnapShot, ADDR Process ; return first process handle

right there! you can push eax instead of SnapShot! 1 cycle compared to pushing 4 cycles. and a couple bytes shorter.

and what the hell is all of this! you add and then you subtract and then i dont know wtf you are doing:



@@:
add eax, 1
cmp BYTE PTR [esi+eax-1], 0
je @F
cmp BYTE PTR [esi+eax-1], "a"
jb @B
cmp BYTE PTR [esi+eax-1], "z"
ja @B
sub BYTE PTR [esi+eax-1], 32
jmp @B
@@:


ok here we go.


add eax, 1 ; 3 bytes
inc eax ; 1 byte. unsigned add 1.

; also dont do this stupid crap:

add eax, 1
cmp BYTE PTR [esi+eax-1], whatever..

; better solution:

xor eax, eax
dec eax ; before hand.
..
inc eax
cmp BYTE PTR [esi+eax], 0
..
sub eax, ProcessNameLength-1 ; because you lost 1 byte size on the dec eax.
; this wont effect code size\speed because ProcessNameLength is a constant


; best solution:
lea esi, Process.szExeFile - 1 ; same size and cycles. no extra commands.
..
inc eax
cmp BYTE PTR [esi+eax], 0
je @F


and then i really didnt understand how you are comparing the 2 string and i have to go since its 5am. but there is always more things to optimize. have fun.
Posted on 2004-11-12 06:22:22 by pwn
Hi skywalker.

You can start by declaring ProcessNameLength as a constant. an immediate value.
that way you dont waste space on data. and your mov and sub dont refer to a memory address, but an immediate value. making it twice as fast.


ProcessNameToSearchFor BYTE "C:\PROGRAM FILES\NETSCAPE\NETSCAPE\NETSCP.EXE", 0

ProcessNameLength equ $ - ProcessNameToSearchFor ; length including null-termination!
ProcessNameLength2 equ $ - ProcessNameToSearchFor-1 ; length not including null-termination!

..


mov SnapShot, eax
mov Process.dwSize, (SIZEOF PROCESSENTRY32)
invoke Process32First, SnapShot, ADDR Process ; return first process handle

right there! you can push eax instead of SnapShot! 1 cycle compared to pushing 4 cycles. and a couple bytes shorter.

and what the hell is all of this! you add and then you subtract and then i dont know wtf you are doing:

Most of the code was written by someone else and I am trying to learn
what is going on.




@@:
add eax, 1
cmp BYTE PTR [esi+eax-1], 0
je @F
cmp BYTE PTR [esi+eax-1], "a"
jb @B
cmp BYTE PTR [esi+eax-1], "z"
ja @B
sub BYTE PTR [esi+eax-1], 32
jmp @B
@@:


ok here we go.


add eax, 1 ; 3 bytes
inc eax ; 1 byte. unsigned add 1.

; also dont do this stupid crap:

add eax, 1
cmp BYTE PTR [esi+eax-1], whatever..

; better solution:

xor eax, eax
dec eax ; before hand.
..
inc eax
cmp BYTE PTR [esi+eax], 0
..
sub eax, ProcessNameLength-1 ; because you lost 1 byte size on the dec eax.
; this wont effect code size\speed because ProcessNameLength is a constant


; best solution:
lea esi, Process.szExeFile - 1 ; same size and cycles. no extra commands.
..
inc eax
cmp BYTE PTR [esi+eax], 0
je @F


and then i really didnt understand how you are comparing the 2 string and i have to go since its 5am. but there is always more things to optimize. have fun.


Thanks for your help, I will look over it so I can understand a little
better what's going on.

One of the things that is harder to get used to in Win32 code I have seen
is the lack of commentation compared to what is in most 16 bit code.

Coders could at least put a few sentences at the top giving a general
description of what the program, dll, or whatever is doing otherwise a lot
of people might get scared off. :-)
Posted on 2004-11-12 17:20:50 by skywalker