How can setting one c# method

This one really has me stumped. I'm working with another developer who called me because he couldn't believe what he was seeing. We stepped through with the debugger together and I saw it too and had no explanation. Here's the scenario. He is writing a method that interacts with a 3rd party COM object through an auto-generated COM wrapper (generated simply by adding the COM component as a reference. Here's the top of his method:

  public bool RefolderDocument(ref IManDocument oDoc)
    {
        string strCustom1 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1);
        string strCustom2 = (string) oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2);

The purpose of the code is to get a project number and subproject number from a "document" object (oDoc).

Here's what happens as you step through. After the first assignment strCustom1 has the expected value "32344" (a project number) and strCustom2 is empty as expected. After the second assignment, strCustom2 gets the subproject number "0002" -- but strCustom1 has been changed to 32334 -- one character has been changed!?

It struck me as some kind of old-school c-language stack-overrun (which I wouldn't expect in a managed application even if it was interoperating with a COM component). We were all baffled. In an attempt to hack around this bizarreness, I tried to copy the contents of the first string to another location like so:

  public bool RefolderDocument(ref IManDocument oDoc)
    {
        string strCustom1 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
        string strCustom2 = string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));

Same results! We were grasping at straws at this point and dropped the code from .NET 4 to .NET 3.5 (CLR 2) but no change. One perhaps relevant point is that this is a service and we are attaching to the service process. The build is targeting x86 and the service location is definitely in the Debug output build folder.

Is there any logical explanation for this? I'm stumped as to how to proceed.


Looks like strCustom1 and strCustom2 have both been set as references back to the result of GetAttributeValueByID. I know not why, and it would be interesting to see if someone else on here (Paging Dr. Skeet lol...) can.

In the short term though, I think you'll find this will solve the issue for you...

 public bool RefolderDocument(ref IManDocument oDoc)
    {
        string strCustom1 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1));
        string strCustom2 = "" + string.Copy((string)oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom2));

My idea is basically to have it evaluate an expression rather than working with the referernce directly...

Martin.

Ps. What's with the string.Copy()?


Likely COM memory management rules aren't being followed by the COM object and it's overwriting memory the CLR believes it owns. Simple things like not creating a new object for GetEnumerator() can really screw up COM interop and the caching it does.

You also have to realize, the way the COM call is actually working is by passing a reference to memory for the string. Although you call it like:

str = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1)

It's really called more like:

hresult = oDoc.GetAttributeValueByID(imProfileAttributeID.imProfileCustom1,&str)

So you can see the COM object has a pointer right into the CLR memory.

In other words, look at the COM object, not your .NET code.


I've encountered problems that looked similar to the one you've described.

I my case, the .NET/compiler/runtine/CLR worked great, and the only problem was visual studio debugger displaying incorrect values. Try writing your values eg to System.Diagnostics.Trace, or to console, to check if this is your case.

链接地址: http://www.djcxy.com/p/6024.html

上一篇: Mediator C ++ GUI示例

下一篇: 如何设置一个C#方法