Python、ArcObjects与.AppRef:如何从IAppROT获取IMxDocument?

2 投票
1 回答
1161 浏览
提问于 2025-04-16 06:17

我正在写一个外部的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 个回答

0

作用域错误(根据评论):

import comtypes.gen.esriArcMapUI as esriArcMapUI 这行代码是用来定义 esriArcMapUI 这个命名空间的,但它是在 GetApp() 这个函数里面运行的,所以这个命名空间只在这个函数内部有效。

撰写回答