NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

API testStand for ModuleAdpater DotNet

Hi Manooch H and Juergen

 

I'm sorry, I've made a mistake in my last post.

It works with TesStand 3.1 and 3.5

It doesn't work with TestStand 4.x

 

In TestStand 4.x, the LoadMemberInfo() method is not working as suspected, like said Juergen.

 

For example, if you do this after having called the LoadMemberInfo() method :

 

tsApiErrChk(TS_DotNetModuleGetParameters (hStepModule, &errorInfo, hTSParametersList), TS_ERROR);

tsApiErrChk(TS_DotNetParametersGetCount (hTSParametersList, &errorInfo, lNbParam), TS_ERROR);

 

With TestStand 4.x, in my example, lNbParam is always equals to 0.

 

Anthony

 

Message 31 of 42
(1,760 Views)

I've verified that LoadMemberInfo does not do anything in TestStand 4.0 and higher. LoadPrototypeFromMetadataToken is required instead. You can get the metadata token using the .NET reflection API. It is a property of the MemberInfo class (and classes dervived from it such as MethodInfo) used by the reflection API.

 

Here is an example of getting member info for a particular member of a class:

 

// Your assembly containing the type must be loaded in the current appdomain.

// Examples of loading an assembly:

// Assembly myAssembly = Assembly.Load("MyassemblyNameOrStrongName"); // this will work if it's in the GAC or application base path

// Assembly myAssembly = Assembly.LoadFrom("C:\\myassembly\\fullpathname.dll"); // this is equivalent to how the adapter loads assemblies specified by path

 

// Once your assembly is loaded  you can do one of the following to get the type for the class:

// For more information see:

// http://msdn.microsoft.com/en-us/library/w3f99sx1.aspx

// http://msdn.microsoft.com/en-us/library/y0cd10tb.aspx

 

Type classType = myAssembly.GetType("MyNamespace.MyClassname");

Type classTypeOtherWay = Type.GetType("MyNamespace.MyClassname, MyAssemblyName");

 

// Now get the member info

// Note we really get back an array of members because of the possibility of overloads so consider that if needed.

// For more info: http://msdn.microsoft.com/en-us/library/xdtchs6z.aspx

 

MemberInfo[] myMembers = classType.GetMember("MyMemberName");

if (myMember.Length > 0)

    metadatatoken =  myMembers[0].MetadataToken;

 

Hope this helps,

-Doug

0 Kudos
Message 32 of 42
(1,758 Views)

Hello everybody.

 

