FAQ
Im trying to produce a small Visual Studio Addin. Taking the
OutlookAddin example and changing the registry place it installs too,
everything works ok.

Examples in C++ show that in the OnConnection method I have to registry
my commands and also pass an instance of my sub class of ICommands.

The C code looks like this:

IApplication* pApplication = NULL;
pApp->QueryInterface(IID_IApplication, (void**) &pApplication)

CCommandsObj::CreateInstance(&m_pCommands);
m_pCommands->AddRef();
m_pCommands->SetApplicationObject(pApplication);

pApplication->SetAddInInfo((long) AfxGetInstanceHandle(),
(LPDISPATCH) m_pCommands, -1, -1, m_dwAddin));


So far Im trying something like this:

self._command = VCCmd(application)
application.SetAddInInfo(AfxGetInstanceHandle(), self._command, -
1, -1, addin )


with VCCmd defined like:

class VCCmd:
_com_interfaces_ = ['_ICommands']
_public_methods_ = []

_application = None

def __init__( self, app ):
self._application = app
print "VCCmd __init__"


Needless to say, its not working, so questions.

1) AfxGetInstanceHandle dosent appear to exist in the win32api... so how
do I call it.

2) am I defining VCCmd correctly to be a subclass of ICommands

3) am I correct in thinking i dont have to explicitly 'cast' application
into an IApplication instance

Many thanks for any light you may be able to shed on the subject

Rich

