我使用的是FileSystemWatcher的监视文件夹。 但是,当有一些事件在目录中进行,我不知道如何寻找谁做对文件的影响。 我尝试使用事件日志。 它只是不能工作。 是否有另一种方式做到这一点?
Answer 1:
我不记得在那里我发现这个代码,但它使用的PInvoke我认为这是这个任务有点大材小用的替代品。 使用FileSystemWatcher
观看文件夹,当一个事件触发,你可以找出哪些用户做出使用该代码的文件变化:
private string GetSpecificFileProperties(string file, params int[] indexes)
{
string fileName = Path.GetFileName(file);
string folderName = Path.GetDirectoryName(file);
Shell32.Shell shell = new Shell32.Shell();
Shell32.Folder objFolder;
objFolder = shell.NameSpace(folderName);
StringBuilder sb = new StringBuilder();
foreach (Shell32.FolderItem2 item in objFolder.Items())
{
if (fileName == item.Name)
{
for (int i = 0; i < indexes.Length; i++)
{
sb.Append(objFolder.GetDetailsOf(item, indexes[i]) + ",");
}
break;
}
}
string result = sb.ToString().Trim();
//Protection for no results causing an exception on the `SubString` method
if (result.Length == 0)
{
return string.Empty;
}
return result.Substring(0, result.Length - 1);
}
SHELL32是DLL的引用:微软壳牌控制和自动化-它是一个COM参考
这里是你如何调用该方法的一些示例的:
string Type = GetSpecificFileProperties(filePath, 2);
string ObjectKind = GetSpecificFileProperties(filePath, 11);
DateTime CreatedDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 4));
DateTime LastModifiedDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 3));
DateTime LastAccessDate = Convert.ToDateTime(GetSpecificFileProperties(filePath, 5));
string LastUser = GetSpecificFileProperties(filePath, 10);
string ComputerName = GetSpecificFileProperties(filePath, 53);
string FileSize = GetSpecificFileProperties(filePath, 1);
Answer 2:
您需要在文件系统上启用审计(和审计仅适用于NTFS)。 您可以通过应用组策略或本地安全策略,做到这一点。 您还必须在要监视的文件启用审核。 你这样做,你修改文件的权限相同的方式。
那么审计事件写入安全事件日志。 您必须监控这个事件日志您有兴趣,这样做的一种方式,审计事件是创建计划任务启动时,您有兴趣记录的事件的应用程序。 开始为每个事件一个新的进程,如果事件不以非常高的速度记录,虽然是唯一可行的。 否则,你可能会遇到性能问题。
基本上,你不想看文件的内容或属性(其外壳功能GetFileDetails
一样)。 此外,您不想使用文件共享API来获取打开了该文件(该网络用户NetGetFileInfo
一样)。 你要知道,上次修改该文件的进程的用户。 这些信息通常不被Windows记录,因为这需要太多的资源做所有文件的活动。 相反,您可以选择性地启用特定用户做特定的文件(和文件夹)specifc操作的审核。
Answer 3:
看来,你需要调用Windows API函数来得到你想要的东西,这涉及的PInvoke。 有些人在另一个论坛一直在寻找到它想通一些东西 ,你可以找到自己在这里解决 。 然而,似乎只有在网络共享文件(不是你的本地计算机上)工作。
对于未来的参考,这是张贴dave4dl代码 :
[DllImport("Netapi32.dll", SetLastError = true)]
static extern int NetApiBufferFree(IntPtr Buffer);
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto, Pack = 4)]
struct FILE_INFO_3
{
public int fi3_id;
public int fi3_permission;
public int fi3_num_locks;
public string fi3_pathname;
public string fi3_username;
}
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileEnum(
string servername,
string basepath,
string username,
int level,
ref IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
IntPtr resume_handle
);
[DllImport("netapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern int NetFileGetInfo(
string servername,
int fileid,
int level,
ref IntPtr bufptr
);
private int GetFileIdFromPath(string filePath)
{
const int MAX_PREFERRED_LENGTH = -1;
int dwReadEntries;
int dwTotalEntries;
IntPtr pBuffer = IntPtr.Zero;
FILE_INFO_3 pCurrent = new FILE_INFO_3();
int dwStatus = NetFileEnum(null, filePath, null, 3, ref pBuffer, MAX_PREFERRED_LENGTH, out dwReadEntries, out dwTotalEntries, IntPtr.Zero);
if (dwStatus == 0)
{
for (int dwIndex = 0; dwIndex < dwReadEntries; dwIndex++)
{
IntPtr iPtr = new IntPtr(pBuffer.ToInt32() + (dwIndex * Marshal.SizeOf(pCurrent)));
pCurrent = (FILE_INFO_3)Marshal.PtrToStructure(iPtr, typeof(FILE_INFO_3));
int fileId = pCurrent.fi3_id;
//because of the path filter in the NetFileEnum function call, the first (and hopefully only) entry should be the correct one
NetApiBufferFree(pBuffer);
return fileId;
}
}
NetApiBufferFree(pBuffer);
return -1; //should probably do something else here like throw an error
}
private string GetUsernameHandlingFile(int fileId)
{
string defaultValue = "[Unknown User]";
if (fileId == -1)
{
return defaultValue;
}
IntPtr pBuffer_Info = IntPtr.Zero;
int dwStatus_Info = NetFileGetInfo(null, fileId, 3, ref pBuffer_Info);
if (dwStatus_Info == 0)
{
IntPtr iPtr_Info = new IntPtr(pBuffer_Info.ToInt32());
FILE_INFO_3 pCurrent_Info = (FILE_INFO_3)Marshal.PtrToStructure(iPtr_Info, typeof(FILE_INFO_3));
NetApiBufferFree(pBuffer_Info);
return pCurrent_Info.fi3_username;
}
NetApiBufferFree(pBuffer_Info);
return defaultValue; //default if not successfull above
}
private string GetUsernameHandlingFile(string filePath)
{
int fileId = GetFileIdFromPath(filePath);
return GetUsernameHandlingFile(fileId);
}
Answer 4:
这已被讨论过很多次。 从同样的问题我的回答:
你不能用FileSystemWatcher的做到这一点异步,但你可以做到这一点同步使用文件系统过滤驱动程序。 司机让你得到执行操作的帐户的用户名。
Answer 5:
使用代码张贴dave4dl和更新声明结构FILE_INFO_3如下,您可以监控的用户名创建和更新的文件操作(这是喜欢的文件共享服务器的FileSystemWatcher的和的Openfiles.exe的功能组合)
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct FILE_INFO_3
{
public int fi3_id;
public int fi3_permission;
public int fi3_num_locks;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_pathname;
[MarshalAs(UnmanagedType.LPWStr)]
public string fi3_username;
}