2014-03-27 55 views
4

我想刪除存儲在USB閃存盤(實際上是一個Android設備的SD卡)中的文件。刪除FolderItem

我要求用戶指出應用程序的文件夾內的SD卡,並且我持有指向它的Shell32.Folder對象。

我可以在文件之間進行迭代(FolderItem對象),但是如何使用Shell32類刪除文件?

通常File.Delete(filePath)不起作用,因爲FolderItem.Path是一個BSTR數據類型,所以也許關鍵是從一種類型轉換爲另一種類型,但我找不到一種方法來做到這一點。

任何想法?

EDIT 1:

FolderItem.Path數據:

「:: {20D04FE0-3AEA-1069-A2D8-08002B30309D} \\\ \ USB#vid_04e8 & pid_6860 & ms_comp_mtp & GT-P5100 #7 & 392be4e4 0000#{6ac27878-a6fa-4155-BA85-f98f491d4f33} \ {SID- 10001,SECZ9519043CHOHB,12530364416} \ {015C008D-013D-0145-D300-D300CB009500} \ {015C00EE-013D-0145- 0201-37012C010901} \ {025901D2-029D-020F-DE01-FE010D02A601}「

這不是File.Delete的有效路徑。任何想法如何轉換?

編輯2:打開的瀏覽文件夾窗口,使用戶可以指出應用程序目錄,他的Android設備的SD卡里面,這樣我就可以用文件夾和文件迭代,並同步一些

方法數據與服務器。使用這種方式時,由於Win8的和SHELL32之間的問題:

public Shell32.Folder GetShell32NameSpace(Object folder) 
{ 
    Type shellAppType = Type.GetTypeFromProgID("Shell.Application"); 
    Object shell = Activator.CreateInstance(shellAppType); 
    return (Shell32.Folder)shellAppType.InvokeMember("NameSpace", System.Reflection.BindingFlags.InvokeMethod, null, shell, new object[] { folder }); 
} 

使用上面的方法,得到的文件夾:

IntPtr windowHandle = new WindowInteropHelper(this).Handle; 
Folder androidPath = BrowseForFolder(windowHandle.ToInt32(), "App's data folder", 0, 0); 

創建和文件複製到應用程序的「數據」文件夾,所以該設備可以識別同步行動,告訴用戶,並關閉應用程序:

byte[] data = new UTF8Encoding(true).GetBytes("sync_cable"); 

if (androidPath != null) 
{ 
    foreach (FolderItem dir in androidPath.Items()) 
    { 
     if (dir.IsFolder && dir.Name == "data") 
     { 
      Folder dataFolder = GetShell32NameSpace(dir.Path); 
      if (dataFolder != null) 
      { 
       string tempPath = Path.GetTempPath(); 
       string path  = Path.Combine(tempPath, flagFileName); 
       File.WriteAllBytes(path, data); 

       Folder localPath = GetShell32NameSpace(tempPath); 
       if (localPath != null) 
       { 
        foreach (FolderItem file in localPath.Items()) 
        { 
         if (file.Name.Contains(flagFileName)) 
         { 
          dataFolder.CopyHere(file); 
          break; 
         } 
        } 
       } 
      } 

      break; 
     } 
    } 
} 

同步後,我要刪除的文件,這樣應用程序可以正常工作:

foreach (FolderItem file in dataFolder.Items()) 
{ 
    if (file.Name.Contains(flagFileName)) 
    { 
     // THIS THROWS AN 'INVALID PATH' EXCEPTION 
     // FileInfo fi = new FileInfo(file.Path); 
     // fi.Delete(); 

     // THIS ALSO THROWS AN 'INVALID PATH' EXCEPTION    
     // File.Delete(file.Path); 

     break; 
    } 
} 

正如在EDIT 1所提到的,我要刪除的文件的file.Path,格式如下:

「:: {20D04FE0-3AEA-1069-A2D8-08002B30309D} \\\?\ USB#vid_04e8 & pid_6860 & ms_comp_mtp & GT-P5100#7 & 392be4e4 0000#{6ac27878-a6fa-4155-BA85-f98f491d4f33} \ {SID- 10001,SECZ9519043CHOHB,12530364416} \ {015C008D-013D-0145- D300-D300CB009500} \ {015C00EE-013D-0145-0201-37012C010901} \ {025901D2-029D-020F-DE01-FE010D02A601}」

