Python、ArcObjects与.AppRef:如何从IAppROT获取IMxDocument?
我正在写一个外部的Python/comtypes脚本(在PythonWin中),需要获取当前ArcGIS 10.0 ArcMap会话的引用(通过ArcObjects COM)。因为这个脚本是在应用程序外部运行的,所以我通过AppROT(运行对象表)来获取应用程序的引用。下面的第一个代码片段是主要的Python驱动模块。在里面有一个函数GetApp(),用来从AppROT中获取应用程序的引用。这个代码运行得很好,返回了单例的AppRef对象上的IApplication。这很合理,ArcObjects的引用似乎也是这样说明的。现在,我的主要目标是获取一个IMxDocument。在主循环中,我成功获取了一个IDocument,并且可以打印出标题。不过,接下来的那一行,进行查询接口时,抛出了一个错误 - NameError: name 'esriArcMapUI' is not defined。这个错误一直出现,即使在关闭PythonWin并重新打开后(在你认为有问题之前,通常都要先尝试这个)。[顺便说一下,第二个代码片段是Q的CType()函数,从SignHelpers.py模块定义并导入的。]所以,我有以下几个问题:
(1) IDocument是哪个COM对象?
(2) 我怎么从我的IDocument获取到想要的IMxDocument?我需要先创建一个新的MxDocument对象吗?[抱歉,这里有两个问题。]
(3) 如果我不需要创建一个新对象,那我该怎么进行QI?
几年前我在VB6中做过很多ArcObjects的工作,所以现在显式的QI和命名空间让我有点困惑。一旦我能获取到IMxDocument,我就能顺利进行下去了。我非常感谢任何人能给我提供的帮助。
另外,我为下面代码的格式感到抱歉。我无法弄清楚如何正确格式化Python代码。缩进不起作用,而且一些Python代码被解释为格式字符。
=== code: main py module ===
import sys, os
sys.path.append('C:\GISdata\E_drive\AirportData\ATL\Scripts')
import comtypes
from SignHelpers import *
def GetApp(app):
"""Get a hook into the current session of ArcMap; \n\
Execute GetDesktopModules() and GetStandaloneModules() first"""
print "GetApp called" #@@@
import comtypes.gen.esriFramework as esriFramework
import comtypes.gen.esriArcMapUI as esriArcMapUI
import comtypes.gen.esriCarto as esriCarto
pAppROT = NewObj(esriFramework.AppROT, esriFramework.IAppROT)
iCount = pAppROT.Count
print "appROT count = ", iCount #@@@
if iCount == 0:
print 'No ArcGIS application currently running. Terminating ...'
return None
for i in range(iCount):
pApp = pAppROT.Item(i) #returns IApplication on AppRef
if pApp.Name == app:
print "Application: ", pApp.Name #@@@
return pApp
print 'No ArcMap session is running at this time.'
return None
if __name__ == "__main__":
#Wrap needed ArcObjects type libraries (.olb)...
... code omitted ...
GetDesktopModules(dtOLB) #These force comtypes to generate
GetStandaloneModules(saOLB) #the Python wrappers for .olb's
#Connect to ArcMap
pApp = GetApp("ArcMap")
pDoc = pApp.Document #IDocument on current Document object
print pDoc.Title
pMxDoc = CType(pDoc, esriArcMapUI.IMxDocument) #QI to IMxDocument on MxDocument
=== code for CType() ===
def CType(obj, interface):
try:
newobj = obj.QueryInterface(interface)
return newobj
except:
return None
1 个回答
作用域错误(根据评论):
import comtypes.gen.esriArcMapUI as esriArcMapUI
这行代码是用来定义 esriArcMapUI 这个命名空间的,但它是在 GetApp() 这个函数里面运行的,所以这个命名空间只在这个函数内部有效。