#IIS Hacks

Server & System Administration Archive · 2007–2013

An independent, non-commercial archive. Not affiliated with, endorsed by or connected to any vendor named in these notes.

Macro detail of a mainboard expansion slot with copper traces fanning out of frame

How to install PHP ISAPI on Windows 2008 IIS7 x64

Archived note. Originally published 3 July 2008 on iishacks.com, with updates added in April 2010 and February 2011. It describes installing 32-bit PHP 4 or PHP 5.2.x as an ISAPI extension under IIS 7 on 64-bit Windows Server 2008, and is preserved here as a record. The approach no longer exists: PHP 5.3 stopped shipping an ISAPI DLL for Windows and FastCGI became the supported way to run PHP on IIS, and Windows Server 2008 is long past end of support. Verify against current vendor documentation before applying any of it to a live system.

The original note

A February 2011 update at the head of the post pointed readers at the newer instructions for installing PHP 5.3 on IIS 7 and 7.5.

With the release of Windows Server 2008 and IIS 7, Microsoft included PHP 5 FastCGI support. The original note held that ISAPI was still faster and, used correctly, very stable. PHP shipped a 32-bit DLL, so it would not work on an x64 system as installed; several ports of PHP to x64 existed, and the note recorded all of them as having proved unstable.

A later update recorded that the same instructions also worked on 32-bit Windows Server 2008, leaving out the two application-pool steps.

The procedure as recorded

  1. Install the PHP 4 or PHP 5 package (32-bit) in C:\PHP, or wherever preferred. The note advised using the Windows installer from php.net only if no extensions were needed, and recommended downloading the PHP zip package otherwise.
  2. Open the Internet Information Services (IIS) Manager.
  3. Double-click Handler Mappings from the main IIS screen.
  4. Click Add Script Map.
  5. Set up the handler mapping for c:\PHP\php5isapi.dll with the extension *.php, and check the options to allow the ISAPI extension and the execution of scripts.
  6. Double-click ISAPI & CGI Restrictions on the main IIS screen. Right-click PHP, select Edit Feature Settings, and check Allow unspecified ISAPI modules.
  7. Right-click the Default Application Pool — or whichever pool is to be used, if more than one exists — and select Advanced Settings.
  8. Change Enable 32-bit Applications to True and click OK. This spawns the application pool in 32-bit mode, so if other modules on the same server need to run in 64-bit mode it is better to separate the website into two application pools, one 32-bit and one 64-bit.
  9. Restart the server.

An April 2010 update refined the build choice. The PHP VC6 x86 thread-safe package was the one to use for ISAPI on PHP 5.2.x. ISAPI was included in 5.2.x but not in 5.3.x — running the 5.3.x branch under ISAPI meant compiling it. The VC6 non-thread-safe package suited FastCGI on 5.2.x, and for 5.3.x PHP introduced VC9 packages, which is what the 2011 FastCGI note covers.

The ISAPI extension model

ISAPI was the native extensibility interface of IIS long before managed modules existed. An ISAPI extension is a DLL that IIS loads into its worker process and calls through a defined entry point. Everything happens in-process: the extension runs on the server’s threads, in the server’s address space, and stays resident between requests.

That residency was the attraction, and it is what stands behind the claim that ISAPI was faster. The alternative on Windows was CGI, where a fresh php.exe was started for every request, used once and torn down; on a busy site that process-creation cost dominated everything else.

The cost of the model was isolation, or the absence of it. An extension fault was a worker-process fault, and it took every request that process was serving; a memory leak in a third-party extension became the web server’s memory leak. There was no boundary to hide behind, which is why the qualifier in the original note — if used correctly — is doing real work.

Why the ISAPI build had to be thread-safe

Running inside the IIS worker process meant running on many threads at once, which imposed a hard requirement: the interpreter and every extension loaded into it had to be safe under concurrent execution. That is why the April 2010 update names the thread-safe VC6 package for ISAPI and the non-thread-safe one for FastCGI. The choice is not a preference; it follows from the execution model. Load a non-thread-safe binary into a multi-threaded host and the failures are intermittent, load-dependent and close to undiagnosable.

The requirement propagated outward to everything the interpreter loaded, and the availability of thread-safe builds of third-party extensions constrained what a Windows PHP stack could run. Opcode accelerators such as eAccelerator, xCache and APC were the deciding case: as long as they only worked in a thread-safe, in-process interpreter, ISAPI remained the configuration that made a busy Windows PHP site perform.

The x64 application pool problem

The 64-bit part of the title is what made the note worth writing: steps 7 and 8 are where installations of this era failed. PHP for Windows was distributed as a 32-bit binary. On x64 Windows Server 2008, IIS worker processes are 64-bit by default, and a 64-bit process cannot load a 32-bit DLL. There is no compatibility shim at the process level; the load simply fails, which is the concrete meaning of the note’s remark that PHP will not work with an x64 system.

Enable 32-bit Applications makes that pool’s worker processes start in 32-bit mode, at which point the DLL loads normally. Because the setting is scoped to a pool rather than the server, one machine can run 32-bit PHP sites alongside 64-bit workloads — the split the note recommends, and the reason those two steps are the ones dropped on 32-bit Windows. The same constraint carried through to the FastCGI era, where it is step 4 of the 2011 note, because bitness rather than the hosting model is what causes it.

Why the approach was abandoned

Two things ended it, close together, and the note’s own updates track both.

PHP 5.3 stopped shipping an ISAPI DLL for Windows. Using ISAPI beyond 5.2.x meant compiling it, which put it out of reach of ordinary deployment — the April 2010 update says so plainly, and that alone made the route a dead end.

At the same time FastCGI on IIS became both viable and better. Running the interpreter as external, recycled php-cgi.exe processes removed the thread-safety requirement, contained crashes and leaks to a single process, and gave the server real control over process lifetime. Once opcode caching worked in that model the last reason to accept an in-process interpreter disappeared, and by February 2011 the note pointed at its own successor.

What remains useful is the shape of the constraint rather than the procedure: bitness has to match at the process level, the execution model dictates which build of the interpreter is legal, and running an interpreter inside the web server buys speed by giving up isolation. Current guidance is in the PHP manual’s Windows installation chapter, current builds are at windows.php.net, and IIS is documented at Microsoft’s IIS documentation home.

The migration note from the same period is migrating websites from IIS6 to IIS7. Related material sits under PHP and Internet Information Server, with the full index at post archives.