“类型不匹配";从COM +(VBScript)访问ref返回的数组时出错 [英] "Type Mismatch" error when accessing array returned by ref from COM+ (VBScript)
问题描述
我有一个正在作为COM +服务器组件运行的.NET 3.5程序集,我想从VBScript(经典ASP页面)中调用此类中的方法.
I have a .NET 3.5 assembly which is being run as a COM+ server component, and I want to call a method in this class from VBScript (a Classic ASP page).
这是方法概述;
public bool FillArray(ref string[] arrayToFill)
{
...
}
我的VBScript如下;
My VBScript is as follows;
Dim myComponent, result, myArray
Set myComponent = Server.CreateObject("MyComponentProgID")
result = myComponent.FillArray(myArray)
Response.Write("IsArray = " & IsArray(myArray) & "<br/>")
Response.Write("UBound = " & UBound(myArray) & "<br/>")
Response.Write("TypeName = " & TypeName(myArray) & "<br/>")
Response.Write("Element 1 = " & myArray(1))
这将导致以下错误(由我对FillArray的调用所在的行触发);
This results in the following error (triggered by the line where I make the call to FillArray);
错误类型:Microsoft VBScript运行时(0x800A0005)无效的过程调用或参数:"FillArray"
启动OLEView,IDL看起来像这样;
Firing up OLEView, the IDL looks like this;
HRESULT FillArray(
[in, out] SAFEARRAY(BSTR)* arrayToFill,
[out, retval] VARIANT_BOOL* pRetVal);
我尝试将方法签名更改为以下内容;
I tried changing my method signature to the following;
public bool FillArray(ref object[] arrayToFill)
这导致了以下IDL;
Which resulted in the following IDL;
HRESULT FillArray(
[in, out] SAFEARRAY(VARIANT)* arrayToFill,
[out, retval] VARIANT_BOOL* pRetVal);
但仍然是相同的无效的过程调用或参数'FillArray'"错误.
But still the same "Invalid procedure call or argument 'FillArray'" error.
最后,我尝试将方法签名更改为此;
Finally, I tried changing my method signature to simply this;
public bool FillArray(ref object arrayToFill)
哪个给出了以下IDL;
Which gave the following IDL;
HRESULT FillArray(
[in, out] VARIANT* arrayToFill,
[out, retval] VARIANT_BOOL* pRetVal);
现在给出了一个新错误;
This gives a new error now;
Microsoft VBScript运行时(0x800A000D)类型不匹配
Microsoft VBScript runtime (0x800A000D) Type mismatch
现在仅在最后一行触发此错误,这是我尝试访问数组元素的时间.如果我注释掉最后一行,则得到以下输出;
This error is only fired off on the final line now, which is when I try to access an element of the array. If I comment the last line out, then I get the following output;
IsArray = True
IsArray = True
UBound = 39
UBound = 39
TypeName = String()
TypeName = String()
因此,很明显,变体被识别为数组,并且具有正确的类型.此外,UBound返回了正确数量的元素,但是由于某些未知原因,我无法访问任何元素.
So, apparently the variant is being recognised as an array, and of the correct type. Also, the correct number of elements are returned by UBound, but I cannot access any of the elements for some unknown reason.
有人知道这是什么原因吗?我自己做了一些研究,并遇到了以下链接;
Does anyone have any idea what might be causing this? I've done some research myself, and came across the following link;
http://connect.microsoft.com/VisualStudio/feedback/details/331632/marshaler-bug-with-vbscript-arrays
我不是100%地确定这是完全相同的问题,因为我没有在VBScript代码中以相同的方式声明数组.我衷心希望这不是一个相同的问题,因为我没有升级到.NET 4.0的范围.
I'm not 100% certain that it's the exact same issue, as I am not declaring my arrays in the same way in my VBScript code. I sincerely hope it's not the same issue, as I have no scope for upgrading to .NET 4.0.
推荐答案
我设法自己解决了这个问题.
I managed to work this one out myself.
事实证明,VBScript不处理非Variant类型的数组.因此,在我的C#代码中,我尝试了这一点;
It turns out that VBScript does not handle arrays which are not of type Variant. So, in my C# code I tried this;
public bool FillArray(ref object arrayToFill)
{
string[] tmpArrayToFill = (string[])arrayToFill;
...
arrayToFill = (object[])tmpArrayToFill
}
"..."指的是通过ref传递到arrayToFill的其他调用.
The "..." refers to further calls which pass along arrayToFill by ref.
不幸的是,这产生了完全相同的错误.
Unfortunately, this produced the exact same error.
使我走上解决之道的原因是"TypeName()"VBScript函数STILL将该类型视为"String()".我很好奇.NET代码中发生了什么,所以写了一个小测试;
What put me on the path to solving this was that the "TypeName()" VBScript function STILL saw the type as "String()". I was curious what was going on in the .NET code, so wrote a small test;
string[] stringArray = new string[1];
Console.WriteLine(stringArray.GetType());
object[] objectArray = (object[])stringArray;
Console.WriteLine(objectArray.GetType());
产生了以下内容;
System.String []
System.String[]
System.String []
System.String[]
这对我来说是个新闻-我没有意识到会是这种情况.我认为期望Object []作为第二种类型是合理的.
This was news to me - I didn't realise that this would be the case. I thought it reasonable to expect Object[] for the second type.
无论如何,我写了一个小的扩展方法来生成一个新对象[]
Anyway, regardless of that, I wrote up a small extension method to generate a new object[]
public static Array ToObjectArray(this Array input)
{
if (input != null)
{
object[] objArray = new object[input.Length];
input.CopyTo(objArray, 0);
return objArray;
}
else
{
return null;
}
}
这只是一个粗略的第一步-将添加更强大的错误处理和对锯齿状数组的支持.
This is just a rough first go at it - more robust error handling and support for jagged arrays are going to be added.
所以我的代码现在看起来像;
So my code now looks like;
public bool FillArray(ref object arrayToFill)
{
string[] tmpArrayToFill = (string[])arrayToFill;
...
arrayToFill = tmpArrayToFill.ToObjectArray();
}
现在,在VBScript中,TypeName返回 Variant(),我可以按预期访问数组.
And now, in the VBScript, TypeName returns Variant() and I can access the array as expected.
希望这将对将来遇到此问题的其他人有所帮助.
Hopefully this will help anybody else who runs into this problem in the future.
这篇关于“类型不匹配";从COM +(VBScript)访问ref返回的数组时出错的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!