Runtime: UnmanagedType.AnsiBStr is marked as obsolete with no alternative given

Created on 28 Sep 2019  路  9Comments  路  Source: dotnet/runtime

Title says it all. After a load of searching I came upon issue dotnet/runtime#28564 and pull request dotnet/corefx#35161 in which it states:

I am leaving the attribute on the following though:

UnmanagedType.AnsiBStr
UnmanagedType.AsAny
UnmanagedType.Currency
UnmanagedType.TBStr
UnmanagedType.VBByRefStr

My reasoning is because the BSTR ones are incredibly nuanced and cause more stress than need be and should be actively discouraged.
...

and from issue dotnet/runtime#28564:

If your application is targeting Windows and only Windows, this API is fine to use and will be around for years to come. If there are plans for your application to run on non-Windows platforms, I would suggest avoiding any API that relates to VARIANT for the time being since support on non-Windows platform is still in question.

I think that using the Obsolete attribute for this is wrong considering the intention seems to be to stop people from using it because of cross-incompatibility. Can a new attribute with a bit more explanation or intention not be built in? Or maybe at least giving a but more of a specific reason in the obsolete attribute.

It's a bit weird to support calling windows API's but mark specific feature Obsolete.

Also, the documentation of UnmanagedType at https://docs.microsoft.com/en-us/dotnet/api/system.runtime.interopservices.unmanagedtype?view=netcore-3.0 does not mention obsolete or the reasoning behind it at all.

For anyone else looking, currently the only workaround I know of is switch off warnings for error 618

```C#

pragma warning disable 618

//and then after the call

pragma warning restore 618

```

area-System.Runtime.InteropServices

All 9 comments

@mika76 The AnsiBSTR is a legacy approach even in Win32 and should be avoided when possible. There is little downside to using BSTR directly and has much better support when manipulating character based data.

It's a bit weird to support calling windows API's but mark specific feature Obsolete.

This is done to discourage use. For data that is non-UNICODE characters an alternative here is Marshal.AllocCoTaskMem.

Is there a specific scenario involving this type or marshaling that is being impacted?

Well we have an old legacy component which we use and I call from .net where the definition (one of many) looks like:
c# [DllImport(@"SomeLibrary.dll", EntryPoint = "GenerateKeyEx", CharSet = CharSet.Ansi)] [return: MarshalAs(UnmanagedType.AnsiBStr)] private static unsafe extern string GenerateKeyEx([MarshalAs(UnmanagedType.AnsiBStr)]string pNameParam, int pDateParam);

AnsiBStr is the only type that works. I'm not a C++ dev so I have no idea how I would use Marshal.AllocCoTaskMem to achieve the same effect?

The AnsiBSTR is a legacy approach

I understand that, but that is exactly why the obsolete flag should not be there in my opinion. If it needs to be there for legacy code then why would you remove it? We all have legacy code we have to deal with...

[EDIT - updated definition - forgot to include it all]

If it needs to be there for legacy code then why would you remove it?

We aren't removing it, but as mentioned this is to "discourage use". An attribute that says "Don't Use This" doesn't exist so we rely on Obsolete instead.

private static unsafe extern string GenerateKeyEx([MarshalAs(UnmanagedType.AnsiBStr)]string pNameParam, int pDateParam);

That is a concerning signature. If possible, could you provide the native signature? It is entirely possible the solution would be to convert this to UnmanagedType.LPStr. Does the native signature really use BSTR?

Ok if it's staying then I guess we can live with the obsolete flag...

As for the signature:

BSTR _stdcall GenerateKeyEx(
    const BSTR _pNameParam,
    const ulong _pDateParam
    );

and it returns SysAllocStringByteLen( .. some const char * ...)

Written looong ago by some long gone dev...

If nothing else, the [Obsolete] on these values could make use of the recently added properties to give them a dedicated diagnostic ID so that the warning can be silenced locally without affecting other Obsolete warnings.

@mika76 Oh boy. I see what you are saying. This is indeed a tough spot to be in. Appreciate you sharing the code. In this case I think we are still going to hold fast because of the desire to keep this API from being used. Hopefully, we can help make this easier for you with @Joe4evr's suggestion. Since this has been captured in #33360 can we close this issue or would you prefer to track this here?

@Joe4evr That is a good idea.

I think the thing that tripped me up is the actual obsolete message

"Marshalling as AnsiBStr may be unavailable in future releases."

If it's still going to stay but should be avoided then maybe the actual message text should be more specific?

@mika76 That is a reasonable compromise. Let me see what I can do here.

Since this has been captured in #33360 can we close this issue or would you prefer to track this here?

I'll close this since you don't need it. Thanks for all your help and understanding.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

nalywa picture nalywa  路  3Comments

EgorBo picture EgorBo  路  3Comments

bencz picture bencz  路  3Comments

jamesqo picture jamesqo  路  3Comments

GitAntoinee picture GitAntoinee  路  3Comments