I am a colleague of Anthony (the topic's creator) and I am using the CVI DLL to generate TestStand steps, and especially DotNet steps.

Actually, the CVI DLL has been created using the TestStand 4.2 API.

 

The problem is that I want to generate steps calling functions into a DotNet 4.0 DLL (it works well with a DotNet 3.5 DLL ).

And the 4.2 API does not allow this.

 

SeqEditor.exe of TestStand needs an additional configuration file to be able to do that. But into my CVI DLL, I don't how I can do.

 

Here are the actions I have done:

1/ Modify the references (of mscorlib.fp, tsadpcvi.fp, tsapicvi.fp and tsutil.fp) into the CVI project to target the TestStand 2010 files

2/ Modifiy the included header and source of mscorlib2 to get the TestStand 2010 ones

 

I tried to use the generated DLL and here is the error I get:

"The target invoked by the LabWindows/CVI .NET Library threw an exception" (Code: -6571)

 

The CVI debugging gave me this error:

NON-FATAL RUN-TIME ERROR: "c:\...\CVI90\samples\dotnet\mscorlib2.c", line 214316, col 5, thread id 0x000018B8:
Function CDotNetInvokeGenericStaticMember: (return value == -6571 [0xffffe655]).

 

Which is located into the following System_Reflection_Assembly_LoadFrom function (at the "__errChk(CDotNetInvokeGenericStaticMember"):

 

int CVIFUNC System_Reflection_Assembly_LoadFrom(
    char * assemblyFile,
    System_Reflection_Assembly * __returnValue,
    CDotNetHandle * __exception)
{
    int __error = 0;
    char * __parameterTypeNames[1];
    unsigned int __parameterTypes[1];
    void * __parameters[1];
    unsigned int __returnValueTypeId;

    if (__exception)
        *__exception = 0;
    if (__returnValue)
        *__returnValue = 0;


    // Pre-process parameter: assemblyFile
    __parameterTypeNames[0] = "System.String";
    __parameterTypes[0] = (CDOTNET_STRING);
    __parameters[0] = &assemblyFile;

    // Pre-process return value
    __returnValueTypeId = CDOTNET_OBJECT;

    // Call static member
    __errChk(CDotNetInvokeGenericStaticMember(
        __assemblyHandle, 
        "System.Reflection.Assembly", 
        0, 
        0, 
        CDOTNET_CALL_METHOD, 
        "LoadFrom", 
        0, 
        0, 
        1, 
        __parameterTypeNames, 
        __parameterTypes, 
        __parameters, 
        &__returnValueTypeId, 
        __returnValue, 
        __exception));


__Error:
    if (__error < 0) {
        _CDotNetGenDisposeScalar(
            __returnValue, 
            CDOTNET_OBJECT);
    }
    return __error;
}

 This function is called into mscorlib2:

Initialize_mscorlib ();

errChk (System_Reflection_Assembly_LoadFrom (sModulePath, &reflectionAssembly, &hException));
errChk (System_Reflection_Assembly_GetType_1 (reflectionAssembly, sClassName, &type, &hException));

 

Do you have any idea to help me?

 

Michael

0 Kudos
Message 33 of 42
(1,425 Views)

A few things to consider

 

1) You cannot use the TestStand 2010 APIs with TestStand 4.2 (i.e. using the TestStand 2010 versions of tsadpcvi.fp, tsapicvi.fp and tsutil.fp doesn't make sense unless you are using TestStand 2010). Are you using TestStand 2010 or TestStand 4.2?

2) If you are using TestStand 2010 there are now newer APIs for specifing .NET modules that are much easier to use and don't require any .NET code on your end. You might want to consider using these newer APIs instead

3) If you are using TestStand 4.2, we do not support using .NET 4.0 with versions of TestStand earlier than TestStand 2010.

4) The config file used to tell a process to use .NET 4.0 even though it is a .NET 2.0 application applies to the whole process including dlls that are loaded.

 

Hope this helps,

-Doug

0 Kudos
Message 34 of 42
(1,421 Views)

Thanks Doug.

Here are my answers.

 

1) Actually, I create a DLL which uses TestStand 4.2 API.

So, I can create Sequence files which can be opened by TestStand 4.2 and 2010.

 

The previous error is raised at the step creation (calling a DotNet 4.0 module), when I try to create a Sequence file with my DLL.

And this with both DLLs (one compiled with *.fp from TestStand 4.2 and the other one compiled with *.fp from TestStand 2010).

 

2) Maybe this can be a solution. Perhaps I have to create a TestStand 2010 DLL using this newer API (instead of simply replacing the *.fp from TestStand 4.2 to TestStand 2012). What do you think about this?

 

3) / 4) This config file allow using TestStand 4.2 to read and execute Sequence file containing DotNet 4.0 steps.

But, in my case, the error comes at the DotNet 4.0 step creation (from the DLL).

 

Michael

0 Kudos
Message 35 of 42
(1,408 Views)

I'm still not all that clear on what you are doing, but here is some information that might be helpful.

 

a) Are you using an app config file with the sequence editor in order to load .NET 4.0 assemblies? (Again note that this is not supported with TestStand 4.2). What .exe is calling your dll? seqedit.exe or something else? If it's something else then that .exe likely also needs an app config file to force the process to use .NET 4.0.

b) Have you looked at the exception returned by LoadFrom? That should tell you exactly why it failed. There was likely a load error of some sort and the exception parameter should contain the details of that error.

