8

ユーザーが任意のディレクトリのファイルを削除したときに、必要な API 関数をフックして、メッセージボックスで単純なブール値の質問をすることでインターセプトしReally Would you like to Delete this file?たいと考えています。ファイルを削除するか、削除を防止するために、ファイルを制御します。

私のOSはWindows 8 x64.

この SO の質問では、名前付きの WinAPI 関数とインターフェイスが存在することを確認した方法で、NtSetFileInformation関数Intercept FIleSytemCall for Deletionをフックすることが最善の選択であると読みましたが、これらの違いはわかりませんが、とにかく、これを始める方法が本当にわかりません...DeleteFileICopyHook

私は VBNET ソリューションを探していることを明確にしたいと思います。Google を介したこれらの API フック ライブラリからの VBNET コードの例がなく、複雑なコードが関与。

編集:私のニーズにぴったりと思われるEasyHookライブラリの例を見つけましたが、それは C# コードであり、成功せずに翻訳しようとしました: EasyHook を使用して ntdll.dll から NtCreateFile API をフックする (c#)NtSetFileInformation

だから、私はDeviareライブラリ2.6でこれを試しましたが、何もしません:

Public Class Form1

    Private _mgr As Deviare2.NktSpyMgr = Nothing
    Private WithEvents _hook As Deviare2.NktHook = Nothing
    Private _proc As Deviare2.INktProcess = Nothing

    Private Shadows Sub Shown() Handles MyBase.Shown

        _mgr = New Deviare2.NktSpyMgr()
        _hook = _mgr.CreateHook("ntdll.dll!NtSetFileInformation", Nothing)
        _hook.Hook()

    End Sub

    Private Sub OnFunctionCalled(ByVal proc As Deviare2.INktProcess,
                                 ByVal callInfo As Deviare2.INktHookCallInfo,
                                 ByVal rCall As Deviare.IRemoteCall) Handles _hook.OnFunctionCalled

        MsgBox("Caught function call in " & proc.Name)

    End Sub

End Class

基本的に、上記のコードは、vb.net で別のプログラムの winapi 関数への呼び出しをフック@mazoulaするここで回答されたものと同じです。命令で例外。_hook.Attach(_mgr.Processes)

また、ライブラリでこれを試しましたEasyHookが、Explorer.exe または CMD からファイルを削除しても何もしません。コードはこの C# コードの翻訳ですhttp://www.codeproject.com/Questions/528094/DeleteFileplushookingpluswithplusEasyHookplussucce :

Imports System.Runtime.InteropServices
Imports EasyHook

Public Class Form1

    <DllImport("kernel32.dll", CharSet:=CharSet.Unicode, CallingConvention:=CallingConvention.StdCall)>
    Private Shared Function DeleteFile(filename As String) As Integer
    End Function

    <UnmanagedFunctionPointer(CallingConvention.StdCall, CharSet:=CharSet.Unicode)>
    Private Delegate Function DeleteFileHandler(filename As String) As Integer

    Private Shared deleted As Boolean = False

    public Function DeleteFileHookInstance(filename As String) As Integer
        MsgBox("works?")
        If deleted Then
            deleted = False
            Return 1
        End If
        If MessageBox.Show((Convert.ToString("Do you really want to delete file ") & filename) + "?", "Confirm delete file", MessageBoxButtons.YesNo, MessageBoxIcon.Question) = DialogResult.Yes Then
            deleted = True
            Return DeleteFile(filename)
        Else
            Return 1
        End If
        'Assume the call is successfull
    End Function

    Public Sub Run()

        Dim hook As EasyHook.LocalHook

        Try
            MsgBox("Creating...")
            hook = LocalHook.Create(LocalHook.GetProcAddress("kernel32.dll", "DeleteFileW"), New DeleteFileHandler(AddressOf DeleteFileHookInstance), Me)
            'It stops here, the main interface receives the reported status 'Creating...' seemly forever, I understand that is for the unexpected restarting of explorer.exe
            MsgBox("Completing...")
            hook.ThreadACL.SetExclusiveACL(New Integer() {0})
            RemoteHooking.WakeUpProcess()
            MsgBox("OK")
        Catch ex As Exception
            MsgBox("CreateHook failed: " + ex.Message)
            System.Diagnostics.Process.GetCurrentProcess().Kill()
        End Try
        While True
            Application.DoEvents()
        End While
    End Sub

    Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
        Run()
    End Sub

End Class
4

3 に答える 3

2

数日前、問題を一時的に解決するためにこのアプローチを書きましたが、すべてのシナリオでメソッドが適切に機能することを 100% 保証しているわけではありません (たとえば、ユーザーはctrl+を押しzてファイルの削除とメソッド ロジックを復元できます)。ファイルのdatetimeプロパティを使用して、最後に削除されたものを選択しようとしますが、これは100%安全ではありません)、これは今では機能しますが、これを行う代わりにAPIフックする方法を学びたい.

