locked
How to get active application? RRS feed

  • Question

  • I develop an UDF in C#:  
    public string GetActiveSheetName()
            {
                string Caller = null;
                Excel.Application oExcel = Marshal.GetActiveObject("Excel.Application") as Excel.Application;
                Caller = oExcel.ActiveSheet.Name;
                return Caller;
            }
    

     


    This works fine if there is only one Excel process running. But if I have two or more instances of Excel are running, it still return first excel application's active sheet name.

    Thursday, December 29, 2011 7:10 AM

Answers

  • I've been working this problem since your previous posting.  After a few days of trying I finally got all the code to work.  I had to use a number of Winn32 API to get it to work.  Here are the steps I used.  I not sure if there is an easier way to do this.

    1) You need to find all the Excel.exe processes.  This was pretty easy to do.  I used the Net Library function Process.GetProcessesByName(@"excel") which returns an array of Processes

    2) I then checked that the Excel.exe window was the active window using Win32 API user32.dll function IsWindowVisible.


    3) I then had to write another function EnumChildWindows(ExcelWin, cb, ref hwndChild) which uses the Win32 API User32.dll function GetClassName().   I needed the child window to be able to extract the excel application from the window.

    4) Next I used the Win32 API Oleacc.dll function AccessibleObjectFromWindow  to get the excel object from the window.

    5) Finally I overload the window object to an excel object and get the sheet name.

     

    //using System.Runtime.InteropServices;
            //using System.Diagnostics;
    
            public delegate bool EnumChildCallback(int hwnd, ref int lParam);
    
            [System.Runtime.InteropServices.DllImport("User32.dll")]
            public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, ref IntPtr lParam);
    
            private static EnumChildCallback cb;
    
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool IsWindowVisible(IntPtr hWnd);
      
    
            [DllImport("Oleacc.dll")]
            private static extern int AccessibleObjectFromWindow(
                IntPtr hwnd, uint dwObjectID, byte[] riid, [MarshalAs(UnmanagedType.IUnknown)]ref object winobj);
    
            [DllImport("User32.dll")]
            public static extern int GetClassName(
                int hWnd, StringBuilder lpClassName, int nMaxCount);
    
            
            public static bool EnumChildProc(int hwndChild, ref int lParam)
            {
                StringBuilder buf = new StringBuilder(128);
    
                GetClassName(hwndChild, buf, 128);
                if (buf.ToString() == "EXCEL7")
                {
                    lParam = hwndChild;
                    return false;
                }
                return true;
            }
    
            public static string GetActiveSheetName()
            {
                
                string activesheetname = null;
                IntPtr activeAppWindow = IntPtr.Zero; 
                IntPtr ExcelWin;
                
    
                Process[] ExcelProcesses = Process.GetProcessesByName(@"excel");
               
                foreach(Process MyProcess in ExcelProcesses)
                {
                    ExcelWin = MyProcess.MainWindowHandle;
                    IntPtr hwndChild = (IntPtr)0;
     
    
                    cb = new EnumChildCallback(EnumChildProc);
                    EnumChildWindows(ExcelWin, cb, ref hwndChild);
    
                
                        if (IsWindowVisible(ExcelWin))
                        {
                       
                        
                           const uint OBJID_NATIVEOM  = 0xFFFFFFF0;
                           Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
                           object winptr = null;
                        
                       
                            int As = AccessibleObjectFromWindow(
                                hwndChild, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), ref winptr);
                            Excel.Window excelwin = (Excel.Window)winptr;
                            Excel.Application XlApp = excelwin.Application;
    
                            Excel.Worksheet sht = (Excel.Worksheet)XlApp.ActiveSheet;
                            activesheetname = sht.Name;
    
    
                            break;
    
                    }
                   
                }
                return activesheetname;
            }    
    

     

     

     

     

     

     

     

     

    • Edited by Joel Engineer Friday, December 30, 2011 4:37 AM
    • Marked as answer by Calvin_Gao Monday, January 9, 2012 5:38 AM
    Friday, December 30, 2011 4:33 AM

