我正在尝试使用CreateFile函数来访问目录信息。但是,我收到了win32错误代码5,这意味着访问被拒绝。请给我建议。
CreateFile(path, GENERIC_READ, FILE_SHARE_READ, IntPtr.Zero, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, IntPtr.Zero);这就是正在进行的调用,正如文档中所指出的那样,正在使用'FILE_FLAG_BACKUP_SEMANTICS‘。DLL导入似乎工作正常,如下所示:
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr CreateFile(string filename,
uint desiredAccess,
uint sharedMode,
IntPtr securityAttributes,
uint creationDisposition,
uint flagsAndAttributes,
IntPtr templateFile);更新:我需要获得一个目录的句柄,这样我才能使用GetFileInformationByHandle()并提取唯一的id。此方法当前适用于文件,但目前不适用于目录。
更新:这个问题的X是我需要一个目录的唯一标识符,而不是它的绝对路径。即使目录被移动或重命名,它也需要保持不变。如上所述,.NET不提供任何唯一标识符,它只能通过使用win32来实现
发布于 2012-04-18 08:18:30
首先,您应该在应用程序中包含清单,以确保它在管理员权限下运行。然后使用AdjustTokenPrivileges接口开启SE_BACKUP_NAME权限。然后,我建议您使用FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE标志作为sharedMode。现在,您应该能够使用CreateFile打开目录句柄,并使用GetFileInformationByHandle获取BY_HANDLE_FILE_INFORMATION。
更新了:可能下面这个简单的演示程序可以帮助你
#include <windows.h>
#include <tchar.h>
int _tmain()
{
HANDLE hAccessToken = NULL;
HANDLE hFile = INVALID_HANDLE_VALUE;
__try {
LUID luidPrivilege;
DWORD dwErrorCode;
BY_HANDLE_FILE_INFORMATION fiFileInfo;
// -----------------------------------------------------
// first of all we need anable SE_BACKUP_NAME privilege
// -----------------------------------------------------
if (!OpenProcessToken (GetCurrentProcess(),
TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY,
&hAccessToken))
__leave;
if (LookupPrivilegeValue (NULL, SE_BACKUP_NAME, &luidPrivilege)) {
TOKEN_PRIVILEGES tpPrivileges;
tpPrivileges.PrivilegeCount = 1;
tpPrivileges.Privileges[0].Luid = luidPrivilege;
tpPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
AdjustTokenPrivileges (hAccessToken, FALSE, &tpPrivileges,
0, NULL, NULL);
if ((dwErrorCode = GetLastError ()) != ERROR_SUCCESS)
__leave;
}
else
__leave;
// -----------------------------------------------------
// now one can open directory and get
// -----------------------------------------------------
hFile = CreateFile (TEXT("C:\\"),
0, //GENERIC_READ,
0, //FILE_SHARE_READ, //FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
__leave;
if (!GetFileInformationByHandle (hFile, &fiFileInfo))
__leave;
_tprintf(TEXT("VolumeSerialNumber: 0x%08X\n"), fiFileInfo.dwVolumeSerialNumber);
_tprintf(TEXT("FileIndex: 0x%08X%08X\n"), fiFileInfo.nFileIndexHigh, fiFileInfo.nFileIndexLow);
}
__finally {
if (hFile != INVALID_HANDLE_VALUE)
CloseHandle (hFile);
if (hAccessToken != NULL)
CloseHandle (hAccessToken);
}
return 0;
}该程序打开C:\目录,并显示卷序列号和文件索引,它们标识了NTFS上的目录。为了使程序更简短,我删除了所有的错误消息(参见__leave语句)。就像我之前提到的,你应该使用requireAdministrator作为"UAC执行级别“(参见链接器设置的”清单文件“部分)。上面的代码是经过测试的,它在我身上工作。您可以在C#中重现相同的代码。
发布于 2020-11-21 17:44:45
更新:也许下面这个简单的演示程序可以帮助你…
我尝试SetFileTime(),但它是错误的。我做了如下修改:
hFile = CreateFile( TEXT("C:\\MyDirectory"),
// 0, //GENERIC_READ,
GENERIC_READ | GENERIC_WRITE,
// 0, //FILE_SHARE_READ, //FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);这是可以的。谢谢。安德烈。
https://stackoverflow.com/questions/10198420
复制相似问题