Added ExecShellWait

git-svn-id: https://svn.code.sf.net/p/nsis/code/NSIS/trunk@6839 212acab6-be3b-0410-9dea-997c60f758d6
This commit is contained in:
anders_k 2017-03-21 22:04:40 +00:00
parent 7650898389
commit 024e01a71e
9 changed files with 60 additions and 31 deletions

View file

@ -27,13 +27,20 @@ Execute the specified program and continue immediately. Note that the file speci
\S2{execshell} ExecShell
\c action command [parameters] [SW_SHOWDEFAULT | SW_SHOWNORMAL | SW_SHOWMAXIMIZED | SW_SHOWMINIMIZED | SW_HIDE]
\c [/INVOKEIDLIST] action command [parameters] [SW_SHOWDEFAULT | SW_SHOWNORMAL | SW_SHOWMAXIMIZED | SW_SHOWMINIMIZED | SW_HIDE]
Execute the specified program using ShellExecute. Note that action is usually "open", "print", etc, but can be an empty string to use the default action. Parameters and the show type are optional. $OUTDIR is used as the working directory. The error flag is set if the process could not be launched.
Execute the specified program using ShellExecuteEx. Note that action is usually "open", "print", etc, but can be an empty string to use the default action. Parameters and the show type are optional. $OUTDIR is used as the working directory. The error flag is set if the process could not be launched.
\c ExecShell "open" "http://nsis.sf.net/"
\c ExecShell "open" "$INSTDIR\readme.txt"
\c ExecShell "print" "$INSTDIR\readme.txt"
\c ExecShell /INVOKEIDLIST "properties" "$TEMP"
\S2{execshellwait} ExecShellWait
\c [/INVOKEIDLIST] action command [parameters] [SW_SHOWDEFAULT | SW_SHOWNORMAL | SW_SHOWMAXIMIZED | SW_SHOWMINIMIZED | SW_HIDE]
Execute the specified program using ExecShell and wait for executed process to quit. It will only wait for executable files and not other file types nor URLs.
\S2{execwait} ExecWait

View file

