CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 4 of 4

Hybrid View

  1. #1
    Join Date
    May 2012
    Location
    London
    Posts
    4

    Error 998 when acessing variable from unmanaged code second time

    Sorry wrong forum - I have reposted to .Net / c sharp forum - sorry

    I am accessing a third party DLL that drives a USB device. The first time I access the DLL I can receive the results of the activity on the device without a problem. If I run the same test again I receive a null value and GetLastError is 998 (error_noaccess).

    The first time I run the test after a reboot I am consistently able to access the variable - the next time I run the test I cannot. Rebooting appears to be the only way to resolve the issue - restarting the application or the development environment do not resolve this issue.

    I am using .net 3.5 running in SharpDevelop.

    Here is the code:

    I wrote a wrapper class for all the calls to the USB driver:
    Code:
    public class USBWrapper
    {
     	[DllImport("USBDriver", CallingConvention= CallingConvention.StdCall)]
     	public static extern Boolean InitUSB();
    	 	
     	[DllImport("USBDriver", CallingConvention= CallingConvention.StdCall)]
     	public static extern Boolean CloseUSB();
    	 	
     	[DllImport("USBDriver", CallingConvention= CallingConvention.StdCall)]
     	public static extern Boolean USBSendCommand(byte Cmd);
    	 	
    	[DllImport("USBDriver", EntryPoint = "USBReadData", CallingConvention= CallingConvention.StdCall, SetLastError = true)]
    	Public static extern Boolean USBReadData(byte EPNumber, long BytesToRead, short[] DataBuffer);
    
    
    	//Codes sent to the device
    	public const byte Start_TEST = 0x00;
    }
    Here is the class that calls the wrapper:
    Code:
    public class USBDevice : IDisposable
    {
    	public bool startUSBDevice(){
    		try {
    			return USBWrapper.InitUSB();
    		} catch (Exception) {
    			return false;
    		}
    	}
    				
    		
    	public byte[] startTest(){
    		int lengthOfStructure = 3;
    		byte[] test;
    		test = sendCommandToDevice(USBWrapper.Start_TEST, lengthOfStructure);
    		return test;
    	}
    		
    		
    	internal byte[] sendCommandToDevice(byte commandToSend, int arrayLength){
    		byte[] arrayForReturnValues = new byte[arrayLength];
    		if (USBWrapper.USBGetCommand(commandToSend,arrayLength, arrayForReturnValues)) {
    			return arrayForReturnValues;
    		} else {
    			throw new Exception("Failed to read command data from device.");
    		}		
    	}
    		
    	public void getTestResults(){
    		try {
    			readDataFromDevice( 57 );
    		} catch (Exception e) {
    			System.Diagnostics.Debug.Print(e.Message);
    		}	
    	}
    	
    	internal void readDataFromDevice(long length){
    		short[] results = new short[57]; 		
    		if (USBWrapper.USBReadData(1, length, results) == true) {
    			System.Diagnostics.Debug.Print("I can read the test results.");
    		}else{
    			System.Diagnostics.Debug.Print(Marshal.GetLastWin32Error().ToString());
    			throw new Exception("Could not read test results.");
    		}
    	}
    	public void Dispose(){
    		killUSBDevice();
    	}
    
    	public bool killUSBDevice(){
    		try {
    			return USBWrapper.CloseUSB();
    		} catch (Exception) {
    			return false;
    		}
    	}
    }
    Here is the nominal function that initiates the test (I've collapsed it to make reading easier):
    Code:
    public static void Main(){
    	byte[] testStart;
    	USBDevice device = new USBDevice();
    
    	device.startUSBDevice();
    	byte[] testStart = device.startTest();
    //wait until you know that the test is complete in here	
    	device.getTestResults();
    	device.killUSBDevice();
    	device=null;
    	GC.Collect();
    	GC.WaitForPendingFinalizers();
    			
    }
    The first time I run it I get an output saying: "I can read the test results.". The next time (and every subsequent time) I run it I get: "Could not read test results.".

    Any ideas about how to fix this would be greatly appreciated.

    Thanks
    Last edited by OptiDev; July 8th, 2012 at 01:44 AM. Reason: Wrong forum

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Error 998 when acessing variable from unmanaged code second time

    Something is wrong here:
    Code:
    internal void readDataFromDevice(long length){
    		short[] results = new short[57];
    Shouldn't what you see in red be "length" and not 57?

    Googling that function you're calling (USBReadDataWithArray) gives no results, so no one knows what that function does or have any description of the arguments, return type, etc. Since this is the function giving the problem, please post the docs to this function. If it's a third party library, then contact the authors and have them solve the problem.

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 7th, 2012 at 03:57 PM.

  3. #3
    Join Date
    May 2012
    Location
    London
    Posts
    4

    Re: Error 998 when acessing variable from unmanaged code second time

    Hi Paul

    Thanks for response. You are right - the 57 should be length - I used 57 there because according the documentation that is the maximum size for the returned array - I've been trying lots of things to get it to work.

    The function call is defined in the header file as:

    BOOL WINAPI USBReadData(BYTE Endpoint,DWORD BytesToRead,PBYTE DataBuffer);

    I have tried various methods of calling this (using a buffer, using a pointer to the memory and using a defined struct) but using the array seems to be the only way that I can get it to work.

    I tried to contact the third party and they told to me write the app in VB 6 despite the fact that MS no longer supports VB 6 - when I pointed this out they had no further suggestion.

    The documentation has this to say:
    EndPoint: number of the reception endpoint - is always 1.
    BytesToRead: Number of bytes expected
    DataBuffer: Pointer to the data to be received. The number of bytes is defined by the parameter BytesToRead.

    
    

  4. #4
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Error 998 when acessing variable from unmanaged code second time

    Quote Originally Posted by OptiDev View Post
    The function call is defined in the header file as:

    BOOL WINAPI USBReadData(BYTE Endpoint,DWORD BytesToRead,PBYTE DataBuffer);

    I have tried various methods of calling this (using a buffer, using a pointer to the memory and using a defined struct) but using the array seems to be the only way that I can get it to work.
    I believe you defined your parameters incorrectly when you translated to C#.
    I tried to contact the third party and they told to me write the app in VB 6 despite the fact that MS no longer supports VB 6 - when I pointed this out they had no further suggestion.
    The DLL seems to be a generic one, i.e. language neutral. Unfortunately you're probably using a language (C#) that the developers are not familiar with. Therefore you're responsible to create the correct pinvoke signature, and I don't believe you did. This seems more appropriate:
    Code:
    [DllImport("USBDriver", EntryPoint = "USBReadData", CallingConvention= CallingConvention.StdCall, SetLastError = true)]
    	Public static extern int USBReadData(byte EPNumber, uint BytesToRead, ref byte DataBuffer);
    The second parameter is a DWORD which is equivalent to "uint", and a PBYTE is translated to "ref byte".

    Please get the pinvoke utility here:

    http://clrinterop.codeplex.com/releases/view/14120

    Regards,

    Paul McKenzie
    Last edited by Paul McKenzie; July 17th, 2012 at 08:01 PM. Reason: Return type should be int, not Boolean

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured