[python-win32] Running a Windows Python service without pythonservice.exe?
Mark Hammond
mhammond at skippinet.com.au
Tue May 11 08:22:28 CEST 2010
On 11/05/2010 12:50 PM, Bill Janssen wrote:
> Mark Hammond<skippy.hammond at gmail.com> wrote:
>
>> That's correct. Using python.exe as the host will involve having a
>> .py script which imports the servicemanager module then call
>> PrepareToHostSingle and instantiate the service class - or something
>> like that :)
>
> How definitive :-). I'm already generating a python script for each
> service, so this could easily be incorporated, if I knew exactly what it
> was I have to do.
>
> 1. Set up the sys.path and os.environ["Path"] properly.
>
> 2. import servicemanager
>
> 3. define my class
>
> 4. call servicemanager.PrepareToHostSingle(my class name)
>
> Seem right?
Sounds about right - but reading pythonservice.cpp is really the
definitive source to what needs to be done. Sadly I can't find anything
more specific, such as a sample.
>> Another alternative is to ship a slightly modified pythonxx.dll - it
>> has a feature where a certain string resource contains the basename of
>> the registry key used at runtime to load the pythonpath - eg, you will
>> find the resource has "2.6" for Python 2.6 builds. Using a resource
>> editor (or even a script using pywin32) to change this to some custom
>> value will mean the pythonpath can be loaded from a private key in the
>> registry, meaning you still get isolation from other installed Python
>> versions.
>
> I could do that, I guess. I'd like to be able to script all the
> preparations, so if it's a GUI step that would be a Bad Thing. But a
> script using pywin32 would be great. So, I need to know a couple of
> things:
>
> 1. What's the name of this "certain string resource"?
>
> 2. How would one write such a pywin32 script :-)?
>
> I wrote this script to answer question #1:
>
> -----------------------------------------------------------------
> import sys, os
>
> import win32api, win32con
>
> handle = win32api.LoadLibrary(sys.argv[1])
> for rname in win32api.EnumResourceNames(handle, win32con.RT_STRING):
> rvalue = win32api.LoadResource(handle, win32con.RT_STRING, rname)
> print rname, rvalue
> -----------------------------------------------------------------
>
> $ python resource.py python26.dll
> 63 ^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^C^@2^@.^@6^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@
> $
>
> So, the "name" is 63, and it's a 38-byte value with a lot of nul
> characters in it. I'm unsure of just how to hack it with UpdateResource
> -- do I just center the replacement text and pad with nul characters?
> And what's the registry key this works against, anyway? I'd have to
> update that as part of my installer, too.
I think the above loaded a string *table*. The resource ID is 1000, and
py2exe has some code to deal with updating this for a file. It does:
from py2exe.resources.StringTables import StringTable, RT_STRING
from py2exe_util import add_resource, load_resource
from py2exe.resources.VersionInfo import RT_VERSION
...
# OK - do the strings.
s = StringTable()
# 1000 is the resource ID Python loads for its winver.
s.add_string(1000, new_winver)
for id, data in s.binary():
add_resource(ensure_unicode(dll_name), data, RT_STRING, id,
False)
While this could be done with pywin32 and the win32api.UpdateResource
function, that would probably require some struct magic - the
StringTable object in py2exe hides some of this from you.
HTH,
Mark
More information about the python-win32
mailing list