我正在尝试创建一个NTFS Junction.从cmd行我可以使用sysinternals中的junction.exe工具执行此操作.结点的DIR cmd输出如下所示:
Volume in drive C has no label.
Volume Serial Number is C8BC-2EBD
Directory of c:\users\cheeso\Documents
03/22/2009 09:45 PM <JUNCTION> My Music [\??\c:\users\cheeso\Music]
05/11/2007 05:42 PM <DIR> My Received Files
03/22/2009 09:46 PM <JUNCTION> my videos [\??\c:\users\cheeso\Videos]
Run Code Online (Sandbox Code Playgroud)
我在某地读过Junctions是Symbolic Links的子集.
所以我尝试使用CreateSymbolicLink创建一个Junction.当我这样做时,我实际上得到了一个符号链接,而不是一个连接点.
09/09/2009 11:50 AM <SYMLINKD> newLink [.\]
Run Code Online (Sandbox Code Playgroud)
还有CreateHardLink.那里的文档说交汇点(又名"重新分析点")是硬链接的子集.但我似乎无法接受这项工作.它完成但没有创建硬链接或联结.
我正在使用.NET/C#,导入如下所示:
[Interop.DllImport("kernel32.dll", EntryPoint="CreateSymbolicLinkW", CharSet=Interop.CharSet.Unicode)]
public static extern int CreateSymbolicLink(string lpSymlinkFileName, string lpTargetFileName, int dwFlags);
[Interop.DllImport("kernel32.dll", EntryPoint="CreateHardLinkW", CharSet=Interop.CharSet.Unicode)]
public static extern bool CreateHardLink(string lpFileName, …Run Code Online (Sandbox Code Playgroud) 我需要获取HDD序列号,以将其用作许可软件的密钥.我在这个url中使用了diskid32代码:http://www.winsim.com/diskid32/diskid32.html 它使用了DeviceIoControl Win32 API和IO控制代码IOCTL_STORAGE_QUERY_PROPERTY.
有效.但是,当我仔细检查硬盘本身上印刷的实际序列号时,我发现该号码的每2个字节都被翻转了.
一个简单的解决方案可能是简单地将字节翻转回来.它适用于Windows XP,Vista和7,但在Windows 8中不需要翻转!
我想知道在Windows XP,Vista和7中翻转字节的确切原因,以及为什么不在Windows 8中翻转.下一个Windows怎么样?
部分代码略有变化:
int drive = 0;
HANDLE hPhysicalDriveIOCTL = 0;
char driveName [256];
sprintf (driveName, "\\\\.\\PhysicalDrive%d", drive);
// Windows NT, Windows 2000, Windows XP - admin rights not required
hPhysicalDriveIOCTL = CreateFile (driveName, 0,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
OPEN_EXISTING, 0, NULL);
if (hPhysicalDriveIOCTL != INVALID_HANDLE_VALUE)
{
_STORAGE_PROPERTY_QUERY query;
DWORD cbBytesReturned = 0; …Run Code Online (Sandbox Code Playgroud) 我正在使用C#项目DeviceIoControl.我已经为我的签名咨询了相关的Pinvoke.net页面:
[DllImport("Kernel32.dll", SetLastError = false, CharSet = CharSet.Auto)]
public static extern bool DeviceIoControl(
SafeFileHandle hDevice,
EIOControlCode IoControlCode,
[MarshalAs(UnmanagedType.AsAny)]
[In] object InBuffer,
uint nInBufferSize,
[MarshalAs(UnmanagedType.AsAny)]
[Out] object OutBuffer,
uint nOutBufferSize,
out uint pBytesReturned,
[In] IntPtr Overlapped
);
Run Code Online (Sandbox Code Playgroud)
我从来没有见过object和前,但MSDN文档听起来前途:[MarshalAs(UnmanagedType.AsAny)]
一种动态类型,它在运行时确定对象的类型,并将对象编组为该类型.该成员仅对平台调用方法有效.
我的问题是:使用此签名的"最佳"和/或"正确"方式是什么?
例如,IOCTL_STORAGE_QUERY_PROPERTY期望InBuffer是一个STORAGE_PROPERTY_QUERY结构.看起来我应该能够定义该结构,创建一个new实例,并将其传递给我的Pinvoke签名:
var query = new STORAGE_PROPERTY_QUERY { PropertyId = 0, QueryType = 0 };
DeviceIoControl(..., query, Marshal.SizeOf(query), ...);
Run Code Online (Sandbox Code Playgroud)
但是,我刚刚System.ExecutionEngineException做了这个,所以我改为:
int …Run Code Online (Sandbox Code Playgroud) 我在比较从用户模式类型 LPWSTR 传递到 LDR 表条目类型 UNICODE_STRING 的字符串时遇到困难
内核 C:
struct {
int pid;
int user_pid;
int size;
int protection_mode;
int allocation_type;
void* address;
void* write_buffer;
LPWSTR module_name;
}
userland_operation;
Run Code Online (Sandbox Code Playgroud)
这个结构体通过 deviceiocontrol 传递给内核。对应的用户空间结构如下:
public struct MemOperation
{
public int Pid;
public int UserPid;
public int Size;
public int protection_mode;
public int allocation_type;
public IntPtr Addr;
public IntPtr WriteBuffer;
[MarshalAs(UnmanagedType.LPWStr)] public String ModuleName;
}
Run Code Online (Sandbox Code Playgroud)
字符串在哪里 ModuleName被编组为 LPWStr。
ModuleName是进程中加载模块的所需搜索词。现在,事情变得棘手了。我可以通过访问的字符串_LDR_DATA_TABLE_ENTRY是UNICODE_STRING. 我想将此 UNICODE_STRING 与我的 LPWSTR 进行比较。
我尝试了以下方法,但没有奏效:
{
UNICODE_STRING …Run Code Online (Sandbox Code Playgroud) 我编写了下面的代码,将0xFF写入USB存储设备上的所有字节.由于某种原因,WriteFile()调用在扇区242开始出错.我在两个独立的USB存储设备上完成了这个操作,然后在十六进制编辑器中检查设备.扇区242似乎是FAT16格式化设备上文件分配表的开始,以及NTFS设备上引导区域的开始.我确信它在这些确切的位置错误并不是巧合,但是我不知道如何改变这种行为.我在WriteFile失败时收到的HRESULT是-2147024891,即E_ACCESSDENIED.有谁知道可能导致问题的原因是什么?
注意:如果您要在本地系统上运行此代码,请非常小心,因为我已经硬编码了USB设备的物理设备ID.请务必使用您尝试写入的设备更新deviceId变量.你不想破坏你的硬盘.
public enum EMoveMethod : uint
{
Begin = 0,
Current = 1,
End = 2
}
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
static extern uint SetFilePointer([In] SafeFileHandle hFile, [In] long lDistanceToMove, [Out] out int lpDistanceToMoveHigh, [In] EMoveMethod dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
static extern SafeFileHandle CreateFile(string lpFileName, uint dwDesiredAccess, uint dwShareMode, IntPtr lpSecurityAttributes, uint dwCreationDisposition, uint dwFlagsAndAttributes, IntPtr hTemplateFile);
[DllImport("kernel32", SetLastError = true)]
internal extern static int ReadFile(SafeFileHandle handle, byte[] bytes, int numBytesToRead, out …Run Code Online (Sandbox Code Playgroud) 在Delphi 7中,我正在开发一个库,该库实现了一个对象,该对象封装了有关连接到系统的电池的信息.除了检索电池的序列号外,它运行良好.
我用于此次调用的代码如下:
function TBattery.GetSerialNumber(hbat: THandle): boolean;
var
bqi: TBatteryQueryInformation;
Serial: PWideChar;
SerialSize,
dwOut: DWORD;
begin
Result := False;
if hbat <> INVALID_HANDLE_VALUE then
begin
ZeroMemory(@bqi, SizeOf(bqi));
dwOut := 0;
bqi.BatteryTag := FBatteryTag;
bqi.InformationLevel := BatterySerialNumber;
SerialSize := 2048;
GetMem(Serial, SerialSize);
try
ZeroMemory(Serial, SerialSize);
Result := DeviceIoControl(hbat, IOCTL_BATTERY_QUERY_INFORMATION, @bqi,
SizeOf(bqi), Serial, SerialSize, @dwOut, nil);
if Result then
FSerialNumber := Serial;
finally
FreeMem(Serial, SerialSize);
end;
end;
end;
Run Code Online (Sandbox Code Playgroud)
不幸的是,DeviceIoControl()总是返回False,如果我GetLastError()之后检查然后它返回错误87,"参数不正确."
这没有多大意义,因为如果我简单地将InformationLevelfrom 更改为BatterySerialNumberto BatteryUniqueID …
我使用下面的代码来获取物理磁盘大小,但返回的大小不正确.我用其他工具检查了尺寸.
以下代码报告
总磁盘空间:8.249.955.840字节
它应该是
总磁盘空间:8.254.390.272字节
如何检索实际/正确的物理磁盘大小?在USB驱动器和普通硬盘上测试.代码很长,这里将它分开来显示.
结构:
[StructLayout(LayoutKind.Sequential)]
internal struct DiskGeometry {
public long Cylinders;
public int MediaType;
public int TracksPerCylinder;
public int SectorsPerTrack;
public int BytesPerSector;
}
Run Code Online (Sandbox Code Playgroud)
原生方法:
internal static class NativeMethods {
[DllImport("Kernel32.dll", SetLastError=true, CharSet=CharSet.Auto)]
public static extern SafeFileHandle CreateFile(
string fileName,
uint fileAccess,
uint fileShare,
IntPtr securityAttributes,
uint creationDisposition,
uint flags,
IntPtr template
);
[DllImport("Kernel32.dll", SetLastError=false, CharSet=CharSet.Auto)]
public static extern int DeviceIoControl(
SafeFileHandle device,
uint controlCode,
IntPtr inBuffer,
uint inBufferSize,
IntPtr outBuffer, …Run Code Online (Sandbox Code Playgroud) 我试图通过使用MSDN上描述的OVERLAPPED结构异步调用DeviceIO函数.我使用FSCTL_ENUM_USN_DATA控制代码枚举NTFS驱动器的MFT,但我不能异步运行它.文件句柄是使用FILE_FLAG_OVERLAPPED创建的,但是我是否使用FILE_FLAG_OVERLAPPED的重叠结构没有区别.该功能不会立即返回.在这两种情况下似乎都是同步的.下面的示例显示了C:\驱动器上前100.000个MFT条目的枚举.由于我不太熟悉重叠结构的使用,我可能做错了.我的问题:如何异步执行DeviceIoControl(hDevice,FSCTL_ENUM_USN_DATA,...)?谢谢你的帮助.
#include "stdafx.h"
#include <Windows.h>
typedef struct {
DWORDLONG nextusn;
USN_RECORD FirstUsnRecord;
BYTE Buffer[500];
}TDeviceIoControlOutputBuffer, *PTDeviceIoControlOutputBuffer;
int _tmain(int argc, _TCHAR* argv[])
{
MFT_ENUM_DATA lInputMftData;
lInputMftData.StartFileReferenceNumber = 0;
lInputMftData.MinMajorVersion = 2;
lInputMftData.MaxMajorVersion = 3;
lInputMftData.LowUsn = 0;
lInputMftData.HighUsn = 0;
TDeviceIoControlOutputBuffer lOutputMftData;
DWORD lOutBytesReturned = 0;
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
OVERLAPPED lOverlapped = { 0 };
lOverlapped.hEvent = hEvent;
LPCWSTR path = L"\\\\.\\C:";
HANDLE hDevice = CreateFile(path, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if …Run Code Online (Sandbox Code Playgroud) 我试图在他们的生命周期中跟踪文件和文件夹(他们可能被移动或重命名).我已经完成了搜索,发现FileSystemWatcher可能是最流行的跟踪文件和文件夹的方式,但是,这对我来说不起作用,因为应用程序可能会也可能不会一直运行.我选择尝试通过ID跟踪文件夹.
我找到了一种方法来跟踪来自此堆栈帖子的答案的ID中的文件.我可以在此答案中基于方法B成功获取文件ID .
在搜索时我发现这个堆栈帖子说明他使用FSCTL_GET_OBJECT_ID找到了他的解决方案.我花了很多时间试图弄清楚如何使用这个功能,但我无法绕过它.我基本上没有从C#中调用本机Windows函数的经验.
任何人都可以为我推动正确的方向吗?我觉得我必须遗漏一些明显的东西.
有没有理由C#无法访问文件/文件夹ID?跟踪文件/文件夹是不常见的?
编辑,添加代码:
static uint returnVal;
//Working example to get File ID
public static string GetFileId(string path)
{
WinAPI.BY_HANDLE_FILE_INFORMATION objectFileInfo = new WinAPI.BY_HANDLE_FILE_INFORMATION();
FileInfo fi = new FileInfo(path);
FileStream fs = fi.Open(FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
WinAPI.GetFileInformationByHandle(fs.Handle, out objectFileInfo);
fs.Close();
ulong fileIndex = ((ulong)objectFileInfo.FileIndexHigh << 32) + (ulong)objectFileInfo.FileIndexLow;
return fileIndex.ToString();
}
public static string GetFolderId(string path)
{
//Get a handle on the given folder
IntPtr cFile = WinAPI.CreateFile( …Run Code Online (Sandbox Code Playgroud) 我正在尝试阅读 NTFS 更改日志,但我注意到我能找到的所有示例代码在 Windows 10 上都失败了,即使它在 Windows 7 上也能运行。
例如,Microsoft 自己的示例Walking a Buffer of Change Journal Records可在 Windows 7 上运行,但是当我在 Windows 10 上运行相同的代码时,当我使用 FSCTL_READ_USN_JOURNAL 调用 DeviceIoControl 时,我收到错误 87(参数不正确)(请注意,前面的调用到 DeviceIoControl 与 FSCTL_QUERY_USN_JOURNAL 成功完成并返回有效数据。)。
我什至将 EXE 编译并在 Windows 7 上运行并将其复制到 Windows 10 机器,但它仍然失败,所以我相信 Windows 10 可能对参数验证或类似的东西更严格?
我以管理员身份运行代码,所以这不是问题。
我找不到对此问题的任何其他引用,但是如果我采用其他人的示例代码并尝试在 Windows 10 上运行它,我会遇到同样的问题。
编辑:
代码本身:
#include <Windows.h>
#include <WinIoCtl.h>
#include <stdio.h>
#define BUF_LEN 4096
void main()
{
HANDLE hVol;
CHAR Buffer[BUF_LEN];
USN_JOURNAL_DATA JournalData;
READ_USN_JOURNAL_DATA ReadData = {0, 0xFFFFFFFF, FALSE, 0, 0};
PUSN_RECORD …Run Code Online (Sandbox Code Playgroud)