@ -8,6 +8,8 @@ Released on ? ?th, 2017
\S2{} Major Changes
\b Added \R{execshellwait}{ExecShellWait}
\b Added \R{writeregmultistr}{WriteRegMultiStr} (\W{http://sf.net/p/nsis/feature-requests/382}{RFE #382}, \W{http://sf.net/p/nsis/patches/219}{patch #219})
\S2{} Minor Changes

View file

@ -876,20 +876,29 @@ static int NSISCALL ExecuteEntry(entry *entry_)
#ifdef NSIS_SUPPORT_SHELLEXECUTE
case EW_SHELLEXEC: // this uses improvements of Andras Varga
{
int x;
TCHAR *buf0=GetStringFromParm(0x00);
TCHAR *buf3=GetStringFromParm(0x31);
TCHAR *buf2=GetStringFromParm(0x22);
SHELLEXECUTEINFO sei;
TCHAR *buf0=GetStringFromParm(0x00); // Verb
TCHAR *buf3=GetStringFromParm(0x31); // File
TCHAR *buf2=GetStringFromParm(0x22); // Parameters
GetStringFromParm(0x15); // For update_status_text_buf1
update_status_text_buf1(LANG_EXECSHELL);
x=(int)(INT_PTR)ShellExecute(g_hwnd,buf0[0]?buf0:NULL,buf3,buf2[0]?buf2:NULL,state_output_directory,parm3);
if (x < 33)
sei.cbSize=sizeof(SHELLEXECUTEINFO);
sei.fMask=parm4;
sei.hwnd=g_hwnd, sei.nShow=parm3;
sei.lpVerb=buf0[0]?buf0:NULL, sei.lpFile=buf3, sei.lpParameters=buf2[0]?buf2:NULL, sei.lpDirectory=state_output_directory;
sei.lpIDList=NULL; // Must set this because SEE_MASK_INVOKEIDLIST might be set
if (!ShellExecuteEx(&sei))
{
log_printf5(_T("ExecShell: warning: error (\"%s\": file:\"%s\" params:\"%s\")=%d"),buf0,buf3,buf2,x);
exec_error++;
}
else
{
if (SEE_MASK_NOCLOSEPROCESS & sei.fMask)
{
WaitForProcess(sei.hProcess);
CloseHandle(sei.hProcess);
}
log_printf4(_T("ExecShell: success (\"%s\": file:\"%s\" params:\"%s\")"),buf0,buf3,buf2);
}
}
@ -910,17 +919,11 @@ static int NSISCALL ExecuteEntry(entry *entry_)
log_printf2(_T("Exec: success (\"%s\")"),buf0);
if (parm2)
{
DWORD lExitCode;
while (WaitForSingleObject(hProc,100) == WAIT_TIMEOUT)
{
MessageLoop(WM_PAINT);
}
GetExitCodeProcess(hProc, &lExitCode);
DWORD lExitCode=WaitForProcess(hProc);
if (parm1>=0) myitoa(var1,lExitCode);
else if (lExitCode) exec_error++;
}
CloseHandle( hProc );
CloseHandle(hProc);
}
else
{

View file

@ -50,7 +50,7 @@
enum
{
EW_INVALID_OPCODE, // zero is invalid. useful for catching errors. (otherwise an all zeroes instruction
// does nothing, which is easily ignored but means something is wrong.
// does nothing, which is easily ignored but means something is wrong)
EW_RET, // return from function call
EW_NOP, // Nop/Jump, do nothing: 1, [?new address+1:advance one]
EW_ABORT, // Abort: 1 [status]
@ -118,7 +118,7 @@ enum
#endif
#ifdef NSIS_SUPPORT_SHELLEXECUTE
EW_SHELLEXEC, // ShellExecute program: 4, [shell action, complete commandline, parameters, showwindow]
EW_SHELLEXEC, // ShellExecute program: 5, [SEE_MASK_FLAG_*, verb, file, parameters, showwindow] (Will wait if SEE_MASK_NOCLOSEPROCESS is set)
#endif
#ifdef NSIS_SUPPORT_EXECUTE

View file

@ -1192,3 +1192,13 @@ void * NSISCALL NSISGetProcAddress(HANDLE dllHandle, TCHAR* funcName)
return GetProcAddress(dllHandle, funcName);
#endif
}
DWORD NSISCALL WaitForProcess(HANDLE hProcess)
{
DWORD excod;
while (WaitForSingleObject(hProcess, 100) == WAIT_TIMEOUT)
MessageLoop(WM_PAINT);
GetExitCodeProcess(hProcess, &excod);
return excod;
}

View file

@ -157,7 +157,9 @@ void NSISCALL MessageLoop(UINT uCheckedMsg);
* @param funcName The name of the function to get the address of.
* @return The pointer to the function. Null if failure.
*/
void * NSISCALL NSISGetProcAddress(HANDLE dllHandle, TCHAR* funcName);
void* NSISCALL NSISGetProcAddress(HANDLE dllHandle, TCHAR* funcName);
DWORD NSISCALL WaitForProcess(HANDLE hProcess);
// Turn a pair of chars into a word
// Turn four chars into a dword

View file

@ -4135,25 +4135,28 @@ int CEXEBuild::doCommand(int which_token, LineParser &line)
ERROR_MSG(_T("Error: %") NPRIs _T(" specified, NSIS_SUPPORT_EXECUTE not defined.\n"), line.gettoken_str(0));
return PS_ERROR;
#endif//!NSIS_SUPPORT_EXECUTE
case TOK_EXECSHELL: // this uses improvements of Andras Varga
case TOK_EXECSHELL:
case TOK_EXECSHELLWAIT:
#ifdef NSIS_SUPPORT_SHELLEXECUTE
{
const TCHAR *verb=line.gettoken_str(1), *file=line.gettoken_str(2), *params=line.gettoken_str(3);
UINT to=0, xflags=0;
static const TCHAR*fn=_T("/INVOKEIDLIST\0/CONNECTNETDRV\0/DOENVSUBST\0/NOIDLIST\0/NOCONSOLE\0/NOZONECHECKS\0/WAITFORINPUTIDLE\0/LOGUSAGE\0/ASYNCOK\0");
static const UINT fv[]={ 0x0000000C, 0x00000080, 0x00000200, 0x00001000,0x00008000, 0x00800000, 0x02000000, 0x04000000,0x00100000 };
for (int k;;) if ((k = line.gettoken_enum(to+1,fn)) < 0) { if (line.gettoken_str(to+1)[0]=='/') PRINTHELP(); break; } else xflags|=fv[k], to++;
const TCHAR *verb=line.gettoken_str(to+1), *file=line.gettoken_str(to+2), *params=line.gettoken_str(to+3), *cnam=get_commandtoken_name(which_token);
ent.which=EW_SHELLEXEC;
ent.offsets[0]=add_string(verb);
ent.offsets[1]=add_string(file);
ent.offsets[2]=add_string(params);
ent.offsets[3]=SW_SHOWNORMAL;
if (line.getnumtokens() > 4)
ent.offsets[0]=add_string(verb), ent.offsets[1]=add_string(file);
ent.offsets[2]=add_string(params), ent.offsets[3]=SW_SHOWNORMAL;
ent.offsets[4]=SEE_MASK_FLAG_NO_UI|SEE_MASK_FLAG_DDEWAIT|xflags|(which_token==TOK_EXECSHELLWAIT ? SEE_MASK_NOCLOSEPROCESS : 0);
if (line.getnumtokens()-to > 4)
{
int tab[8]={SW_SHOWDEFAULT,SW_SHOWNORMAL,SW_SHOWMAXIMIZED,SW_SHOWMINIMIZED,SW_HIDE,SW_SHOW,SW_SHOWNA,SW_SHOWMINNOACTIVE};
int a=line.gettoken_enum(4,_T("SW_SHOWDEFAULT\0SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0SW_HIDE\0SW_SHOW\0SW_SHOWNA\0SW_SHOWMINNOACTIVE\0"));
if (a < 0) PRINTHELP()
ent.offsets[3]=tab[a];
int a=line.gettoken_enum(to+4,_T("SW_SHOWDEFAULT\0SW_SHOWNORMAL\0SW_SHOWMAXIMIZED\0SW_SHOWMINIMIZED\0SW_HIDE\0SW_SHOW\0SW_SHOWNA\0SW_SHOWMINNOACTIVE\0"));
if (a >= 0) ent.offsets[3]=tab[a]; else PRINTHELP()
}
tstring detail=tstring(verb)+(_T(" ")+!*verb)+tstring(file);
ent.offsets[5]=add_string(detail.c_str());
SCRIPT_MSG(_T("ExecShell: %") NPRIs _T(": \"%") NPRIs _T("\" \"%") NPRIs _T("\" %") NPRIs _T("\n"),verb,file,params,line.gettoken_str(4));
SCRIPT_MSG(_T("%") NPRIs _T(": %") NPRIs _T(": \"%") NPRIs _T("\" \"%") NPRIs _T("\" %") NPRIs _T("\n"),cnam,verb,file,params,line.gettoken_str(to+4));
DefineInnerLangString(NLF_EXEC_SHELL);
}
return add_entry(&ent);

View file

@ -80,7 +80,8 @@ static tokenType tokenlist[TOK__LAST] =
{TOK_EXCH,_T("Exch"),0,1,_T("[$(user_var)] | [stack_item_index]"),TP_CODE},
{TOK_EXEC,_T("Exec"),1,0,_T("command_line"),TP_CODE},
{TOK_EXECWAIT,_T("ExecWait"),1,1,_T("command_line [$(user_var: return value)]"),TP_CODE},
{TOK_EXECSHELL,_T("ExecShell"),2,2,_T("(open|print|etc) command_line [parameters [showmode]]\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_HIDE|SW_SHOW)"),TP_CODE},
{TOK_EXECSHELL,_T("ExecShell"),2,11,_T("[flags] verb command_line [parameters [showmode]]\n verb=(open|print)\n showmode=(SW_SHOWNORMAL|SW_SHOWMAXIMIZED|SW_SHOWMINIMIZED|SW_HIDE|SW_SHOW)"),TP_CODE},
{TOK_EXECSHELLWAIT,_T("ExecShellWait"),2,11,_T("[flags] verb command_line [parameters [showmode]]"),TP_CODE},
{TOK_EXPANDENVSTRS,_T("ExpandEnvStrings"),2,0,_T("$(user_var: output) string"),TP_CODE},
{TOK_FINDWINDOW,_T("FindWindow"),2,3,_T("$(user_var: handle output) WindowClass [WindowTitle] [Window_Parent] [Child_After]"),TP_CODE},
{TOK_FINDCLOSE,_T("FindClose"),1,0,_T("$(user_var: handle input)"),TP_CODE},

View file

@ -176,6 +176,7 @@ enum
TOK_EXEC,
TOK_EXECWAIT,
TOK_EXECSHELL,
TOK_EXECSHELLWAIT,
TOK_CALLINSTDLL,
TOK_REGDLL,
TOK_UNREGDLL,