2010-07-13 56 views
4

我有一些VB6代碼不能輕易修改,看起來像這樣:VB6變型到.NET類型

Dim cCount as Long 
Dim rCount as Long 
Dim result() 

Set mx = CreateObject("Component.Class") 
Dim rtn = mx.GetList(rCount,cCount,result) 

它會調用該方法是目前我們已經遷移到VB6組件。 NET有一個問題。我們不確定結果()是什麼類型,因爲它是變體類型。我們已經嘗試過對象,對象[],對象[] [],字符串,字符串[]等,其中沒有任何工作。

下面是一個例子:

public bool GetList(ref long rCount, ref long cCount, ref object result) 
{ 
    ... 
} 

我甚至試過設置第三個參數去VariantWrapper因爲它會根據需要添加的ByRef:

public bool GetList(ref long rCount, ref long cCount, VariantWrapper result) 
{ 
    ... 
} 

任何想法我可以設置進入的結果爲了讓我沒有未處理的異常?

我已經創建了一個測試接口(用於COM),測試類和測試VB6應用程序,以確保它是變體的問題。所以,它的定義如下所示:

.NET接口:

[DispId(1)] 
[ComVisible(true)] 
string Test(ref object[] value); 

VB 6方法:

Private Sub Command1_Click() 
    Set mx = CreateObject("Component.Class") 
    Dim result() 
    MsgBox mx.Test(result) 
End Sub 

相同的問題,如上所述。在VB6中,它只是拋出我。如果我編譯並運行它,我會得到一個通用的.NET異常,並將它拋出。

+2

您可以看到'result()'是如何聲明並通過的,但不知道'GetList'返回後如何使用它? – Jay 2010-07-13 19:22:44

+0

因此,當Variant()類型被分配給結果並傳入GetList時,.NET會彈出一個錯誤提示。 – 2010-07-13 19:31:00

+0

添加VariantWrapper會給我一個錯誤5非法過程調用。 – 2010-07-13 19:58:14

回答

1

mx.GetList(rCount,cCount,result)行上放置一個斷點。點擊後,添加一個「快速觀看」表達式mx.GetList(rCount,cCount,result)。 toolwindow應該顯示結果運行時類型是什麼。很可能它是一個「comresult」,並不會提供很多信息,但它可能提供了返回類型的提示。

+0

我修改了代碼,只要它碰到方法,它就會返回一個真正的布爾值。如果我將結果變量切換到不同的類型並在一個快速的VB6測試應用程序中進行測試,它就可以正常工作。 – 2010-07-13 19:49:02

1

我認爲ref關鍵字可能會在這裏造成一些麻煩。類型必須完全匹配才能工作。

但是,如果你的方法只是簡單地接受由任何object參考,(而不是ref)時,它可以通過任何事情,因爲一切從object在.NET中派生的。

這轉換成VB6/COM互操作性,我不知道。但似乎這至少是值得一試:

C#代碼

public string GetTypeName(object value) 
{ 
    return value.GetType().FullName; 
} 

VB6代碼

Set mx = CreateObject("Component.Class") 
Dim result() 

MsgBox mx.GetTypeName(result) 

這是否給你什麼?


這是一個想法。我可能在這裏死了 - 我沒有太多的將VB6應用程序遷移到.NET的經驗 - 但是在我看來,如果你可以得到(C#等價的)這一行......

Set mx = CreateObject("Component.Class") 

...那麼你是金。您可以使用反射來找出GetList方法需要的參數。

首先得到較mx類型的System.Type對象:該類型

Type mxType = mx.GetType(); 

然後找到GetList方法(S):

MethodInfo[] getListMethods = mxType.GetMember("GetList") 
    .OfType<MethodInfo>() 
    .Where(m => m.GetParameters().Length == 3) 
    .ToArray(); 

這會給你一個MethodInfo[]陣列中的所有的公共過載GetList取3個參數。從這裏,可能的類型result將是:

Type[] possibleResultTypes = getListMethods 
    .Select(m => m.GetParameters()[2].ParameterType) 
    .ToArray(); 
+0

這不會起作用,因爲VB6應用程序正在傳遞到C#中。這不是一個問題,我需要在VB6中使用哪些類型,因爲它是在C#中設置COM方法的類型。 VB6類型是Variant()。 C#類型應該是object []或VariantWrapper,這兩者都不起作用。 – 2010-07-13 19:57:34

+0

@Jason:我覺得我很困惑。你是說這是你的VB6代碼拋出異常?你只是想弄清楚如何定義你的C#方法,以便你可以從VB6調用它?或者是倒退? – 2010-07-14 12:27:16

+0

我想弄清楚如何定義我的C#方法,所以我可以從VB6調用它。但是,VB6並沒有拋出異常,而是.NET。調用轉到Interop中的類庫,但由於它是一個.NET程序集,.NET會生成異常。 – 2010-07-14 13:28:35

4

你的C#聲明是錯誤的。由於歷史原因,VB6「長」是32位。這是C#端的一個int。由於堆棧框架錯誤,您無法正確傳遞「結果」參數。

它應該是C#中的變體,object []的SafeArray。

+0

我已將它切換到 bool GetList(ref int rCount,ref int cCount,ref object [] result); 它仍然不起作用。我得到了一個。NET異常馬上。 – 2010-07-13 21:28:25

+0

請不要讓我猜這個例外。 – 2010-07-13 21:32:43

+0

Hans,引發的異常是「Visual Basic產生了一個異常......」它只發生在Variant()類型的結果中。我創建了一個新的.NET方法來測試(下面是我的簽名形式的接口):string Test(ref object [] value);然後,我創建了一個測試VB6應用程序,如下所示:Private Sub Command1_Click()Set mx = CreateObject(「Component.Class」)Dim result()MsgBox mx.Test(result)End Sub與上述相同的問題。正如我最初所描述的那樣,它不喜歡Variant類型。 – 2010-07-13 21:40:10

0

我知道這只是在如何使用的.Net,你傳遞給Variant這樣的引用:

int port = 2; 
object pvPort = new System.Runtime.InteropServices.VariantWrapper(port); 
gimp.SetPort(ref pvPort); 

在此之後,把一個斷點,並檢查變量類型,如果你不知道這件事。

主要是使用VariantWrapper所以DLL知道。