expect on windows

4 views
Skip to first unread message

tony summerfelt

unread,
Jun 21, 2002, 12:59:15 PM6/21/02
to
i've been using expect on windows, and i'm pretty happy with the results.
i've run an expect script as a service on windows 2000 using firedaemon.

i have the following trap code:

trap {
set sig [trap -name]
logmsg "--------------------"
logmsg "Exiting via SIG$sig"
logmsg "--------------------"
quit
} {SIGINT SIGTERM SIGQUIT}

this works fine except as a service. i have no idea what signal windows
sends to stop a service, but it's nothing that this code knows about.

can expect trap a service termination?


--
http://home.cogeco.ca/~tsummerfelt1

David Gravereaux

unread,
Jun 21, 2002, 5:44:41 PM6/21/02
to
tony summerfelt <snow...@hotmail.com> wrote:

>can expect trap a service termination?

I doubt it very much. Doesn't your service wrapper take care of closing
down the Tcl interp?
--
David Gravereaux <davy...@pobox.com>
Tomasoft Engineering, Hayward, CA
[species: human; planet: earth,milkyway,alpha sector]

tony summerfelt

unread,
Jun 21, 2002, 11:49:40 PM6/21/02
to
On Fri, 21 Jun 2002 at 21:44 GMT, David Gravereaux <davy...@pobox.com> wrote:

> I doubt it very much. Doesn't your service wrapper take care of closing
> down the Tcl interp?