また、明らかに、これはファイルの永久削除では機能しません。

Imports System.IO
Imports Shell32

Public Class Test

    Private SH As New Shell
    Private RecycleBin As Folder = SH.NameSpace(ShellSpecialFolderConstants.ssfBITBUCKET)
    Private WithEvents FSW As New FileSystemWatcher

    Private Shadows Sub Load() _
    Handles MyBase.Load

        With FSW
            .Path = "C:\Test"
            .IncludeSubdirectories = True
            .Filter = "*"
            .NotifyFilter = NotifyFilters.FileName Or NotifyFilters.DirectoryName
            .EnableRaisingEvents = True
        End With

    End Sub

    Private Sub OnItemDeleted(sender As FileSystemWatcher, e As FileSystemEventArgs) _
    Handles FSW.Deleted

        Dim DeletedItems As IEnumerable(Of FolderItem) =
            RecycleBin.Items.Cast(Of FolderItem).
                             Where(Function(Item) Item.Name = e.Name).
                             OrderBy(Function(Item) Item.ModifyDate)

        Dim LastDeletedItem As Shell32.FolderItem = DeletedItems.LastOrDefault

        If LastDeletedItem IsNot Nothing Then

            If (LastDeletedItem.IsFolder AndAlso Directory.Exists(e.FullPath)) _
               OrElse (Not LastDeletedItem.IsFolder AndAlso File.Exists(e.FullPath)) Then

                Throw New Exception(String.Format("¿ Item has been restored ?: {0}", e.FullPath))
                Exit Sub

            End If

            LastDeletedItem.InvokeVerb("undelete")

        End If

    End Sub

End Class
于 2014-01-06T03:47:15.293 に答える
2

私だったら、自分のアーキテクチャを見直して、本当にすべてのファイルの削除を防ぐ必要があるかどうかを確認します。おそらく、いくつかの重要なディレクトリ (および場合によっては、それらのディレクトリ内のいくつかの重要なファイル) での削除を防ぐ必要があるだけです。これにより、UI の煩わしさが軽減されます。

于 2014-01-06T00:57:29.270 に答える
1

必要なのは、ディレクトリ ウォッチャーです。Visual Studio には機能が組み込まれています。以下のコードを試してください。

Imports System.IO

Module Watcher

Const DirectoryName As String = "C:\Database\2010Admin Updated"

Private intCreated As Integer



Sub Main()

Dim Watcher As New FileSystemWatcher(DirectoryName)

Try

' Add delegates for events

AddHandler Watcher.Created, New FileSystemEventHandler(AddressOf Watcher_Created)

AddHandler Watcher.Changed, New FileSystemEventHandler(AddressOf Watcher_Changed)

AddHandler Watcher.Deleted, New FileSystemEventHandler(AddressOf Watcher_Deleted)

AddHandler Watcher.Renamed, New RenamedEventHandler(AddressOf Watcher_Renamed)

' Must do this

Watcher.EnableRaisingEvents = True

' Display instructions and wait to exit

Console.WriteLine("Make changes to the " & DirectoryName & "directory.")

Console.WriteLine("You will see the events generated.")

Console.WriteLine("Press ENTER to exit.")

Console.ReadLine()

Finally

Watcher.Dispose()

End Try

End Sub

Private Sub Watcher_Created(ByVal sender As Object, ByVal e As FileSystemEventArgs)

Dim objWriter As New System.IO.StreamWriter("C:\dbupdated.txt", True)

Console.WriteLine("Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine(Now() & "Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine()

objWriter.Close()

intCreated += 1

If intCreated Mod 2 = 0 Then

MsgBox("File Created: " & e.FullPath)

End If

End Sub

Private Sub Watcher_Changed(ByVal sender As Object, ByVal e As FileSystemEventArgs)

Dim objWriter As New System.IO.StreamWriter("C:\dbupdated.txt", True)

Console.WriteLine("Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine(Now() & "Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine()

objWriter.Close()

End Sub

Private Sub Watcher_Deleted(ByVal sender As Object, ByVal e As FileSystemEventArgs)

Dim objWriter As New System.IO.StreamWriter("C:\dbupdated.txt", True)

Console.WriteLine("Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine(Now() & "Event: File {0} {1}", e.FullPath, e.ChangeType)

objWriter.WriteLine()

objWriter.Close()

End Sub

Private Sub Watcher_Renamed(ByVal sender As Object, ByVal e As RenamedEventArgs)

Dim objWriter As New System.IO.StreamWriter("C:\dbupdated.txt", True)

Console.WriteLine("Event: File {0} {1} to {2}", e.OldFullPath, e.ChangeType, e.FullPath)

objWriter.WriteLine(Now() & "Event: File {0} {1} to {2}", e.OldFullPath, e.ChangeType, e.FullPath)

objWriter.WriteLine()

objWriter.Close()

End Sub



End Module

実行してみてください (コンソール アプリケーションとして)。

于 2013-12-31T23:10:10.970 に答える