PRB: Script Error Occurs When Referencing Non-variant Array (165967)
The information in this article applies to:
- Microsoft Visual Basic, Scripting Edition 1.1
- Microsoft Visual Basic, Scripting Edition 2.0
- Microsoft Visual Basic, Scripting Edition 3.0
- Microsoft JScript 1.0
- Microsoft JScript 2.0
- Microsoft Internet Explorer (Programming) 4.0
- Microsoft Active Server Pages
This article was previously published under Q165967 SYMPTOMS When a script attempts to reference the elements of an
array returned by a component, the script engine reports: "Object doesn't support this property or method
'<object>.<method>'" CAUSE The VBSCRIPT active scripting engine supplied by Microsoft
only supports the indexing of SAFEARRAYs of VARIANTs. While VBSCRIPT is capable
of accepting arrays of non-variant type for the purposes of boundary checking
and passing it to other automation objects, the engine does not allow
manipulation of the array contents at this time.
The JSCRIPT active
scripting engine does not provide support for testing the bounds or indexing
SAFEARRAYs of any type including VARIANTs. However, JSCRIPT is capable of
passing SAFEARRAYs from one automation object to another. RESOLUTION To function correctly with applications and components that
host VBSCRIPT, automation objects should create SAFEARRAYs of VARIANTs.
Non-VARIANT data should be packaged in the VARIANT elements of the SAFEARRAY to
be returned to the VBSCRIPT engine.
Scripts written in VBSCRIPT
should use the TypeName function to check the data type of a variable. The
TypeName function returns the string "Variant()," excluding the quotes, when
passed an array of VARIANTs.
Scripts written in JSCRIPT should use
the typeof operator to test the data type of a variable. The typeof operator
returns the string "unknown," excluding the quotes for datatypes unsupported by
JSCRIPT. STATUS This behavior is by design. MORE INFORMATION The VBSARRAY is a simple Active Template Library (ATL)
version 2.1 component object that demonstrates this behavior. The component
implements a dual interface Ivbsa that supports three methods: TestBstrs,
TestVariants, and TestPassArray. The first demonstrates the problem by
returning a SAFEARRAY of BSTRs. The second demonstrates the solution by
packaging each of the BSTRs in a VARIANT. The third demonstrates that an array
of non-VARIANT type can be passed from component to VBSCRIPT or JSCRIPT to
component. The data remains intact. Here is the implementation of
TestVariants:
// Return a VARIANT array of VARIANTs which hold BSTRs
STDMETHODIMP Cvbsa::TestVariants(VARIANT * pvaVariant)
{
HRESULT hr = NOERROR;
LPSAFEARRAY psa;
SAFEARRAYBOUND rgsabound[] = { 3, 0 }; // 3 elements, 0-based
int i;
if (!pvaVariant)
{
return E_INVALIDARG;
}
VariantInit(pvaVariant);
psa = SafeArrayCreate(VT_VARIANT, 1, rgsabound);
if (!psa)
{
return E_OUTOFMEMORY;
}
VARIANT vFlavors[3];
for (i = 0; i < 3; i++)
{
VariantInit(&vFlavors[i]);
V_VT(&vFlavors[i]) = VT_BSTR;
}
V_BSTR(&vFlavors[0]) = SysAllocString(OLESTR("Vanilla"));
V_BSTR(&vFlavors[1]) = SysAllocString(OLESTR("Chocolate"));
V_BSTR(&vFlavors[2]) = SysAllocString(OLESTR("Espresso Chip"));
if (!V_BSTR(&vFlavors[0]) || !V_BSTR(&vFlavors[1]) ||
!V_BSTR(&vFlavors[2]))
{
hr = E_OUTOFMEMORY;
goto Error;
}
{
//Plug references to the data into the SAFEARRAY
LPVARIANT rgElems;
if (FAILED(hr = SafeArrayAccessData(psa,(LPVOID*)&rgElems)))
{
goto Error;
}
for (i = 0; i < 3; i++)
{
rgElems[i] = vFlavors[i];
}
SafeArrayUnaccessData(psa);
}
V_VT(pvaVariant) = VT_ARRAY | VT_VARIANT;
V_ARRAY(pvaVariant) = psa;
return NOERROR;
Error:
for (i = 0; i < 3; i++)
{
if (V_BSTR(&vFlavors[i])
{
VariantClear(&vFlavors[i]);
}
}
return hr;
}
Here is the JSCRIPT code from VBSARRAY.HTM, the test page included with
the sample, that checks the datatype of a variable:
<SCRIPT LANGUAGE=JSCRIPT>
function JScriptSafeArrayTest()
{
pvaBstr = SimpleComponent.TestBstrs()
if (typeof(pvaBstr) == "unknown")
{
Alert("JSCRIPT cannot handle the type returned by TestBstrs()")
SimpleComponent.TestPassedArray(pvaBstr)
}
pvaVariant = SimpleComponent.TestVariants()
if (typeof(pvaVariant) == "unknown")
{
Alert("JSCRIPT cannot handle the type returned by TestVariants()")
SimpleComponent.TestPassedArray(pvaVariant)
}
}
</SCRIPT>
To demonstrate the problem and the solution, perform the following
steps: - Follow the instructions below on obtaining the sample
component VBSARRAY.DLL and sample page VBSARRAY.HTM.
- Register the component VBSARRAY.DLL using a tool such as
REGSVR32.EXE.
- Launch Internet Explorer, and load the test page
VBSARRAY.HTM.
- Follow the instructions on the page, clicking the various
buttons and observing the resulting behavior.
The sample component was created using the Active Template
Library version 2.1 including with Visual C++ 5.0 in the Visual Studio 97
environment. If you have Visual Studio 97, you can load the VBSARRAY project
directly. Otherwise, you can open the relevant source file VBSA.CPP in any
editor to see how the SAFEARRAY is constructed in both the VARIANT and the BSTR
cases. Search for the implementation of both Cvbsa::TestVariants and
Cvbsa::TestBstrs in the source file. The following files are available for
download from the Microsoft Download Center: For
additional information about how to download Microsoft Support files, click the
following article number to view the article in the Microsoft Knowledge Base: 119591 How to Obtain Microsoft Support Files from Online Services
Microsoft scanned this file for viruses. Microsoft used the most
current virus-detection software that was available on the date that the file
was posted. The file is stored on security-enhanced servers that help to
prevent any unauthorized changes to the file.
REFERENCES Platform SDK Automation Reference
Microsoft
Visual Basic Scripting Edition Language Reference
Modification Type: | Minor | Last Reviewed: | 8/5/2004 |
---|
Keywords: | kbdownload kbfile kbprb kbsample KB165967 |
---|
|