RemoteDirectory.Getfiles issue

Aug 18, 2011 at 10:21 PM

Hey everyone, pretty new to the wrapper and must say so far I've been impressed!

I do, however have issues with the above method.

If I start my desktop app with the device docked it works like a charm, but if I disconnect and reconnect or start the program before connecting I get two different errors:

On d/c and r/c: RapiException: The operation completed successfully

On load before connect: COMException: Interface not registered (Exception from HRESULT: 0x80040155)

This is the code I am having issues with - winCEdev is the Device and all I want to do is get it to look for an .id file in a certain folder to get a id tag:

    Private Function getDeviceTag() As String
        Dim rd As String = Nothing
        Dim rm As String = "Application\GUK"
        Dim fi() As String = RemoteDirectory.GetFiles(winCEdev, rm, "*.id")
        For Each fl As String In fi
            rd = (Split(fl, ".")(0))
        Next
        Return rd
    End Function
Coordinator
Aug 19, 2011 at 3:06 AM
Edited Aug 19, 2011 at 3:07 AM

Is this happening with the 1.3.1 release? If you haven't downloaded in the last couple of days, please get the update which fixes a problem with losing interfaces after a disconnect.

If you have the latest version, then you need to watch the DeviceConnected and DeviceDisconnected events as demonstrated on the Documentation page. Each time there is a connect you need to capture the new RemoteDevice. Each time there is a disconnect you need to dispose of the RemoteDevice instance.

Aug 19, 2011 at 11:16 AM
Edited Aug 19, 2011 at 11:29 AM

Hi

I have the same issue. version 1.3.1

