Code:
' RMAShell.bas : Runs RMA.EXE on files dragged-and-dropped onto application, ' for each command line parameter specified. ' ' RMA.EXE (Real Media Analyzer)is a console app that analyzes/repairs RealMedia files ' ' Author: David Gwillim ' Date: 11 February 2005 ' Version: 1.0.3 ' ' History: v1.0.0 Initial release ' v1.0.1 Added progress display in main text box showing file name being processed ' v1.0.2 Added Ctrl-A accelerator to Result textbox for selecting all the text ' v1.0.3 Fix to ERASE RMFiles() array after processing, to prevent accidental repeat ' Added version number to title bar ' ' Copyright (c) 2005 by David Gwillim. Released to the Public Domain for use by others. ' ' Console Child Process spawning code was based on the Microsoft article: ' "Spawn Console Processes with Redirected Standard Handles" ' ID: Q190351 ' Also inspired by some C++ coding by Ted Ferenc in his RunConsoleApp freeware program ' See his website: [url="http://www.ndrw.co.uk/free/runconsoleapp/"]http://www.ndrw.co.uk/free/runconsoleapp/[/url] ' ' More useful info from Nick Adams at the code project: ' See: [url="http://www.codeproject.com/threads/redir.asp"]http://www.codeproject.com/threads/redir.asp[/url] ' ' Thanks also to Semen Matusovski who's posting on the PowerBasic forums prompted me ' to get this code running. ' ' Many thanks to Alexey Pavluchenko for writing RMA.EXE. You can obtain a copy of this ' freeware from: [url="http://www.anime.com.ua/misc/alexey/rma.htm"]http://www.anime.com.ua/misc/alexey/rma.htm[/url] ' #COMPILE EXE #DIM ALL #REGISTER NONE #INCLUDE "Win32Api.Inc" $VERSION = "1.0.3" %TXT_RESULT = 100 %TXT_OPTS = 101 %BTN_RUN = 102 %BTN_EXIT = 103 $DO_THIS = "Drag-and-drop RealMedia files to here from Windows Explorer ..." GLOBAL Result AS STRING GLOBAL Opts() AS STRING GLOBAL RMFiles() AS STRING FUNCTION ShellConsoleApp (CmdLine AS STRING, _ StartDirectory AS ASCIIZ, _ Result AS STRING, _ BYVAL dwMillisecondsWait AS DWORD _ ) AS LONG ' Set security attributes LOCAL sa AS SECURITY_ATTRIBUTES sa.nLength = SIZEOF(SECURITY_ATTRIBUTES) sa.lpSecurityDescriptor = 0& sa.bInheritHandle = 1 ' TRUE ' Create a new anonymous pipe LOCAL hReadPipeTmp AS DWORD, hReadPipe AS DWORD, hWritePipe AS DWORD, hWritePipeErr AS DWORD IF CreatePipe(hReadPipeTmp, hWritePipe, sa, BYVAL 0) = 0 THEN _ FUNCTION = -4: EXIT FUNCTION LOCAL dwCP AS DWORD dwCP = GetCurrentProcess() ' Create a duplicate of the output write handle for the std error ' write handle. This is necessary in case the child application ' closes one of its std output handles. IF DuplicateHandle(dwCP,hWritePipe,GetCurrentProcess(),hWritePipeErr, _ 0,1, _ ' has to be inheritable %DUPLICATE_SAME_ACCESS)=0 THEN FUNCTION = -5 : EXIT FUNCTION ' Create new pipe read handle ' Set the inheritance properties to FALSE. Otherwise, the child ' inherits these handles; resulting in non-closeable ' handles to the pipes being created. IF DuplicateHandle(dwCP,hReadPipeTmp,dwCP,hReadPipe, _ 0&, 0&, _ ' make it uninheritable. %DUPLICATE_SAME_ACCESS) = 0 THEN FUNCTION = -5 : EXIT FUNCTION ' we no longer need the original (inheritable) handle CloseHandle(hReadPipeTmp) ' Spawn the child process LOCAL SI AS STARTUPINFO, pi AS PROCESS_INFORMATION, ExitCode AS LONG SI.cb = SIZEOF(STARTUPINFO) SI.dwFlags = %STARTF_USESTDHANDLES OR %STARTF_USESHOWWINDOW SI.wShowWindow = %SW_HIDE '%SW_SHOWDEFAULT SI.hStdOutput = hWritePipe SI.hStdError = hWritePipeErr IF CreateProcess (BYVAL 0&, _ ' name of executable module BYVAL STRPTR(CmdLine), _ ' command line string BYVAL 0&, _ ' process security attributes BYVAL 0&, _ ' thread security attributes 1, _ ' handle inheritance flag %CREATE_NEW_CONSOLE OR %IDLE_PRIORITY_CLASS, _ ' creation flags BYVAL 0&, _ ' new environment block StartDirectory, _ ' process initial drive and directory si, _ ' appearance of process main window pi _ ' structure that receives identification information about the new process ) = 0 THEN FUNCTION = -1: EXIT FUNCTION ' the child process is launched so we can close handles we no longer need CloseHandle hWritePipe CloseHandle hWritePipeErr ' read from the pipe attached to the child process LOCAL chBuf AS ASCIIZ * 1024,BytesRead AS LONG DO IF ReadFile(hReadPipe, chBuf, SIZEOF(chBuf), BytesRead, BYVAL 0) = 0 THEN EXIT DO IF BytesRead = 0 THEN EXIT DO Result = Result + LEFT$(chBuf, BytesRead) LOOP ' make sure process gets terminated WaitForSingleObject PI.hProcess, dwMillisecondsWait GetExitCodeProcess PI.hProcess, ExitCode ' report the exit code of the child process Result = Result & $CRLF & "[Child Process Exit Code = " & FORMAT$(ExitCode,"") & "]" & $CRLF & $CRLF IF ExitCode = %STILL_ACTIVE THEN TerminateProcess pi.hProcess, 0: FUNCTION = -3 ELSE FUNCTION = ExitCode IF LEN(Result) THEN OemToCharBuff BYVAL STRPTR(Result), BYVAL STRPTR(Result), LEN(Result) ' Close the rest of the process and pipe handles CloseHandle hReadPipe CloseHandle pi.hThread CloseHandle pi.hProcess END FUNCTION FUNCTION GetAppPath() AS STRING ' get the folder where this EXE was launched from LOCAL appFilename AS ASCIIZ * 255 LOCAL PathPos AS LONG ' GetModuleFileName GetModuleHandle(""), appFilename, 255 PathPos = INSTR(-1,appFilename,"\") FUNCTION = LEFT$(appFilename,PathPos) END FUNCTION SUB RunRMA(hDlg AS DWORD) LOCAL CmdLine AS STRING, ExitCode AS LONG, i AS LONG, j AS LONG LOCAL AppPath AS ASCIIZ * %MAX_PATH, AppShortPath AS ASCIIZ * %MAX_PATH LOCAL Msg AS STRING IF ARRAYATTR(RMFiles(),0) = 0 THEN ' make sure we dropped some files to process BEEP Result = $DO_THIS EXIT SUB END IF ' find out what folder we were launched from as that is where we expect to find RMA.EXE AppPath = GetAppPath() ' obviate any problems with CreateProcess on earlier Windows versions GetShortPathName AppPath, AppShortPath, SIZEOF(AppShortPath) ' just for the record ... Result = "[Number Of Files Processed By RMA = " & FORMAT$(ARRAYATTR(RMFiles(),4),"") & "]" & $CRLF & $CRLF ' process all the dropped files, running RMA.EXE on each one ' for each of the specified command line options FOR i = LBOUND(RMFiles) TO UBOUND(RMFiles) Msg = "Processing file #" & FORMAT$(i,"") & ":" & $CRLF & RMFiles(i) CONTROL SET TEXT hDlg,%TXT_RESULT,Msg FOR j = LBOUND(Opts) TO UBOUND(Opts) ' run the console app with various options on the passed file name CmdLine = AppShortPath & "RMA.EXE " & Opts(j) & " " & $DQ & RMFiles(i) & $DQ ' launch the RMA.EXE child process ExitCode = ShellConsoleApp (CmdLine , AppPath, Result, 15000) ' wait a maximum of 15 secs ' process any error codes SELECT CASE ExitCode CASE -1: MSGBOX "Can't start the program",, CmdLine CASE -2: MSGBOX "Can't read the console Output",, CmdLine CASE -3: MSGBOX "Execution canceled (time out)",, CmdLine CASE -4: MSGBOX "CreatePipe() failed",, CmdLine CASE -5: MSGBOX "DuplicateHandle() failed",, CmdLine END SELECT NEXT NEXT 'Clean up any lines just ending in CRs in Result REPLACE $CRLF WITH CHR$(255) IN Result REPLACE $CR WITH $CRLF IN Result REPLACE CHR$(255) WITH $CRLF IN Result ' deallocate the file name array ERASE RMFiles() END SUB CALLBACK FUNCTION CB_Exit() AS LONG DIALOG END CBHNDL END FUNCTION CALLBACK FUNCTION CB_Run() AS LONG LOCAL DragFileName AS STRING LOCAL DragFileCount AS LONG LOCAL OptsStr AS STRING LOCAL i AS LONG ' clear the result variable Result = "" ' get the command line options (separated by the ";" character) CONTROL GET TEXT CBHNDL,%TXT_OPTS TO OptsStr REDIM Opts(1 TO PARSECOUNT(OptsStr,";")) PARSE OptsStr,Opts(),";" DragFileCount = ARRAYATTR(RMFiles(),4) IF DragFileCount > 0 THEN CONTROL SET TEXT CBHNDL,%TXT_RESULT,"Processing " & FORMAT$(DragFileCount,"") & " files using Real Media Analyzer ..." END IF ' run RMA on the files for each of the options RunRMA(CBHNDL) CONTROL SET TEXT CBHNDL,%TXT_RESULT,Result END FUNCTION CALLBACK FUNCTION CB_Main() AS LONG LOCAL hDrop AS DWORD LOCAL DragFileName AS ASCIIZ * %MAX_PATH LOCAL DragFileCount AS LONG LOCAL i AS LONG, hCtl AS DWORD SELECT CASE AS LONG CBMSG CASE %WM_COMMAND IF CBCTLMSG = 1 THEN ' Accelerator IF CBCTL = %TXT_RESULT THEN CONTROL HANDLE CBHNDL,%TXT_RESULT TO hCtl SendMessage(hCtl,%EM_SETSEL,0,-1) END IF END IF CASE %WM_DROPFILES hDrop = CBWPARAM DragFileCount = DragQueryFile(hDrop, -1, DragFileName, SIZEOF(DragFileName)) IF DragFileCount = 0 THEN EXIT FUNCTION REDIM RMFiles(1 TO DragFileCount) Result = "Number Of Files To Process = " & FORMAT$(DragFileCount,"") & $CRLF & $CRLF FOR i = 1 TO DragFileCount DragQueryFile(hDrop, i-1, DragFileName, SIZEOF(DragFileName)) RMFiles(i) = DragFileName Result = Result & DragFileName & $CRLF NEXT DragFinish(hDrop) CONTROL SET TEXT CBHNDL,%TXT_RESULT,Result END SELECT END FUNCTION FUNCTION PBMAIN LOCAL hDlg AS DWORD DIM AccelTbl(1 TO 1) AS ACCELAPI LOCAL hAccel AS DWORD ' create and launch the GUI DIALOG NEW 0,"Real Media Analyzer (GUI Shell) v" & $VERSION,,,400,200, _ %WS_SYSMENU OR %WS_CAPTION, _ %WS_EX_WINDOWEDGE OR %WS_EX_ACCEPTFILES _ ' allow drag-and-drop TO hDlg AccelTbl(1).FVIRT = 0 AccelTbl(1).KEY = 1 ' ASCII for Ctrl-A AccelTbl(1).CMD = %TXT_RESULT ACCEL ATTACH hDlg, AccelTbl() TO hAccel 'MSGBOX "hAccel = " & FORMAT$(hAccel,"") 'add the controls CONTROL ADD TEXTBOX,hDlg,%TXT_RESULT,$DO_THIS,5,5,390,165, _ %ES_READONLY OR %ES_MULTILINE OR %WS_VSCROLL OR %ES_WANTRETURN OR _ %ES_AUTOVSCROLL OR %ES_NOHIDESEL, %WS_EX_CLIENTEDGE CONTROL ADD LABEL, hDlg,-1, _ "RMA Command Line Options (multiple options must be separated with ';' characters)", _ 9,174,300,8 CONTROL ADD TEXTBOX, hDlg,%TXT_OPTS,"-d;-cv",9,182,300,12 CONTROL ADD BUTTON, hDlg,%BTN_RUN,"Run",320,176,30,18 CALL CB_Run() CONTROL ADD BUTTON, hDlg,%BTN_EXIT,"Exit",360,176,30,18 CALL CB_Exit() CONTROL SET FOCUS hDlg,%BTN_RUN ' wait for user interaction DIALOG SHOW MODAL hDlg CALL CB_Main END FUNCTION
Comment