<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Decrypt my World : Interop</title><link>http://blogs.msdn.com/alejacma/archive/tags/Interop/default.aspx</link><description>Tags: Interop</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>The use of MSXML is not supported in .NET applications</title><link>http://blogs.msdn.com/alejacma/archive/2008/09/08/the-use-of-msxml-is-not-supported-in-net-applications.aspx</link><pubDate>Mon, 08 Sep 2008 14:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8933022</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8933022.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8933022</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P&gt;The other day I was working with a customer of mine on a &lt;STRONG&gt;.NET&lt;/STRONG&gt; application which was suffering from a &lt;STRONG&gt;memory leak&lt;/STRONG&gt;. The weird thing was that the application could run just fine for 10 days in a row&amp;nbsp;before the memory began growing and growing. What was going on? Why was the &lt;STRONG&gt;Garbage Collector&lt;/STRONG&gt; suddenly deciding to stop working? Additionally, this issue was happening with both .NET 1.1 and 2.0. Weird.&lt;/P&gt;
&lt;P&gt;So we got a dump of a .NET 1.1 version of the application when the issue began. We used Adplus to take a hang dump we could analize (&lt;A class="" href="http://support.microsoft.com/kb/286350" mce_href="http://support.microsoft.com/kb/286350"&gt;How to use ADPlus to troubleshoot "hangs" and "crashes"&lt;/A&gt;).&lt;/P&gt;
&lt;P mce_keep="true"&gt;We loaded &lt;STRONG&gt;SOS&lt;/STRONG&gt; debugger extension (the one that comes with .NET Framework 1.1):&lt;/P&gt;&lt;PRE&gt;0:000&amp;gt;&lt;STRONG&gt;.load sos&lt;/STRONG&gt;
&lt;/PRE&gt;
&lt;P&gt;And we went to check all objects currently on the heap:&lt;/P&gt;&lt;PRE&gt;0:000&amp;gt;&lt;STRONG&gt; !dumpheap -stat&lt;/STRONG&gt;
Loaded Son of Strike data table version 5 from "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"
Loading the heap objects into our cache.
total &lt;STRONG&gt;1,958,563&lt;/STRONG&gt; objects
Statistics:
        MT      Count     TotalSize Class Name
...
&lt;/PRE&gt;
&lt;P&gt;Almost 2 million objects! That is a lot. Are any of them ready for finalization?&lt;/P&gt;&lt;PRE&gt;0:000&amp;gt;&lt;STRONG&gt; !finalizequeue&lt;/STRONG&gt;
Loaded Son of Strike data table version 5 from "C:\WINNT\Microsoft.NET\Framework\v1.1.4322\mscorwks.dll"
&lt;STRONG&gt;SyncBlock to be cleaned up: 6371&lt;/STRONG&gt;
----------------------------------
MTA interfaces to be released: 0
Total STA interfaces to be released: 0
----------------------------------
generation 0 has 215 finalizable objects (0x17daef74-&amp;gt;0x17daf2d0)
generation 1 has 0 finalizable objects (0x17daef74-&amp;gt;0x17daef74)
generation 2 has 15,317 finalizable objects (0x17da0020-&amp;gt;0x17daef74)
&lt;STRONG&gt;Ready for finalization 0 objects&lt;/STRONG&gt; (0x17daf2d0-&amp;gt;0x17daf2d0) - Freachable queue
All Finalizable Objects Statistics:
        MT      Count     TotalSize Class Name