All replies

  • I've been working this problem since your previous posting.  After a few days of trying I finally got all the code to work.  I had to use a number of Winn32 API to get it to work.  Here are the steps I used.  I not sure if there is an easier way to do this.

    1) You need to find all the Excel.exe processes.  This was pretty easy to do.  I used the Net Library function Process.GetProcessesByName(@"excel") which returns an array of Processes

    2) I then checked that the Excel.exe window was the active window using Win32 API user32.dll function IsWindowVisible.


    3) I then had to write another function EnumChildWindows(ExcelWin, cb, ref hwndChild) which uses the Win32 API User32.dll function GetClassName().   I needed the child window to be able to extract the excel application from the window.

    4) Next I used the Win32 API Oleacc.dll function AccessibleObjectFromWindow  to get the excel object from the window.

    5) Finally I overload the window object to an excel object and get the sheet name.

     

    //using System.Runtime.InteropServices;
            //using System.Diagnostics;
    
            public delegate bool EnumChildCallback(int hwnd, ref int lParam);
    
            [System.Runtime.InteropServices.DllImport("User32.dll")]
            public static extern bool EnumChildWindows(IntPtr hWndParent, EnumChildCallback lpEnumFunc, ref IntPtr lParam);
    
            private static EnumChildCallback cb;
    
    
            [DllImport("user32.dll")]
            [return: MarshalAs(UnmanagedType.Bool)]
            static extern bool IsWindowVisible(IntPtr hWnd);
      
    
            [DllImport("Oleacc.dll")]
            private static extern int AccessibleObjectFromWindow(
                IntPtr hwnd, uint dwObjectID, byte[] riid, [MarshalAs(UnmanagedType.IUnknown)]ref object winobj);
    
            [DllImport("User32.dll")]
            public static extern int GetClassName(
                int hWnd, StringBuilder lpClassName, int nMaxCount);
    
            
            public static bool EnumChildProc(int hwndChild, ref int lParam)
            {
                StringBuilder buf = new StringBuilder(128);
    
                GetClassName(hwndChild, buf, 128);
                if (buf.ToString() == "EXCEL7")
                {
                    lParam = hwndChild;
                    return false;
                }
                return true;
            }
    
            public static string GetActiveSheetName()
            {
                
                string activesheetname = null;
                IntPtr activeAppWindow = IntPtr.Zero; 
                IntPtr ExcelWin;
                
    
                Process[] ExcelProcesses = Process.GetProcessesByName(@"excel");
               
                foreach(Process MyProcess in ExcelProcesses)
                {
                    ExcelWin = MyProcess.MainWindowHandle;
                    IntPtr hwndChild = (IntPtr)0;
     
    
                    cb = new EnumChildCallback(EnumChildProc);
                    EnumChildWindows(ExcelWin, cb, ref hwndChild);
    
                
                        if (IsWindowVisible(ExcelWin))
                        {
                       
                        
                           const uint OBJID_NATIVEOM  = 0xFFFFFFF0;
                           Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
                           object winptr = null;
                        
                       
                            int As = AccessibleObjectFromWindow(
                                hwndChild, OBJID_NATIVEOM, IID_IDispatch.ToByteArray(), ref winptr);
                            Excel.Window excelwin = (Excel.Window)winptr;
                            Excel.Application XlApp = excelwin.Application;
    
                            Excel.Worksheet sht = (Excel.Worksheet)XlApp.ActiveSheet;
                            activesheetname = sht.Name;
    
    
                            break;
    
                    }
                   
                }
                return activesheetname;
            }    
    

     

     

     

     

     

     

     

     

    • Edited by Joel Engineer Friday, December 30, 2011 4:37 AM
    • Marked as answer by Calvin_Gao Monday, January 9, 2012 5:38 AM
    Friday, December 30, 2011 4:33 AM
  • Thank you very much!

    If there is only one instance, it works fine. But if there are more than one instance, it doesn't work fine.

    • Edited by zqsntws Friday, December 30, 2011 7:11 AM
    Friday, December 30, 2011 6:48 AM