2012-05-31 46 views
4

我正在將最初寫入vb6的應用程序轉換爲vb.net。這個應用程序做的一件事是它發送一個「Type」對象到一個dll。我試圖將類型轉換爲一個結構和p /調用dll,但它似乎並沒有工作。我已經堅持了一個星期的任何幫助將非常感激將vb6類型轉換爲VB.net或C#結構

這裏是該類型

'Define WICS Communications Control Block (CCB). 
Type WicsCCBType ' Create user-defined type. 
    CCBNum As String * 1 
    CCBVer As String * 1 
    Resp1 As String * 4 
    Resp2 As String * 4 
    PLUA As String * 8 
    LLUA As String * 8 
    Mode As String * 8 
    ReqMax As String * 5 
    ResMax As String * 5 
End Type  

VB6的代碼,並在這裏是DLL是如何調用

Private Declare Sub WICSRASP Lib "wicsrasp.dll" (MyWicsCCB As WicsCCBType) 
WICSRASP MyWicsCCB 

這是我用vb.net試過但它不起作用

'Define WICS Communications Control Block (CCB). 
    <System.Runtime.InteropServices.StructLayoutAttribute(_ 
      System.Runtime.InteropServices.LayoutKind.Sequential, _ 
      CharSet:=System.Runtime.InteropServices.CharSet.[Unicode])> _ 
    Structure WicsCCBType ' Create user-defined type. 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=1)> Dim CCBNum As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=1)> Dim CCBVer As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=4)> Dim Resp1 As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=4)> Dim Resp2 As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim PLUA As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim LLUA As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=8)> Dim Mode As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=5)> Dim ReqMax As String 
     <MarshalAs(UnmanagedType.ByValTStr, sizeconst:=5)> Dim ResMax As String 
    End Structure 

這裏是我試圖稱之爲的地方

<System.Runtime.InteropServices.DllImportAttribute("C:\windows\system32\wicsrasp.dll")> _ 
    Public Shared Sub WICSRASP(
        ByRef CCB As WicsCCBType, 
        ByRef Request As DAWicsRequestType, 
        ByRef Response As DAWicsResponseType) 
    End Sub 

Dim CCB As New modWICSDiary.WicsCCBType() 
CCB.CCBNum = "B" 
      CCB.CCBVer = "2" 
      CCB.LLUA = "  " 
      CCB.Mode = "CICSMO2 " 
      CCB.ReqMax = "2100 " 
      CCB.ResMax = "2100 " 
      CCB.Resp1 = "0 " 
      CCB.Resp2 = "0 " 
      CCB.PLUA = "WICSPLU " 

    NativeMethods.WICSRASP(CCB) 

至於價值觀,相同的值提前

+0

你需要更加努力。提供它如何完全失敗。 –

+0

說實話,你不應該試圖創建一個.NET版本的VB6結構,你應該創建一個傳遞給WICSRASP的C數據結構的.NET版本。如果你有這個文件(比如頭文件),那麼這會更容易。 – tcarvin

回答

1

我不知道OP是否已經解決了這個問題,但這裏是我的看法。

VB6中的UDT中的固定長度字符串不會編組爲指針,而是內聯到結構中。另外,在編組之前,VB6將Unicode轉換爲Ansi。而VB6使用4字節對齊方式。

該類型將在內存中使用填充來查看此內容,每個連續的字段在圖中均被命名爲A到I,並且_由於對齊而成爲填充字節。

CCBNum As String * 1  
| 
|+-CCBVer As String * 1  
|| 
|| Resp1 As String * 4 
|| | 
|| | Resp2 As String * 4  
|| | | 
|| | | PLUA As String * 8  
|| | | | 
|| | | |  LLUA As String * 8  
|| | | |  | 
|| | | |  |  Mode As String * 8  
|| | | |  |  | 
|| | | |  |  |  ReqMax As String * 5  
|| | | |  |  |  | 
|| | | |  |  |  |  ResMax As String * 5 
|| | | |  |  |  |  | 
|| | | |  |  |  |  | 
VV V V V  V  V  V  V 

AB__CCCCDDDDEEEEEEEEFFFFFFFFGGGGGGGGHHHHH___IIIII___ 

因此字符集應該是ANSI,所述StructAlignment應4.使用ByValTString的是好的,由於是採用SizeConst的。

+0

謝謝你解決了這個問題 – user889829

1

VB6的將「元帥」所有這些字符串元素作爲ANSI字符串VB6的類型

再次感謝你的工作。相應地更改Vb.Net編組代碼。

  • 試試UnmanagedType.LPStr在那些MarshalAs屬性?
  • 嘗試將CharSet從Unicode更改爲Ansi?
  • 嘗試Pack=4StructLayoutAttribute

有用的鏈接,解釋了Declare

+0

當我嘗試獲取異常(當我調用dll方法時)「嘗試讀取或寫入受保護的內存,這通常表示其他內存已損壞。」 – user889829

+0

我認爲我在編輯答案,當您發佈該評論!你是否嘗試過更改字符集? – MarkJ

+0

嘗試在'StructLayoutAttribute'中包含'Pack = 4'? – MarkJ

0

VB6使用BSTRs的VB6所做的假設,不是嗎?你不應該當BSTR嗎?

+0

當使用Declare調用DLL時,VB6將Unicode轉換爲ANSI。 http://vb.mvps.org/tips/vb5dll.asp – MarkJ

+0

Dan Appleman剛剛查找了我的「Moving to VB.NET」。他說:「事實上,在你調用帶有字符串參數的Win32 API函數的任何情況下,你都會聲明字符串ByVal As String ... VB.NET在Declare語句中提取一個快速的函數...換句話說,這是VB.NET保持語法與VB6兼容的地方。「 – SSS

+0

總結他更詳細的解釋,顯然VB.NET在傳遞之前創建了字符串的副本,即使您已經聲明瞭ByVal。 – SSS