EDIT 3:

如這裏建議的,我試圖使用P- /調用刪除文件,但沒有成功。

[DllImport("kernel32.dll", CharSet = CharSet.Unicode)] 
[return: MarshalAs(UnmanagedType.Bool)] 
internal static extern bool DeleteFile(string lpFileName); 

調用方法:

foreach (FolderItem file in dataFolder.Items()) 
{ 
    if (file.Name.Contains(flagFileName)) 
    { 
     // ... 
     bool deleted = DeleteFile(file.Path); 
     // ... 
    } 
} 

該方法返回false,且文件不會被刪除。我在事件查看器中查看發生了什麼的線索,但什麼都沒發現。

+1

這不是它工作的方式。當您添加對shell32.dll的引用時,則使用內置於CLR中的COM互操作。它會自動在BSTR和System.String之間來回轉換 –

+0

感謝@HansPassant,我明白了。所以,FolderItem.Path已經是一個託管字符串,但其內容不是File.Delete的工作形式。在這種情況下,我該如何轉換此路徑?甚至用shell刪除文件? – MarcVit

+0

'ToString()'怎麼樣?似乎你應該從中得到一個'String'。 – Hogan

回答

0

看起來像「\?\」的路徑部分告訴你這是一條很長的路徑。令人遺憾的是,CLR無法處理長路徑(它被限制爲MAX_PATH = 260廢話)。我相信你可以使用WinAPI的DeleteFile來實現你想要的。

http://msdn.microsoft.com/en-us/library/windows/desktop/aa363915(v=vs.85).aspx

使用的PInvoke,你將所有設置。

http://pinvoke.net/default.aspx/kernel32/DeleteFile.html?diff=y

+0

他已經嘗試過...... –

+0

@ B.K。奇。我做了一個快速搜索,發現了這個博客,測試了結果,他們在Win8上爲我工作。 http://blogs.msdn.com/b/bclteam/archive/2007/03/26/long-paths-in-net-part-2-of-3-long-path-workarounds-kim-hamilton.aspx - - 可能是導致問題的前綴。 – whoisj

0

的GUID前綴( 「:: {20D04FE0-3AEA-1069-A2D8-08002B30309D}」)是用於我的電腦(見https://msdn.microsoft.com/en-us/library/windows/desktop/cc144096(v=vs.85).aspx)的標準連接點。

我懷疑該文件不能被刪除使用諸如shell API DeleteFile之類的方法,因爲它不在文件系統中(可以使用FolderItem.IsFileSystem檢查它),因爲android設備使用MTP連接。

我已經能夠使用FolderItem.InvokeVerb(「刪除」)刪除這些文件。這會產生一個確認對話框,可以使用某些版本的SendKeys(例如免費軟件Nirsoft的Nircmd.exe)將其解除。以下是VBA示例:

Private Sub SampleDelete() 

Const sFolder = "::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\\?\usb#vid_054c&pid_04cb#10fbd475671683#{6ac27878-a6fa-4155-ba85-f98f491d4f33}\SID-{10001,00000000000000000000000005671683,7513636864}\{00000007-0000-0000-0000-000000000000}\{000057F1-0000-0000-66A5-884D99020600}" 
Const sFileName = "test.txt" 

' requires reference to Shell32.dll 
Dim oShell As New Shell32.Shell 
Dim oFolder As Shell32.Folder 
Dim oFile As Shell32.FolderItem 

Set oFolder = oShell.Namespace(sFolder) 
If Not oFolder Is Nothing Then 
    Set oFile = oFolder.ParseName(sFileName) 
    If Not oFile Is Nothing Then 
     Debug.Print "File system? " & oFile.IsFileSystem 
     ' dismiss the confirmation dialog 
     SendKeys "~" 
     ' Alternatively use an external function, like this freeware utility 
     ' Shell "nircmd.exe sendkey enter press", vbHide 
     oFile.InvokeVerb "Delete" 
    Else 
     Debug.Print "File not found" 
    End If 
Else 
    Debug.Print "Folder not found" 
End If 

Set oShell = Nothing 
Set oFolder = Nothing 
Set oFile = Nothing 

End Sub