“类型不匹配";从COM +(VBScript)访问ref返回的数组时出错 [英] "Type Mismatch" error when accessing array returned by ref from COM+ (VBScript)

查看:47
本文介绍了“类型不匹配";从COM +(VBScript)访问ref返回的数组时出错的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个正在作为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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