i run expect.exe as a service with the expect script as a parameter
(using firedaemon). obviously the call to stop a service isn't one of the
standard signals (i'm guessing here).

if nothing else that could be tacked on to the long list of things that
need to be done for a windows version of expect (ie. an argument for the trap
command that it will recognize the call to stop a service)

i've never really pushed expect on windows, but it works fine for everything
i've tried...

--
http://home.cogeco.ca/~tsummerfelt1

Gerald W. Lester

unread,
Jun 22, 2002, 1:15:06 AM6/22/02
to
The windows services do not send signals to stop a service. The use the windows
event mechanism. There is an extension that supports this protocol. Jeff Hobbs
may be able to point you to it.

tony summerfelt wrote:

--
+--------------------------------+---------------------------------------+
| Gerald W. Lester | "The man who fights for his ideals is |
| Gerald...@cox.net | the man who is alive." -- Cervantes |
+--------------------------------+---------------------------------------+


David Gravereaux

unread,
Jun 22, 2002, 2:33:50 AM6/22/02
to
"Gerald W. Lester" <Gerald...@cox.net> wrote:

>obviously the call to stop a service isn't one of the
>> standard signals (i'm guessing here).

Standard.. What is "standard" when it comes to windows? signal() is a command
in the MS runtime. It does the minimum AnsiC requirements or so.

http://msdn.microsoft.com/library/en-us/vccore98/HTML/_crt_signal_constants.asp

When it comes to Win32 console applications, tclsh being one,
ConsoleCtrlHandlers are/should be used for "signals".

http://msdn.microsoft.com/library/en-us/dllproc/conchar_599u.asp
http://msdn.microsoft.com/library/en-us/dllproc/conchar_5zz9.asp

Then there's a thing called a "console event pump". Similar to windows "message
pump" for GUI applications. This would be the place to catch a
SIGWNCH (<- the window size change one).


int main (void)
{
DWORD dwRead, i;
CONSOLE_CURSOR_INFO cci = {100, 1};
MOUSE_EVENT_RECORD lastMouse;
CMclWaitableCollection groupedHandles;
DWORD dwRet;
HANDLE oldBuffer;

ConIn = CreateFile("CONIN$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
oldBuffer = CreateFile("CONOUT$", GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, OPEN_EXISTING, 0, 0L);
ConOut = CreateConsoleScreenBuffer(GENERIC_READ|GENERIC_WRITE,
FILE_SHARE_READ|FILE_SHARE_WRITE, 0L, CONSOLE_TEXTMODE_BUFFER, 0L);

if (!ConIn || !oldBuffer || !ConOut) {
WriteFile(GetStdHandle(STD_ERROR_HANDLE), "need console! die, die!\n",
24, &dwRet, 0L);
return -1;
}

SetConsoleCtrlHandler(ConsoleHandler, TRUE);
SetConsoleActiveScreenBuffer(ConOut);
SetConsoleMode(ConIn, ENABLE_WINDOW_INPUT|ENABLE_MOUSE_INPUT);
SetConsoleCursorInfo(ConOut, &cci);
SetConsoleOutputCP(437); // us-ascii code page.

// Index 0, highest priority goes first.
groupedHandles.AddObject(stop);

// Console handles are waitable objects.
// Index 1
groupedHandles.AddObject(ConIn);

again:
// Wait for any (either) to signal.
dwRet = groupedHandles.Wait(FALSE, INFINITE);

if (!CMclWaitSucceeded(dwRet, groupedHandles.GetCount()) ||
CMclWaitSucceededIndex(dwRet) == 0) {
// stop event or some other error, so die.
CloseHandle(ConIn);
CloseHandle(ConOut);
SetConsoleActiveScreenBuffer(oldBuffer);
return 0;
}

ReadConsoleInput(ConIn, Records, RECORD_SIZE, &dwRead);
for (i = 0; i < dwRead; i++) {
switch (Records[i].EventType) {
case KEY_EVENT:
HandleKey(&Records[i].Event.KeyEvent);
break;
case MOUSE_EVENT:
if (isDiff(&lastMouse, &Records[i].Event.MouseEvent)) {
lastMouse = Records[i].Event.MouseEvent;
HandleMouse(&Records[i].Event.MouseEvent);
}
break;
case WINDOW_BUFFER_SIZE_EVENT:
HandleWindow(&Records[i].Event.WindowBufferSizeEvent);
break;
}
}
goto again;
}

void
HandleWindow(WINDOW_BUFFER_SIZE_RECORD *wbsr)
{
/* do that SIGWNCH thing here */
}


It sure would be nice to have a modern, well-behaved Expect extension for
windows that supports Stubs and namespaces and all that good stuff.

David Gravereaux

unread,
Jun 22, 2002, 8:46:19 AM6/22/02
to
David Gravereaux <davy...@pobox.com> wrote:

>It sure would be nice to have a modern, well-behaved Expect extension for
>windows that supports Stubs and namespaces and all that good stuff.

Then you could use something like MFC's CComModule class and build a "service
Tcl shell" and from that Tcl_PkgRequire(interp, "Expect", "5.32", 0); or just
let the script call it in.

I'm staring at some code that does this right now. I wish I could share this,
but here a small piece of it.

void CServiceModule::Run(int argc, char **argv)
{
int newArgc;
char **newArgv;

_Module.dwThreadID = GetCurrentThreadId();

HRESULT hr = CoInitialize(NULL);
// If you are running on NT 4.0 or higher you can use the following call
// instead to make the EXE free threaded.
// This means that calls come in on a random RPC thread
// HRESULT hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);

_ASSERTE(SUCCEEDED(hr));

// This provides a NULL DACL which will allow access to everyone.
CSecurityDescriptor sd;
sd.InitializeFromThreadToken();
hr = CoInitializeSecurity(sd, -1, NULL, NULL,
RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE,
NULL);
_ASSERTE(SUCCEEDED(hr));

hr = _Module.RegisterClassObjects(CLSCTX_LOCAL_SERVER |
CLSCTX_REMOTE_SERVER, REGCLS_MULTIPLEUSE);
_ASSERTE(SUCCEEDED(hr));

LogEvent(_T("Service started"), EVENTLOG_INFORMATION_TYPE,
SC_MSG_SERVER_STARTED);
if (m_bService) {
SetServiceStatus(SERVICE_RUNNING);
}
m_stopWasLogged = 0;

setlocale(LC_ALL, "C");
fixargv(argc, argv, this, &newArgc, &newArgv);

m_asyncHandler = Tcl_AsyncCreate(AsyncHandler, this);


Tcl_Main(newArgc, newArgv, ConnectServerInit);

/*
* Ensure that finalize occurs in the correct thread!
*/

Tcl_Finalize();

_Module.RevokeClassObjects();

CoUninitialize();

Jeffrey Hobbs

unread,
Jun 22, 2002, 5:46:39 PM6/22/02
to
tony summerfelt wrote:
>
> On Fri, 21 Jun 2002 at 21:44 GMT, David Gravereaux <davy...@pobox.com> wrote:
>
> > I doubt it very much. Doesn't your service wrapper take care of closing
> > down the Tcl interp?
>
> i run expect.exe as a service with the expect script as a parameter
> (using firedaemon). obviously the call to stop a service isn't one of the
> standard signals (i'm guessing here).
>
> if nothing else that could be tacked on to the long list of things that
> need to be done for a windows version of expect (ie. an argument for the trap
> command that it will recognize the call to stop a service)

trap of signals (signal/raise in C) is completely different on Windows,
and only works inside an app for the most part. Windows does not send
"signals" like you are expecting them, as Gerald noted it uses the Windows
event mechanism to pump its messages around. Matt Newman wrote tclsvc,
which is basically a thin wrapper around this to allow Tcl scripts to be
Windows services (or just respond to the event mechanism). I have made
mods which make it work in a threaded environment, but the basic code can
be found here along with other nice Windows tidbits:
http://www.sensus.org/tcl/index.htm

--
Jeff Hobbs The Tcl Guy
Senior Developer http://www.ActiveState.com/
Tcl Support and Productivity Solutions

tony summerfelt

unread,
Jun 23, 2002, 12:52:19 PM6/23/02
to
On Sat, 22 Jun 2002 at 06:33 GMT, David Gravereaux <davy...@pobox.com> wrote:

> It sure would be nice to have a modern, well-behaved Expect extension for
> windows that supports Stubs and namespaces and all that good stuff.

all my systems programming was on dos, otherwise i'd volunteer my efforts
in this area.

i take it the original expect on windows was a brute force effort just to
get it work...

--
http://home.cogeco.ca/~tsummerfelt1

tony summerfelt

unread,
Jun 23, 2002, 12:56:11 PM6/23/02
to
On Sat, 22 Jun 2002 at 21:46 GMT, Jeffrey Hobbs <Je...@ActiveState.com> wrote:

> event mechanism to pump its messages around. Matt Newman wrote tclsvc,

if that worked with the expect it would probably solve my problem.

--
http://home.cogeco.ca/~tsummerfelt1

David Gravereaux

unread,
Jun 23, 2002, 4:29:07 PM6/23/02
to
tony summerfelt <snow...@hotmail.com> wrote:

>i take it the original expect on windows was a brute force effort just to
>get it work...

Agreed!

Reply all
Reply to author
Forward
0 new messages