NI TestStand

cancel
Showing results for 
Search instead for 
Did you mean: 

Add C/C++ DLL step for "PlaySound" (winmm.dll)

Solved!
Go to solution

I've been digging through the examples and forum to try to find my answer, but haven't come up with a solution yet.

 

I currently have a DLL that has a call to the Windows system "winmm.dll" (Windows\System32 directory) into an ActiveX step adapter, I can play a sound. (used C# and VB 6 code in the past)

  I use it mostly to play a sound to indicate that my code has hit a "Failed" step for debugging.

 

I'm trying to re-organize my test systems to make them (there are 2 independent systems) so that I can check them into TFS (source control) and allow them to be absolute path independent, using only relative paths for all of the sequence and DLL calls.

 

The problem that I have is that I use the same Process Model for both, and I don't want to have an absolute path the the DLL that contains the "Play Sound" function in the DLL.  The Process Model is called by TestStand on the top of the stack.

 

I've been trying to access the "winmm.dll" to play the sound and the "mciexecute" function, but I can't get the step configured in my Process Model ProcessModelPostStepFailure subsequence.

 

When configuring the Action step (as a "C/C++ DLL adpapter, to the dll, I keep hitting roadblock in that I get errors.

  How do I configure this adapter to match the function calls to the "mciexecute".

 

C# Code uses System.Media.SoundPlayer reference:

//This is called by TestStand
public static void PlaySound(String Path)
{
SoundPlayer spWave = new SoundPlayer(Path);
spWave.Play();
}

 

and VB 6 code is:

Private Declare Function mciExecute Lib "winmm.dll" (ByVal FileName As String) As Integer

'# Function to Play a sound. Used for Error reporting, or whatever.
Public Function Sound(ByVal FileName As String) As Integer
'Arg: Filename is the full path to a .WAV file to play.
'Play the sound
Sound = mciExecute("Play " & FileName)
End Function

 

Can this be done through an adapter step in TestStand?

  How do I mock up the adapter call correctly for the 'mciExecute" function?

 

Mike

0 Kudos
Message 1 of 7
(6,311 Views)

Hi Mike,

 

You won't be able to directly call those two functions of winmm.dll in TestStand's C/C++ adapter because TestStand does not handle the parameter types expected for those two functions. If you use the DLL you have been using, what is preventing you from using relative paths? As long as the DLL is in one of the search directories, TestStand should be able to locate it with relative paths.

Humphrey H.
Applications Engineer
National Instruments
0 Kudos
Message 2 of 7
(6,294 Views)
Solution
Accepted by topic author Mikef

Humphrey is incorrect. You can call this dll directly from TestStand. Most function prototypes can be called directly from TestStand. You will however have to manually specify the prototype since the dll does not have type information from which TestStand can automatically get the prototype. Just specify the prototype as shown in the file screenshot1.jpg (return value is a 32-bit integer, parameter is a const C string). You can also call the .NET API directly from the .NET adapter as shown in the file screenshot2.jpg

 

 

Download All
0 Kudos
Message 3 of 7
(6,287 Views)

I stand corrected. 

Humphrey H.
Applications Engineer
National Instruments
0 Kudos
Message 4 of 7
(6,264 Views)

Dug9000,

 

I gave both examples a try.

  The first, using the C/C++ DLL kept giving me an error:

    "The specified command requires an alias, file, driver or device name. Please supply one."

I tried all kinds of different forms of the string, including null terminated, and passing in from a Locals.sString variable, but no go.

 

The other example, using the .NET call was able to parse correctly (return value as an object) but won't play the .WAV file.

   Sure seems like it should...  Essentially, it's the same call that I have in my originall C# DLL.

 

I'm befuddled. 

 

I'm curious (if I can get this to work) would a person be able to make any call to the functions in the .NET library in a similar manner?

  

Thanks for the suggestion though.

 

Mike

 

0 Kudos
Message 5 of 7
(6,238 Views)

@Mikef wrote:

Dug9000,

 

I gave both examples a try.

  The first, using the C/C++ DLL kept giving me an error:

    "The specified command requires an alias, file, driver or device name. Please supply one."

I tried all kinds of different forms of the string, including null terminated, and passing in from a Locals.sString variable, but no go.

 

The other example, using the .NET call was able to parse correctly (return value as an object) but won't play the .WAV file.

   Sure seems like it should...  Essentially, it's the same call that I have in my originall C# DLL.

 

I'm befuddled. 

 

I'm curious (if I can get this to work) would a person be able to make any call to the functions in the .NET library in a similar manner?

  

Thanks for the suggestion though.

 

Mike

 


What might be happening is that you might not be specifying the file path correctly. If you are directly specifying the file path in the parameter expression as a string literal then you need to escape the backslashes (e.g. "C:\\dir1\\dir2\\file.wav"). If you are creating a local string variable then you don't need to escape the backslashes when setting the variable (i.e. Locals.MyPath should be set to C:\dir1\dir2\file.wav).

 

>> I'm curious (if I can get this to work) would a person be able to make any call to the functions in the .NET library in a similar manner?

 

Yes, you can call into the .NET framework assemblies directly using the .NET adapter. You just need to know which assembly the class you are using is located in. Most are either in System or mscorlib. Microsoft's documentation on MSDN usually says what module a class is from. For large amounts of .NET code though I would still recommend creating a .NET assembly to do the work and calling that from TestStand rather than creating a bunch of .NET steps.

 

-Doug

0 Kudos
Message 6 of 7
(6,226 Views)

I finally got back to working on the problem (vacation) and found that I hadn't enter ALL of the ".NET Invocation:"

 

I had "SoundPlayer(System.String)"

   but needed to add the "SoundPlayer(System.String).Play()

Missed that detail.

 

Works OK, Thanks.

 

Mike

0 Kudos
Message 7 of 7
(6,132 Views)