(2012年 VB.net)从每个正在运行的 Excel 实例中获取“xlApp”?

(In VB.net 2012) Obtain "xlApp" from each running Excel instances?

提问人:Shodan 提问时间:7/26/2023 最后编辑:braXShodan 更新时间:7/26/2023 访问量:32

问:

基于此代码

我正在尝试枚举每个excel实例,然后为每个实例获取“xlApp”对象

注意:您可以通过单击开始菜单中的 Excel 链接来创建多个 Excel 实例,但在启动时按住左 alt 按钮,它会询问您是否要创建新实例

到目前为止,我的代码(编译和运行没有错误,但没有在列表中返回 xlApp 对象)

Imports System.Runtime.InteropServices
Imports System.Text
Imports Excel = Microsoft.Office.Interop.Excel

Module Module1

    Private Const EXCEL7 As String = "EXCEL7"
    Private Const GW_CHILD As Integer = 5
    Private Const GW_HWNDNEXT As Integer = 2

    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Private Function FindWindowEx(ByVal parentHandle As IntPtr, _
                                  ByVal childAfter As IntPtr, _
                                  ByVal className As String, _
                                  ByVal windowTitle As String) As IntPtr
    End Function

    <DllImport("Oleacc.dll")> _
    Private Function AccessibleObjectFromWindow(ByVal hwnd As Integer, _
                                                ByVal dwObjectID As UInteger, _
                                                ByVal riid As Byte(), _
                                                ByRef ptr As Excel.Window) As Integer
    End Function

    Private Function EnumerateExcelInstances() As System.Collections.Generic.List(Of Excel.Application)
        Dim excelInstances As New System.Collections.Generic.List(Of Excel.Application)()

        Try
            Dim hwnd = FindWindowEx(IntPtr.Zero, IntPtr.Zero, "XLMAIN", Nothing)

            While hwnd <> IntPtr.Zero
                Dim hwndChild = FindWindowEx(hwnd, IntPtr.Zero, EXCEL7, Nothing)

                If hwndChild <> IntPtr.Zero Then
                    Dim ptr As Excel.Window = Nothing
                    Dim guid As New Guid("{00020400-0000-0000-C000-000000000046}")
                    AccessibleObjectFromWindow(hwndChild.ToInt32(), &HFFFFFFF0UI, guid.ToByteArray(), ptr)

                    If ptr IsNot Nothing Then
                        excelInstances.Add(ptr.Application)
                    End If
                End If

                hwnd = FindWindowEx(IntPtr.Zero, hwnd, "XLMAIN", Nothing)
            End While
        Catch ex As Exception
            Console.WriteLine("Error: " & ex.Message)
        End Try

        Return excelInstances
    End Function

    Sub Main()
        Dim excelInstances = EnumerateExcelInstances()

        For Each xlApp In excelInstances
            Console.WriteLine("Excel Process ID: " & xlApp.Hwnd)

            If xlApp.Workbooks.Count > 0 Then
                Console.WriteLine("Opened Workbooks:")

                For Each wb As Excel.Workbook In xlApp.Workbooks
                    Console.WriteLine(wb.Name)
                Next
            Else
                Console.WriteLine("No workbooks are open.")
            End If
        Next
    End Sub
End Module

您可以使用以下 vbc 命令将其保存到 listexcel.vb 来编译它(您可能需要将路径调整为 Microsoft.Office.Interop.Excel.dll,并且路径中必须有 vbc)

vbc /r:C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll /r:System.dll listexcel.vb

您可以使用以下代码列出每个 Excel 进程的每个窗口句柄。(测试工作)

Imports System.Runtime.InteropServices
Imports System.Text

Module Module1

    ' Define the class name of the Excel application main window
    Private Const xlMainWindowClass As String = "XLMAIN"

    Sub Main()
        Console.WriteLine("Running Excel instances:")

        ' Enumerate all windows
        EnumWindows(Function(hWnd, lParam) As Boolean
                        ' Get the window's class name
                        Dim className As New StringBuilder(256)
                        GetClassName(hWnd, className, className.Capacity)

                        ' If the window is an Excel main window, print its handle
                        If className.ToString() = xlMainWindowClass Then
                            Console.WriteLine(hWnd.ToString())
                        End If

                        ' Continue enumeration
                        Return True
                    End Function, IntPtr.Zero)
    End Sub

    ' Delegate and methods for EnumWindows
    Private Delegate Function EnumWindowsProc(hWnd As IntPtr, lParam As IntPtr) As Boolean

    <DllImport("user32.dll")>
    Private Function EnumWindows(callback As EnumWindowsProc, lParam As IntPtr) As Boolean
    End Function

    <DllImport("user32.dll")>
    Private Function GetClassName(hWnd As IntPtr, lpClassName As StringBuilder, nMaxCount As Integer) As Integer
    End Function

End Module

您可以用它来编译和测试

    vbc /r:C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll /r:System.dll listexcelpidhwnd.vb

现在,我的目标是为每个正在运行的 excel 实例打印所有工作簿名称,测试代码如下(经过测试工作)

Imports Microsoft.Office.Interop

Module Module1
    Sub Main()
        Dim xlApp As Excel.Application = Nothing
        Dim xlWorkbooks As Excel.Workbooks = Nothing

        Try
            ' Get a reference to Excel
            xlApp = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)
        Catch
            ' If Excel is not running, exit
            Console.WriteLine("Excel is not running.")
            Return
        End Try

        ' Get a reference to the Workbooks collection
        xlWorkbooks = xlApp.Workbooks

        ' Enumerate the workbooks
        If xlWorkbooks.Count > 0 Then
            Console.WriteLine("Opened workbooks:")
            For i As Integer = 1 To xlWorkbooks.Count
                Console.WriteLine(xlWorkbooks.Item(i).Name)
            Next
        Else
            Console.WriteLine("No workbooks are open.")
        End If

        ' Clean up
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlWorkbooks)
        System.Runtime.InteropServices.Marshal.FinalReleaseComObject(xlApp)
    End Sub
End Module

您可以用它来编译和测试

    vbc /r:C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Excel\15.0.0.0__71e9bce111e9429c\Microsoft.Office.Interop.Excel.dll /r:System.dll listworkbooks.vb
Excel vb.net

评论

0赞 braX 7/26/2023
learn.microsoft.com/en-us/office/troubleshoot/......
0赞 Shodan 7/27/2023
此方法仅返回第一个 excel 实例的 xlApp 对象。解决方案是使用 AccessibleObjectFromWindow,但是我的代码有问题,我不确定是什么

答: 暂无答案