C#的Microsoft的Detours库监控某个路径下被锁定的文件是否被修改的详细代码
时间: 2023-12-06 20:44:16 浏览: 204
Detours Version 3.0源码及静态库.rar
以下是一个使用Detours库监控文件是否被修改的C#代码示例:
```csharp
using System;
using System.IO;
using Microsoft.Detours;
class Program
{
static void Main(string[] args)
{
// 设置需要监控的文件路径
string filePath = "C:\\test.txt";
// 创建一个文件监控对象
using (var fileMonitor = new FileMonitor(filePath))
{
// 注册文件修改事件处理程序
fileMonitor.FileChanged += (sender, e) =>
{
Console.WriteLine("文件 {0} 被修改", e.FilePath);
};
// 启动文件监控
fileMonitor.Start();
// 等待用户按下回车键退出
Console.ReadLine();
}
}
}
class FileMonitor : IDisposable
{
private readonly string _filePath;
private IntPtr _hFile;
private IntPtr _hFileMapping;
private FileStream _fileStream;
private readonly byte[] _buffer = new byte[1024];
private readonly object _lock = new object();
private bool _disposed;
public event EventHandler<FileChangedEventArgs> FileChanged;
public FileMonitor(string filePath)
{
_filePath = filePath;
}
public void Start()
{
// 打开文件并创建文件映射
_fileStream = new FileStream(_filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
_hFile = _fileStream.SafeFileHandle.DangerousGetHandle();
_hFileMapping = NativeMethods.CreateFileMapping(_hFile, IntPtr.Zero, NativeMethods.PAGE_READONLY, 0, 0, null);
// 监视文件修改
NativeMethods.DetourTransactionBegin();
NativeMethods.DetourUpdateThread(System.Threading.Thread.CurrentThread);
NativeMethods.DetourAttach(ref _hFileMapping, new IntPtr(0), 0);
NativeMethods.DetourTransactionCommit();
}
public void Stop()
{
// 停止监视文件修改
NativeMethods.DetourTransactionBegin();
NativeMethods.DetourUpdateThread(System.Threading.Thread.CurrentThread);
NativeMethods.DetourDetach(ref _hFileMapping, new IntPtr(0));
NativeMethods.DetourTransactionCommit();
// 关闭文件映射和文件流
NativeMethods.CloseHandle(_hFileMapping);
_fileStream.Dispose();
}
protected virtual void OnFileChanged(FileChangedEventArgs e)
{
var handler = FileChanged;
if (handler != null)
{
handler(this, e);
}
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (!_disposed)
{
if (disposing)
{
_fileStream.Dispose();
}
NativeMethods.CloseHandle(_hFileMapping);
_disposed = true;
}
}
~FileMonitor()
{
Dispose(false);
}
private void ReadChanges()
{
// 读取文件内容并检查是否发生了变化
lock (_lock)
{
_fileStream.Seek(0, SeekOrigin.Begin);
int bytesRead = _fileStream.Read(_buffer, 0, _buffer.Length);
if (bytesRead > 0)
{
byte[] currentBuffer = new byte[bytesRead];
Array.Copy(_buffer, currentBuffer, bytesRead);
if (!ByteArrayComparer.Instance.Equals(currentBuffer, _lastBuffer))
{
OnFileChanged(new FileChangedEventArgs(_filePath));
_lastBuffer = currentBuffer;
}
}
}
}
private volatile byte[] _lastBuffer = new byte[0];
private static class NativeMethods
{
public const uint PAGE_READONLY = 0x02;
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFileMapping(IntPtr hFile, IntPtr lpFileMappingAttributes, uint flProtect, uint dwMaximumSizeHigh, uint dwMaximumSizeLow, string lpName);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int WaitForSingleObject(IntPtr hHandle, int dwMilliseconds);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int WaitForMultipleObjects(int nCount, IntPtr[] lpHandles, bool bWaitAll, int dwMilliseconds);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool GetOverlappedResult(IntPtr hFile, [System.Runtime.InteropServices.In] ref NativeOverlapped lpOverlapped, out int lpNumberOfBytesTransferred, bool bWait);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern void Sleep(uint dwMilliseconds);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern void SetLastError(int dwErrCode);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetLastError();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentThread();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetThreadId(IntPtr hThread);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int GetCurrentThreadId();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool IsDebuggerPresent();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern void DebugBreak();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern void OutputDebugString(string lpOutputString);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryPerformanceCounter(out long lpPerformanceCount);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool QueryPerformanceFrequency(out long lpFrequency);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern void GetSystemTimeAsFileTime(out long lpSystemTimeAsFileTime);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern int VirtualQuery(IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, int dwLength);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool FlushInstructionCache(IntPtr hProcess, IntPtr lpBaseAddress, int dwSize);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DetourTransactionBegin();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DetourTransactionCommit();
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DetourUpdateThread(IntPtr hThread);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DetourAttach(ref IntPtr ppPointer, IntPtr pDetour, int cbSkip);
[System.Runtime.InteropServices.DllImport("kernel32.dll", SetLastError = true)]
public static extern bool DetourDetach(ref IntPtr ppPointer, IntPtr pDetour, int cbSkip);
}
private class ByteArrayComparer : System.Collections.Generic.IEqualityComparer<byte[]>
{
public static readonly ByteArrayComparer Instance = new ByteArrayComparer();
public bool Equals(byte[] x, byte[] y)
{
if (x == null || y == null) return false;
if (x.Length != y.Length) return false;
for (int i = 0; i < x.Length; i++)
{
if (x[i] != y[i]) return false;
}
return true;
}
public int GetHashCode(byte[] obj)
{
if (obj == null) return 0;
int hash = 17;
foreach (byte b in obj)
{
hash = hash * 31 + b;
}
return hash;
}
}
private class FileChangedEventArgs : EventArgs
{
public string FilePath { get; private set; }
public FileChangedEventArgs(string filePath)
{
FilePath = filePath;
}
}
}
```
这段代码使用了Detours库的API函数来监视文件的修改。它创建了一个FileMonitor对象,并在对象的Start方法中打开文件并创建文件映射。然后它使用Detours的API函数将文件映射附加到当前线程,并启动一个循环来读取文件内容并检查是否发生了变化。如果文件内容发生了变化,FileMonitor对象会触发一个FileChanged事件。最后,当FileMonitor对象被Dispose时,它会关闭文件映射和文件流。
阅读全文