locked
Get Excel.Application With Plan B (Have Excel ProcessID; HWND; Name) as a workaround in Debug Mode RRS feed

  • Question

  • 64bit PC, MS Access 2010, Visual Studio 2013 - VB.Net; Windows 10 - up to date

    In VS 2013 the following code line works at Runtime CSLID but in Debug-mode it fails:
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    Thus I am looking for a Plan B that I can use in Debug mode - the following code works in Debug Mode:
            AppActivate("Microsoft Excel")
            XLHWnd = FindWindow("XLMAIN", vbNullString)
            Dim p() As Process = System.Diagnostics.Process.GetProcessesByName("Excel")
            Dim Title As String = p(0).MainWindowTitle
            Dim ProcIdXL As Integer = GetWindowThreadProcessId(XLHWnd, ProcIdXL)

    Thus other facts located,
    1) The instance of Excel that I need is Active due to code line "AppActivate("Microsoft Excel")"
    2) Have the applicable HWND from "XLHWnd = FindWindow("XLMAIN", vbNullString)"  [HWND=1377058]
    3) Just for fun, I have the appropriate "Title" (see above)  [Microsoft Excel - myFile.xlsm]
    4) Have the Thread ProcessID for the Excel.Application   [ProcIdXL=2256]

    Because GetActiveObject("Excel.Application") fails in Debug Mode, how can I "Set" the Open Excel Application Object when I have the Excel ProcessID, HWND and Name?

    Believe me I have been working on this for two days.  (I know stop the whine)

    TIA Dennis  



    Monday, January 18, 2016 3:25 PM