...
&lt;/PRE&gt;
&lt;P&gt;So apparently there are no objects ready to be finalized, but we have 6371 SyncBlocks ready to be cleaned up. Why? What are those SyncBlocks?&lt;/P&gt;&lt;PRE&gt;0:000&amp;gt; &lt;STRONG&gt;!finalizequeue -detail
To be cleaned Com Data&lt;/STRONG&gt;
0x4edc1b8  &lt;STRONG&gt;ComPlusWrapper&lt;/STRONG&gt;
0x4edc590  &lt;STRONG&gt;ComPlusWrapper&lt;/STRONG&gt;
...
0x4e227b8  &lt;STRONG&gt;ComPlusWrapper&lt;/STRONG&gt;
&lt;STRONG&gt;SyncBlock to be cleaned up: 6371&lt;/STRONG&gt;
----------------------------------
MTA interfaces to be released: 0
Total STA interfaces to be released: 0
...
&lt;/PRE&gt;
&lt;P&gt;Ok, so those SyncBlocks are related to &lt;STRONG&gt;ComPlusWrappers&lt;/STRONG&gt; which need to be cleaned up. It seems the application is referencing some &lt;STRONG&gt;COM objects&lt;/STRONG&gt; which are not needed anymore.&lt;/P&gt;
&lt;P&gt;And what is the &lt;STRONG&gt;Finalizer&lt;/STRONG&gt; thread doing that is not cleaning up those objects? Is it too busy?&lt;/P&gt;&lt;PRE&gt;0:000&amp;gt; &lt;STRONG&gt;!threads&lt;/STRONG&gt;
ThreadCount: 23
UnstartedThread: 0
BackgroundThread: 17
PendingThread: 0
DeadThread: 0
                                  PreEmptive   GC Alloc                     Lock     
        ID  ThreadOBJ       State     GC       Context           Domain     Count APT Exception
  0  0x7a4 0x0013e1b8      0xa020 Enabled  0x00000000:0x00000000 0x00138fa0     0 MTA
  &lt;STRONG&gt;2  0x484 0x0014a508      0xb220 Enabled  0x00000000:0x00000000 0x00138fa0     0 MTA (Finalizer)&lt;/STRONG&gt;
