Implementing IPersistStorage using PythonCOM
Edward Blakes
eblakes at drwtrading.com
Fri Dec 8 12:15:41 EST 2000
Thanks for responding Mark. I really appreciate your time (as well as your
work with PythonCOM, in the first place). See my comments inline.
"Mark Hammond" <MarkH at ActiveState.com> wrote in message
news:3A307D8C.10909 at ActiveState.com...
> Edward Blakes wrote:
>
> > CATID_PerspectiveAttributeTypeServer = pythoncom.MakeIID("{a guid}")
> > CLSID_PythonSample = pythoncom.MakeIID("{a guid}")
>
> This is probably a problem - it means a new GUID will be created each
> time it is run - definitely not what you want. Paste generated GUIDs
> directly into the code.
>
My understanding was that this simply converts a string to a PyIID, not
generates a brand new GUID. As you will see below, I directly placed the
string per your suggestion, but to no avail.
> Also - you _really_ should get my book ;-) The discussion on debugging
> is what you need the most.
>
I have it! That's how I got this far!
> Adding this:
>
I made the changes suggested, got more output but with the same result.
Given your response I believe I clipped important information that, in its
absence, mislead you. So that I won't do that again, I am placing the entire
source here so that you can run it directly. I hate the length but I want
you to have all the information needed.
Begin code.
import struct
import pythoncom
import win32api
import win32ui
from win32com import storagecon
from winerror import S_OK
class DummyAttr:
SampleProperty = ""
_public_attrs_ = ["SampleProperty"]
_public_methods_ = ["DoSomething", "GetClassID", "IsDirty", "InitNew",
"Load", "Save", "SaveCompleted", "HandsOffStorage"]
_reg_clsid_ =
_reg_progid_ = "PerspectiveAttribute.PythonSample"
_reg_catids_ = ["{5A0E5630-78E2-11D2-9D2E-00105A10A8F3}"]
_com_interfaces_ = [pythoncom.IID_IPersist,
pythoncom.IID_IPersistStorage]
def __init__(self):
self.SampleProperty = "This is an initial value"
win32ui.OutputDebugString("self.SampleProperty = " +
self.SampleProperty + "\n")
def DoSomething(self):
import win32ui
win32ui.MessageBox("Hello from DoSomething", "Message")
def GetClassID(self):
return "{D7929F71-133C-4F63-BE0B-BEC0842E7847}"
def IsDirty(self):
return 1
def InitNew(self):
return S_OK
def Load(self, pStg):
try:
pStream = pStg.OpenStream("ATTRSAVESTREAM",
storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE, 0, 0)
lenData = pStream.Read(struct.calcsize('l'))
samplePropertyLen = struct.unpack('l', lenData)[0]
self.SampleProperty = pStream.Read(samplePropertyLen)
return S_OK
except:
win32api.OutputDebugString('Caught exception in
DummyAttr.Load\n')
pass
def Save(self, pStg, fSameAsLoad):
try:
pStream = pStg.CreateStream("ATTRSAVESTREAM",
storagecon.STGM_READ|storagecon.STGM_SHARE_EXCLUSIVE|storagecon.STGM_CREATE,
0, 0)
samplePropertyLen = len(self.SampleProperty)
data = struct.pack('l', samplePropertyLen)
pStream.Write(data)
pStream.Write(self.SampleProperty)
return S_OK
except:
win32api.OutputDebugString('Caught exception in
DummyAttr.Save\n')
pass
def SaveCompleted(self, pStg):
return S_OK
def HandOffStorage(self):
return S_OK
class LockBytes:
_public_methods_ = [ 'ReadAt', 'WriteAt', 'Flush', 'SetSize',
'LockRegion', 'UnlockRegion', 'Stat' ]
_com_interfaces_ = [ pythoncom.IID_ILockBytes ]
def __init__(self, data = ""):
import pywintypes
import time
self.data = data
now = pywintypes.Time(time.time())
self.ctime = now
self.mtime = now
self.atime = now
def ReadAt(self, offset, cb):
print "ReadAt"
result = self.data[offset:offset + cb]
return result
def WriteAt(self, offset, data):
print "WriteAt " +str(offset)
print "len " + str(len(data))
print "data:"
#print data
if len(self.data) >= offset:
newdata = self.data[0:offset] + data
print len(newdata)
if len(self.data) >= offset + len(data):
newdata = newdata + self.data[offset + len(data):]
print len(newdata)
self.data = newdata
return len(data)
def Flush(self, whatsthis=0):
print "Flush" + str(whatsthis) #+ "Data:" + self.data
return S_OK
def SetSize(self, size):
print "Set Size" + str(size)
if size > len(self.data):
self.data = self.data + "\000" * (size - len(self.data))
else:
self.data = self.data[0:size]
return S_OK
def LockRegion(self, offset, size, locktype):
print "LockRegion"
pass
def UnlockRegion(self, offset, size, locktype):
print "UnlockRegion"
pass
def Stat(self, statflag):
print "returning Stat " + str(statflag)
return (
"PyMemBytes",
storagecon.STGTY_LOCKBYTES,
len(self.data),
self.mtime,
self.ctime,
self.atime,
storagecon.STGM_DIRECT|storagecon.STGM_READWRITE|storagecon.STGM_CREATE ,
storagecon.STGM_SHARE_EXCLUSIVE,
"{00020905-0000-0000-C000-000000000046}",
0, # statebits ?
0
)
def Test():
import win32com.client
import win32com.server.util
import win32com.server.dispatcher
useDispatcher = win32com.server.dispatcher.DefaultDebugDispatcher
# Create the server
origObj = DummyAttr()
aServer = win32com.server.util.wrap(origObj,
pythoncom.IID_IPersistStorage, useDispatcher=useDispatcher)
aServerDisp =
win32com.client.dynamic.Dispatch(aServer.QueryInterface(pythoncom.IID_IDispa
tch))
# Test a server method
aServerDisp.DoSomething()
# Test persistence
aLockBytes = win32com.server.util.wrap(LockBytes(),
pythoncom.IID_ILockBytes, useDispatcher=useDispatcher)
pStg = pythoncom.StgCreateDocfileOnILockBytes(aLockBytes,
storagecon.STGM_DIRECT|storagecon.STGM_CREATE|storagecon.STGM_READWRITE|stor
agecon.STGM_SHARE_EXCLUSIVE, 0)
# Show initial property value
print "SampleProperty = " + aServerDisp.SampleProperty
aServerDisp.SampleProperty = "1st change"
print "SampleProperty = " + aServerDisp.SampleProperty
persistStg = aServer.QueryInterface(pythoncom.IID_IPersistStorage)
persistStg.Save(pStg, 1)
origObj.Save(pStg,1)
aServer.Save(pStg, 1)
pStg.Commit(storagecon.STGC_DEFAULT)
aServerDisp.SampleProperty = "2nd change"
print "SampleProperty = " + aServerDisp.SampleProperty
persistStg.Load(pStg)
aServer.Load(pStg)
print "SampleProperty = " + aServerDisp.SampleProperty
def Register():
from win32com.server.register import UseCommandLine
return UseCommandLine(DummyAttr)
if __name__ == '__main__':
import sys
if "/test" in sys.argv:
print "Testing..."
Test()
else:
Register()
When I run the above, I still get the 'member not found' error. While you're
at it, feel free to comment on my use of the struct module. I couldn't
figure out any other way of writing data to streams. Don't know if it will
work b/c of the member problem.
Ed
eblakes at drwtrading.com
More information about the Python-list
mailing list