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 并重新打开(在得出结论认为有问题之前您总是想尝试)之后,该错误仍然会持续发生。 [顺便说一句,第二个代码片段是 QI 的 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
I am writing an external Python/comtypes script (in PythonWin) that needs to get a reference to the current ArcGIS 10.0 ArcMap session (through the ArcObjects COM). Because the script is outside the application boundary, I am getting the application reference through the AppROT (running object table). The first code snippet below is the main Python driver module. In it is a function GetApp() to grab an application reference from the AppROT. This code works fine and returns IApplication on the singleton AppRef object. Makes sense, and that's what the ArcObjects reference seems to indicate. Now, my main goal is to get to an IMxDocument. In the main loop, I get to an IDocument successfully and can print the title. The next line, though, a Query Interface, throws an error - NameError: name 'esriArcMapUI' is not defined. The error occurs consistently, even after closing PythonWin and reopening (which you always want to try before you conclude that you have a problem). [BTW, the second code snippet is the CType() function for QI, defined in and imported from the SignHelpers.py module.] So, here are my questions:
(1) What COM object is the IDocument on?
(2) How do I get from my IDocument to the intended IMxDocument? Do I need to create a new MxDocument object first? [Sorry. Two questions there.]
(3) If I don't have to create a new object, then how do I do the QI?
I did a lot of ArcObjects work in VB6 quite a few years ago, so explicit QI's and namespaces are putting the screws to me at the moment. Once I can get to an IMxDocument I will be home free. I would appreciate any help anyone can give me with this.
Also, I apologize for the formatting of the code below. I could not figure out how to get Python code to format correctly. Indentation doesn't work, and some of the Python code is interpreted as formatting characters.
=== 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
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
范围错误(根据注释):
定义 esriArcMapUI 命名空间所需的
import comtypes.gen.esriArcMapUI as esriArcMapUI
语句正在 GetApp() 函数内运行,因此命名空间是该函数的本地命名空间。Scoping error (per the comments):
The
import comtypes.gen.esriArcMapUI as esriArcMapUI
statement needed to define the esriArcMapUI namespace was being run within the GetApp() function, so the namespace was local to the function.