...
0:000&amp;gt; &lt;STRONG&gt;~2s&lt;/STRONG&gt;
0:002&amp;gt; &lt;STRONG&gt;kL100&lt;/STRONG&gt;
ChildEBP RetAddr  
02a5f980 77f8822a &lt;STRONG&gt;NTDLL!ZwWaitForSingleObject&lt;/STRONG&gt;+0xb
02a5f9f4 77f8819b NTDLL!RtlpWaitForCriticalSection+0x9e
02a5f9fc 72e55ff1 NTDLL!RtlEnterCriticalSection+0x46
02a5fa08 72e56010 &lt;STRONG&gt;msxml3!X_CRITICAL_SECTION::Enter&lt;/STRONG&gt;+0xc
02a5fa10 72e5b735 msxml3!CSMutex::Enter+0xd
02a5fa20 72e5b6fd msxml3!RemovePointerFromCache+0x2e
02a5fa2c 72e55cfe msxml3!GCObject::~GCObject+0x15
02a5fa38 72e55c21 msxml3!_array&amp;lt;_reference&lt;TEMPLATEACTION&gt; &amp;gt;::`vector deleting destructor'+0xd
02a5fa44 72e5b5b6 msxml3!Base::weakRelease+0x19
02a5fa54 72e5b565 msxml3!Base::_release+0x95
02a5fa5c 72e5685d msxml3!DefaultWriter::Release+0xd
02a5fa74 72e60805 msxml3!assign+0x26
02a5fa8c 72e5ff5f msxml3!NodeData::setText+0x1e
02a5fa98 72e5b5a5 msxml3!Node::finalize+0x73
02a5faa8 72e60b7d msxml3!Base::_release+0x76
02a5fac0 72e6098b msxml3!Node::setNodeParent+0x7f
02a5fae0 72e5ff9a msxml3!Node::_remove+0x90
02a5faec 72e5b5a5 msxml3!Node::finalize+0x65
02a5fafc 72e60ae4 msxml3!Base::_release+0x76
02a5fb14 72e5c36e msxml3!Node::_release+0x77
02a5fb2c 72e5c1a7 msxml3!Node::_release+0x8d
02a5fb40 72e5b54e msxml3!Node::Release+0x26
02a5fb4c 72e70e12 msxml3!release+0x17
02a5fb58 72e70ddf msxml3!DOMNodeList::~DOMNodeList+0x16
02a5fb64 72e56962 msxml3!DOMNamedNodeMapList::`vector deleting destructor'+0x16
02a5fba4 72e5b8e3 msxml3!__comexport::Release+0x62
02a5fbac 79221be1 &lt;STRONG&gt;msxml3!_dispatchEx&lt;ISERVERXMLHTTPREQUEST,&amp;LIBID_MSXML2,&amp;IID_ISERVERXMLHTTPREQUEST,0&gt;::Release&lt;/STRONG&gt;+0x10
02a5fbdc 79232e77 mscorwks!SafeRelease+0x56
02a5fbf8 79232ea8 mscorwks!IUnkEntry::Free+0x7c
02a5fc04 79232f86 mscorwks!ComPlusWrapper::ReleaseAllInterfaces+0xa
02a5fe3c 79232e0d mscorwks!ComPlusWrapper::ReleaseAllInterfacesCallBack+0x135
02a5fe48 7923303c mscorwks!ComPlusWrapper::Cleanup+0x16
02a5fe58 79233302 mscorwks!ComPlusContextCleanupGroup::CleanUpWrappers+0x19
02a5fe64 792335bc mscorwks!ComPlusApartmentCleanupGroup::ReleaseCleanupGroup+0xe
02a5fe74 792325bb mscorwks!ComPlusApartmentCleanupGroup::ReleaseCleanupGroupCallback+0x51
02a5fe98 792324dc mscorwks!ComPlusApartmentCleanupGroup::CleanUpWrappers+0xa8
02a5fed0 791fea3d &lt;STRONG&gt;mscorwks!ComPlusWrapperCleanupList::CleanUpWrappers&lt;/STRONG&gt;+0x84
02a5fedc 791fe9cd &lt;STRONG&gt;mscorwks!SyncBlockCache::CleanupSyncBlocks&lt;/STRONG&gt;+0x85
02a5fee0 791bbd18 &lt;STRONG&gt;mscorwks!Thread::DoExtraWorkForFinalizer&lt;/STRONG&gt;+0x23
02a5ff20 791cf03c mscorwks!GCHeap::FinalizerThreadStart+0xbb
02a5ffb4 7c57b3bc mscorwks!Thread::intermediateThreadProc+0x44
02a5ffec 00000000 KERNEL32!BaseThreadStart+0x52
&lt;/PRE&gt;
&lt;P&gt;Interesting. The Finalizer thread is trying to &lt;STRONG&gt;free an&lt;/STRONG&gt; &lt;STRONG&gt;MSXML3&lt;/STRONG&gt; &lt;STRONG&gt;object&lt;/STRONG&gt;, it entered a &lt;STRONG&gt;critical section&lt;/STRONG&gt; and it's waiting for it to be released. We took a few more dumps and the Finalizer thread always stayed the same. It didn't move a bit. It's hung in there. So no wonder Garbage Collector can't free memory.&lt;/P&gt;
&lt;P&gt;Why is &lt;STRONG&gt;Finalizer thread hung on a critical section when freeing MSXML objects&lt;/STRONG&gt;?&lt;/P&gt;
&lt;P&gt;Well, check this: &lt;/P&gt;
&lt;P&gt;&lt;A class="" href="http://support.microsoft.com/kb/815112" mce_href="http://support.microsoft.com/kb/815112"&gt;The use of MSXML is not supported in .NET applications&lt;/A&gt;&lt;/P&gt;
&lt;P&gt;&lt;EM&gt;MSXML uses threading models and garbage-collection mechanisms that are not compatible with the .NET Framework.&lt;/EM&gt;&lt;/P&gt;
&lt;P&gt;Summing up, we fail to garbage-collect msxml objects&amp;nbsp;because of these incompatibilities. This issue affects all versions of the Framework and MSXML. The only alternative we have is to use .Net's &lt;STRONG&gt;System.Xml namespace&lt;/STRONG&gt; to work with XML as suggested by previous article.&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8933022" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/WinDbg/default.aspx">WinDbg</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Debugging/default.aspx">Debugging</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Interop/default.aspx">Interop</category></item><item><title>How to modify an Interop assembly to change the return type of a method (VB.NET)</title><link>http://blogs.msdn.com/alejacma/archive/2008/08/04/How-to-modify-an-Interop-assembly-to-change-the-return-type-of-a-method-_2800_VB.NET_2900_.aspx</link><pubDate>Mon, 04 Aug 2008 09:52:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8828576</guid><dc:creator>alejacma</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/alejacma/comments/8828576.aspx</comments><wfw:commentRss>http://blogs.msdn.com/alejacma/commentrss.aspx?PostID=8828576</wfw:commentRss><description>&lt;P&gt;Hi all,&lt;/P&gt;
&lt;P mce_keep="true"&gt;In some situations we may need to &lt;STRONG&gt;reference&lt;/STRONG&gt; a &lt;STRONG&gt;COM dll&lt;/STRONG&gt; in our &lt;STRONG&gt;Visual Studio&lt;/STRONG&gt; project in order to use a specific &lt;STRONG&gt;COM object&lt;/STRONG&gt; within our &lt;STRONG&gt;.NET&lt;/STRONG&gt; application, and thanks to &lt;STRONG&gt;COM Interop&lt;/STRONG&gt; we can do it. When we add a reference to a COM dll in our project, a &lt;STRONG&gt;COM Interop assembly&lt;/STRONG&gt; gets generated so we can use COM objects in the dll &lt;EM&gt;almost&lt;/EM&gt; like any other .NET object. And I say almost because i.e. .NET needs to &lt;STRONG&gt;translate COM types&lt;/STRONG&gt; to .NET types and it doesn't always do the conversion the way we like or need. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Let's see this with the following real &lt;STRONG&gt;example&lt;/STRONG&gt;:&lt;/P&gt;
&lt;P mce_keep="true"&gt;We are writing an &lt;STRONG&gt;Exit Module&lt;/STRONG&gt; for our &lt;STRONG&gt;Certification Authority&lt;/STRONG&gt;. We are trying to obtain the &lt;STRONG&gt;raw binary data&lt;/STRONG&gt; for a certificate issued by our CA. We are calling &lt;STRONG&gt;CCertServerExit.GetCertificateProperty("RawCertificate", PROPTYPE_BINARY)&lt;/STRONG&gt; (&lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa385074(VS.85).aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa385074(VS.85).aspx"&gt;ICertServerExit::GetCertificateProperty Method&lt;/A&gt;) to achieve that. But GetCertificateProperty is returning a String and not an array of bytes, because .NET &lt;STRONG&gt;interop layer&lt;/STRONG&gt; is converting a VARIANT of type &lt;STRONG&gt;BSTR&lt;/STRONG&gt; (vt = VT_BSTR) to a &lt;STRONG&gt;.NET&amp;nbsp;String&lt;/STRONG&gt;. Because of this return type, .NET is &lt;STRONG&gt;trimming the last byte&lt;/STRONG&gt; of the binary certificate when the number of bytes is odd. .NET strings &lt;STRONG&gt;cannot represent&lt;/STRONG&gt; BSTRs that contain an &lt;STRONG&gt;odd number of bytes&lt;/STRONG&gt;. &lt;/P&gt;
&lt;P mce_keep="true"&gt;Fortunately we can &lt;STRONG&gt;modify the Interop assembly&lt;/STRONG&gt; and choose a different return type for that method. This modification will allow us to get all the bytes in the certificate. These are the &lt;STRONG&gt;steps&lt;/STRONG&gt; to do this:&lt;/P&gt;
&lt;P mce_keep="true"&gt;1) &lt;STRONG&gt;Extract IL&lt;/STRONG&gt; from &lt;STRONG&gt;Interop.CertClientLib.dll&lt;/STRONG&gt; interop assembly generated by VS IDE when we added &lt;STRONG&gt;CertCli COM reference&lt;/STRONG&gt; to our VS project:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;EM&gt;ildasm.exe Interop.CertClientLib.dll /out:temp.il&lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&lt;BR&gt;2) Delete Interop.CertClientLib.dll file. &lt;/P&gt;
&lt;P mce_keep="true"&gt;3) Delete CertCli COM reference from our project.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;4) &lt;STRONG&gt;Modify temp.il&lt;/STRONG&gt; and change the declaration of &lt;STRONG&gt;GetCertificateProperty&lt;/STRONG&gt; in base and derived classes to take an IntPtr for the last output parameter instead of a VARIANT *:&lt;/P&gt;&lt;PRE&gt;instance void 
GetCertificateProperty([in] string  marshal( bstr) strPropertyName,
                       [in] int32 PropertyType,
                       [out] native int pvarPropertyValue) runtime managed internalcall
