【问题标题】:Can images be read from an iPhone programmatically using CreateFile in Windows?可以在 Windows 中使用 CreateFile 以编程方式从 iPhone 读取图像吗?
【发布时间】:2020-03-05 06:14:31
【问题描述】:

当 iPhone 连接到 Win7 计算机时,可以使用资源管理器(以及我的应用程序的打开文件对话框)查看图像。但是,文件位置不包含驱动器号。

例如Computer\Apple iPhone\Internal Storage\DCIM\800AAAAA\IMG_0008.JPG 而不是E:\DCIM\800AAAAA\IMG_0008.JPG,后者在 SD 卡、USB 驱动器等中很常见...

我尝试使用 CreateFileW 从 iPhone 读取图像,但失败并显示“(错误代码:3)系统找不到指定的路径。”我也试过用 Chrome 访问它们,但也失败了。

有什么建议吗?

【问题讨论】:

    标签: iphone windows winapi filesystems createfile


    【解决方案1】:

    该文件夹实际上是所谓的“虚拟文件夹”,在文件系统上没有完整路径。您将需要使用从打开的对话框返回的 shell 项来获取文件的内容,而不是使用 CreateFile。

    数据应该可以访问,但您应该按照the MSDN documentation 的说明进行操作。我相信可能有更好的例子(因为这只是提供指导)。

    编辑粗略的过程是从 IFileOpenDialog 获取 IShellItem,然后绑定到流,然后读取流(假设只读) - 请记住,这段代码几乎没有错误处理或检查或安全:

    if (pitem->GetDisplayName(SIGDN_NORMALDISPLAY, &destName) == S_OK) {
        std::cout << destName << std::endl;
        CoTaskMemFree(destName);
    }
    IStream *pistream;
    if (pitem->BindToHandler(0, BHID_Stream, IID_PPV_ARGS(&pistream)) == S_OK) {
        char input[1024];
        long to_read = 1024;
        unsigned long read;
        while (S_OK == pistream->Read(input, to_read, &read)) {
           std::cout << input << std::endl;
        }
        pistream->Release();
    }
    pitem->Release();
    

    【讨论】:

      【解决方案2】:

      大多数情况下,此类设备作为 Shell 命名空间扩展插入到 Windows 资源管理器中,而不像带有驱动器号的 USB 记忆棒。大多数普通文件命令,如 CopyFile(..)、FindFirst() 或 GetFileInfo(..) 都不能直接在这样的 Shell 命名空间扩展中使用。只有 CopyHere(..) 有效。 我需要很长时间才能弄清楚如何枚举相机上的文件,现在还要在带有 vb.net 程序的 Android 设备上枚举文件,并将我的图片复制到我的 Windows PC:

      Public Const MyComputer As Integer = &H11&
      
      Sub EnumMyComputer()
        Dim oItem As Object
        Dim res As Integer
      
        For Each oItem In DirectCast(CreateObject("Shell.Application").Namespace(MyComputer).Items, System.Collections.IEnumerable)
          Debug.Print(oItem.Type.ToString)
          if oItem.Type.ToString="Tragbares Medienwiedergabegerät" then '<- check, adopt!
            res = EnumNamespaceItems(oItem, "", oItem.Name.ToString, 0)
          End If
        Next oItem
      End Sub
      
      Function EnumNamespaceItems(oItem As Object, SrcCPath As String, SrcDPath As String, folderLevel As Integer) As Integer
        Dim y As Object
        Dim tempFullFileName As String
      
        Debug.Print(StrDup(folderLevel, "  ") & "\" & oItem.Name.ToString & "  (" & oItem.Path.ToString & ")")
        For Each y In DirectCast(oItem.GetFolder.items, System.Collections.IEnumerable)
          'Debug.Print(StrDup(folderLevel, "  ") & SrcDPath & y.Name.ToString)
          If y.IsFolder = True Then
            Dim n1 As Integer
            n1 = EnumNamespaceItems(y, SrcCPath & y.Path.ToString & "\", SrcDPath & y.Name.ToString & "\", 1 + folderLevel)
            If n1 < 0 Then 'failure: Cancel
              EnumNamespaceItems = n1
              Exit Function
            End If
          Else 'it's a file:
            Debug.Print(StrDup(folderLevel, "  ") & " " & y.Name.ToString)
            tempFullFileName = System.IO.Path.GetTempPath() & y.Name.ToString
            ' CopyFile is not possible here if SrcCPath is like "::{…}…":
            ' My.Computer.FileSystem.CopyFile(SrcCPath & y.Name.ToString , fFile.FullName)
            Dim suc As Integer = CopyHereFileWait(y, My.Computer.FileSystem.SpecialDirectories.Temp)
            If suc >= 0 Then 'now we can do things like this:
              Dim MyFileInfo As System.IO.FileInfo = My.Computer.FileSystem.GetFileInfo(tempFullFileName)
              Dim fileDate As Date = MyFileInfo.LastWriteTime
            End If 'suc
          End If 'else y.IsFolder
        Next y
        EnumNamespaceItems = 0
      End Function
      
      Function CopyHereFileWait(sourceNamespaceObject As Object, targetFolder As String) As Integer
        Dim fsMyStream As System.IO.FileStream
        Dim n1 As Integer
        Dim taregetFullFileName As String
      
        n1 = Len(targetFolder)
        If Mid(targetFolder, n1, 1) = "\" Then
          targetFolder = Microsoft.VisualBasic.Left(targetFolder, n1 - 1)
        End If
        taregetFullFileName = targetFolder & "\" & sourceNamespaceObject.Name.ToString
        Dim oNsTargetFolder As Object
        oNsTargetFolder = CreateObject("Shell.Application").Namespace(CStr(targetFolder))
        oNsTargetFolder.copyHere(sourceNamespaceObject)
        'returns immediately and is doing the work in the background
        n1 = 0
        Do
          Threading.Thread.Sleep(50) 'ms
          Try
            fsMyStream = System.IO.File.Open(taregetFullFileName, IO.FileMode.Open, IO.FileAccess.ReadWrite)
            fsMyStream.Close()
            CopyHereFileWait = n1
            Exit Function
          Catch ex As Exception
            Debug.Print(ex.Message)
          End Try
          n1 = n1 + 1
        Loop While n1 < 400 'timeout 400*50ms = 20s
        CopyHereFileWait = -n1
      End Function
      

      您可以添加以检查带有 y.Name.ToString="DCIM"(在 folderLevel=1 上)的文件夹和带有“.jpg”的文件。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-02-17
        • 1970-01-01
        相关资源
        最近更新 更多