在Windows Server 2012上从C#调用Win32 Dll

时间:2013-10-11 08:16:43

标签: pinvoke windows-server-2012

我有一个应用程序调用用Delphi编写的Win32 Dll。我的应用程序是用C#开发的,在IIS下运行。除了Windows Server 2012之外,我可以在Server 2003以上的每个Windows版本上成功调用Delphi Dll。对外部方法的调用不会返回任何错误,也不会出现错误日志中的任何内容。它永远不会返回任何数据。

在我的C#中我声明:

[DllImport("MyTest.dll", CharSet = CharSet.Unicode,
       CallingConvention = CallingConvention.StdCall)]
    public static extern void Encrypt(string szPlainText, StringBuilder szCipherText);

然后我用以下内容调用该函数:

StringBuilder encText = new StringBuilder(128);
StringBuilder plainString = new StringBuilder("test");

Encrypt(plainString.ToString(), encText);

WinServer 2012中是否有更改会阻止其工作?

我可以访问的Delphi代码如下:

procedure Encrypt(szPlainText: PChar; szCipherText : PChar) ; stdcall ; export;
var
   sTemp : String ;
   sPlainText : String ;
   cipher : TCipher ;

 begin
   cipher := TLogixCipher.Create ;
   sPlainText := szPlainText ;

   sTemp  := cipher.Encrypt(sPlainText ) ;
   StrPCopy(szCipherText,sTemp);    
   FreeAndNil(cipher) ;
 end;

1 个答案:

答案 0 :(得分:2)

注意:编写此答案是为了与问题的原始版本相匹配。自编写以来,问题已更改为包含下面建议的更改。


启动时p / invoke声明可能是错误的。第一个参数是输入参数(我假定),因此应声明为字符串。我会像这样声明p / invoke:

public static extern void Encrypt(
    string szPlainText, 
    StringBuilder szCipherText
);

这并不重要,但是当函数返回时,将纯文本编组回托管代码没有什么意义,因为纯文本不会改变。

第二个问题是你需要在调用之前在szCipherText参数中分配缓冲区。

所以,假设您知道缓冲区需要长度为100,那么您可以这样写:

StringBuilder CipherText = new StringBuilder(100);
Encrypt(PlainText, CipherText);

此函数的机制可能是密文长度和纯文本相同。在这种情况下,您的电话将是:

StringBuilder CipherText = new StringBuilder(PlainText.Length);
Encrypt(PlainText, CipherText);

您注意到您调用的函数不会返回任何错误。这并不奇怪,因为它没有这样做的机制。

为什么你的代码现在开始出现错误?您已经切换操作系统,这似乎已经引发了变化。但所有这一切都意味着你的代码一直都是错误的,而你现在才开始使用它。您正在使用的新版操作系统的行为与您的错误代码不同。


在您进行各种更新后,问题中的代码现在是正确的。这让我怀疑Delphi代码确实返回空字符串。在这种情况下,逻辑结论是cipher.Encrypt返回空字符串。尝试用这个函数替换Delphi代码来测试接口:

procedure Encrypt(szPlainText: PChar; szCipherText: PChar); stdcall;
begin
  StrPCopy(szCipherText, szPlainText);    
end;