All replies

  • 64bit PC, MS Access 2010, Visual Studio 2013 - VB.Net; Windows 10 - up to date

    I have two related Visual Studio 2013 Express Projects:
      ToolsVarious (Is compiled as a COM visible .dll file and has 23 Methods/Procedures)
      DebugProject (Windows Form Application that contains one of the above 23 Methods/Procedures for "live" debugging)

    GetActiveObject("Access.Application") or GetActiveObject("Excel.Application") works fine in the .dll file
    which is called in Excel VBA (as compared to debugging in VS 2013, where VS 2013 is the Active Object).

    GetActiveObject fails when the following code is used in debug mode:
    Activate("Microsoft Excel")
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    Whereas, GetActiveObject works! if I use the following code in debug mode:
    System.Diagnostics.Process.Start(xlsPath & xlsMasterFileName)xls
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    I believe it works because there is no doubt that the Active Object is Excel - as it was just opened!

    What code could I place in the Debug project (currently open in VS 2013 as a Windows Form Application)
    to make Excel the Active Object so that GetActiveObject("Excel.Application") works?

    Bottom line, I need to make the open Excel application addressable in the Interop Automation code in DebugProject (in the Windows Form Application).

    Also, would someone explain what is the "why" behind this differing behavior? 

    TIA Dennis





    Monday, January 18, 2016 1:17 AM
  • 64bit PC, MS Access 2010, Visual Studio 2013 - VB.Net; Windows 10 - up to date

    This was posted for a day in Access-Developers with no attempts to assist.  This site being VB orientated - is a hope.

    I have two related Visual Studio 2013 Express Projects:
       ToolsVarious (Is compiled as a COM visible .dll file and has 23 Methods/Procedures)
       DebugProject (Windows Form Application that contains one of the above 23 Methods/Procedures for "live" debugging)

    GetActiveObject("Access.Application") or GetActiveObject("Excel.Application") works fine in the .dll file
     which is called in Excel VBA (as compared to debugging in VS 2013, where VS 2013 is the Active Object).

    GetActiveObject fails when the following code is used in debug mode:
     Activate("Microsoft Excel")
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    Whereas, GetActiveObject works! if I use the following code in debug mode:
    System.Diagnostics.Process.Start(xlsPath & xlsMasterFileName)xls
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    I believe it works because there is no doubt that the Active Object is Excel - as it was just opened!

    What code could I place in the Debug project (currently open in VS 2013 as a Windows Form Application)
     to make Excel the Active Object so that GetActiveObject("Excel.Application") works?

    Bottom line, I need to make the open Excel application addressable in the Interop Automation code in DebugProject (in the Windows Form Application).

    Also, would someone explain what is the "why" behind this differing behavior?


    TIA Dennis

    Monday, January 18, 2016 11:07 AM
  • Just another thought: What is you compilation platform target? Not that you run a 64bit version when debugging and a 32bit version in your library or vice versa.

    Monday, January 18, 2016 11:14 AM
  • Stefan,

    Thanks for your time and knowledge.

    I hope I understand your question.  The following info is from the "Compile" tab of the respective project.

    The COMM visible .dll project works fine and is compiled for AnyCPU (the question "Prefer 32 bit") is grayed out

    As to the DebugProject is now Set to AnyCPU but the "Prefer 32 bit" is available but not checked!  Should it be checked?  Both projects are targeting/using MS Office 2010 32bit. 

    Dennis

    UPDATE:

    I did select the question "Prefer 32 bit" for the DebugProject but the errors continue. 

    • Edited by DennisCPA Monday, January 18, 2016 5:31 PM
    Monday, January 18, 2016 5:01 PM
  • Check the Office version, but I guess you've installed the 32bit version. In this case I would test a compilation with x86 as target.

    Monday, January 18, 2016 5:10 PM
  • Stefan,

    Still get an error.

    That said I have additional information that may help get to a solution:

    In VS 2013 the following code line works at Runtime CSLID but in Debug-mode it fails:
    xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    Thus I am looking for a Plan B that I can use in Debug mode - the following code works in Debug Mode:
            AppActivate("Microsoft Excel")
            XLHWnd = FindWindow("XLMAIN", vbNullString)
            Dim p() As Process = System.Diagnostics.Process.GetProcessesByName("Excel")
            Dim Title As String = p(0).MainWindowTitle
            Dim ProcIdXL As Integer = GetWindowThreadProcessId(XLHWnd, ProcIdXL)

    Thus other facts located,
    1) The instance of Excel that I need is Active due to code line "AppActivate("Microsoft Excel")"
    2) Have the applicable HWND from "XLHWnd = FindWindow("XLMAIN", vbNullString)"  [HWND=1377058]
    3) Just for fun, I have the appropriate "Title" (see above)  [Microsoft Excel - myFile.xlsm]
    4) Have the Thread ProcessID for the Excel.Application   [ProcIdXL=2256]

    Because GetActiveObject("Excel.Application") fails in Debug Mode, how can I "Set" the Open Excel Application Object when I have the Excel ProcessID, HWND and Name?

    Believe me I have been working on this for two days.  (I know stop the whine)

    Dennis

    UPDATE:

    Stefan, While in Debug Mode I can create a New instance of Excel and the  following code line works fine: xlsAppMain = DirectCast(System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application"), Excel.Application)

    But the instance of Excel that I have open before running the Debug code I cannot seem to access thus all of the attempts above.

    Ultimately, the code is compiled into a .dll file which ends up being called from Excel.  Thus I am attempting to that Excel instance via GetActiveObject as I cannot close it (as it is running the .dll). 
    • Edited by DennisCPA Monday, January 18, 2016 6:03 PM
    Monday, January 18, 2016 5:44 PM
  • Hi DennisCPA,

    Based on your description, your question is more related to Excel development. We will move your thread to Excel for developers forum for dedicated help.

    Best Regards,
    Li Wang


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Tuesday, January 19, 2016 2:11 AM
  • Hi DennisCPA,

    What do you mean it did not work in winform? Did you get any error message? It would be helpful if you could share us a simple demo to reproduce your issue through OneDrive.

    Best Regards,

    Edward


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.


    Wednesday, January 20, 2016 6:17 AM
  • Hi DennisCPA,

    Based on my test with Marshal.GetActiveObject method, it works fine in debug mode, what’s the detail error message that you get?

    For Plan B, could you provide the detail code?

    Regards

    Starain


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Wednesday, January 20, 2016 7:25 AM
  • The error message was:
     "A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
     Additional information: Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"

    In addition I attempted the following approach but it also failed: "Cannot create ActiveX":
     xlsApp = CType(GetObject(, "Excel.Application"), Excel.Application)

    ***********************************************************************************

    SUCCESS!!  (I figured it out by trial and error over a few days)
    Either 1) The sequence and/or timing ?? of the following code works on debug and regular(?) mode (COMM .dll) and/or 2) "New Excel.Application" may have done the trick.
     
            Dim xlsApp As New Excel.Application
            XLHWnd = FindWindow("XLMAIN", vbNullString)
            If XLHWnd > 0 Then
                'If HLXWnd > 0 it means that an already Open Excel VBA called this Procedure via a COMM DLL file
                'not the debug mode of Visual Studio thus no need to load alother Excel file 
                Try
                    xlsApp.Workbooks.Open(myPath & xlWBFile)
                    'Need about 5 seconds for Excel to boot up
                    System.Threading.Thread.Sleep(5000)
                Catch ex As Exception
                    System.GC.Collect()
                    MsgBox("User Canceled Processing ...... Press OK to Continue")
                    Exit Sub
                 End Try
            End If
            xlsApp = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")

    If you could explain what/why was causing the error I would greatly appreciate it!

    Thanks Dennis






    • Edited by DennisCPA Wednesday, January 20, 2016 3:34 PM
    Wednesday, January 20, 2016 2:49 PM
  • Edward,

    The error message was:
     "A first chance exception of type 'System.Runtime.InteropServices.COMException' occurred in mscorlib.dll
     Additional information: Operation unavailable (Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE))"

    In addition I attempted the following approach but it also failed: "Cannot create ActiveX":
     xlsApp = CType(GetObject(, "Excel.Application"), Excel.Application)

    ***********************************************************************************

    SUCCESS!!  (I figured it out by trial and error over a few days)
    Either 1) The sequence and/or timing ?? of the following code works on debug and regular(?) mode (COMM .dll) and/or 2) "New Excel.Application" may have done the trick.
     
            Dim xlsApp As New Excel.Application
            XLHWnd = FindWindow("XLMAIN", vbNullString)
            If XLHWnd > 0 Then
                'If HLXWnd > 0 it means that an already Open Excel VBA called this Procedure via a COMM DLL file
                'not the debug mode of Visual Studio thus no need to load another Excel file 
                 Try
                     xlsApp.Workbooks.Open(myPath & xlWBFile)
                     'Need about 5 seconds for Excel to boot up
                     System.Threading.Thread.Sleep(5000)
                 Catch ex As Exception
                     System.GC.Collect()
                     MsgBox("User Canceled Processing ...... Press OK to Continue")
                     Exit Sub
                 End Try
             End If
            End If
            xlsApp = System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application")

    If you could explain what/why was causing the error I would greatly appreciate it!

    Thanks Dennis


    P.S. I just realized that this thread is in the Access Forum.  Can you move it to Excel Developers?

    • Edited by DennisCPA Wednesday, January 20, 2016 7:45 PM correction
    Wednesday, January 20, 2016 3:01 PM
  • Hi DennisCPA,

    For the code of New Excel.Application, it creates a new excel process instead of the existed one, you could check it in the task manager.

    Since we couldn’t reproduce that issue and haven’t your detail code, it’s better to share a sample project that could reproduce that issue on the OneDrive.

    Regards

    Starain


    We are trying to better understand customer views on social support experience, so your participation in this interview project would be greatly appreciated if you have time. Thanks for helping make community forums a great place.
    Click HERE to participate the survey.

    Friday, January 22, 2016 2:02 AM
  • Nearly chipped a tooth with a similar issue in C++, different Automation server - but I checked to have it also with Excel.

    Here's my take on it, a tad late but I hope it could help other beginners like me...

    Any System.Runtime.InteropServices.Marshal.GetActiveObject approach must be based on the Win32 GetActiveObject system call (i.e. function, directly called in C++), which in turn I expect to be based on some ROT (Running Objects Table) queries. The ROT is populated voluntarily by each automation server like Excel for each of its document/instance (i.e. they could choose to register with ROT or not) and I assume the registration could be per user account.

    Any New Object approach must be based on the Win32 CreateObject system call (directly called in C++). This is based on system-wide settings of automation servers (HKLM base in registry) and thus always user account independent.

    So CreateObject approaches should work in any circumstances. For GetActiveObject make sure Visual Studio and the Automation Server (say Excel) run in the same user context. I, for reasons I would not like to remind here, happened to start VS as Administrator and Excel as an ordinary user.

    There was once a MS tool called Rotview  that could help with such issues, but it is no longer available with MS. Just Google the name and you will quickly find a nice third party utility. Run it to see whether your Automation Server is registered in ROT for the desired user(Excel always is registered; make it an external tool in VS to run it in the same user context as VS)


    • Edited by AlexCbz Wednesday, September 7, 2016 9:31 PM
    Wednesday, September 7, 2016 9:30 PM