If
you buy into the notion that dhttp is a service
that can usefully enable groupware development, and your target group
is—as most are—Windows based, you’ll want a more
elegant way to run dhttp than by launching Perl
from the command line at system start-up. One way to hide the
dhttp process from the user is to use the Windows
Scripting Host (WSH). For example, if you rename the main
dhttp driver from dhttp
to
dhttp.pls
, then you can run it like this:
dhttp.pls
In this mode, there’s no command console. Instead WSH runs
dhttp, thanks to the PerlScript layer that enables
ActivePerl to plug into WSH. If you package the previous command into
a .CMD
file and refer to that file from the
Windows start-up folder, dhttp will start silently
when Windows starts. Of course, it will run silently too. Messages
that went to the default error channel, STDERR, won’t appear,
so you’ll need to log them or—when you want them to
appear to an interactive user—convert statements that print to
STDERR into statements that use the WScript->echo(
)
method.
The real problem here is system shutdown. The
dhttp server spends nearly all its time blocked on
an accept( )
call, waiting for the next incoming
connection. As a result, the process that runs
dhttp can’t react to Windows messages. When
Windows tries to tell that process that it wants to shut down,
there’s no response. Windows then invites the user to forcibly
terminate the process—and that’s hardly the desired
effect.
Is there a way to make dhttp a true Windows application that can process Windows messages? This amounts to asking if Perl itself can run as a true Windows application rather than as a Win32 console application. Historically Perl has always been easy to embed. In just a few lines of C code you can slave a Perl interpreter to a compiled program. When ActiveState released ActivePerl, the version of Perl that finally merged the core Perl codebase with ActiveState’s Win32 enhancements (e.g., ISAPI Perl, Win32::OLE, and more), the conventional way to embed Perl wasn’t supported. But ActiveState supplied another way: PerlEz, a DLL that a host Win32 application can use to embed Perl.
PerlEz is part of the answer, but there remains the problem of
getting at Windows messages. Embedded in a Windows application,
dhttp still blocks on the accept(
)
call in its central request-handling loop. What to do?
Run PerlEz, and in turn dhttp, on a background
thread. That way, the application’s primary thread can continue
to pump Windows messages, and the application can shut down normally.
Example 15.11
presents a minimal solution using
Microsoft Foundation
Classes (MFC).
Example 15-11. Embedding dhttp Using PerlEz
#include "stdafx.h" #include "resource.h" #include "dhttp.h" #include "/ap/lib/core/perlez.h" CTheApp NEAR theApp; UINT PerlEzProc(LPVOID pParam ) { PerlEzCreateOpt("c:\dhttp\dhttp","-Ic:\dhttp\lib","9191"); return 0; } CMainWindow::CMainWindow() { LoadFrame(IDR_MAINFRAME); } void CMainWindow::OnPaint() {} void CMainWindow::OnAbout() { CDialog about(IDD_ABOUTBOX); about.DoModal(); } BEGIN_MESSAGE_MAP( CMainWindow, CFrameWnd ) //{{AFX_MSG_MAP( CMainWindow ) ON_WM_PAINT() ON_COMMAND(ID_APP_ABOUT, OnAbout) //}}AFX_MSG_MAP END_MESSAGE_MAP() BOOL CTheApp::InitInstance() { m_pMainWnd = new CMainWindow; m_pMainWnd->ShowWindow(m_nCmdShow); m_pMainWnd->UpdateWindow(); AfxBeginThread(PerlEzProc,NULL); return TRUE; }
Since the window doesn’t display anything, you might simply
omit the ShowWindow( )
call and run it
invisibly. Alternatively, you might place an OLE control on the
canvas and route status messages into that control.