简体   繁体   English

如何在 WPF 应用程序中从智能手机导入多个文件?

[英]How to import multiple files from a smartphone in a WPF app?

We encounter a problem using Microsoft.Win32.OpenFileDialog in a WPF app (targeting .NET Framework 4.7.2).我们在 WPF 应用程序(针对 .NET Framework 4.7.2)中使用Microsoft.Win32.OpenFileDialog时遇到问题。

We want to be able to import multiple files from a smartphone connected to a computer via USB connection.我们希望能够从通过 USB 连接连接到计算机的智能手机导入多个文件。 However, it seems impossible to do so using the OpenFileDialog , because it fires message box "Cannot open multiple items from this location. Try selecting a single item instead."但是,使用OpenFileDialog似乎不可能这样做,因为它会触发消息框“无法从该位置打开多个项目。请尝试选择单个项目。” . . You can reproduce it using this simple code and selecting at least 2 pictures from your smartphone:您可以使用这个简单的代码复制它,并从您的智能手机中选择至少 2 张图片:

var openFileDialog = new Microsoft.Win32.OpenFileDialog();
openFileDialog.Multiselect = true;
openFileDialog.ShowDialog();

This problem is known (see here and here ) and related to the MTP protocol.这个问题是已知的(参见此处此处)并且与 MTP 协议有关。 The problem does not occur with a smartphone connected using the alternative "USB Mas Storage" (UMS), but this option is not available on modern smartphones.使用替代“USB Mas Storage”(UMS)连接的智能手机不会出现此问题,但现代智能手机上不提供此选项。

The UWP FileOpenPicker seems to handle better the selection of multiple items (see here to see how to use it in a WPF app) but we accounter an InvalidCastException when using PickMultipleFilesAsync . UWP FileOpenPicker似乎可以更好地处理多个项目的选择(请参阅此处了解如何在 WPF 应用程序中使用它),但我们在使用PickMultipleFilesAsync时会考虑InvalidCastException The problem is described here and the answers suggest that FileOpenPicker cannot be used in WPF .NET Framework apps.问题在此处进行了描述,答案表明FileOpenPicker不能在 WPF .NET 框架应用程序中使用。

As said in the comments, an other way to achieve this would be to implement a file picker from skratch, using the MTP protocol for the smartphone devices.正如评论中所说,实现此目的的另一种方法是使用智能手机设备的 MTP 协议从 skratch 实现文件选择器。 The downside of this approach is that the .NET and UWP file pickers offer a lots of great features and are fully integrated to the OS.这种方法的缺点是 .NET 和 UWP 文件选择器提供了许多出色的功能,并且完全集成到操作系统中。

We have run out of ideas to solve this problem, so my question is:我们已经没有解决这个问题的想法了,所以我的问题是:

Is there a way to import multiple files from a smartphone using the Windows file picker in a WPF app targeting .NET Framework?有没有办法在针对 .NET 框架的 WPF 应用程序中使用 Windows 文件选择器从智能手机导入多个文件?

The same question has been asked on the Microsoft Q&A . Microsoft Q&A上也提出了同样的问题。

I'm a bit late to reply but I found the solution thanks to the Microsoft Q&A thread .我回复有点晚了,但由于微软问答线程,我找到了解决方案。

As far as I know, it's not possible to select multiple files from a MTP device using the Microsoft.Win32.OpenFileDialog because you can not set all the IFileOpenDialog options.据我所知,不可能使用Microsoft.Win32.OpenFileDialog从 MTP 设备 select 多个文件,因为您无法设置所有IFileOpenDialog选项。

As a result, you need to use your own IFileOpenDialog to set the options: be sure to add the FOS_ALLOWMULTISELECT option and remove the FOS_FORCEFILESYSTEM :因此,您需要使用自己的IFileOpenDialog来设置选项:确保添加FOS_ALLOWMULTISELECT选项并删除FOS_FORCEFILESYSTEM

ComFileDialog.IFileOpenDialog fileOpenDialog = null;
ComFileDialog.IShellItemArray shellItemArray = null;
ComFileDialog.IShellItem shellItem = null;
try
{
    // Set options
    fileOpenDialog = (ComFileDialog.IFileOpenDialog)new ComFileDialog.FileOpenDialogRCW();
    fileOpenDialog.GetOptions(out var options);
    options |= ComFileDialog.FOS_ALLOWMULTISELECT | ComFileDialog.FOS_FILEMUSTEXIST | ComFileDialog.FOS_PATHMUSTEXIST;
    fileOpenDialog.SetOptions(options);

    // Show window
    if (fileOpenDialog.Show() != ComFileDialog.S_OK)
    {
        return;
    }

    // Get results
    if (fileOpenDialog.GetResults(out shellItemArray) != ComFileDialog.S_OK)
    {
        return;
    }

    uint items = 0;
    if (shellItemArray.GetCount(out items) != ComFileDialog.S_OK)
    {
        return;
    }

    // Result loop
    for (uint item = 0; item < items; item++)
    {
        try
        {
            if (shellItemArray.GetItemAt(item, out shellItem) != ComFileDialog.S_OK)
            {
                continue;
            }

            // Use the IShellItem
        }
        finally
        {
            if (shellItem != null)
            {
                Marshal.ReleaseComObject(shellItem);
                shellItem = null;
            }
        }
    }
}
finally
{
    if (fileOpenDialog != null)
    {
        Marshal.ReleaseComObject(fileOpenDialog);
    }
    if (shellItemArray != null)
    {
        Marshal.ReleaseComObject(shellItemArray);
    }
    if (shellItem != null)
    {
        Marshal.ReleaseComObject(shellItem);
    }
}

You can find find the Window Shell API Interfaces on pinvoke.net:您可以在 pinvoke.net 上找到 Window Shell API 接口:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM