Excel BeforeRightClick TransparentProxy

When VSTO was in Beta 2 the Excel "BeforeRightClick" event handler would receive an instance of an Excel.Range type.   Now, instead of the range it receives a Transparent Proxy that consequently causes my Application.Intersect() method invokation to fail ("No such interface supported (Exception from HRESULT: 0x80004002 (E_NOINTERFACE))").  


I'm not sure where the Transparent Proxy came from, it was not in the Beta 2 code, but it seems like when I try to use it, the Intersect method now fails.

Can anyone help out

Thanks,
- jim


Answer this question

Excel BeforeRightClick TransparentProxy

  • markep12

    WRT this.Application vs. ThisApplication. This has been duely noted and I will be pushing to make sure we come to the correct resolution on this.

    The reason you only see this with the Intersect() method is because not all Excel OM methods use the COM locale parameter. This makes the unwrapping/closure issue particularly insideous as it leads to weird errors for the developer down the line.

    I also agree with your comments on the OM when used with C#. Obviously the best solution here would be to provide a better OM that was written with managed code in mind. Other than telling your that we're completely aware of this issue I can't comment further on Microsoft's plans at this time.

    Let me know if I can be of further help...

    Ade
    Developer, VSTO

  • Yes!

    Hello Ade,

    First off, thanks a lot for your response, it did the trick.  Let me know if this seems like a sound way to integrate your suggestion.  Instead of "wrapping" the application object every time I want to get a reference to it, I moded the code generated by the IDE for the ThisWorkbook type and changed the assignment of ThisApplication in the Initialize() method to wrap the Application object:

    [Microsoft.VisualStudio.Tools.Applications.Runtime.StartupObjectAttribute(0)]

    [System.Security.Permissions.PermissionSetAttribute(System.Security.Permissions.SecurityAction.Demand, Name="FullTrust")]

    public sealed partial class ThisWorkbook : Microsoft.Office.Tools.Excel.Workbook, Microsoft.VisualStudio.Tools.Applications.Runtime.IStartup {

    ...

    [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]

    [global::System.ComponentModel.EditorBrowsableAttribute(System.ComponentModel.EditorBrowsableState.Never)]

    public void Initialize() {

    this.HostItemHost = ((Microsoft.VisualStudio.Tools.Applications.Runtime.IHostItemProvider)(this.RuntimeCallback.GetService(typeof(Microsoft.VisualStudio.Tools.Applications.Runtime.IHostItemProvider))));

    this.DataHost = ((Microsoft.VisualStudio.Tools.Applications.Runtime.ICachedDataProvider)(this.RuntimeCallback.GetService(typeof(Microsoft.VisualStudio.Tools.Applications.Runtime.ICachedDataProvider))));

    object hostObject = null;

    this.HostItemHost.GetHostObject("Microsoft.Office.Interop.Excel.Application", "Application", out hostObject);

    this.ThisApplication = (Microsoft.Office.Interop.Excel.Application)Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.Wrap(typeof(Microsoft.Office.Interop.Excel.Application),

    ((Microsoft.Office.Interop.Excel.Application)(hostObject)));

    Globals.ThisWorkbook = this;

    System.Windows.Forms.Application.EnableVisualStyles();

    this.InitializeCachedData();

    this.InitializeControls();

    this.InitializeComponents();

    this.InitializeData();

    this.BeginInitialization();

    }

    ...

    }

    Regards,

    Dima Kherson



  • Mauro Araujo

    You can do this. The downside is that this is generated code and may be regenerated by the IDE if you modify the project in some way. In which case your modification will get "reverted".

    If you simply change your customization code to use this.Application, rather than ThisApplication, then you'll get a wrapped object back and will not have to modify the generated code. Both properties return the same Application object.

    The fact that ThisApplication isn't wrapped is a bug, both properties should behave identically.

    Ade


  • DotNETKans - 2005

    I've been playing around with my app after I had intergrated the above fix into it.  Everything seems to work fine but the performance has significantly degraded--it seems 3-4 times slower than before.  Hence, I decided to selectively use a "wrapped" Application object and take the change I had made in my previous post out.  This way the performance of the app reverted back to its norm.  Still, it makes me wonder as to the cause of such inconvenience.  Is it simply a matter of an app written under Beta 2 having quircky behavior when ported to RTM (a.k.a. the IDE-generated code is faulty)   Or is this something that VSTO developers will have to continue to cope with on the ongoing basis

    Regards,

    Dima Kherson

  • Werwolf13

    Ade,

     Thank you for the reply. Dima and I are a working on this together. As Dima mentioned above, the explanation and solution you provided did resolve our issue.

    - Jim

  • Nicole Johanson MSFT

    I've expanded a bit more on this in my latest blog post.

    http://spaces.msn.com/members/AdeMiller/

    Ade



  • Lydon

    Ade,

    In our specific case the Locale is irrelevant so perhaps it would be best to turn off the LCID proxy by setting the attribute as your described.  As to the this.Application vs Globals.ThisWorkbook.ThisApplication point.  The code doesn't always execute in the context where this.Application is available such as a Worksheet or Workbook.  Hence, I have to make explicit use of Globals.ThisWorkbook.ThisApplication.  The only failure that I've run into so far (due to this bug) was when I called the Application.Intersect() method but I've mended that situation by employing your fix.

    On a separate note, the PIAs for Office seem a bit raw.  Are there plans to create a "finer" layer to use in C# that can better accomodate for optional params by using overloads and "params" arguments   Also, many properties and methods still take and return "object" where they should be able to return a more specific type.  In fact, the method I had troubles with--Application.Intersect()--is a perfect example of a horrific method from the point of view of a C# programmer.  I had to write a wrapper for it in order to not have to pass it 30! arguments on every call:

    public Excel.Range Intersect(Excel.Range range1, Excel.Range range2, params Excel.Range[] args)

    {

    if (range1 == null) throw new ArgumentNullException("range1");

    if (range2 == null) throw new ArgumentNullException("range2");

    if (args.Length > 28) throw new ArgumentOutOfRangeException("args", "Cannot exceed 28 elements");

    object[] args2 = new object[28];

    args.CopyTo(args2, 0);

    object missing = Type.Missing;

    for (int i = args.Length; i < args2.Length; i++) args2Idea = missing;

    return _Application.Intersect(range1, range2, args2[0], args2[1], args2[2], args2[3], args2[4], args2[5], args2Devil, args2[7], args2Music, args2[9], args2[10],

    args2[11], args2[12], args2[13], args2[14], args2[15], args2[16], args2[17], args2[18], args2[19], args2[20], args2[21], args2[22], args2[23], args2[24],

    args2[25], args2[26], args2[27]);

    }

    Overall, it seems that at the moment VB.NET is the language better suited for VSTO. 

    In any case, we're grateful for your help.

    Regards,

    Dimitry Kherson



  • General

    The LCID proxy effects performance but this should be a one time hit for the most part when objects are first referenced, most of the results are cached. You may find improved performance in the RTM version. We did some additional work on the LCID between Beta2 and RTM, including some bug fixes and caching work. You're running RTM but the app was originally written under Beta 2 correct

    If you really don't want to use the LCID proxy you have two options:

    1) You can turn it off entirely by setting the following attribute in the AssemblyInfo.cs file:

    [assembly: ExcelLocale1033(false)]

    I wouldn't recommend this. If you do this customizations running in non EN-US locales WILL NOT WORK.

    2) You can also unwrap and wrap specific calls, again you have to be careful with locale issues because Excel OM calls to methods/properties that have a COM locale parameter will FAIL in non EN-US locales.

    I may be able to help you further but I'd need to know more about what your application is doing with wrapped objects. It's possible that you're doing a lot of OM access, maybe in a tight loop and the proxy is effecting perf. If you can send me more detail I'll think about it some more.

    Ade Miller
    Developer, VSTO



  • sql2k5 newbie

    The TransparentProxy you're seeing is part of the VSTO solution to the Locale issue in Excel. See Eric's blog for more detail.

    http://blogs.msdn.com/eric_carter/archive/2005/06/15/429515.aspx


    I think the problem here is that your application object is unwrapped - if so this is a bug.

    There is a known issue where the ThisApplication property returns an upwrapped object, e.g:

    Globals.ThisWorkbook.ThisApplication

    If you use this.Application to obtain your Application object you will not see this problem. 

    You can tell if the object was correctly wrapped using System.Runtime.Remoting.RemotingServices.IsTransparentProxy, this will return true if the LcidProxy is enabled.
    You can also wrap an unwrapped object using the Wrap() method, e.g.

    Application app = (Application)Microsoft.Office.Tools.Excel.ExcelLocale1033Proxy.Wrap(typeof(Application), Globals.ThisWorkbook.ThisApplication);

    Please let me know if this solves your problem.

    Thanks,

    Ade Miller
    Developer, VSTO


  • Excel BeforeRightClick TransparentProxy