c) Nothing linked against the TestStand 2010 .fp's should ever be called from earlier versions of TestStand. If you want something to be called from both 4.2 and 2010 you should only link against the 4.2 .fp files. NOTE: It can work to use the 2010 .fps in 4.2, but you have to be very careful not to call any apis that don't exist in 4.2 or it will crash and potentially corrupt memory.

d) .NET 2 - 3.5 use what is called the .NET 2.0 clr (Common language runtime). .NET 4.0 uses a new clr (i.e. the .NET 4.0 clr). TestStand 4.2 only supports the .NET 2.0 clr. TestStand 2010 supports the .NET 4.0 clr with the use of an app config file as described in the documentation.

 

Hope this helps,

-Doug

0 Kudos
Message 36 of 42
(1,403 Views)

Thank you for support.


a) I am using an external EXE which calls the DLL (compiled from a CVI project) to create a Sequence file with steps calling DotNet 4.0 modules.

You say that this EXE also needs a config file, but is it the same as seqedit.exe.config?

 

b) Here is the error content (it is raised at the NewStep call from the DLL):

cvi_error.png

So, there seems to be a problem at the NewStep loading

 

c) If I understand well, I have to create the DLL with TestStand 4.2 *.fp files. And then, I have to use the config file introduced in a) ?

 

d) "TestStand 2010 supports the .NET 4.0 clr with the use of an app config file as described in the documentation"

You meant TestStand 4.2, no?

 

Michael

0 Kudos
Message 37 of 42
(1,398 Views)

a) Yes, this might be the source of the problem. Copy seqedit.exe.config to the directory of your external exe and rename it to yourexename.exe.config

 

b) The loadfrom function you are calling returns more info in the exception parameter, you will need to use CVI's .net apis to get more info out of that exception. You should look at the Message property of the exception for more details.

 

d) No. Although it might work in some cases, we do not support using .NET 4.0 with TestStand 4.2. If it's working ok for you in the cases you care about then it is up to you, however .NET 4.0 is not officially supported by TestStand until TestStand 2010.

 

-Doug

0 Kudos
Message 38 of 42
(1,390 Views)

a) I tried to use this config file (found here: http://www.ni.com/pdf/manuals/373435e.pdf#page=96&zoom=100) near my EXE and with my DLL (compiled with TestStand 4.2 API). But it does not change anything (same error).

 

b) I have added the following code, just after the CDotNetInvokeGenericStaticMember call (into System_Reflection_Assembly_LoadFrom) :

if (hException != NULL)
{
    CDotNetGetExceptionInfo (hException, NULL, &message, &source, &trace, NULL, NULL);	
    printf ("Exception occurred!\n" 
        "\tThe message is %s\n" 
        "\tThe source is %s\n" 
        "\tThe stack trace is %s\n", message, source, trace); 
    CDotNetFreeMemory (message); 
    CDotNetFreeMemory (source); 
    CDotNetFreeMemory (trace); 
    CDotNetDiscardHandle (hException); 
}

 But, it closes my application. Note that I have declared message, source and trace...

 

d) Ok, thank you for this information.

 

Michael

0 Kudos
Message 39 of 42
(1,380 Views)

I have corrected an error into my program which causes the previous error (sorry for this).

 

After this, I executed another time and here is the output of my debugger:

CLR:(C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System.Xml\v4.0_4.0.0.0__b77a5c561934e089\System.Xml.dll) 
Rejecting native image because dependency C:\Windows\Microsoft.Net\assembly\GAC_MSIL\System\v4.0_4.0.0.0__b77a5c561934e089\System.dll is not native

There is no exception raised.

 

What is OK is that I haven't any error.

The created Sequence File can be opened by TestStand 2010 (using SeqEdit.exe.config).

 

I have to do other tests to be sure.

Thank you for your help.

 

Michael

0 Kudos
Message 40 of 42
(1,373 Views)