Followed the instructions exactly, I can still get all the device information, but when I call the getFolderPath method it throws an error:

 private void OnConnection(bool connected, RemoteDevice dev)   
{           

this.Connected = connected;
            if (connected)           
{               
this.DeviceId = dev.DeviceId.ToString();               
this.DeviceName = dev.Name;               
           
string deviceProgramFilesDirectory = dev.GetFolderPath(SpecialFolder.ProgramFiles);

}

......

I have downloaded the source to see if I can find more, but unfortunately I have just been summoned to work on some SQL, so will probably only get back to this on Monday.

Thanks

 

edit: Exception information (Removed additional stack trace from my code).

System.Runtime.InteropServices.COMException was unhandled by user code 
Message=Interface not registered (Exception from HRESULT: 0x80040155) 
Source=RAPI2 
ErrorCode=-2147221163 
StackTrace:       
at System.Devices.Interop.IRAPIDevice.CreateSession()       
at System.Devices.RemoteDevice.get__session()       
at System.Devices.RemoteDevice.GetFolderPath(SpecialFolder folder)       

Aug 19, 2011 at 11:58 AM

Here is the vb code for my DeviceConnected and DeviceDisconnected handlers.

    Private Sub devConnect(ByVal sender As Object, ByVal e As System.EventArgs) Handles devConn.DeviceConnected
        If Me.InvokeRequired Then
            Dim dlg As New devConnectDelegate(AddressOf devConnect)
            Dim param() As Object = {Me, Nothing}
            Me.Invoke(dlg, param)
        Else
            winCEdev = devConn.Devices.FirstConnectedDevice
            If winCEdev IsNot Nothing Then
                devStatus.Text = "Scanner Connected: " & getDeviceTag()
                devStatus.ForeColor = Color.DarkGreen
                isAlive = True
                devName = getDeviceTag()
                getDeviceReceipts()
            End If
        End If
    End Sub

    Private Sub devDisconnect(ByVal sender As Object, ByVal e As System.EventArgs) Handles devConn.DeviceDisconnected
        If Me.InvokeRequired Then
            Dim dlg As New devDisconnectDelegate(AddressOf devDisconnect)
            Dim param() As Object = {Me, Nothing}
            Me.Invoke(dlg, param)
        Else
            winCEdev = Nothing
            devStatus.Text = "Scanner Not Connected"
            devStatus.ForeColor = Color.Red
            devName = Nothing
            isAlive = False
        End If
    End Sub

I run the deviceConnected sub in the onLoad to check for an existing device connection - on the assumption it won't pick up a connection that existed before I started up.

I omitted to mention, the device OS is WinCE 5.0....

Aug 19, 2011 at 4:30 PM

Also, yes, this is on the latest version of RAPI2 I downloaded yesterday...

Coordinator
Aug 19, 2011 at 5:48 PM

I don't know if this is a problem, but the RemoteDevice object is not thread-safe or thread-aware. It can only be accessed from the thread on which is was created.

SUPERKEW, does the call to dev.Name work correctly before the failure on dev.GetFolderPath?

Aug 19, 2011 at 6:15 PM

Hi dahall

Yes the call does run correctly every time.

When I run the app for the first time, I run the OnConnection method, and if the device is connected it works.

Then I have the event listener set up as in your sample, and when ever a device is connected the OnConnection is called again.

Strange thing is, that if a device is not connected, and I connect it when the app is running then the GetFolderPath does not work. If the device was connected when the app started then it does work.

Every time I connect the device, the dev.Name works correctly.

I hope this is enough information.

I would be able to give you more source code if required. The device I am using is a Timble and running windows mobile 6.

Aug 20, 2011 at 12:37 PM
Edited Aug 20, 2011 at 12:51 PM

okay, I've re-written the connect/disconnect handlers to reflect the vb equivalent of what is in the RAPI2 doc.

It still won't handle disconnect/reconnect properly, giving RAPIException messages of "Operation completed successfully", but the COMExceptions have now gone if i dock the scanner after starting the program.

I get the same RAPIException error with any RemoteDevice, RemoteDirectory or RemoteFile methods I try to execute.

GetName works correctly every time, just seems to be anything that deals with files on the device that throws the exception.

Desperate to figure out a solution here... I have to give this solution to a customer so can't give them niggly bugs to deal with.

Aug 25, 2011 at 4:01 PM
Edited Aug 25, 2011 at 4:04 PM

I have the same problem, everithing is ok but call RemoteDirectory.GetFiles, the problem there is only after you connect, disconnect and then reconnect the device. The error is the same.
I have the delegates in the events.
With the same code without RemoteDirectory call, Device.Platform and Device.Name, always work properly even if I connect and disconnect many times the device



Aug 30, 2011 at 2:13 AM

I ran into a similar problem, but only on certain devices (a Honeywell 6100 running CE 5.0, for example).

My desktop application downloads files created on the device and on devices exhibiting this issue, it works fine the first time, but after disconnecting and reconnecting, a RAPIException ("Operation completed successfully" !) is thrown when calling RemoteDirectory.GetFiles().

I finally seemed to have worked around this issue as follows:

Catch the RAPIException.

Dispose the RemoteDevice and call FirstConnectedDevice to get another one.

Retry the operation.

I hope that helps someone!

Aug 30, 2011 at 2:16 AM

I was thinking CE5 might be the common denominator - it's the Motorola MT2000 I'm having issues with...

I thought I'd tried disposing and recalling as you say above, but maybe I'm doing it wrong.

If you have a code sample I can use I'd greatly appreciate it :)

Aug 30, 2011 at 7:32 AM

The problem is on CE5 for me too. Calling CeRapiUninit in the disconnect event solved all the problems to me. This is the code I add in VB, I hope this helps fot you too

 

Public Declare Function CeRapiUninit Lib "rapi.dll" () As Integer 

Private Sub DeviceDisconnected()   

CeRapiUninit()   

...

End Sub

Aug 30, 2011 at 4:43 PM

Thanks, Regular!  I read your other thread, but it wasn't obvious to me that these were related.  I invoked CeRapiUninit in my disconnect handler and things appear to be working well.  I know longer need the retry loop that I described yesterday.  Here is what I did:

        [DllImport("rapi.dll")]
        internal static extern int CeRapiUninit();

        void rapi2_DeviceDisconnected(object sender, EventArgs e) {
            CeRapiUninit();
        }

Aug 31, 2011 at 2:17 PM
Edited Aug 31, 2011 at 3:11 PM

Hi peep

 

I have narrowed down my issue but still not resolved it. For now I have taken the RAPI project and included it into my solution so it is easier to debug.

I ran the test app, and the gui app in the source code and it works. The forms app also works perfectly.


My problem is that I am working in WPF, and .NET 3.5. My error happens when re-connecting the device and trying to get file information. I have got it down to this method in the RAPI project.

 

internal IRAPISession _session
		{
			get
			{
				if (iSession == null)
				{
					iSession = iDev.CreateSession();
					iSession.CeRapiInit();
				}
				return iSession;
			}
		}

 

The iDev is not null, but the error happens on the CreateSession() method. 

This is the error: Interface not registered (Exception from HRESULT: 0x80040155).

Google isn't really a help. But I will keep trying.

If anyone has insight into this, it would be greatly appreciated!

 

EDIT: I think this is a threading issue. I noticed that if I change

 

this.Invoke(new BoolMethod(this.OnConnection), true);

 

to

 

 OnConnection(true);

then the sample application also breaks.

 

Sep 1, 2011 at 10:55 AM
Edited Sep 1, 2011 at 10:56 AM

I have resolved the problems on my side with a bit of a hack.

I am pretty sure it is to do with threading, and WPF.

When I had the event handler set up to listen for the device to be connected I would always receive the problem. So I removed the event handler to listen for connection and have created a manual event to check for a device.

As I said it is a bit of a work around, but it does the job. 

When a device is connected I create a new device manager class and then subscribe to the disconnect event. On disconnect I dispose of the handler and device.

 

 private static RemoteDeviceManager mgr;
 private static RemoteDevice dev;

 

 

private void mgr_DeviceDisconnected(object sender, EventArgs e)
        {
            dev = null;
            Dispatcher.CurrentDispatcher.Invoke(new BoolMethod(this.OnConnection), false);
            mgr.Dispose();
        }

public void CheckDeviceConnected()
        {
            mgr = new RemoteDeviceManager();
            mgr.DeviceDisconnected += new EventHandler(mgr_DeviceDisconnected);
            dev = mgr.Devices.FirstConnectedDevice;
            if (dev != null)
                Dispatcher.CurrentDispatcher.Invoke(new BoolMethod(this.OnConnection), true);
        }

 

I hope this will help anyone who is stuck.

May 8, 2012 at 4:16 PM
Edited May 8, 2012 at 4:24 PM

I'm having the same issue.

If I subscribe the connected event of the manager, the returning device gets me an exception when I try to access any properties such as SystemInformation or OSVersion or when i try to perform any operation like copying files or accessing device registry.

If I don't subscribe the event and perform a manual polling checking if the device is connected like superkew suggests, it works great. I'm using the latest version and VS2010. My app is a WPF Application and i also tried the same code in a WinForm Application and it works fine subscrubing the connected event.

Thanks

Coordinator
May 10, 2012 at 5:32 PM

f_benedini, do you have some sample code that shows the 2.0 library failing as you describe? If so, will you post it so I can use it to troubleshoot?

May 13, 2012 at 9:26 AM

Hello Dahall,

here’s the sample code you requested. Put it in a WPF project, start it, connect via active sync and then check for the properties in the systeminfo object and you’ll get exceptions. It works well if you use the emulator instead of a real device and also if you build a WinForm Project

thanks.

using System;

using System.Devices;

using System.Windows;

namespace WPFTestRapi2

{

/// <summary>

/// Interaction logic for MainWindow.xaml

/// </summary>

public partial class MainWindow : Window

{

RemoteDeviceManager _mgr;

RemoteDevice _dev;

delegate void BoolMethod(bool value);

public MainWindow()

{

InitializeComponent();

_mgr = new RemoteDeviceManager();

_mgr.DeviceConnected += new EventHandler<RemoteDeviceConnectEventArgs>(mgr_DeviceConnected);

}

void mgr_DeviceConnected(object sender, RemoteDeviceConnectEventArgs e)

{

_dev = _mgr.Devices.FirstConnectedDevice;

Dispatcher.Invoke(new BoolMethod(this.OnConnection), true);

}

private void OnConnection(bool connected)

{

_dev = connected ? _mgr.Devices.FirstConnectedDevice : null;

// the dev instance obtained here gives me an exception when i try to access

// the system information object.

// The same code in a WinForm Project works well.

//The same code also works well in a WPF project ONLY IF USING the emulator.

}

private void mgr_DeviceDisconnected(object sender, EventArgs e)

{

Dispatcher.Invoke(new BoolMethod(this.OnConnection), false);

}

}

}

Descrizione: MAG_LOGO Descrizione: microsoft

Ing. Fabio Benedini

f.benedini@magconsulting.it

MAG Consulting S.r.l.

Sede Amm. : Via A. Cadlolo, 38 - 00136 Roma

Sede Oper. : Via C. Pascal, 6 - 00167 Roma

Tel. +39 06 35340166 +39 06 6381596

Fax +39 06 233248417

info@magconsulting.it

Questo messaggio e i suoi allegati sono indirizzati esclusivamente alle persone indicate. La diffusione, copia o qualsiasi altra azione derivante dalla conoscenza di queste informazioni sono rigorosamente vietate. Qualora abbiate ricevuto questo documento per errore siete cortesemente pregati di darne immediata comunicazione al mittente e di provvedere alla sua distruzione, Grazie.

This e-mail and any attachments is confidential and may contain privileged information intended for the addressee(s) only. Dissemination, copying, printing or use by anybody else is unauthorised. If you are not the intended recipient, please delete this message and any attachments and advise the sender by return e-mail, Thanks.

Descrizione: rispetta l'ambienteRispetta l'ambiente. Non stampare questa mail se non è necessario.

Coordinator
May 15, 2012 at 4:40 AM

So, using the following class, with two labels (label1 & label2) on the main form, I was able to make this consistently work using the latest source code. Let me know what you are doing differently to make this fail.

public partial class MainWindow : Window
{
   RemoteDeviceManager _mgr;
   delegate void BoolMethod(bool value);

   public MainWindow()
   {
      InitializeComponent();
      _mgr = new RemoteDeviceManager();
      _mgr.DeviceConnected += mgr_DeviceConnected;
      _mgr.DeviceDisconnected += mgr_DeviceDisconnected;
      using (RemoteDevice dev = _mgr.Devices.FirstConnectedDevice)
         WriteStatus(label1, dev, dev != null);
   }

   private void mgr_DeviceConnected(object sender, RemoteDeviceConnectEventArgs e)
   {
      WriteStatus(label1, e.Device, true);
      Dispatcher.Invoke(new BoolMethod(this.OnConnection), true);
   }

   private void mgr_DeviceDisconnected(object sender, RemoteDeviceConnectEventArgs e)
   {
      WriteStatus(label1, e.Device, false);
      Dispatcher.Invoke(new BoolMethod(this.OnConnection), false);
   }

   private void WriteStatus(System.Windows.Controls.Label lbl, RemoteDevice dev, bool connected)
   {
      if (connected)
         lbl.Content = string.Format("{0} Connected. OS: {1}", dev.Name, dev.OSVersion);
      else
         lbl.Content = string.Format("{0} Disconnected.", dev == null ? "All Devices" : dev.Name);
   }

   private void OnConnection(bool connected)
   {
      using (RemoteDevice dev = _mgr.Devices.FirstConnectedDevice)
         WriteStatus(label2, dev, dev != null);
   }
}
May 15, 2012 at 1:39 PM
Edited May 15, 2012 at 1:39 PM

Ths code doesn't work for me. I tried it with a real device, an Opticon H25+Windows CE 6.0. The same code against the Mobile Emulator works.

Here's the error message:

This operation cannot be completed on a disconnected device.

and here's the stack trace:

   in System.Devices.RemoteDevice.get_ISession()
   in System.Devices.RemoteDevice.get_OSVersion()
   in WpfApplication1.MainWindow.WriteStatus(Label lbl, RemoteDevice dev, Boolean connected) in D:\Documenti\Visual Studio 2010\Projects\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:riga 51
   in WpfApplication1.MainWindow.mgr_DeviceConnected(Object sender, RemoteDeviceConnectEventArgs e) in D:\Documenti\Visual Studio 2010\Projects\WpfApplication1\WpfApplication1\MainWindow.xaml.cs:riga 38
   in System.Devices.RemoteDeviceManager.OnDeviceConnected(RemoteDevice dev)
   in System.Devices.RemoteDeviceManager.DeviceConnecting(RAPI_DEVICEINFO& devInfo)

 

Thanks.

Coordinator
May 16, 2012 at 5:59 PM

f_benedini, did you reference the updated assembly? There is a new download for 2.0.

May 17, 2012 at 9:50 AM

Yes dahall, I did it but I'm getting the same result. Now sometimes works (1 out of 20 tries) but I don't know if I did not notice it before.

Thanks

Coordinator
May 18, 2012 at 7:35 PM

I am not able to reproduce this at all with the two Windows Mobile devices I have or the emulator. One last thought for you to try: Instead of passing a reference to a RemoteDevice or storing one in a class variable and then using it, will you try recreating it each time you need it and seeing if it still throws exceptions. Use the code below each time:

using (RemoteDeviceManager trm = new RemoteDeviceManager())
{
   using (RemoteDevice tdev = trm.Devices.FirstConnectedDevice)
   {
      if (tdev != null)
      {
         // Call your code to interact with the device here...
      }
   }
}
May 22, 2012 at 12:35 PM

Still getting error.

This the code I tested:

using System.Devices;
using System.Windows;

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        RemoteDeviceManager _mgr;
        delegate void BoolMethod(bool value);

        public MainWindow()
        {
            InitializeComponent();
            _mgr = new RemoteDeviceManager();
            _mgr.DeviceConnected += mgr_DeviceConnected;
            _mgr.DeviceDisconnected += mgr_DeviceDisconnected;
            using (RemoteDevice dev = _mgr.Devices.FirstConnectedDevice)
                WriteStatus(label1, dev, dev != null);
        }

        private void mgr_DeviceConnected(object sender, RemoteDeviceConnectEventArgs e)
        {
            WriteStatus(label1, e.Device, true);
            Dispatcher.Invoke(new BoolMethod(this.OnConnection), true);
        }

        private void mgr_DeviceDisconnected(object sender, RemoteDeviceConnectEventArgs e)
        {
            WriteStatus(label1, e.Device, false);
            Dispatcher.Invoke(new BoolMethod(this.OnConnection), false);
        }

        private void WriteStatus(System.Windows.Controls.Label lbl, RemoteDevice dev, bool connected)
        {
            if (connected)
                lbl.Content = string.Format("{0} Connected. OS: {1}", dev.Name, dev.OSVersion);
            else
                lbl.Content = string.Format("{0} Disconnected.", dev == null ? "All Devices" : dev.Name);
        }

        private void OnConnection(bool connected)
        {

            using (RemoteDeviceManager trm = new RemoteDeviceManager())
            {
                using (RemoteDevice tdev = trm.Devices.FirstConnectedDevice)
                {
                    if (tdev != null)
                    {
                        WriteStatus(label2, tdev, tdev != null);
                    }
                }
            }


        }
    }
}

Coordinator
May 22, 2012 at 5:01 PM

I have tried to reproduce this and I can't. At this point, I would encourage you to download the source for the project and play around with the internals. I am out of answers. Mi dispiace molto. Se hai successo, fammi sapere.