weixin_39996035
2021-01-11 11:40 阅读 0

InvalidOperationException when calling GetData on IDataObject

-beer commented on Fri Nov 16 2018

In porting our test suite to .NET Core 3.0, I'm seeing a new failure in one of our tests. When trying to call the GetData API on an instance of IDataObject returned from Clipboard.GetDataObject, I get an InvalidOperationException with the following message:

This type has a ComVisible(false) parent in its hierarchy, therefore QueryInterface calls for IDispatch or class interfaces are disallowed

This may be related to issue dotnet/coreclr#149

To reproduce the issue: - clone the repo https://github.com/nick-beer/IDataObjectBug - Run the test DataObject_Fails from within the 'Tests' folder

该提问来源于开源项目:dotnet/runtime

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享

20条回答 默认 最新

  • weixin_39789327 weixin_39789327 2021-01-11 11:40

    There seems to be a difference in the interface definitions between core and desktop framework.

    In desktop, IDataObject is decorated with COM attributes.

    In core, it is not.

    点赞 评论 复制链接分享
  • weixin_39603778 weixin_39603778 2021-01-11 11:40

    are you sure? https://github.com/dotnet/corefx/blob/c3154a9642a92aa15704abce7bf695b3e9db55f5/src/System.Runtime.InteropServices/src/System/Runtime/InteropServices/ComTypes/IDataObject.cs#L18-L21

    Be careful with source.dot.net, that doesn't handle reference assemblies very well.

    Moreover, the IDataObject used in this repro is actually defined by PresentationCore. src/WPF/src/PresentationCore/CSharp/System/Windows/IDataObject.cs

    Here's a simpler repro:

    C#
    using System;
    using System.Windows;
    
    namespace testClipboard
    {
        class Program
        {
            [STAThread]
            static void Main(string[] args)
            {
                var data = new TestClipboardData("ABC");
                var dataObject = new DataObject();
                dataObject.SetData(data);
                Clipboard.SetDataObject(dataObject);
    
                IDataObject clipboardData = Clipboard.GetDataObject();           
    
                var testClipboardData = clipboardData.GetData(typeof(TestClipboardData)) as TestClipboardData;
    
            }
    
            [Serializable]
            internal class TestClipboardData
            {
                public string Text { get; private set; }
    
                public TestClipboardData(string text)
                {
                    Text = text;
                }
            }
        }
    }
    
    
    点赞 评论 复制链接分享
  • weixin_39603778 weixin_39603778 2021-01-11 11:40

    this is happening because System.Type is not COMVisible in .NETCore.

    Winforms has nearly the same code but doesn't hit this because they wrap the COM object with a managed object that will always translate the GetObject call to use a string instead of type.

    WPF on the other hand, does not wrap the COM object so it returns the raw interface. When the test code calls GetObject(type) that's what triggers the runtime to complain about the COM visibility of System.Type.

    To workaround the caller can avoid calling GetObject(type) and instead just call GetObject(type.FullName).

    To fix this (if the runtime doesn't add back COMVisibility to System.Type) WPF can wrap with a managed object like WinForms does, but I think the better fix would be to add back COMVisible to System.Type. / any reason not to do that?

    点赞 评论 复制链接分享
  • weixin_39897127 weixin_39897127 2021-01-11 11:40

    cc

    点赞 评论 复制链接分享
  • weixin_39918043 weixin_39918043 2021-01-11 11:40

    I think the better fix would be to add back COMVisible to System.Type

    We are not going to make any of the regular managed types ComVisible. It is even worse compatibility nightmare than binary serialization. The workaround you have suggested is the right way to fix this.

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    This has been an issue for a while and was actually discovered by when he was writing some tests, I can't seem to find what we did to either move on or document this thought. do you happen to recall the PR?

    点赞 评论 复制链接分享
  • weixin_39603778 weixin_39603778 2021-01-11 11:40

    are you talking about this: https://github.com/dotnet/corefx/issues/31079#issuecomment-406037340

    I agree that we can make a tactical fix in WPF here, but that's just because we have another interface member we can call to get the same job done without relying on Type being COMVisible. I can imagine that the full extent of this break could be rather difficult to track down and not always fixable. At the very least we should update the exception message to let folks know what type the runtime is complaining about and document the extent of the types that we've removed COMVisible from. It may also be worthwhile to scan all the interfaces we use with COM to see where else we're relying on deprecated COM visibility.

    点赞 评论 复制链接分享
  • weixin_39603778 weixin_39603778 2021-01-11 11:40

    https://github.com/dotnet/corefx/issues/33638 is another issue caused by Type not being COMVisible.

    点赞 评论 复制链接分享
  • weixin_40005887 weixin_40005887 2021-01-11 11:40

    member we can call to get the same job done without relying on Type being COMVisible. I can imagine that the full extent of this break could be rather difficult to track down and not always fixable. At the very least we should update the exception message to let folks know what type the runtime is complaining abou

    thoughts on the above? It seems this is what remains of this issue.

    点赞 评论 复制链接分享
  • weixin_40005887 weixin_40005887 2021-01-11 11:40

    I'd like to get consensus on what if anything to do here so we can get it to happen for 3.0 if we need to..?

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    At the very least we should update the exception message to let folks know what type the runtime is complaining about and document the extent of the types that we've removed COMVisible from. It may also be worthwhile to scan all the interfaces we use with COM to see where else we're relying on deprecated COM visibility.

    I would agree with statement above. We definitely should update the exception message to indicate the true underlying issue so people aren't banging their heads against the wall trying to figure it out. This tactical fix does seem like something we should handle in coreclr though, unless I am missing something that is related to changes in corefx.

    点赞 评论 复制链接分享
  • weixin_40005887 weixin_40005887 2021-01-11 11:40

    given your comment above, shall we move to CoreCLR? I think it makes a lot of sense to do this in 3.0 if it will help customers unblock themselves without having to reach out to us.

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    Yep. Moving this to CoreCLR makes sense. Is there a way to move the issue across repos so we don't lose context?

    点赞 评论 复制链接分享
  • weixin_40005887 weixin_40005887 2021-01-11 11:40

    yes - the recommended way is to use https://github-issue-mover.appspot.com. It is "approved" for these repos.

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    , , or Do any of you have a suggestion on what could better convey the issue to the user?

    "This type has a ComVisible(false) parent in its hierarchy... "

    Is technically the issue and

    ... therefore QueryInterface calls for IDispatch or class interfaces are disallowed."

    is some implementation detail about what the ComVisible attribute implies. I am struggling to come up with a message that could convey the issue in an actionable way by the user. Suggestions are welcome.

    点赞 评论 复制链接分享
  • weixin_40005887 weixin_40005887 2021-01-11 11:40

    Can the message include the name of the type ("this type") and name of the problematic "parent"?

    We can also, if it's helpful, add a fwlink to some documentation that explains what to do. It's pretty ugly but there is precedent. Usually folks just search for the message string or error code.

    eg

    
     3343:     <value>Type '{0}' cannot be serialized by XmlSerializer, serialization code for the type is missing. Consult the SDK documentation for adding it as a root serialization type. http://go.microsoft.com/fwlink/?LinkId=613136</value>
    
    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    Including the current type is possible. Getting at the parent is going to require a bit more work. We use a flag that was set to indicate some base class isn't visible. This means we would need to walk the hierarchy again, not impossible just annoying.

    I guess it is the right thing to do so I will do it. Thanks for the suggestion.

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    I don't think your small example fails anymore. I am not entirely sure why it doesn't, but I can't get it to fail with the latest Core 3.0 preview.

    点赞 评论 复制链接分享
  • weixin_39603778 weixin_39603778 2021-01-11 11:40

    We worked around that specific case in WPF by making it do the same thing WinForms was doing. https://devdiv.visualstudio.com/DevDiv/_git/DotNet-Trusted/commit/78579857c2a7226db1e08d3c8b818bc9f83aa149?refName=refs%2Fheads%2Fmaster&_a=compare&path=%2Fsrc%2FWPF%2Fsrc%2FPresentationCore%2FCSharp%2FSystem%2FWindows%2Fclipboard.cs

    You'll need to construct a different repro to test this, sorry.

    点赞 评论 复制链接分享
  • weixin_39915820 weixin_39915820 2021-01-11 11:40

    Oh, glad you were able to work around it. Thanks for the clarification.

    点赞 评论 复制链接分享

相关推荐