https://www.rpatterson.net/Ross Patterson's Blog - Posts tagged pse122023-08-22T15:29:28.253997+00:00ABloghttps://www.rpatterson.net/blog/python-web-apps-on-iis/Python Web Apps on IIS2017-11-12T00:00:00+00:00Ross Patterson<section id="python-web-apps-on-iis">
<blockquote>
<div><p>Can Plone work better on Windows? I have a working proof-of-concept with Web Platform Installer, Web Matrix and IIS Express that may improve Plone’s installation story. Help me get it out the door.</p>
</div></blockquote>
<p>Please don’t get me wrong, I hate Microsoft and Windows as much as the
next OSS or Python web developer. I just feel it’s important to be
honest with ourselves about <em>why</em> they’re bad. I grow a little tired
of all the griping sessions whenever the sorry state of <a class="reference external" href="http://plone.org">Plone’s</a> Windows <a class="reference external" href="http://plone.org/products/plone">installer</a> support is discussed. I think
there’s plenty to gripe about and there’s plenty that Microsoft does
poorly but lets also be honest with ourselves. If Microsoft didn’t do
some things really well they wouldn’t be a problem for us and we
wouldn’t even be discussing whether to support them as a platform.</p>
<p>At any rate, the discussions about the Windows installer at the 2012
<a class="reference external" href="http://www.coactivate.org/projects/cioppino/project-home">Cioppino Sprint</a> were as
frustrating and disappointing as ever. When everyone was through
griping, however, I couldn’t find anyone who at the end of that
discussion thought we could afford strategically to drop the Windows
installer or leave it to a 3rd party.</p>
<p>I’ve started putting Microsoft’s Web Platform Installer, Web Matrix, and IIS Express together for <a class="reference external" href="https://github.com/plone/Installers-UnifiedInstaller/blob/cioppino-webpi/platforms/webpi">Plone 4.2 and Python 2.7</a>
and have a proof-of-concept working on my Windows VM that actually
gives us Open Source all the way up to IIS, see the screenshot above.
Plone is actually really snappy running this way even on my very slow
Windows VM.</p>
<p>Below I document what I’ve learned as I proceeded and my final
findings. If you read nothing else please read the <a class="reference internal" href="#help-needed">Help Needed!</a>
section and let me know if you or anyone else can help me get this to
a place where others can try it out. I’ll be sprinting on this at the
<a class="reference external" href="https://weblion.tlt.psu.edu/FogBugz/default.asp?W1139">post-PSE sprints</a> so anyone
who has IIS or Windows installer experience, I’d love to sprint with
you on this.</p>
<nav class="contents" id="contents">
<p class="topic-title">Contents</p>
<ul class="simple">
<li><p><a class="reference internal" href="#python-web-apps-on-iis" id="id3">Python Web Apps on IIS</a></p>
<ul>
<li><p><a class="reference internal" href="#help-needed" id="id4">Help Needed!</a></p></li>
<li><p><a class="reference internal" href="#supporting-windows" id="id5">Supporting Windows</a></p></li>
<li><p><a class="reference internal" href="#notes-and-findings" id="id6">Notes and Findings</a></p>
<ul>
<li><p><a class="reference internal" href="#hosting" id="id7">Hosting</a></p></li>
<li><p><a class="reference internal" href="#packaging" id="id8">Packaging</a></p></li>
<li><p><a class="reference internal" href="#installing" id="id9">Installing</a></p></li>
<li><p><a class="reference internal" href="#miscellaneous-links-and-references" id="id10">Miscellaneous Links and References</a></p></li>
</ul>
</li>
</ul>
</li>
</ul>
</nav>
<section id="help-needed">
<h2><a class="toc-backref" href="#id4" role="doc-backlink">Help Needed!</a></h2>
<p>Primarily, I need help with things that I can’t do with just Web
Deploy and WebPI. For example, the way IIS does FastCGI means that a
configuration change has to be made to the global IIS config for
<em>each</em> FastCGI app. IOW, it can’t be done in the app/deployment-local
<code class="docutils literal notranslate"><span class="pre">web.config</span></code> file. I know the shell command to run to make the
change, but I don’t know how to package that properly so that it runs
with escalated privileges when necessary.</p>
<p>Similarly, we need to figure out how to handle ZEO in the way that is
closest to “correct” for IIS. Should we just install an autostart
service? IIS have a database provisioning and control framework. Can
that be adapted to also manage ZODB databases and control running ZEO
processes? Or should we just wrap it up in such a way that ZEO is
started the first, and only the first time, IIS launches the IIS
process and shuts it down when stopping the app? If so, how?</p>
<p>Since we’re using WSGI via FastCGI using Flup, we’re dependent on
Zope’s WSGI server. Unfortunately it lacks the publication hooks used
by things like <a class="reference external" href="http://pypi.python.org/pypi/plone.app.theming">plone.app.theming</a> and
<a class="reference external" href="http://pypi.python.org/pypi/plone.app.caching">plone.app.caching</a>.
This is really a bug in the Zope2 WSGI publisher and as such affects
all WSGI deployments, not just Windows. <a class="reference external" href="http://blog.hannosch.eu/">@Hanno</a> and <a class="reference external" href="http://davisagli.com">@davisagli</a>
think they’ll be able to get to this on in the next few days.</p>
<p>Finally, if I’m wrong about any of the <em>technical</em> stuff in here, I’d love
to hear about it. The documentation is crap for all this stuff and it
has been way too hard to figure it all out, so I’d love any leg up I
can get.</p>
</section>
<section id="supporting-windows">
<h2><a class="toc-backref" href="#id5" role="doc-backlink">Supporting Windows</a></h2>
<p>One thing that came out of the discussion, that I thought was
interesting, was the sentiment that if we were going to support
Windows we shouldn’t do it while telling Windows users to take a leap
at the same time. IOW, we say we support windows out of one side of
our mouths, and blame users for choosing windows out the other side of
our mouths when they encounter fundamental problems or find them
selves encountering an unfamiliar learning curve. I see two things
behind such problems: lack of integration with typical Windows tool
chains, and differences in the documentation.</p>
<p>The differences in the documentation largely come from the fact that
the current windows installer isn’t based off the <a class="reference external" href="https://github.com/plone/Installers-UnifiedInstaller">unified installer</a> so the
buildout/package layout is different than what’s in most of our docs.
To that end, I started looking into what it would take to build a
Windows installer from the unified installer.</p>
<p>The lack of integration with typical Windows tool chains is a much
bigger issue and much of that issue is a problem for most Python web
applications, not just Plone. My research did, however, turn up some
very promising new tools from Microsoft that we may be able to use to
provide a better experience for Windows Plone developers and Windows
Plone deployments.</p>
<p>There are also two major audiences that tend to make use of Plone’s
Windows support: developers and deployments. <a class="reference external" href="http://www.stevemcmahon.com/">Steve McMahon</a> believes that most of the Windows
downloads are by developers looking to get started doing Plone
integrations or custom Plone development. Another target the
installer has been used for, and this is more of what I’ve seen in my
experience as a developer, is as a basis for production Plone
deployments running on Windows servers. I definitely trust Steve’s
sense more than my own, but the good news is that this new Windows
tool chain seeks to provide a nicely integrated experience from web
app development through to web app deployment.</p>
<p>So for the latter half of the sprint and ever since then, I’ve been
obsessed with the Web Platform Installer (WebPI or WPI), IISExpress,
and Web Matrix tool chain. The WebPI is actually a <a class="reference external" href="http://blogs.iis.net/kateroh/archive/2009/10/24/web-pi-extensibility-custom-feeds-installing-custom-applications.aspx">fairly open
framework</a>
for describing web frameworks and web apps including dependencies and
arbitrary installation commands in an <a class="reference external" href="http://learn.iis.net/page.aspx/607/integrate-the-windows-web-application-gallery-into-a-control-panel#04">extended atom feed</a>. Helicon
uses this to provide a <a class="reference external" href="http://www.helicontech.com/zoo">Django install story</a> nicely integrated with this Windows
tool chain. Using IISExpress and Web Matrix also allows developers
to work in a local environment isolated to their user directory
without needing to have the full IIS ($$$) installed.</p>
</section>
<section id="notes-and-findings">
<h2><a class="toc-backref" href="#id6" role="doc-backlink">Notes and Findings</a></h2>
<p>Below is a loosely organized grab-bag of notes and findings I recorded
while working on this. I publish it here only for reference.</p>
<section id="hosting">
<h3><a class="toc-backref" href="#id7" role="doc-backlink">Hosting</a></h3>
<ul>
<li><p><a class="reference external" href="http://code.google.com/p/isapi-wsgi/">ISAPI-WSGI</a> doesn’t support IISExpress</p>
<p>The ISAPI-WSGI OSS project is used by a number of <a class="reference external" href="http://trac.edgewall.org/wiki/TracOnWindowsIisIsapi">Python WSGI
projects</a> to
support IIS. <a class="reference external" href="http://forums.iis.net/p/1181859/1996996.aspx#1996996">ISAPI-WSGI depends on py2win32 which in turn depends
on IIS 6</a> or
the IIS 7 plugin providing IIS 6 compatibility. The IIS 6
compatibility plugin <a class="reference external" href="http://forums.iis.net/p/1181859/1999841.aspx#1999841">isn’t supported on IISExpress</a>.</p>
</li>
<li><p>IIS only supports FastCGI</p>
<p>This is how the WebPI and Web Matrix tool chain support PHP apps
or other apps, such as plone, that need to have long running
separate processes to run efficiently. This <a class="reference external" href="http://www.iis.net/ConfigReference/system.webServer/fastCgi">FCGI support</a> is
also restricted to using Windows named pipes. IOW, no TCP sockets
to a separately running FCGI server process.</p>
</li>
<li><p>No current FCGI to WSGI gateway works with Windows</p>
<p>The <a class="reference external" href="http://www.fastcgi.com/drupal/node/6?q=node/22#S2.2">FastCGI spec</a> calls for
the <code class="docutils literal notranslate"><span class="pre">STDIN_FILENO</span></code> to refer to a socket which is then used for
two-way communication between the server and the process handling
requests. Naturally, Microsoft has embraced and extended this
standard in IIS such that instead of a single socket it uses two
Windows Named Pipes one each for receiving and sending. IIS may
also support TCP sockets behind the scenes. This means that
anything that expects to use normal sockets for FCGI, like <a class="reference external" href="http://trac.saddi.com/flup">flup</a> won’t work with IIS. I can find no
other OSS FCGI to WSGI gateway that supports Windows named pipes.</p>
</li>
<li><p><a class="reference external" href="http://iirf.codeplex.com/">IIRF</a> doesn’t support IISExpress</p>
<p>We might be able to use <a class="reference external" href="http://cheeso.members.winisp.net/Iirf20Help/frames.htm">Ionic’s Isapi Rewrite Filter</a> to
proxy IIS requests through to a separately running Python process.
This is less then ideal since it may make the Web Matrix
experience less integrated and requiring more un-Windows-like
knowledge. IIRF doesn’t support IISExpress, at any rate, though
it may be possible to manually install it into IISExpress.</p>
</li>
<li><p><a class="reference external" href="http://www.helicontech.com/zoo/module.htm">Helicon Zoo Module</a></p>
<p>I suppose the lack of other working options is exactly why Helicon
Tech built it’s own solution for this. I prefer to have OSS all the
way up to IIS itself, but that’s difficult when you play in the
Microsoft sandbox. At least it looks like Helicon has paid some
attention to <a class="reference external" href="http://www.helicontech.com/articles/running-django-on-windows-with-performance-tests">performance</a>.
Furthermore, having company support may yield better long term
maintenance for IIS support than an OSS project in the Microsoft
universe. That still doesn’t mean I like it.</p>
<aside class="system-message">
<p class="system-message-title">System Message: INFO/1 (<span class="docutils literal">/builds/rpatterson/ross-pattersons-site/blog/python-web-apps-on-iis/index.rst</span>, line 15); <em><a href="#id1">backlink</a></em></p>
<p>Duplicate explicit target name: “flup”.</p>
</aside>
<p>Part of the Helicon Zoo Module is a <cite>zoofcgi.py</cite> script which is
their own FCGI-WSGI gateway that seems to use <code class="docutils literal notranslate"><span class="pre">STDIN_FILENO</span></code>
instead of sockets to do the FCGI communication. IOW, Helicon has
written a totally new FCGI-WSGI gateway that works with IIS’s broken
FCGI implementation. In their implementation I see a lot that looks
familiar from <a class="reference external" href="http://trac.saddi.com/flup">flup</a>.</p>
</li>
<li><p>Modifying zoofcgi.py to run Plone</p>
<p>Unfortunately, Helicon’s <cite>zoofcgi.py</cite> only supports a Django WSGI
app or a example wsgi app, with no way that I saw to use it to run
an arbitrary WSGI app. Replace the <cite>run_example_app()</cite> function
with the following to <a class="reference external" href="http://blog.vrplumber.com/index.php?/archives/2421-TurboGears-as-a-Twisted-WSGI-Application-in-125-seconds.html">enable loading of an arbitrary WSGI app</a>
from a <a class="reference external" href="http://pastedeploy.readthedocs.io/en/latest/index.html?highlight=loadapp#introduction">Paste</a>
<cite>*.ini</cite> file:</p>
<blockquote>
<div><div class="highlight-python notranslate"><div class="highlight"><pre><span></span><span class="kn">from</span> <span class="nn">paste.script.util.logging_config</span> <span class="kn">import</span> <span class="n">fileConfig</span>
<span class="kn">from</span> <span class="nn">paste.deploy</span> <span class="kn">import</span> <span class="n">loadapp</span>
<span class="k">def</span> <span class="nf">run_example_app</span><span class="p">():</span>
<span class="n">config</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">environ</span><span class="o">.</span><span class="n">get</span><span class="p">(</span><span class="s1">'WSGI_CONFIG_FILE'</span><span class="p">)</span>
<span class="k">if</span> <span class="n">config</span><span class="p">:</span>
<span class="n">config</span> <span class="o">=</span> <span class="n">os</span><span class="o">.</span><span class="n">path</span><span class="o">.</span><span class="n">abspath</span><span class="p">(</span> <span class="n">config</span> <span class="p">)</span>
<span class="n">fileConfig</span><span class="p">(</span><span class="n">config</span><span class="p">)</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">loadapp</span><span class="p">(</span><span class="s1">'config:</span><span class="si">%s</span><span class="s1">'</span><span class="o">%</span><span class="p">(</span><span class="n">config</span><span class="p">,))</span>
<span class="k">else</span><span class="p">:</span>
<span class="n">application</span> <span class="o">=</span> <span class="n">example_application</span>
<span class="k">if</span> <span class="n">__debug__</span><span class="p">:</span> <span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'run_fcgi: STARTED'</span><span class="p">)</span>
<span class="n">FCGIServer</span><span class="p">(</span><span class="n">application</span><span class="p">)</span><span class="o">.</span><span class="n">run</span><span class="p">()</span>
<span class="k">if</span> <span class="n">__debug__</span><span class="p">:</span> <span class="n">logging</span><span class="o">.</span><span class="n">info</span><span class="p">(</span><span class="s1">'run_fcgi: EXITED'</span><span class="p">)</span>
</pre></div>
</div>
</div></blockquote>
<p>In <cite>~My DocumentsIISExpressconfigapplicationhost.config</cite> change
<cite><engine name=”python.2.7.pipe”…</cite> to:</p>
<blockquote>
<div><div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><engine</span><span class="w"> </span><span class="na">name=</span><span class="s">"python.2.7.pipe"</span>
<span class="w"> </span><span class="na">fullPath=</span><span class="s">"%SystemDrive%\Plone42\zeocluster\bin\zopeskelpy.exe"</span>
<span class="w"> </span><span class="na">arguments=</span><span class="s">"%SystemDrive%\ZooExpress\Workers\python\zoofcgi.py"</span>
<span class="w"> </span><span class="na">transport=</span><span class="s">"NamedPipe"</span>
<span class="w"> </span><span class="na">protocol=</span><span class="s">"fastcgi"</span><span class="w"> </span><span class="nt">/></span>
</pre></div>
</div>
</div></blockquote>
<p><cite>web.config</cite> in the site root:</p>
<blockquote>
<div><div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="cp"><?xml version="1.0" encoding="UTF-8"?></span>
<span class="nt"><configuration></span>
<span class="w"> </span><span class="nt"><system.webServer></span>
<span class="w"> </span><span class="nt"><heliconZoo></span>
<span class="w"> </span><span class="nt"><application</span><span class="w"> </span><span class="na">name=</span><span class="s">"wsgi.project"</span><span class="w"> </span><span class="nt">></span>
<span class="w"> </span><span class="nt"><environmentVariables></span>
<span class="w"> </span><span class="nt"><add</span><span class="w"> </span><span class="na">name=</span><span class="s">"WSGI_CONFIG_FILE"</span><span class="w"> </span><span class="na">value=</span><span class="s">"%APPL_PHYSICAL_PATH%\wsgi.ini"</span><span class="w"> </span><span class="nt">/></span>
<span class="w"> </span><span class="nt"></environmentVariables></span>
<span class="w"> </span><span class="nt"></application></span>
<span class="w"> </span><span class="nt"></heliconZoo></span>
<span class="w"> </span><span class="nt"><handlers></span>
<span class="w"> </span><span class="nt"><add</span><span class="w"> </span><span class="na">name=</span><span class="s">"wsgi.project"</span>
<span class="w"> </span><span class="na">scriptProcessor=</span><span class="s">"python.2.7.pipe"</span>
<span class="w"> </span><span class="na">path=</span><span class="s">"*"</span>
<span class="w"> </span><span class="na">verb=</span><span class="s">"*"</span>
<span class="w"> </span><span class="na">modules=</span><span class="s">"HeliconZoo_x86"</span><span class="w"> </span><span class="nt">/></span>
<span class="w"> </span><span class="nt"></handlers></span>
<span class="w"> </span><span class="nt"></system.webServer></span>
<span class="nt"></configuration></span>
</pre></div>
</div>
</div></blockquote>
<p>It should be possible to re-use <cite>zoofcgi.py</cite> without modifying it by
making it importable, IOW putting it’s dir on <cite>sys.path</cite>. Ideally,
I’d like to see instead is a library that can wrap the named pipes
provided by IIS such that they emulate a normal socket.</p>
</li>
<li><p><a class="reference external" href="https://github.com/rpatterson/iiswsgi">iiswsgi</a> and <a class="reference external" href="https://github.com/rpatterson/iiswsgi/blob/master/filesocket.rst">filesocket</a></p>
<aside class="system-message">
<p class="system-message-title">System Message: INFO/1 (<span class="docutils literal">/builds/rpatterson/ross-pattersons-site/blog/python-web-apps-on-iis/index.rst</span>, line 15); <em><a href="#id2">backlink</a></em></p>
<p>Duplicate explicit target name: “flup”.</p>
</aside>
<p>I implemented a crude <a class="reference external" href="https://github.com/rpatterson/iiswsgi/blob/master/filesocket.rst">socket-like implementation called filesocket</a>
that wraps two open files and acts like a socket. Then I copied and
pasted all the bits from <a class="reference external" href="http://trac.saddi.com/flup">flup</a> that
depend too rigidly on actual socket or on things not available in
windows and <a class="reference external" href="https://github.com/rpatterson/iiswsgi/blob/master/iiswsgi.py">adapted them as needed</a>.
Finally, I wrapped all that up with the necessary <a class="reference external" href="http://pastedeploy.readthedocs.io/en/latest/">paste.deploy</a> bits so that IIS can launch Plone
as a WSGI app, after adding bits from the <a class="reference external" href="http://build.pythonpackages.com/buildout/plone/4.2.x">WSGI buildout</a> to the
unified installer, from a Paste ini file, using the <a class="reference external" href="http://build.pythonpackages.com/buildout/plone/plone-mod-wsgi.ini.in">paster config
without a server</a>
since we’re interfacing directly with IIS. Finally, add the
following to <code class="docutils literal notranslate"><span class="pre">configuration/system.webServer/fastCgi</span></code> in <code class="docutils literal notranslate"><span class="pre">~\My</span>
<span class="pre">Documents\IISExpress\config\applicationhost.config</span></code>:</p>
<blockquote>
<div><div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><application</span><span class="w"> </span><span class="na">fullPath=</span><span class="s">"C:\Python27\python.exe"</span>
<span class="w"> </span><span class="na">arguments=</span><span class="s">"-u C:\Plone42\zeocluster\bin\iiswsgi-script.py -c C:\Plone42\zeocluster\production.ini"</span>
<span class="w"> </span><span class="na">monitorChangesTo=</span><span class="s">"C:\Plone42\zeocluster\production.ini"</span>
<span class="w"> </span><span class="na">maxInstances=</span><span class="s">"1"</span><span class="nt">></span>
<span class="nt"></application></span>
</pre></div>
</div>
</div></blockquote>
<p>This is one of the things I need help with. This can be done using
the IIS <a class="reference external" href="http://learn.iis.net/page.aspx/114/getting-started-with-appcmdexe/">appcmd.exe</a>
program but I need to know how to do this during the Web PI install
process.</p>
<p>It works and now we have Open Source all the way up to IIS!</p>
</li>
<li><p>Zope namespace URLs</p>
<p>Zope has a lot of special URL structures like <cite>++resource++foo.css</cite>
but <a class="reference external" href="http://blogs.iis.net/thomad/archive/2007/12/17/iis7-rejecting-urls-containing.aspx">IIS chokes on these</a>. Add
the <a class="reference external" href="http://learn.iis.net/page.aspx/296/top-10-changes-in-iis7/">following</a> to
web.config:</p>
<blockquote>
<div><div class="highlight-xml notranslate"><div class="highlight"><pre><span></span><span class="nt"><system.webServer></span>
<span class="w"> </span><span class="nt"><security></span>
<span class="w"> </span><span class="nt"><requestFiltering</span>
<span class="w"> </span><span class="na">allowDoubleEscaping=</span><span class="s">"true"</span><span class="nt">></span>
<span class="w"> </span><span class="nt"></requestFiltering></span>
<span class="w"> </span><span class="nt"></security></span>
...
</pre></div>
</div>
</div></blockquote>
</li>
<li><p>WebMatrix not launching instance until it’s been run in the foreground</p>
<p>I’m noticing that the Plone instance keeps restarting. Before I
fixed the pluses in URL issue, it at least eventually got running
stably after several restarts, but now it’s restarting much more
frequently. I thought it was caused by putting the resource
registries in development mode because it means more requests and
the number of requests that IIS lets build up before restarting the
FCGI process is reached. When Plone is warming up, almost all of
these request pile up. But I’ve also seen it be perfectly stable
with the resource registries development mode on so I’ll need to
catch this in the act again to debug.</p>
<p>Since then, I think the problem is that for some reason it needs to
be started in foreground mode before WebMatrix/IISExpress can
successfully start it.</p>
</li>
<li><p>How to restart in debug-mode? Logging?</p>
<p>What is the best way to make debugging information accessible to the
MS toolchain? What’s the best way give WebMatrix developers and IIS
admins to restart the instance in foreground-mode and/or debug-mode?
What about giving them more integrated access to the logs? Should
the default buildout configuration of the unified installer for
Windows use event log handlers?</p>
<p>Currently, the error reporting out of WebMatrix/IISExpress when
launching the instance or anything else fails is miserable. Is
there something we can do to better integrate with it’s trace logs
such that more Zope/Plone/Console/UNIXy specific output is reflected
somewhere?</p>
</li>
<li><p>Fixed two Windows bugs</p>
<p><a class="reference external" href="http://jaredforsyth.com/blog/2010/apr/28/accessinit-hash-collision-3-both-1-and-1/#the-solution">Docutils 0.7 conflicts with PIL</a>
causing:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="n">AccessInit</span><span class="p">:</span> <span class="nb">hash</span> <span class="n">collision</span><span class="p">:</span> <span class="mi">3</span> <span class="k">for</span> <span class="n">both</span> <span class="mi">1</span> <span class="ow">and</span> <span class="mi">1</span>
</pre></div>
</div>
<p>Upgrading to <a class="reference external" href="http://sourceforge.net/tracker/?func=detail&atid=422030&aid=2993756&group_id=38414">Docutils 0.9 fixes this</a>.</p>
<p>Also <a class="reference external" href="http://zope3.pov.lt/trac/changeset/126494">contributed a fix to Zope2</a> that addresses many of
the stale lock file problems on windows.</p>
</li>
</ul>
</section>
<section id="packaging">
<h3><a class="toc-backref" href="#id8" role="doc-backlink">Packaging</a></h3>
<ul>
<li><p>Creating a Web Deploy Package</p>
<p>Microsoft provides some <a class="reference external" href="http://learn.iis.net/page.aspx/722/reference-for-the-web-application-package/">docs</a>
for creating Web Deploy packages. It may also be possible to use
the <a class="reference external" href="http://learn.iis.net/page.aspx/422/packaging-and-restoring-a-web-site/">msdeploy</a>
tool to make a package in a more automated way.</p>
<p>More helpful pages about making web deploy packages:</p>
<ul class="simple">
<li><p><a class="reference external" href="http://blog.jumptree.com/2010/lessons-learned-mspi/">Lessons Learned from Packaging our ASP.NET Application for the
Microsoft Web Platform Installer</a></p></li>
<li><p><a class="reference external" href="http://learn.iis.net/page.aspx/578/package-an-application-for-the-windows-web-application-gallery/">Package an Application for the Windows Web Application Gallery</a></p></li>
</ul>
</li>
<li><p>Bootstrapping the Unified Installer</p>
<p>The first time building the Web Deploy package based on the Unified
Installer, some things need to be installed and configured that can’t
really be automated. Some of these steps shouldn’t be necessary in
the long run, since it should be possible to use the existing Web PI
feed to install the dependencies now that the feed is working. Much
of this should also be added to the Unified Installer in some sort of
platform specific way. But if the Web PI feed ever needs to be
created anew, or maybe when switching Python versions, it may be
necessary to do the same things I had to do on my Windows VM to begin
creating the Web PI feed and Plone Web Deploy package. I’m
documenting all that in a <a class="reference external" href="https://github.com/plone/Installers-UnifiedInstaller/blob/cioppino-webpi/platforms/webpi/README.rst">README in the Unified Installer</a>.</p>
</li>
<li><p>Non-buildout root Web Deploy Package?</p>
<p>For my proof-of-concept, I manually created a <code class="docutils literal notranslate"><span class="pre">web.config</span></code> file in
the <code class="docutils literal notranslate"><span class="pre">zeocluster</span></code> folder of the buildout created by the Unified
Installer and then manually added that as a “site” in WebMatrix.
Eventually, we need to figure out how to make the Unified Installer
buildout root also be the root of the site for
WebMatrix/IISExpress/IIS or how to have a web deploy package where
the root of the installed site is a subdirectory of the web deploy
package.</p>
</li>
<li><p>Deploying to a path with spaces</p>
<p>I ran into the following error when the buildout was at a location
with spaces in the path:</p>
<div class="highlight-default notranslate"><div class="highlight"><pre><span></span><span class="ne">WindowsError</span><span class="p">:</span> <span class="p">[</span><span class="n">Error</span> <span class="mi">87</span><span class="p">]</span> <span class="n">The</span> <span class="n">parameter</span> <span class="ow">is</span> <span class="n">incorrect</span>
</pre></div>
</div>
<p>To try to narrow down the issue, I used buildout to create a
debug-mode only script with the following part:</p>
<blockquote>
<div><div class="highlight-cfg notranslate"><div class="highlight"><pre><span></span><span class="k">[debug]</span>
<span class="na">recipe</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">zc.recipe.egg</span>
<span class="na">eggs</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">${instance:eggs}</span>
<span class="na">entry-points</span><span class="w"> </span><span class="o">=</span><span class="w"> </span><span class="s">debug=Zope2.Startup.run:run</span>
<span class="na">initialization</span><span class="w"> </span><span class="o">=</span>
<span class="w"> </span><span class="na">import sys</span>
<span class="w"> </span><span class="na">sys.argv.extend(["-C", r"${instance</span><span class="o">:</span><span class="s">location}\etc\zope.conf",</span>
<span class="w"> </span><span class="na">"-X", "debug-mode</span><span class="o">=</span><span class="s">on"])</span>
</pre></div>
</div>
</div></blockquote>
<p>The script this produces works just fine, so the problem is in the
<a class="reference external" href="http://pypi.python.org/pypi/plone.recipe.zope2instance">plone.recipe.zope2instance</a> recipe.</p>
</li>
<li><p>Installing FastCGI application, running bootstrap and buildout</p>
<p>Using <code class="docutils literal notranslate"><span class="pre"><runCommand></span></code> in <code class="docutils literal notranslate"><span class="pre">manifest.xml</span></code> is possible in theory:</p>
<ul class="simple">
<li><p><a class="reference external" href="http://forums.iis.net/t/1161375.aspx">http://forums.iis.net/t/1161375.aspx</a></p></li>
<li><p><a class="reference external" href="http://stackoverflow.com/questions/1511792/runcommand-provider-in-msdeploys-manifest-xml-file">http://stackoverflow.com/questions/1511792/runcommand-provider-in-msdeploys-manifest-xml-file</a></p></li>
</ul>
<p>I tried adding doing this and then just adding a site from a folder
in WebMatrix, nothing. But it may be that WebMatrix doesn’t do
anything with <code class="docutils literal notranslate"><span class="pre">manifest.xml</span></code> when adding a site that way so I’ll
have to try it by adding it to the WebPI feed. May also want to
experiment with manually using <code class="docutils literal notranslate"><span class="pre">msdeploy.exe</span></code>.</p>
</li>
</ul>
</section>
<section id="installing">
<h3><a class="toc-backref" href="#id9" role="doc-backlink">Installing</a></h3>
<ul>
<li><p>Writing the Web Platform Installer Atom Feed</p>
<p>Microsoft provides a <a class="reference external" href="http://msdn.microsoft.com/en-us/library/microsoft.web.platforminstaller.aspx">reference</a>
to what elements and attributes it adds to the ATOM namespace.</p>
</li>
<li><p><a class="reference external" href="http://docs.python.org/distutils/builtdist.html#creating-windows-installers">bdist_wininst</a> Python Installers aren’t silent</p>
<p>Windows MSI installers seem to support a <cite>/verysilent</cite> flag.
Unfortunatley, the Python <cite>distutils</cite> support for building Windows
installers has <a class="reference external" href="http://thread.gmane.org/gmane.comp.python.distutils.devel/6601/focus=6602">no silent option</a>.
A <a class="reference external" href="http://sourceforge.net/tracker/?func=detail&aid=3324407&group_id=78018&atid=551957#artifact_comment_5222052">workaround</a>
may be to use Web PI’s support for arbitrary installer commands to
extract the installer without running it. It may also work to
convert the wininst packages into <a class="reference external" href="http://stackoverflow.com/questions/3044359/unattended-install-of-binary-python-packages-modules-for-windows">MSI packages</a>.</p>
<p>In short, we need MSI’s for <a class="reference external" href="http://www.pythonware.com/products/pil/">PIL</a>, and <a class="reference external" href="http://sourceforge.net/projects/pywin32/files/pywin32/Build%20217/">pywin32</a>,
and binary windows eggs for <a class="reference external" href="http://lxml.de/index.html#download">lxml</a>.</p>
<p>Researching free software to build MSI’s. We need custom actions
support, so <a class="reference external" href="http://www.advancedinstaller.com/feats-list.html">Advanced Installer won’t do</a>.</p>
<p>It turns out that <a class="reference external" href="http://packages.python.org/distribute/easy_install.html">easy_install</a> can make
an egg out of a <code class="docutils literal notranslate"><span class="pre">bdist_wininst</span></code> exe installer. So we can now move
all those dependencies into buildout by using <cite>find-links</cite> that
point to the <code class="docutils literal notranslate"><span class="pre">bdist_wininst</span></code> exe downloads. This is how I’m
getting pywin32 now.</p>
</li>
<li><p>Get the SHA1 Hash of the Web Deploy Package</p>
<p>Microsoft provides a <a class="reference external" href="http://learn.iis.net/page.aspx/1082/web-deploy-parameterization">tool</a> for generating this hash. I’m not sure
if using this tool is strictly necessary or if there may be a way
to get the <cite>msdeploy</cite> tool to do this as a part of a more
automated packaging process.</p>
</li>
<li><p>Web App Gallery</p>
<p>Microsoft actually has a <a class="reference external" href="http://learn.iis.net/page.aspx/619/windows-web-application-gallery/">web application gallery</a>
that they say applications can <a class="reference external" href="http://learn.iis.net/page.aspx/789/testing-a-web-application-zip-package-for-inclusion-with-the-web-application-gallery/">submit</a>
their application to. If approved, these applications would be
available in Web PI without requiring the user to enter a custom
feed.</p>
</li>
</ul>
</section>
<section id="miscellaneous-links-and-references">
<h3><a class="toc-backref" href="#id10" role="doc-backlink">Miscellaneous Links and References</a></h3>
<ul class="simple">
<li><p><a class="reference external" href="http://countergram.com/pylons-lighttpd-flup">Paster/INI flup FCGI-WSGI config</a></p></li>
<li><p><a class="reference external" href="http://mercurial.selenic.com/wiki/HgWebInIisOnWindows">launching CGI/FCGI processes</a></p></li>
<li><p><a class="reference external" href="http://www.iis.net/ConfigReference">IIS Configuration Reference</a></p></li>
<li><p><a class="reference external" href="http://learn.iis.net/page.aspx/860/iis-express/">So called IISExpress docs</a></p></li>
</ul>
<div class="note update admonition">
<p class="admonition-title">Updated on 12 November 2017</p>
<p>Imported from Plone on Mar 15, 2021. The date for this update is the last
modified date in Plone.</p>
</div>
</section>
</section>
</section>
Can Plone work better on Windows? I have a working proof-of-concept with Web Platform Installer, Web Matrix and IIS Express that may improve Plone’s installation story. Help me get it out the door.2012-03-31T00:00:00+00:00