Search Discussions

  • Mark Hammond at Jan 30, 2004 at 11:53 pm

    Crawley wrote:

    Im trying to produce a small Visual Studio Addin. Taking the
    OutlookAddin example and changing the registry place it installs too,
    everything works ok.

    Examples in C++ show that in the OnConnection method I have to registry
    my commands and also pass an instance of my sub class of ICommands.

    The C code looks like this:

    IApplication* pApplication = NULL;
    pApp->QueryInterface(IID_IApplication, (void**) &pApplication)

    CCommandsObj::CreateInstance(&m_pCommands);
    m_pCommands->AddRef();
    m_pCommands->SetApplicationObject(pApplication);

    pApplication->SetAddInInfo((long) AfxGetInstanceHandle(),
    (LPDISPATCH) m_pCommands, -1, -1, m_dwAddin));


    So far Im trying something like this:

    self._command = VCCmd(application)
    application.SetAddInInfo(AfxGetInstanceHandle(), self._command, -
    1, -1, addin )


    with VCCmd defined like:

    class VCCmd:
    _com_interfaces_ = ['_ICommands']
    _public_methods_ = []

    _application = None

    def __init__( self, app ):
    self._application = app
    print "VCCmd __init__"


    Needless to say, its not working, so questions.

    1) AfxGetInstanceHandle dosent appear to exist in the win32api... so how
    do I call it.
    AfxGetInstanceHandle returns the handle to your MFC built DLL. The
    assumption is that your object is built into a nice, single little DLL.

    This doesn't make sense for Python. Your code is not implemented in a
    DLL at all, but in a .py file. There are a few DLLs involved
    (pythonxx.dll, pythoncomxx.dll), and the handles to these can be found
    pretty easily - but it is unclear if that helps you.

    You really need to determine *why* SetAddInInfo() wants a DLL handle and
    what the implications are. My guess is that it expects to be able to
    pull Win32 resources (such as bitmaps, menus, etc) from that DLL, which
    may be a problem.
    2) am I defining VCCmd correctly to be a subclass of ICommands
    That looks OK, assuming that the type library where ICommands is defined
    has been registered for universal support. You will note the Outlook
    addin sample specifies the generic IDTExtensibility interface - if
    ICommands is VS specific (and therefore in a different typelib), then it
    is likely you also need to specify that additional typelib.
    3) am I correct in thinking i dont have to explicitly 'cast' application
    into an IApplication instance
    Correct - the framework will automatically perform a QI in most cases.
    Of course, if your object is not implemented correctly, this QI will fail.
    Many thanks for any light you may be able to shed on the subject
    Register your addin with "--debug" on the command-line. Then use the
    Pythonwin "Remote Trace Collector" tool, and you should see lots of
    output as your object is instantiated and used. You should also be able
    to see most exceptions raised by your object, which are generally
    invisible without this debugging technique.

    When you get it working, consider contributing it back as a sample I can
    put next to the Outlook one ;)

    Mark.
  • Crawley at Jan 31, 2004 at 11:21 am
    Thanks for the reply,

    Now I think Ive figured out whats going on. Im getting the following
    error:

    Traceback (most recent call last):
    File "E:\Python23\lib\site-packages\win32com\universal.py", line 170,
    in dispatch
    retVal = ob._InvokeEx_(meth.dispid, 0, meth.invkind, args, None,
    None)
    File "E:\Python23\lib\site-packages\win32com\server\policy.py", line
    322, in _InvokeEx_
    return self._invokeex_(dispid, lcid, wFlags, args, kwargs,
    serviceProvider)
    File "E:\Python23\lib\site-packages\win32com\server\policy.py", line
    601, in _invokeex_
    return DesignatedWrapPolicy._invokeex_( self, dispid, lcid, wFlags,
    args, kwArgs, serviceProvider)
    File "E:\Python23\lib\site-packages\win32com\server\policy.py", line
    541, in _invokeex_
    return func(*args)
    File "E:\code\Python\VCAddin.py", line 69, in OnConnection
    application.SetAddInInfo(None, self._command, -1, -1, addin )
    File "E:\Python23\lib\site-packages\win32com\client\dynamic.py", line
    460, in __getattr__
    raise AttributeError, "%s.%s" % (self._username_, attr)
    exceptions.AttributeError: <unknown>.SetAddInInfo


    Which I believe is because the object I'm calling does not support the
    SetAddInInfo method.


    After a bit of investigation, this makes sense as my class extends
    _IDTExtensibility2 and for that the application parameter is of type
    'Object'. I cant see how to cast this into an IApplication instance,
    which is what I need to call my function.

    Ive also tried making my object derive from IDSAddin (what VC uses), but
    when I try the following (GUID found
    here:http://msdn.microsoft.com/library/default.asp?url=/library/en-
    us/vcug98/html/_asug_how_add.2d.ins_connect_and_disconnect.asp)

    universal.RegisterInterfaces('{C0002F81-AE2E-11cf-AD07-00A0C9034965}', 0,
    1, 0, ["_IDSAddin"])

    I get the following error:

    Traceback (most recent call last):
    File "E:\code\Python\VCAddin.py", line 33, in ?
    universal.RegisterInterfaces('{C0002F81-AE2E-11cf-AD07-
    00A0C9034965}', 0, 1, 0, ["_IDSAddin"])
    File "E:\Python23\lib\site-packages\win32com\universal.py", line 21, in
    RegisterInterfaces
    tlb = pythoncom.LoadRegTypeLib(typelibGUID, major, minor, lcid)
    pywintypes.com_error: (-2147319779, 'Library not registered.', None,
    None)

    Am I using the wrong name ('_IDSAddin') or the wrong GUID or is something
    more major going wrong.

    Thanks for your help

    Rich
  • Mark Hammond at Jan 31, 2004 at 10:15 pm

    Crawley wrote:
    File "E:\Python23\lib\site-packages\win32com\client\dynamic.py", line
    460, in __getattr__
    raise AttributeError, "%s.%s" % (self._username_, attr)
    exceptions.AttributeError: <unknown>.SetAddInInfo


    Which I believe is because the object I'm calling does not support the
    SetAddInInfo method.
    For some reason, the object you are using does not have makepy support,
    which is unusual.
    After a bit of investigation, this makes sense as my class extends
    _IDTExtensibility2 and for that the application parameter is of type
    'Object'. I cant see how to cast this into an IApplication instance,
    which is what I need to call my function.
    Generally, you can do a QueryInterface for the object. However, if the
    object does not support IDispatch, you will haver trouble - we don't
    support arbitrary interfaces when calling them, only implementing them.


    ob = ob._obj_.QueryInterface(
    Ive also tried making my object derive from IDSAddin (what VC uses), but
    when I try the following (GUID found
    here:http://msdn.microsoft.com/library/default.asp?url=/library/en-
    us/vcug98/html/_asug_how_add.2d.ins_connect_and_disconnect.asp)

    universal.RegisterInterfaces('{C0002F81-AE2E-11cf-AD07-00A0C9034965}', 0,
    1, 0, ["_IDSAddin"])

    I get the following error:
    The GUID must be for a type library. If you run "makepy.py -i", then
    you will get a list of all valid typelibs you can use, and the params
    for it.

    Mark.
  • Crawley at Jan 31, 2004 at 10:31 pm
    Mark Hammond <mhammond at skippinet.com.au> wrote in
    news:bvh9f0$1gej$1 at arachne.labyrinth.net.au:
    Generally, you can do a QueryInterface for the object. However, if
    the object does not support IDispatch, you will haver trouble - we
    don't support arbitrary interfaces when calling them, only
    implementing them.

    ob = ob._obj_.QueryInterface(
    I take it the chances of this working are slim to none ?
    The GUID must be for a type library. If you run "makepy.py -i", then
    you will get a list of all valid typelibs you can use, and the params
    for it.
    Bum!

    Perhaps I should look at implementing the actual addin in C++ and then
    embed python into it so that most the work can be done by that.

    Thanks for your help anyway

    Rich


    From http Sat Jan 31 23:56:15 2004
    From: http (Paul Rubin)
    Date: 31 Jan 2004 14:56:15 -0800
    Subject: OT: why do web BBS's and blogs get so slow?
    Message-ID: <7xbrojk9rk.fsf_-_@ruckus.brouhaha.com>

    Lots of times, when a blog (that supports user comments) or a web BBS
    gets heavily loaded, it slows down horribly, even when it's hosted at
    an ISP on a fast computer with plenty of net bandwidth. I'm wondering
    what those programs are doing, that makes them bog down so badly.
    Anyone know what the main bottlenecks are? I'm just imagining them
    doing a bunch of really dumb things.

    I'm asking this on clpy because thinking about the problem naturally
    made me wonder how I'd write a program like that myself, which of
    course would mean using Python.

    FWIW, here's how I'd do it:

    1) It would be single threaded web server (asyncore, twistedmatrix)
    with a select loop talking to a socket, either on port 80 directly, or
    to a proxy web server running mod_gzip, SSL, and so forth.

    2) It might use MySQL for infrequent operations like user info lookup
    at login time or preference updates, but not for frequent operations
    like reading and posting messages. User session info and preferences
    would be in ram during a session, in a python dict indexed by a
    browser session cookie.

    3) The message store would be two files, one for metadata and one for
    message text. Both of these would be mmap'd into memory. There would
    be a fixed length of metadata for each message, so getting the
    metadata for message #N would be a single array lookup. The metadata
    would contain the location in the text file where the message text is
    and its length, so getting the text would take just one memcpy. The
    box would have enough ram to hold all recently active messages in ram
    almost all the time. Paging to disk is left to the host OS's virtual
    memory system. From the application's point of view everything is
    always in ram. Digging up old messages might take some page faults,
    but doing that should be relatively rare. New messages are always
    appended to the files, keeping memory and paging behavior fairly
    localized. There might be a third file for an activity log, which is
    append-only (serial access). Ideally that would be on a separate disk
    from the message disk, to reduce head contention.

    4) Finding all N messages in an active discussion thread might require
    chasing N pointers in the metadata file, but that would usually be at
    most a few thousand small lookups, all in ram, and the thread info
    would be cached in ram in the application once found. Fancier disk
    structures could speed this up but probably arn't needed.

    A site like Slashdot gets maybe 20(?) page views per second at busy
    times, and around 10,000 new messages a day of maybe 1 kbyte each, a
    mere 10 MB per day of message text, no problem to keep in ram. I'd
    like to think that the above scheme could handle Slashdot's traffic
    level pretty easily on one or two typical current PC's with IDE disks,
    one PC for the BBS application and the other (if needed) for a proxy
    server running gzip and caching static pages. Am I being naive and/or
    missing something important? Slashdot itself uses a tremendous amount
    of hardware by comparison.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
grouppython-list @
categoriespython
postedJan 29, '04 at 11:00p
activeJan 31, '04 at 10:31p
posts5
users4
websitepython.org

People

Translate

site design / logo © 2022 Grokbase