[python-win32] Access to .NET components from Python (Was: Win32 COM starter book)

Jens B. Jorgensen jens.jorgensen@tallan.com
Fri, 20 Dec 2002 10:15:28 -0600


Mark Hammond wrote:

>>Compile with csc /target:library MyAssembly.cs, register with
>>regasm MyAssembly.dll /tlb:MyAssembly.tlb, and try to test it. Nope,
>>OLE error 0x80131522. Google tells me that this means I need my
>>assembly in the same directory as the executable! (That's Python, not
>>the script - so definitely not where I'd like to put my random DLLs).
>>    
>>
>
>Yeah, this is .NET for you.  If you want it publically available, you must create a strongly named assembly and stick it in the GAC.  There are 2 choices - very public or very private.  However, the "very public" isn't as bad as it sounds - you are guaranteed to get the *except* object you compiled against, regardless of naming clashes, etc.
>
As an aside I was trying to do this same thing just to try it. I run 
regasm but I *still* can't get the object to create itself. It doesn't 
matter if the object is in the current directory or the python directory 
(same dir as python.exe). It still doesn't find it and I get 'Class not 
registered'. Is it absolutely necessary to stick it in the gac in order 
to be able to create it? This doesn't make sense to me because then why 
bother with regasm? I had regasm first do the .tlb thing and that didn't 
work so I generated the reg file and added it manually. The contents of 
the reg file show:

REGEDIT4

[HKEY_CLASSES_ROOT\JTest]
@="JTest"

[HKEY_CLASSES_ROOT\JTest\CLSID]
@="{AD4D463B-FC29-3FE5-B82D-569A34325989}"

[HKEY_CLASSES_ROOT\CLSID\{AD4D463B-FC29-3FE5-B82D-569A34325989}]
@="JTest"

[HKEY_CLASSES_ROOT\CLSID\{AD4D463B-FC29-3FE5-B82D-569A34325989}\InprocServer32]
@="C:\WINNT\System32\mscoree.dll"
"ThreadingModel"="Both"
"Class"="JTest"
"Assembly"="JTest, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
"RuntimeVersion"="v1.0.3705"

[HKEY_CLASSES_ROOT\CLSID\{AD4D463B-FC29-3FE5-B82D-569A34325989}\ProgId]
@="JTest"

[HKEY_CLASSES_ROOT\CLSID\{AD4D463B-FC29-3FE5-B82D-569A34325989}\Implemented 
Cate
gories\{62C8FE65-4EBB-45E7-B440-6E39B2CDBF29}]

I checked in the registry to make sure it was really in there and sure 
enough it is. Looking at what gets registered I imagine mscoree.dll must 
peek back into the registry when CoGetClass is called so it can get the 
Class, Assembly, and Runtime Version vars. At that point I guess it 
would search the current directory for JTest.dll. It does not find it 
for me though:

 >>> from win32com.client import Dispatch
 >>> o = Dispatch('JTest')
Traceback (most recent call last):
  File "<stdin>", line 1, in ?
  File "C:\Python22\Lib\site-packages\win32com\client\__init__.py", line 
92, in
Dispatch
    dispatch, userName = 
dynamic._GetGoodDispatchAndUserName(dispatch,userName,c
lsctx)
  File "C:\Python22\Lib\site-packages\win32com\client\dynamic.py", line 
81, in _
GetGoodDispatchAndUserName
    return (_GetGoodDispatch(IDispatch, clsctx), userName)
  File "C:\Python22\Lib\site-packages\win32com\client\dynamic.py", line 
72, in _
GetGoodDispatch
    IDispatch = pythoncom.CoCreateInstance(IDispatch, None, clsctx, 
pythoncom.II
D_IDispatch)
pywintypes.com_error: (-2147221164, 'Class not registered', None, None)
 >>>

and like I say I have a copy in the current directory where above was 
run from as well as a copy in c:\Python22 where python.exe is installed. 
Shouldn't the assembly get found?

>
>  
>
>>OK, copy the thing there for now.
>>
>>    
>>
>>>>>from win32com.client import Dispatch
>>>>>net = Dispatch("CTest")
>>>>>net.Test()
>>>>>          
>>>>>
>>Hola Mundo!
>>What is your name:
>>kjhas
>>Buenos Dias, kjhas!
>>Traceback (most recent call last):
>>  File "<stdin>", line 1, in ?
>>TypeError: 'NoneType' object is not callable
>>
>>Pretty good - it works. But what is the TypeError at the bottom? My C#
>>code has finished OK. Is it something "on the way back" from .NET to
>>Python?
>>    
>>
>
>Yep - we are seeing a VB friendly implementation - thus "net.Test" is actually making the call (even though it looks like a property reference!)  This function returns None, and we are trying to call it.
>
>Use EnsureDispatch() or makepy manually to get it working.
>
>Mark.
>  
>

-- 
Jens B. Jorgensen
jens.jorgensen@tallan.com

"With a focused commitment to our clients and our people, we deliver value through customized technology solutions"