Excel VBA中Microsoft Office实例之间的通信

Excel VBA中Microsoft Office实例之间的通信,excel,vba,ms-word,Excel,Vba,Ms Word,我正在尝试在实例a上创建一个VBA脚本,用于复制Word实例B上的基本内容,该实例由具有临时和不可预测名称的tier程序生成,因此我无法使用GetObjectPath来获取具有该路径的实例,因为我没有该路径 我的临时解决方案是从实例a运行此命令的PowerShell,以获取标题中包含Word的所有窗口的名称。。。并将其存储在VBA变量中,以检测名称是否来自实例a以外的其他实例: Get-Process |Where-Object {$_.mainWindowTitle -like "*Word*

我正在尝试在实例a上创建一个VBA脚本,用于复制Word实例B上的基本内容,该实例由具有临时和不可预测名称的tier程序生成,因此我无法使用GetObjectPath来获取具有该路径的实例,因为我没有该路径

我的临时解决方案是从实例a运行此命令的PowerShell,以获取标题中包含Word的所有窗口的名称。。。并将其存储在VBA变量中,以检测名称是否来自实例a以外的其他实例:

Get-Process |Where-Object {$_.mainWindowTitle -like "*Word*"} |format-table mainwindowtitle 

它可以工作,但我不敢相信,即使路径未知,也无法直接从VBA检测应用程序的所有运行实例

我在VBA中尝试过这样丑陋的东西来跨越不同的实例,但没有成功:

Sub GetAllInstance()
Dim WordApp As Word.Application, wordInstance As Object
Set WordApp = GetObject(, "Word.Application")

For Each wordInstance In WordApp
    MsgBox (wordInstance)
Next wordInstance

End Sub
并且Immediate命令向我显示GetObject仅包含有关实例A的信息,即使在单独的实例上打开了3个文档,也只会生成1个文档:

?WordApp.Documents.Count
1
编辑20/02:

在Cindy的建议下,我改变了我的方法尝试处理流程,我成功地检测到我运行实例的不同PID,代码如下:

Sub IsProcessRunning()
    Dim process As String
    Dim objList As Object
    Dim xprocess As Variant
    Dim wdApp As Word.Application

    process = "Word.exe"

    Set objList = GetObject("winmgmts:") _
        .ExecQuery("select ProcessID from win32_process where name='" & process & "'")


For Each xprocess In objList
    Debug.Print xprocess.ProcessID
    AppActivate (xprocess.ProcessID)
    Set wdApp = GetObject(, "Word.Application")
    Debug.Print wdApp.Workbooks(1).Name
Next xprocess

End Sub
不幸的是,激活一个应用程序并不能清除ROT,我现在正试图找到一种方法来清除它并刷新它,以便在ROT中注册新激活的应用程序,并将GetObject用于好的实例。

终于找到了一个解决方案! 使用下面的代码,因为我知道我的第三个软件在哪里生成带有新实例的临时文件,所以我使用HWND和user32 lib中的GetWindowText搜索文件名。它允许我使用完整路径分配GetObject,并在两个独立实例的两个文档之间进行交互。感谢Cindy和Mathieu的帮助:

' API declaration
Const GW_HWNDNEXT = 2
Private Declare PtrSafe Function GetWindow Lib "user32" (ByVal hWnd As Long, ByVal wCmd As Long) As Long
Private Declare PtrSafe Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare PtrSafe Function GetClassName Lib "user32" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As String, ByVal nMaxCount As Long) As Long
Private Declare PtrSafe Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hWnd As Long, ByVal lpString As String, ByVal cch As Long) As Long

Private Sub CommandButton1_Click()

    Dim openDoc As Document, sourceDoc As Document, targetDoc As Object
    Dim hWndThis As Long
    Dim sTitle As String
    Dim xTable As Table

    ''' INITIALIZATION '''

    'Assign the source Document
    Set sourceDoc = ActiveDocument

    'Detect each instance by Window Name, then assign it to different object
    hWndThis = FindWindow(vbNullString, vbNullString)
        While hWndThis
            sTitle = Space$(255)
            sTitle = Left$(sTitle, GetWindowText(hWndThis, sTitle, Len(sTitle)))

                If sTitle Like "*tmp*.DOC*" Then
                    FileToOpen = Left(sTitle, Len(sTitle) - 8)
                    Set targetDoc = GetObject("C:\Users\xxxxx\AppData\Local\Temp" & "\" & FileToOpen)
                    GoTo EndLoop:
                End If
            hWndThis = GetWindow(hWndThis, GW_HWNDNEXT)
        Wend
    EndLoop:
End Sub

我不敢相信没有办法检测所有正在运行的实例-为什么?VBA在该应用程序的进程空间内运行。每个应用程序实例在设计上都是自己的思洛存储器:这样您就可以在不影响彼此的情况下使实例崩溃。跨进程通信是可能的,通过OLE自动化-这就是为什么您不能在例如两个Excel实例之间粘贴特殊内容的原因。顺便说一句,感谢您的精确性,我说我不敢相信,因为Windows API允许很多东西,我实际上正试图通过使用user32库找到一种方法,我会告诉你,如果我明天发现了什么有趣的东西,你会遇到问题的一个原因是,根据设计,Word只注册了一个实例。因此,你只能通过过程,而不是查找运行实例的正常方式。非常感谢这些技术信息,你刚刚了解了我的问题所在。我会处理好这个过程,如果我找到了解决方案,我会回来的