13 Replies Latest reply on May 21, 2011 1:12 AM by dhollebeek

    PBObjLib.Application in C# from Process or Hwnd

    KoryBW

      Hi,

       

      How do I get a .NET PBObjLib.Applicaiton from either a Process or an Hwnd.  I am trying to discover all the open Process Books and save them off so that I can restore the user's desktop.  I am able to get an IDispatch or an IAccessible but so far I have not been able to convert that to a dotnet object.

       

      Thanks,
      -Kory

        • Re: PBObjLib.Application in C# from Process or Hwnd
          hanyong

          Hi Kory,

           

          May I ask what is the method that you are using now to get to running ProcessBook instance?

           

          What I've tried so far is to go through the list of processes and identifying ProcessBook instances, getting the Windows handle from the process and finally using AccessibleObjectFromWindow to get access to ProcessBook object model. This is referencing a couple of posts online about getting the running office applications like http://blogs.msdn.com/b/andreww/archive/2008/11/30/starting-or-connecting-to-office-apps.aspx.

           

          I still haven't got too much success to calling the AccessibleObjectFromWindow method... keeps getting a COM error from the call. Is this what you have been trying to do?

            • Re: PBObjLib.Application in C# from Process or Hwnd
              KoryBW

              Yes, I have tried to use AccessibleObjectFromWindow.  I was able to get that to work but only to return an IAccessible.  I can also get that to return me an IDispatch.  But if I QI either of those for a Display, ProcessBook or application, I just get null.  I have also used the RunningObjectTable but, that returns the same object for every instance that I have open.  Online I read that you cannot use the running object table for multiple instances.

                • Re: PBObjLib.Application in C# from Process or Hwnd
                  hanyong

                  Looks like you have made it further than I have. May not be able to help you much here. Can we take a look at the code you have?

                   

                  Attached is what I have been doing so far. I'm getting null for the return pointer as well... and the return code from the AccessibleObjectFromWindow call basically translate to a E_FAIL COM error.

                   

                  Kory Balic-Wilson

                  Online I read that you cannot use the running object table for multiple instances.

                  I've tried using System.Runtime.InteropServices.Marshal.GetActiveObject() to get running ProcessBook instance from the ROT. When there are multiple instances of ProcessBook running, it is only able to get 1 of the instance, typically the earliest started instance. 

                    • Re: PBObjLib.Application in C# from Process or Hwnd
                      dhollebeek

                      Here's an off-the-wall idea.  If you develop a tiny add-in that gets the Application object and calls SetWindowLongPtr on the PB main window on startup, then you could pick up the pointer to the Application object by calling GetWindowLongPtr.

                        • Re: PBObjLib.Application in C# from Process or Hwnd
                          KoryBW

                          Here is my code:

                           

                          I can get the actual IAccessible object and I can get an IDispatch...

                           
                          PointList points = this.TheOsiPiServer.GetPoints("tag = '*'");
                          
                          foreach (PIPoint pt in points)
                          {
                             coll.Add(new Obj(pt.Name, pt.Description, pt.PointType))
                          }
                          
                                  [DllImport("oleacc.dll")]
                                  public static extern int AccessibleObjectFromWindow(IntPtr hwnd, uint dwObjectID, byte[] refID, out IntPtr pcObtained);
                          
                                  public enum NativeMsg : uint
                                  {
                                      CHILDID_SELF = 0,
                                      CHILDID_1 = 1,
                                      OBJID_LIENT = 4, //0xFFFFFFC
                                      OBJID_NATIVEOM = 0xFFFFFFF0,
                                  }
                                                                        
                                  private Guid guidApplicationFromROT = new Guid("{7BFECD80-1B23-101C-B28E-00AA0022EF07}");
                                  private Guid guidIDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
                                  private Guid guidDisplay = new Guid("{D3C2BF11-8F53-4CBA-876A-D394913EAC77}");
                                  private Guid guidProcbook = new Guid("{0590B287-40F4-4B82-A905-3037D7EA27B8}");
                                  private Guid guidApplication = new Guid("{BD0B2C22-0913-4468-A9E1-F63CA980D9D9}");
                                  
                          
                          
                                  private IAccessible GetIAccessible()
                                  {
                                      Process[] arrProcs = Process.GetProcessesByName("ProcBook");
                          
                                      IntPtr ptrHwnd = arrProcs[0].MainWindowHandle;
                          
                                      IntPtr procbook = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(UUID)));
                                      IntPtr procbookp = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
                                      uint u = 0x00000000;
                                      AccessibleObjectFromWindow(ptrHwnd, u, guidIDispatch.ToByteArray(), out procbookp);
                          
                                      procbook = Marshal.ReadIntPtr(procbookp);
                                      
                                      IntPtr iAccessiblePtr = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(UUID)));
                          
                                      Guid iAccessibleGuid = new Guid(0x618736e0, 0x3c3d, 0x11cf, 0x81, 0xc, 0x0, 0xaa, 0x0, 0x38, 0x9b, 0x71);
                          
                                      Marshal.QueryInterface(procbookp, ref iAccessibleGuid, out iAccessiblePtr);
                          
                                      Accessibility.IAccessible acc = (Accessibility.IAccessible)Marshal.GetTypedObjectForIUnknown(iAccessiblePtr, typeof(Accessibility.IAccessible));
                          
                                      string sName = acc.get_accName();
                                      object o = acc.get_accValue();
                                      object o2 = acc.accParent;
                          
                                      return acc;
                                     
                                  }
                          
                                  private PBObjLib.Application GetApplication()
                                  {
                                      Process[] arrProcs = Process.GetProcessesByName("ProcBook");
                          
                                      IntPtr ptrHwnd = arrProcs[0].MainWindowHandle;
                          
                                      //IntPtr procbook = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(UUID)));
                                      IntPtr procbookp = Marshal.AllocCoTaskMem(Marshal.SizeOf(typeof(IntPtr)));
                                      uint u = 0x00000000;
                                      int hr = AccessibleObjectFromWindow(ptrHwnd, u, guidIDispatch.ToByteArray(), out procbookp);
                          
                                      PBObjLib.Application pbinstance = null;
                                      if (hr >= 0)
                                      {
                                          pbinstance = (PBObjLib.Application)procbookp.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, procbookp, null);
                          
                                          //procbook = Marshal.ReadIntPtr(procbookp);
                                          //pbinstance = (PBObjLib.Application)procbook.GetType().InvokeMember("Application", System.Reflection.BindingFlags.GetProperty, null, procbook, null);
                                      }
                          
                                      return pbinstance;
                          
                                  }
                          

                           

                           

                           

                          • Re: PBObjLib.Application in C# from Process or Hwnd
                            KoryBW

                            Hi, I am new to ProcessBook...  can you have an addin that runs when the open ProcessBook without user intervention?