2017-02-27 3 views
1

Je dois énumérer le contenu d'un appareil Android MTP et transférer des fichiers de l'appareil vers un PC Windows.WPD API - Impossible de transférer le contenu de l'appareil (SSCCE inclus)

En suivant le guide trouvé ici Transferring Content from a Device to a PC J'ai tenté de transférer un document texte simple dans un répertoire spécifié. Cependant, le fichier de sortie est toujours vide, même lorsque la valeur retournée indique que X number of bytes have been written.

J'ai créé un SSCCE en utilisant uniquement l'API Windows recommandé appelle de reproduire facilement la question. J'ai utilisé la documentation API et le official sample project pour référence.

main.cpp

Qt project file

Pour tester, j'ai un téléphone Android connecté via MTP avec un dossier sur la racine appelé testFolder et à l'intérieur il y a un fichier testfile.txt avec le texte hello world. Lors de l'exécution de cette application, la sortie indique que 11 octets ont été écrits, mais le fichier est vide. S'il vous plaît essayez-le vous-même?

Je n'arrive pas à comprendre pourquoi le fichier est toujours vide. Des idées?

Merci pour votre temps.

+0

Pas grand chose à voir avec Qt mais avec Win32 API. Il est difficile de comprendre ce qui s'est passé avec votre code, mais vous pouvez essayer d'obtenir la dernière erreur et la description: https://msdn.microsoft.com/en-us/library/windows/desktop/ms680582(v=vs.85) .aspx – AlexanderVX

+0

@AlexanderVX Merci! Juste implémenté cela et il n'y avait pas d'erreur. Appelant 'GetLastError()' a également renvoyé 0. La grande chose qui m'a bloqué est que le fichier a été créé et 'StreamCopy' signale que 8 octets ont été écrits.Voici ma mise en œuvre exacte de cette prise directement de l'échantillon https://github.com/pauldotknopf/WindowsSDK7-Samples/blob/master/multimedia/wpd/wpdapisample/cpp/ContentTransfer.cpp#L80 – mrg95

+0

Peut-être que outputPath.toStdWString () .c_str() fait une chaîne de caractères large de wchar_t mais le flux s'attend à un caractère char? Et puis zéro d'un octet du caractère large vient et qui est traduit à la fin de la chaîne? – AlexanderVX

Répondre

2
hr = SHCreateStreamOnFile(strOriginalFileName, STGM_CREATE|STGM_WRITE, &finalFileStream); 

Il est généralement utile de reconnaître les modèles de codage courants. Chaque fois que vous créez un fichier, vous devez toujours fermer le fichier. Dans le langage C vous avez fopen(), vous devez appeler fclose(). Dans le winapi vous avez CreateFile(), vous devez appeler CloseHandle(). Même dans les environnements d'exécution où une grande partie de la gestion des ressources est automagique, comme .NET, lorsque vous créez un FileStream, vous devez appeler Close() ou utiliser l'instruction en utilisant l'instruction.

Le code ne fait rien pour fermer explicitement finalFileStream.

Cela a des conséquences, vous en avez trouvé un. À court d'une fuite de mémoire, l'implémentation de SHCreateStreamOnFile ne sait pas quand vider les données tamponnées mais pas encore écrites dans le fichier. Vous finissez donc avec un fichier sans contenu. Le contrat pour tout pointeur d'interface comme IStream est que vous devez toujours appeler explicitement sa fonction Release(). Notez que le code oublie de le faire de manière cohérente pour tous les les pointeurs d'interface qu'il utilise. Pas le seul problème, lorsque vous appelez CoInitialize/Ex(), vous devez appeler CoUninitialize(). Utilisez simplement la règle d'or, vous devez toujours nettoyer explicitement dans un code comme celui-ci.

Fix:

hr = StreamCopy(finalFileStream, ...); 
    if (FAILED(hr)) saysomething(hr);   // Forgotten in original code 
    finalFileStream->Release();    // Now it is good. 

Vous pouvez utiliser un type intelligent pointeur en C++ comme CComPtr<> pour le faire automagiquement.

+0

Ah! Ça a du sens maintenant. Je vois maintenant que l'API dit d'utiliser CComPtr <>, je suis en train de développer pour Windows 7 et ce n'est pas une option. Je vais essayer et accepter la réponse. Merci beaucoup! – mrg95