3

Are there any libraries available for VB.net which will enable me to easily access a MTP device? I'd like to be able to find out what devices are connected, list the contents of them and copy files to and from them.

Everything I've seen so far (either at Stack Overflow, on the Microsoft site or with a simple Google search) is either in C++, C# or some other language that isn't VB.net. The Microsoft documentation goes completely over my head.

As a result, it's all non-starter unless I plan to learn a new language.

I did find MTPSharp which gave me hope. However there is no documentation, it doesn't appear to be fully implemented, my attempts to do certain things return an exception and the author tells me that it's written against an old API I shouldn't use and is unable to help me with the questions I have.

Is there really no hope for someone who wants to use VB.net?

Cor
  • 389
  • 1
  • 2
  • 14
Richard
  • 1,471
  • 7
  • 23
  • 47

3 Answers3

7

A Window Portable Device Class Lib

Note: this is the work of Christophe Geers from a series of blogs which can be found here

I mainly added a few functions, a VB console test, and converted it to a Class Lib. I tweaked a few things in the code to streamline it, but they are not worth further mention.

Documentation:

Study Mr Geers' blog.

Visual Studio's IntelliSense will also be valuable in identifying the properties and methods available.

Important Notes

Caveat

I have very few portable devices (and cant find one), so testing was rather limited.

Files and Folders

The term File and Folder in this context can be misleading.

As the article makes clear, there is a PortableDeviceObject type (class) from which both PortableDeviceFile and PortableDeviceFolder inherit. PortableDeviceObject has a property collection named Files, but that collection actually contains PortableDeviceObjects. Any one of the items in that collection may in fact be another folder.

I started to implement a Folders collection as well, then figured out why it is the way it is. Since a folder can contain sub-folders, it would be more confusing and problematic to link files to subfolders to folders to a PortableDevice. So, I left it.

This means each item in the Files collection must be tested to see whether it is really a File or a Folder. This would typically be done one of two ways:

' using VB operator
If TypeOf item Is PortableDeviceFolder Then
    Console.Beep()
End If

' using NET Type method
If item.GetType Is GetType(PortableDeviceFolder) Then
    Console.Beep()
End If

To make things slightly simpler and more object oriented, I added an IsFile and IsFolder function to PortableDeviceObject which allows:

If item.IsFolder Then
   DisplayFolderContents(dev, CType(item, PortableDeviceFolder))
End If

There is also a method which returns an ItemType enum value (there is also a static version which may be useful):

' using GetItemType
If item.GetItemType = PortableDeviceObject.ItemTypes.File Then
    Console.Beep()
End If

Resources

Mr Geers' original source

Another C# Project for WPD which may be useful

MSDN Windows Portable Devices documentation for more information when you get ready to make mods later.

A VB Console app (just a translation) shows how to use some of the functions. Study the blog fr details.

The code is long, would largely duplicate Mr Geers' blog, and I am disinclined to post code which is not mine. Besides, C# code would apparently do you little good if you can't compile it to a DLL. So, to answer the question posed, Are there any libraries available for VB.net which will enable me to easily access a MTP device?:

Yes. The modified source, project files (VS2012), a new VB console test app and Binaries (PortableDevices.dll) can be downloaded from DropBox. The bin/compile folders includes Builds for AnyCPU/Release and x86/Release

  • I think you will want to keep the Interop.* DLLs located in those folders with the PortableDevice.DLL. For instance, copy them both along with the DLL to your tools directory. I am not sure why he did it that way.
  • To use the new Class Lib in a project, you obviously will need a add a reference to your brand new PortableDevice.DLL.

Of course, with the project source files you can load it and recompile to whatever format you desire. VS compiles C# projects the same way you do in VB.

enter image description here

Works on My MachineTM

Again, to be clear, this is not my work. I mainly compiled it to DLL.

Ňɏssa Pøngjǣrdenlarp
  • 38,411
  • 12
  • 59
  • 178
  • Wow, that's pretty awesome. Thank you very much! I've given it a go but it throws an unhandled exception when looking at my Galaxy S3. Is there any way I could be really cheeky and ask if you don't mind grabbing my email from my profile so I can send you this message? I promise not to waste too much of your time. – Richard Oct 31 '14 at 17:21
  • I was afraid of that - I had only 2 devices to test it on and a large number of others have come out since his code even. If you open the project the VB test app will run the C# code in the LIB prj. When it errors, you could tell me the line and actual exception and I'll see if I can goggle a fix. Need more info though like when it happens, where, what etc. – Ňɏssa Pøngjǣrdenlarp Oct 31 '14 at 17:30
  • I'm just grateful for what you've done so far. So I plugged in the Galaxy S3 and it has two storage areas ("Internal storage" and "SD card"). When I run the C# code I get an error at line 107 `this._device.Content(out content);` "Object reference not set to an instance of an object.". `content` is NULL but there is a `DeviceID` set. – Richard Oct 31 '14 at 17:44
  • I *suspect* the deal is that the "Internal storage" and "SD card" things are Devices within your Device (nested). So, as with IsFile, IsFolder it might need an IsDevice. You could change the VB code to NOT poll that device based on the name and see if it also crashed on both of them. – Ňɏssa Pøngjǣrdenlarp Oct 31 '14 at 18:00
  • There is only one device connected and the FriendlyName appears to be `""`. It fails when it tries to get the content. My (uneducated) guess is that each one is a device within a device. [edit] just spotted your comment :) – Richard Oct 31 '14 at 18:01
  • If I stick `if (device.FriendlyName.Equals("\"\""))` around the `getContents` call and `foreach` then it executes fine but displays nothing. Looks like there is only one device. – Richard Oct 31 '14 at 18:07
  • I looked at that other WPD project and while it is more extensive, the chewy center is nearly identical to Geers blog. I am not sure this API is meant to be used with that device though. I think it is intended for less intelligent devices like a eBook reader, camera etc. When connected, you could try to use "Open as Portable Device" from Explorer (right click) on either the device or internal storage items. – Ňɏssa Pøngjǣrdenlarp Nov 01 '14 at 12:46
  • Unfortunately when I right-click the device there is no "Open as Portable Device" option (presumably because it's already a portable device). Right-clicking on the storage items just shows open, open in new window and properties menu items. – Richard Nov 05 '14 at 14:48
  • As I said, I am not sure that API is meant for a device like a Tablet which has an OS to manage things. It appears to be a means to allow Windows to do things like get content type (GIF, MP3, AVI...etc) transfer etc on a device with limited smarts. – Ňɏssa Pøngjǣrdenlarp Nov 05 '14 at 15:04
1

(this should be a comment to this answer, but I don't have enough reputation to add comments)

@Richard said:

When I run the C# code I get an error at line 107 this._device.Content(out content); "Object reference not set to an instance of an object.".

Adding the line:

this.Connect();

before line 107 solved the problem for me.

Formalist
  • 349
  • 3
  • 12
1

This MediaDevices nuget package should suit you.

From package description:

API to communicate with MTP / WPD devices like smart phones, tablets and cameras. Documentation included.

(GitHub link).

To open a device and write a file on it:

var devices = MediaDevice.GetDevices();
using (var device = devices.First(d => d.FriendlyName == "My Cell Phone"))
{
  device.Connect();

  device.CreateDirectory(@"\Phone\Documents\Temp");

  using(FileStream stream = File.OpenRead(@"C:/Temp/Test.txt"))
  {
    device.UploadFile(stream, @"\Phone\Documents\Temp\Test.txt");
  }
  device.Disconnect();
}
Formalist
  • 349
  • 3
  • 12