&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;5) &lt;STRONG&gt;Generate&lt;/STRONG&gt; a new &lt;STRONG&gt;Interop.CertClientLib.dll&lt;/STRONG&gt; which includes these modifications:&lt;BR&gt;&amp;nbsp;&lt;BR&gt;&lt;EM&gt;ilasm.exe /DLL temp.il /res:temp.res /out=Interop.CertClientLib.dll&lt;BR&gt;&lt;/EM&gt;&amp;nbsp;&lt;BR&gt;6) Modify our project's references to use this new DLL.&lt;BR&gt;&amp;nbsp;&lt;BR&gt;7) Change our &lt;STRONG&gt;.NET code&lt;/STRONG&gt; to use the IntPtr calling convention. Manage Variant objects from IntPtr and free the memory after its use. &lt;STRONG&gt;Sample&lt;/STRONG&gt;:&lt;/P&gt;&lt;PRE&gt;&amp;lt;DllImport("Oleaut32.dll", PreserveSig:=False)&amp;gt; _
Private Shared Sub VariantClear(ByVal var As IntPtr)
End Sub

'Exit Module Notify callback
Public Sub Notify(ByVal ExitEvent As Integer, ByVal Context As Integer) Implements CERTEXITLib.ICertExit.Notify

    Trace.WriteLine("&amp;gt;&amp;gt; Notify")

    Dim oCSE As New CERTCLIENTLib.CCertServerExit
    oCSE.SetContext(Context)

    Trace.WriteLine(String.Format("ExitEvent = {0}", ExitEvent))
    If ExitEvent = 1 Then 'Issue

        ' Allocate memory to hold VARIANT
        '
        Dim variantObjectPtr As IntPtr
        variantObjectPtr = Marshal.AllocHGlobal(2048)

        ' Get VARIANT containing certificate bytes
        '
        oCSE.GetCertificateProperty("RawCertificate", DataTypeEnum.Binary, variantObjectPtr)

        ' Read ANSI BSTR information from the VARIANT as we know RawCertificate property 
        ' is ANSI BSTR. Please note that the below code is written based on how the 
        ' VARIANT structure looks like in C/C++
        '
        Dim bstrPtr As IntPtr
        bstrPtr = Marshal.ReadIntPtr(variantObjectPtr, 8)

        Dim bstrLen As Integer
        bstrLen = Marshal.ReadInt32(bstrPtr, -4)

        Dim certBytes(bstrLen - 1) As Byte
        Marshal.Copy(bstrPtr, certBytes, 0, bstrLen)

        Trace.WriteLine(String.Format("Certificate length = {0}", certBytes.Length))

        ' Clear the VARIANT which will free the memory allocated for the VARIANT members
        '
        VariantClear(variantObjectPtr)

        ' Get certificate
        '
        Dim x509 As New X509Certificate(certBytes)

        ' Store the certificate in the certificate store
        '
        Dim store As New StoreClass
        Dim cert As New CertificateClass
        Dim data As String = Convert.ToBase64String(x509.GetRawCertData)

        cert.Import(data)
        store.Open(CAPICOM_STORE_LOCATION.CAPICOM_LOCAL_MACHINE_STORE, _
                    "My", _
                    CAPICOM_STORE_OPEN_MODE.CAPICOM_STORE_OPEN_READ_WRITE)
        store.Add(cert)

        ' Get VARIANT containing Serial Number
        '
        oCSE.GetCertificateProperty("SerialNumber", DataTypeEnum.String, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        Dim variantObject As Object
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Serial Number
        '
        Dim serialNo As String = variantObject

        Trace.WriteLine(String.Format("Serial Number = {0}", serialNo))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Distinguished Name
        '
        oCSE.GetCertificateProperty("DistinguishedName", DataTypeEnum.String, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Serial Number
        '
        Dim distinguishedName As String = variantObject

        Trace.WriteLine(String.Format("DistinguishedName = {0}", distinguishedName))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Not Before date
        '
        oCSE.GetCertificateProperty("NotBefore", DataTypeEnum.Date, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Not Before date
        '
        Dim validFrom As Date = variantObject

        Trace.WriteLine(String.Format("Not Before = {0}", validFrom.ToString))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Get VARIANT containing Not After date
        '
        oCSE.GetCertificateProperty("NotAfter", DataTypeEnum.Date, variantObjectPtr)

        ' Construct Variant .NET object from IntPtr
        '
        variantObject = Marshal.GetObjectForNativeVariant(variantObjectPtr)

        ' Get Not After date
        '
        Dim validTo As Date = variantObject

        Trace.WriteLine(String.Format("Not After = {0}", validTo.ToString))

        ' Free memory
        '
        VariantClear(variantObjectPtr)

        ' Free the memory block allocated to hold VARIANT 
        '
        Marshal.FreeHGlobal(variantObjectPtr)

    End If

    Trace.WriteLine("&amp;lt;&amp;lt; Notify")

End Sub

&lt;/PRE&gt;
&lt;P mce_keep="true"&gt;Note: Becareful when translating the sample to &lt;STRONG&gt;C#&lt;/STRONG&gt;: "&lt;EM&gt;Dim certBytes(bstrLen - 1) As Byte&lt;/EM&gt;" will translate to "&lt;EM&gt;byte[] rawCert = new byte[bstrLen];&lt;/EM&gt;".&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;BR&gt;I've also seen this kind of issues when referencing &lt;STRONG&gt;CAPICOM.dll&lt;/STRONG&gt; (&lt;STRONG&gt;Interop.CAPICOM.dll&lt;/STRONG&gt; &lt;STRONG&gt;interop assembly&lt;/STRONG&gt;). These errors may appear when we are i.e. decrypting a string:&lt;/P&gt;
&lt;P mce_keep="true"&gt;&lt;EM&gt;&lt;STRONG&gt;System.Runtime.InteropServices.COMException: ASN1 unexpected end of data. &lt;BR&gt;System.Runtime.InteropServices.COMException: ASN1 bad tag value met.&lt;/STRONG&gt;&lt;/EM&gt;&lt;/P&gt;
&lt;P mce_keep="true"&gt;For instance, &lt;A class="" href="http://msdn.microsoft.com/en-us/library/aa388181.aspx" mce_href="http://msdn.microsoft.com/en-us/library/aa388181.aspx"&gt;CAPICOM.Utilities.ByteArrayToBinaryString&lt;/A&gt; returns a BSTR that represents the binary data being passed as an input parameter. The interop layer assigns the BSTR to a .NET string which removes the last byte and makes the data even. By using an IntPtr as return type we can access the complete binary data as we've already seen. In this case we'll replace "&lt;EM&gt;string marhal(bstr)&lt;/EM&gt;" to "&lt;EM&gt;native int&lt;/EM&gt;" just before each ByteArrayToBinaryString occurrence in the IL file.&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;I hope this helps.&lt;/P&gt;
&lt;P&gt;Cheers,&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Alex (Alejandro Campos Magencio)&lt;/P&gt;
&lt;P mce_keep="true"&gt;&amp;nbsp;&lt;/P&gt;
&lt;P&gt;Credits: Sample code has been provided by my colleague Prabagar Ramadasse. Thank you Prabagar!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8828576" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/alejacma/archive/tags/CAPICOM/default.aspx">CAPICOM</category><category domain="http://blogs.msdn.com/alejacma/archive/tags/Interop/default.aspx">Interop</category></item></channel></rss>