... [Sidnei da Silva]
Simplifying a lot what the existing Zope 2 installer does, it basically creates a 'software home', a default 'instance home' and registers the services. All but the first part is done manually for Zope 3, so I can see the lack of glow there.
There's also that Zope2 sticks Python inside of Zope, but Zope3 sticks Zope inside of Python. A consequence is that you can't install more than one instance of Zope3 under a single Windows account, but can install any number of Zope2s. In the other direction, it's always a puzzle for Zope2 Windows users to figure out how to give their Zope access to packages installed in their (own, separate) Python. For Zope3 that's a no-brainer.
Supposing there is a existing python installation, how difficult is it to get a distutils-based windows installer to be extracted to a random directory outside site-packages?
distutils has no support for that.
My guess is that it's basically unzip it.
What are you trying to accomplish? (I know you're trying to push code into some directory other than under Lib/site-packages, but I don't know which code or why.)
If that's the case, we can simplify the Zope 2 inno installer to:
1. include a distutils-based windows installer for the Zope 2 source 2. include some setup scripts
Then on installation
1. find or install according python
Note that Zope also needs pywin32 to be installed.
2. unpack the distutils-based windows installer into Program Files\Zope
OK, so you're trying to preserve that ... what? You're neither sticking Python inside Zope nor Zope inside Python? BTW, _how_ do you unpack this at install time? You can't, for example, assume that a Windows box has any unzip utility (let alone some specific one). So this part would probably be simpler if you point Inno at a Zope tree and let _it_ package it and unpack it. Maybe the way to get such a tree is to build a distutils installer for Zope and run it on your own box, pointing Inno at the tree it creates, then throw the distutils installer away <0.3 wink>.
3. create a default 'instance home', pointing to the installed python
An instance home _certainly_ doesn't belong inside the user's Python -- but maybe I don't know what you mean by these words (I'm probably misreading "pointing to"). It should be possible to create any number of distinct instance homes.
4. register the services
Steps 2-4 are reasonably simple to me, the tricky one is 1.
Maybe somone will hit me for this ;-), but we have Inno code for #1 in one of our other installers. It goes like this: [Code] var // Path to the user's Python installation, found from the registry. // Procedure SetPythonInstallPath deduces this. gPythonInstallPath: String; function InitializeSetup(): boolean; begin gPythonInstallPath := ''; // don't know yet Result := True; end; ... // Look up Python's install path in the registry. Use HKCU first, because // a "user-only" instance is supposed to take precedence. If no Python is // installed, this will leave gPythonInstallPath as an empty string. procedure SetPythonInstallPath(); begin RegQueryStringValue(HKCU, 'Software\Python\PythonCore\2.4\InstallPath', '', gPythonInstallPath); if gPythonInstallPath = '' then // not in HKCU, so try HKLM RegQueryStringValue(HKLM, 'Software\Python\PythonCore\2.4\InstallPath', '', gPythonInstallPath); end; // Expose gPythonInstallPath to {code:...} clauses. function GetPythonDir(Default: String): String; begin Result := gPythonInstallPath; end; ... procedure SetupDependencies(); var PythonSetupFile: String; PyWin32SetupFile: String; ... begin PythonSetupFile := 'python-2.4.2.msi'; PyWin32SetupFile := 'pywin32-205.win32-py2.4.exe'; ... // Setup python, unless it is already installed. SetPythonInstallPath(); if gPythonInstallPath = '' then begin if not ShellExec('open', ExpandConstant('{tmp}\files\' + PythonSetupFile), '', '', SW_SHOW, ewWaitUntilTerminated, ErrorCode) then FatalError('Unable to install python'); // Try again to find the install path. SetPythonInstallPath(); if gPythonInstallPath = '' then // This shouldn't happen ... but if it does, we dare not leave this // variable empty: the installer blithely goes on to copy files // into the Windows system32 directory if we do. That should never // be allowed. gPythonInstallPath := ExpandConstant('{tmp}\NoPython\'); end; // Setup pywin32 if not Exec(ExpandConstant('{tmp}\files\' + PyWin32SetupFile), '', '', SW_SHOW, ewWaitUntilTerminated, ErrorCode) then FatalError('Unable to install PythonWin32'); ... The key is that the Python installer creates a registry entry, so you can guess whether Python is installed by looking at that. Note that this Inno code doesn't try to do silent installs -- and it always runs the pywin32 installer.