DOBON.NET DOBON.NETプログラミング掲示板過去ログ

フォルダの削除可能かの確認

環境/言語:[NET Framework 1.1]
分類:[.NET]

タスク→スケジュール→夜間バッチで
バックアップ処理を実行しています

バックアップ先のフォルダは
API関数(SHFileOperation)を使用して一旦、削除します
※削除するフォルダ内にはファイル、サブフォルダ等が存在する前提

問題は
対象フォルダが削除不可のとき(共有フォルダ、アクセス権限がない)
API関数だとエラートラップされません

スケジュール実行すると
削除の箇所で処理が止まります(裏でメッセージボックスが表示されている?)

事前に削除可能かの判断が必要かと思うのですが
どの様な方法があるのでしょうか?

また、他に案があればアドバイスを願います


現状のコードです
Private Structure SHFILEOPSTRUCT
Public hWnd As IntPtr
Public wFunc As Int32
<MarshalAs(UnmanagedType.LPStr)> Public pFrom As String
<MarshalAs(UnmanagedType.LPStr)> Public pTo As String
Public fFlags As Int16
Public fAnyOperationsAborted As Boolean
Public hNameMappings As IntPtr
<MarshalAs(UnmanagedType.LPStr)> Public lpszProgressTitle As String
End Structure

<DllImport("SHELL32.DLL", CharSet:=CharSet.Ansi)> _
Private Shared Function SHFileOperation(ByRef lpFileOp As SHFILEOPSTRUCT) As Integer
End Function

Public Const FO_MOVE As Int32 = &H1 'ファイルの移動(pFrom から pTo へ移動)
Public Const FO_COPY As Int32 = &H2 'ファイルのコピー(pFrom から pTo へコピー)
Public Const FO_DELETE As Int32 = &H3 'ファイルの削除(pFrom を削除 pTo は無視されます)
Public Const FO_RENAME As Int32 = &H4 'ファイル名変更(pFrom の名前変更)

Public Const FOF_MULTIDESTFILES As Int16 = &H1 '受け側に複数のファイルを指定
Public Const FOF_CONFIRMMOUSE As Int16 = &H2 '処理なし
Public Const FOF_SILENT As Int16 = &H4 '進捗ダイアログボックス非表示
Public Const FOF_RENAMEONCOLLISION As Int16 = &H8 '同一ファイル名の場合名前変更(コピ〜○○○)
Public Const FOF_NOCONFIRMATION As Int16 = &H10 '確認操作なし
Public Const FOF_WANTMAPPINGHANDLE As Int16 = &H20 'マッピングハンドル取得
Public Const FOF_ALLOWUNDO As Int16 = &H40 '削除の際ごみ箱に移動する
Public Const FOF_FILESONLY As Int16 = &H80 'ファイルのみを対象(*.* が指定された時)
Public Const FOF_NOCONFIRMMKDIR As Int16 = &H200 'フォルダ作成確認なし
Public Const FOF_SIMPLEPROGRESS As Int16 = &H100 '進捗ダイアログボックス表示
Public Const FOF_NOERRORUI As Int16 = &H400

Dim destinationFolder As DirectoryInfo

destinationFolder = New DirectoryInfo("\\XXXX\YYYY")

If destinationFolder.Exists = True Then

DeleteFolder(destinationFolder.FullName)


End If

Private Function DeleteFolder( _
ByVal folder As String _
) As Boolean
Dim SFO As New SHFILEOPSTRUCT
Dim result As Integer

SFO.hWnd = Me.Handle
SFO.wFunc = FO_DELETE
SFO.pFrom = folder & Chr(0) & Chr(0)
SFO.fFlags = FOF_NOCONFIRMMKDIR + FOF_NOCONFIRMATION + FOF_SILENT
SFO.fAnyOperationsAborted = True
SFO.hNameMappings = IntPtr.Zero

result = SHFileOperation(SFO)
Application.DoEvents()
Return result = 0

End Function
■No20795に返信(しばさんの記事)
> 事前に削除可能かの判断が必要かと思うのですが
> どの様な方法があるのでしょうか?

ファイルやフォルダはロックしなければ
他のプロセスからいつ操作されるかわかりません。
事前に削除可能か調べても、
調べて実際に削除するわずかの間に変更される可能性もあります。

ロックされてるファイルは、ロックしてるのが自分であったとしても
削除や移動ができませんので、
ファイルの削除や移動では、
かならず失敗した場合の処理をしなければいけないことになります。

どうせ失敗時の例外処理をしなければいけないのですから、
事前に調べなくても場合によっては十分です。

SHFileOperationはシェル用の関数ですから、
ユーザーの入力があるのが前提ですので、
夜間バッチにはお勧めしません。
シェルが忙しかったり、死んでるときには使えませんし、
システムサービスに変えたりするときに困ります。
どうしても使いたいのであれば、
UIが出ないようにきちんとフラグを立てましょう。

よく覚えてませんが、
確かFOF_NO_UIとFOF_NOERRORUIが必要だったと思います。
れい様、回答有難うございます

FOF_NOERRORUI

でエラーメッセージが表示されない事は
確認できました

この対応で処理が止まる事は回避できますが
(以降の処理で何らかの例外が発生?)

SHFileOperationはやっぱり良くないと

言う事なので、他の削除方法を試してみます


失礼します
解決済み!
■No20801に返信(しばさんの記事)
> この対応で処理が止まる事は回避できますが
> (以降の処理で何らかの例外が発生?)

SHFileOperationは、問題発生時にnonzeroを返します。
それを見れば、ダメだったかどうかがわかります。

他の関数を使っても、ダメなときはダメで、どうにもなりません。
結局ダメなときの処理は必要です。

> SHFileOperationはやっぱり良くないと
> 言う事なので、他の削除方法を試してみます

変わったことをしないで
普通にDeleteFileで削除するのがよいかと。
>また、他に案があればアドバイスを願います
夜間バッチとのことで、色々ご苦労があるものですネ
>対象フォルダが削除不可のとき(共有フォルダ
というのは、私には理解できなかったです
もしかして、バックの方に書き込みする時に、権限が操作できれば解決したりして。

無責任な話ですが、別の、新規の今日の日付のTopのフォルダーを作って
そこにバックアップするなら、成功するような気がしますが・・・
失礼致しました。

DOBON.NET | プログラミング道 | プログラミング掲示板