COM互操作在发布模式下失败

时间:2011-06-29 11:10:16

标签: c# com com-interop windows-search

我有一个控制台应用程序,它使用ComImport调用Windows搜索。 虽然这在调试模式下工作正常...控制台应用程序在发布模式下崩溃。 可能是什么问题?

[ComImport]
    [Guid("9DAA54E8-CD95-4107-8E7F-BA3F24732D95")]
    [ClassInterface(ClassInterfaceType.None)]
    [TypeLibType(TypeLibTypeFlags.FCanCreate)]
    public class WordBreaker : IWordBreaker
    {
        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public virtual extern bool Init([In] bool query, [In] uint maxTokenSize);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public virtual extern void BreakText([In, MarshalAs(UnmanagedType.LPStruct)] TEXT_SOURCE textSource,
            [In] IWordSink wordSink, [In] IPhraseSink phraseSink);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public virtual extern void ComposePhrase([In, MarshalAs(UnmanagedType.LPWStr)] string noun, [In] uint nounLen,
            [In, MarshalAs(UnmanagedType.LPWStr)] string modifier, [In] uint modifierLen,
            [In] uint attachmentType, [Out] out IntPtr phrase, [In, Out] ref uint phraseLen);

        [MethodImpl(MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
        public virtual extern IntPtr GetLicenseToUse();
    }

访问WordBreaker.BreakText函数时,代码在发布模式下失败。

它正在我的代码中使用,如下所示

if (!string.IsNullOrWhiteSpace(text))
                try
                {
                    IWordBreaker breaker = new WordBreaker();
                    bool reqLicense = breaker.Init(query, 256);
                    if (reqLicense)
                    {
                        IntPtr lic = breaker.GetLicenseToUse();
                        string licText = Marshal.PtrToStringUni(lic);
                    }
                    TEXT_SOURCE source = new TEXT_SOURCE();
                    source.fillTextBuffer = FillTextBuffer;
                    source.buffer = text;
                    source.cur = 0;
                    source.end = (uint)(text.Length);
                    breaker.BreakText(source, new WordSink(result), null);
                }
                catch (Exception ex)
                {
                    Console.Out.WriteLine(ex.ToString());
                    //log4net.LogManager.GetLogger(typeof(WindowsIntegration)).Error("BreakText", ex);
                }
            var resultWithoutNoise = NoiseWord.Remove(result);
            return resultWithoutNoise;
        }

崩溃恰好发生在breaker.BreakText 在应用程序崩溃之前,BreakText函数被多次调用(在500到7000次之间)。

crashdump说明了有关异常信息的内容 The thread tried to read from or write to a virtual address for which it does not have the appropriate access. 注意:我的代码中没有使用任何线程。

3 个答案:

答案 0 :(得分:1)

代码至少需要一个错误所引用的线程。 至于崩溃的类型,它本质上是一个访问冲突,可以是空指针/对象引用(在本机代码中),也可以是运行缓冲区。 检查什么值。串。你失败时传入的长度等等。

答案 1 :(得分:1)

这看起来像垃圾收集器将文本移动到另一个位置,因此source.buffer中记录的地址不再有效。您没有包含声明TEXT_SOURCE的来源,因此我无法对此发表评论。但是BreakText的声明是不正确的。不应该在那里使用MarshalAs(UnmanagedType.LPStruct)。 UnmanagedType.LPStruct仅支持一种特定情况:将System.Guid值类型视为具有额外级别间接的非托管GUID。请参阅http://blogs.msdn.com/b/adam_nathan/archive/2003/04/23/56635.aspxHow do I marshal a structure as a pointer to a structure?

答案 2 :(得分:0)

如果您无法重现该问题且仅在发布时进行此操作,我强烈建议您添加日志记录以缩小问题范围。

当您缩小问题范围时,我会编辑上面的帖子,以包含有关崩溃的更详细信息。