lua-users home
lua-l archive

[Date Prev][Date Next][Thread Prev][Thread Next] [Date Index] [Thread Index]


Kenneth wrote:
> is it possible to use os.execute() and have it NOT wait for any return
> code, i.e. I don't get those annoying command prompts lingering around
> after I've launched another program.

I wrote some CreateProcess wrappers a while ago to spawn, wait for
finish, and kill procs.  They're not tested extremely well, but might
be a basis to explore creating a process that continues even if the
Lua prog has exited.



#include <windows.h>
#include <shlwapi.h>
#include <tchar.h>
#include <limits.h>

typedef struct {
	HANDLE hProcess;
	HANDLE hThread;
} process_t;

static void
push_last_error(lua_State *L)
{
	LPVOID lpMsgBuf;
	DWORD dw = GetLastError();
	FormatMessage(
			FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
			NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
			(LPTSTR) &lpMsgBuf, 0, NULL);
	lua_pushstring(L, lpMsgBuf);
	LocalFree(lpMsgBuf);
}

static int
lspawn(lua_State *L)
{
	int n = lua_gettop(L);    /* number of arguments */
	if (n != 1) {
		lua_pushstring(L, "wrong number of arguments to function `spawn'");
		lua_error(L);
	} else {
		/* Inspired by MSDN ms-help://MS.MSDN.vAug06.en/dllproc/base/creating_processes.htm */
		STARTUPINFO si;
		PROCESS_INFORMATION pi;
		LPTSTR szCmdline = lua_tostring(L, 1);

		ZeroMemory(&si, sizeof(si));
		si.cb = sizeof(si);
		ZeroMemory(&pi, sizeof(pi));

		if (! CreateProcess(NULL, szCmdline, NULL, NULL, FALSE, DETACHED_PROCESS,
				NULL, NULL, &si, &pi)) {
			lua_pushnil(L);
			push_last_error(L);
			return 2;
		} else {
			process_t *p = (process_t *) lua_newuserdata(L, sizeof(process_t));
			p->hProcess = pi.hProcess;
			p->hThread = pi.hThread;
			return 1;
		}
	}
	return 0;
}

static int
lkill(lua_State *L)
{
	int n = lua_gettop(L);    /* number of arguments */
	if (n != 1) {
		lua_pushstring(L, "wrong number of arguments to function `kill'");
		lua_error(L);
	} else {
		process_t *p = (process_t *) lua_touserdata(L, 1);
		luaL_argcheck(L, p != NULL, 1, "'process handle' expected");
		if (! TerminateProcess(p->hProcess, 0)) {
			push_last_error(L);
			return 1;
		} else {
			CloseHandle(p->hProcess);
			CloseHandle(p->hThread);
			free(p);
			return 0;
		}
	}
	return 0;
}

static int
lwaitfor(lua_State *L)
{
	int n = lua_gettop(L);    /* number of arguments */
	if (n != 1 && n != 2) {
		lua_pushstring(L, "wrong number of arguments to function `waitfor'");
		lua_error(L);
	} else {
		process_t *p = (process_t *) lua_touserdata(L, 1);
		DWORD millis = INFINITE;
		luaL_argcheck(L, p != NULL, 1, "'process handle' expected");
		if (n == 2) {
			lua_Number i = lua_tonumber(L, 2);
			luaL_argcheck(L, i >= 0 && i < INT_MAX, 1, "'milliseconds' expected");
			millis = i;
		}
		switch (WaitForSingleObject(p->hProcess, millis)) {
			default:
				lua_pushnil(L);
				push_last_error(L);
				return 2;
			case WAIT_TIMEOUT:
				lua_pushstring(L, "timeout");
				return 1;
			case WAIT_OBJECT_0: {
				DWORD code;
				if (! GetExitCodeProcess(p->hProcess, &code)) {
					lua_pushnil(L);
					push_last_error(L);
					return 2;
				} else {
					lua_pushstring(L, "exit");
					lua_pushnumber(L, code);
					CloseHandle(p->hProcess);
					CloseHandle(p->hThread);
					free(p);
					return 2;
				}
			}
		}
	}
	return 0;
}

...

	lua_register(L, "spawn", lspawn);
	lua_register(L, "kill", lkill);
	lua_register(L, "waitfor", lwaitfor);

...

C:\tmp> lua50
Lua 5.0.3  Copyright (C) 1994-2006 Tecgraf, PUC-Rio
> p=spawn("notepad")
> =waitfor(p, 1000)
timeout
> =waitfor(p)
exit    0
> p=spawn("notepad")
> =kill(p)
>

Robby

--
r dot raschke at tombob dot com