在C#中调用Delphi COM对象会引发AccessViolationException

时间:2018-12-10 09:02:44

标签: c# delphi com

我正在尝试将字符串发送到Delphi COM对象,并期望从该对象得到答案,但是由于某种原因,它引发了AccessViolationException。 这是它引发的异常,将异常翻译为英语的描述是:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。程序输出(带有堆栈跟踪的顶部):

  

QManservice已启动。
  按任意键停止。
  请求获取订单。
  收到的字符串:S $ GET ORDERS,

     

Onnverwerkte设置:System.AccessViolationException:正在向schrijven van beveiligd geheugen注入全部水分。被暗杀了。

     

bij Microsoft.Win32.Win32Native.SysStringByteLen(IntPtr bstr)
    bij System.StubHelpers.BSTRMarshaler.ConvertToManaged(IntPtr bstr)
    bij QMan_SafanDarley.IWLM_.Send(String Msg,String&Answer)
    D:\ Michael \ C#Projects \ QManServiceConsoleApp \ OrderEditor_WCF \ QManService.cs:regel 210中的bij WorkLoadManagerServiceDefinitions.QManService.SendStringtoCON(String codToSend)     在D:\ Michael \ CR Projects \ QManServiceConsoleApp \ OrderEditor_WCF \ QManService.cs:regel中的bij WorkLoadManagerServiceDefinitions.QManService.RequestGetOrders()    ...

这是调用COM的代码

private string SendStringToCOM(string cmdToSend)
    {
        try
        {
            Console.WriteLine($"String received: {cmdToSend}");
            if (WLM == null)
            {
                WLM = new WLM_();
            }
            string answer = string.Empty;
            WLM.Send(cmdToSend, out answer);
            Console.WriteLine("Answer received");
            return answer;
        } catch(Exception e)
        {
            Console.WriteLine(e.Message);
            Console.ReadKey();
            return string.Empty;
        }
    }

这是Delphi中接收呼叫的代码,它根据接收到的命令将其发送到另一个处理数据库的单元。

function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
    Result := fmProduction.AnalyzeData(Msg, 0);
end;

我应该补充一点,这可以在我的电脑和同事的电脑上使用,但不能在第三台电脑上使用。 关于如何解决此问题的任何建议?

2 个答案:

答案 0 :(得分:1)

function TWLM_.Send(const Msg: WideString; out Answer: WideString) : Integer;
begin
    Result := fmProduction.AnalyzeData(Msg, 0);
end;

在这里,您没有为Answer参数分配任何内容。这是作为out参数传递的,这意味着需要该方法为其分配某些内容。它的行为与函数返回值完全相同。

如果不给该变量分配任何内容,则该方法在为该变量分配堆栈空间时将具有任何(未分配)值。这不是指向WideString的有效指针,但是使用方代码将尝试将其封送为out。有时这会立即崩溃,有时不会,有时可能只是破坏其他数据。无论哪种情况,都是错误的。

在本机Delphi代码中,您可能会习惯使用varout参数behaving quite similarly-在两种情况下,对于引用类型,调用代码的指针都可用于读取和写入。接受参数的方法。如果该方法选择不修改该值,则不需要这样做。但是,对于托管互操作,期望方法总是分配out参数。 C#强制执行此操作,但Delphi不执行。

在这种情况下,您在C#端传递的空字符串根本不会传递到方法中-您可能希望它应保持为空字符串,未经Delphi代码修改,而是通过将参数设置为调用代码期望使用const locationPermissionRationale = { title: "Location Access", message: 'Need for detect your location to select location nearby you easily' // how to create Positive and Negative alert dialog button here ? buttonNeutral: "Ask Me Later", buttonNegative:"Cancel", buttonPositive: "OK" 参数作为该参数的返回值,并立即用返回的值(在本例中为无意义的指针)覆盖传递的变量。扩展地,在C#端变量在传递给此方法之前可能具有的任何值,在Delphi / COM端将无法访问。

答案 1 :(得分:-1)

在我的情况下,

@J ...关于未分配答案参数的评论是问题。我有一位同事更改了dll,以便为参数分配一个值,这似乎可以修复错误,现在它可以按预期的方式工作。