精华内容
下载资源
问答
  • 什么是Windows USB设备路径,它是如何格式化的?   Windows操作系统依靠唯一的设备路径来唯一标识连接到系统的每个USB设备/接口。设备路径字符串用于与USB设备通信,并传递给CreateFile()Win...

     

    什么是Windows USB设备路径,它是如何格式化的?




     

    Windows操作系统依靠唯一的设备路径来唯一标识连接到系统的每个USB设备/接口。设备路径字符串用于与USB设备通信,并传递给CreateFile()Win32 API函数。


    USB设备路径格式


    在大多数情况下,Windows格式化USB设备路径,如下所示:


    \?usb#vid_ vvvv&pid_ ppppssss#{ gggggggg-gggg-gggg-gggg-gggggggggggg }


    其中:
    vvvv是以4个十六进制字符表示的USB供应商ID。
    pppp是以4个十六进制字符表示的USB产品ID。
    ssss是以n个字符表示的USB串行字符串。
    gggggggg-gggg-gggg-gggg-ggggggggggg是用于将应用程序链接到设备的设备接口GUID,其中加载了特定的驱动程序。


    CP210x VCP驱动程序GUID是:


    A2A39220-39F4-4b88-AECB-3D86A35DC748 }


    GUID在驱动程序或驱动程序INF文件中分配,并由应用程序用于过滤已加载该驱动程序的设备。


    用于接口的复合USB设备路径格式


    对于具有多个接口的复合设备,每个接口的设备路径可能如下所示:


    \?usb#vid_ vvvv&pid_ pppp&mi_ iiaaaaaaaaaaaaaaaa#{ gggggggg-gggg-gggg-gggg-gggggggggggg }


    其中:
    vvvv是以4个十六进制字符表示的USB供应商ID。
    pppp是以4个十六进制字符表示的USB产品ID。
    ii是USB接口编号。
    aaaaaaaaaaaaaaaa是基于物理USB端口地址和/或接口号的特殊Windows生成的字符串。
    gggggggg-gggg-gggg-gggg-ggggggggggg是用于将应用程序链接到设备的设备接口GUID,其中加载了特定的驱动程序。


    唯一设备路径


    Windows要求设备路径对于每个USB设备和接口都是唯一的。如果两个USB设备插入到具有相同VID / PID /串行字符串的同一机器中,则上述USB设备路径格式将不会为两个设备生成唯一的字符串。在这种情况下,Windows会生成与复合USB设备路径格式部分中描述的格式相似的唯一字符串如果USB设备iSerial索引设置为0,则表示该设备没有串行字符串,也会使用此方法。


    使用设备路径信息的注册表项


    设备路径对于定位USB设备注册表项很有用,其中存储了设备实例的其他设置和信息。USB设备注册表项存储在以下位置:


    [HKLMSYSTEMCurrentControlSetEnumUSBVID_ VVVV&PID_ PPPP SSSS ]


    其中:
    vvvv是USB供应商ID。
    pppp是USB产品ID。
    ssss是USB串行字符串或唯一的Windows生成字符串。


    例如,CP210x VCP驱动程序将COM端口号存储在Device ParametersPortName注册表项中,如下图所示。



    使用设备管理器查找设备路径参数


    可以使用设备管理器获取供应商ID,产品ID,串行字符串或唯一字符串。打开USB设备的属性,然后单击“详细信息”选项卡。从组合框中选择“设备实例路径”属性,显示设备实例路径,该路径共享用于CreateFile()的设备路径的组件。设备实例路径的格式略有不同,如下图所示。


     

    展开全文
  • 装window系统和ubuntu系统的时候,由于操作不当装完了ubuntu后进入Windows磁盘脱机读取不出来,磁盘偶尔能显示出来,但是怎么也打不开,总是提醒请尝试首先向改卷分配驱动器号或者路径使其联机。解决方案1.打开...

    装window系统和ubuntu系统的时候,由于操作不当装完了ubuntu后进入Windows磁盘脱机读取不出来,磁盘偶尔能显示出来,但是怎么也打不开,总是提醒请尝试首先向改卷分配驱动器号或者路径使其联机。



    解决方案


    1.打开命令行终端cmd

    2.输入Diskpart,会进入一个Diskpart的命令行界面

    3.输入如下几个命令

    List Disk:显示本机的所有磁盘,以便正确操作目标磁盘
    Select Disk 1:选择1号磁盘
    Clean :清除0号磁盘上的所有分区
    Create Partition Primary Size=512000 创建主分区,容量为:512000MB
    Active:激活主分区
    Format Quick:快速格式化当前分区
    Create Partition Extended:创建扩展分区
    Create Partition Logical Size=512000:创建逻辑分区一,容量为:512000MB
    Format Quick:快速格式化当前分区
    Create Partition Logical Size=512000:创建逻辑分区二,容量为:512000MB
    Format Quick :快速格式化当前分区
    Create Partition Logical :创建逻辑分区三,大小为剩余的容量
    Format Quick :快速格式化当前分区
    Exit :退出Diskpart命令环境
    Exit :退出命令窗口

    以上基本可以解决问题


    微软技术中心命令行工具技术参考

    https://technet.microsoft.com/zh-cn/library/cc766465(v=ws.10).aspx



    展开全文
  • windows无法完成格式化解决办法,亲测可用。
  • windows下初始化格式化磁盘

    千次阅读 2016-10-21 11:38:29
    #include "stdafx.h" #include "CMDiskManager.h" CMDiskManager::CMDiskManager(){} /* 获取磁盘分区信息 vDiskNo:磁盘序号 */ DWORD CMDiskManager::GetLayoutInfo(DWORD vDiskNo) ... //磁盘内部路径 //生成

    新买来的硬盘是未初始化的,以我的理解就是没有引导扇区的,通常是没有MBR,如下图磁盘1,右边有大小,但显示“未分配”,

    左边显示“没有初始化”, 点鼠标右键就可以【初始化磁盘】。


    初始化时可以选择MBR和GPT, MBR方式顶多支持2T硬盘的。

    初始化后


    初始化后可以新建简单卷了,之前是不行的:



    CreateDisk(1, 3) 就是把磁盘1分为3个分区



    奇怪,如果只分1个区,就是自动以NTFS格式化掉, 而分3个区,还会提示是否格式化。


    如果想回到刚买回来的空白状态怎么办呢? 用DestroyDisk()就可以了


    代码: 

    CPP:CMDiskManager.cpp

    #include "stdafx.h"
    #include "CMDiskManager.h"
    
    CMDiskManager::CMDiskManager(){}
    
    //获取磁盘大小,单位是MB
    int CMDiskManager::GetDiskSize(DWORD vDiskNo)
    {
    	HANDLE hDevice;               // handle to the drive to be examined 
    	BOOL bResult;                 // results flag
    	DWORD junk;                   // discard results
    
    	char diskPath[256];				//磁盘内部路径
    	//生成磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    
    	hDevice = CreateFile(TEXT(diskPath),  // drive 或者 用"\\\\.\\PhysicalDrive0"  代表第一块磁盘
    		GENERIC_READ,                // no access to the drive
    		FILE_SHARE_READ | // share mode
    		FILE_SHARE_WRITE,
    		NULL,             // default security attributes
    		OPEN_EXISTING,    // disposition
    		0,                // file attributes
    		NULL);            // do not copy file attributes
    
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		return (FALSE);
    	}
    	
    	GET_LENGTH_INFORMATION pdg;
    	bResult = DeviceIoControl(hDevice,  // device to be queried
    		IOCTL_DISK_GET_LENGTH_INFO,  // operation to perform
    		NULL, 0, // no input buffer
    		&pdg, sizeof(pdg),     // output buffer
    		&junk,                 // # bytes returned
    		(LPOVERLAPPED)NULL);  // synchronous I/O
    
    	CloseHandle(hDevice);
    
    /*	INT64 nUseSize = disk_len.Length.QuadPart;
    	INT64 sizeGB = nUseSize / 1014 / 1024 / 1024;
    	CString szSize;
    	szSize.Format(L"C盘大小 %I64d GB", sizeGB);
    	*/
    	int MB = pdg.Length.QuadPart >> 20;
    	//CString s; 
    	//s.Format("C盘大小 %f GB", MB/1024.0);
    	//AfxMessageBox(s, 0, MB_OK);  
    	//float x = (float) MB ;
    	return MB  ;
    }
    
    
    /*
    获取磁盘分区个数
    vDiskNo:磁盘序号
    */
    int CMDiskManager::GetPartNum(DWORD vDiskNo)
    {
    	char diskPath[256];				//磁盘内部路径
    	//生成磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    	HANDLE hDevice;               //硬盘句柄 handle to the drive to be examined
    	BOOL result;                  //结果标志 results flag
    	DWORD readed;                 // discard results
    
    	hDevice = CreateFile(
    		diskPath,
    		GENERIC_READ | GENERIC_WRITE,
    		FILE_SHARE_READ | FILE_SHARE_WRITE,
    		NULL,           //default security attributes  
    		OPEN_EXISTING, // disposition  
    		0,              // file attributes  
    		NULL
    		);
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
    		return int(-1);
    	}
    
    	DRIVE_LAYOUT_INFORMATION_EX* dl;
    	DWORD tSize = 0x4000; // sizeof(DRIVE_LAYOUT_INFORMATION_EX) * 10;
    	dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(tSize);
    	if (NULL == dl)
    	{
    		(void)CloseHandle(hDevice);
    		return (int)-2;
    	}
    
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
    		NULL,
    		0,
    		dl,
    		tSize,
    		&readed,
    		NULL
    		);
    
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_GET_DRIVE_LAYOUT_EX Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return int(-3);
    	}
    
    	CString tPartitionStyle = "RAW";
    	switch (dl->PartitionStyle){
    	case 0:
    		tPartitionStyle = "MBR";
    		break;
    	case 1:
    		tPartitionStyle = "GPT";
    		break;
    	}
    
    	//printf("dl->PartitionCount = %d", dl->PartitionCount);
    	TRACE("dl->PartitionCount = %d, tPartitionStyle:%s \n", dl->PartitionCount, tPartitionStyle.GetBuffer());
    
    	//printf("dl->PartitionCount = %d", dl->PartitionCount);
    	int tRet = dl->PartitionCount/4;
    	//TRACE("dl->PartitionCount tRet = %d", tRet);
    
    	free(dl);
    	(void)CloseHandle(hDevice);
    
    	return tRet;
    }
    
    //读MBR信息
    BOOL CMDiskManager::ReadMBR(int vDiskNo, LPVOID *pBuffer)
    {
    	HANDLE hDevice;
    	DWORD dwSize;
    	DWORD dwOverRead;
    	BOOL bRet = TRUE;
    	char diskPath[256];				//磁盘内部路径
    	//生成磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    
    	hDevice = CreateFile(TEXT(diskPath),
    		GENERIC_READ | GENERIC_WRITE,
    		FILE_SHARE_READ | FILE_SHARE_WRITE,
    		NULL,
    		OPEN_EXISTING,
    		0,
    		NULL);
    	if (hDevice == INVALID_HANDLE_VALUE) {
    		TRACE("Open \\\\.\\PhysicalDrive failed. Error=%u\n", GetLastError());
    		return FALSE;
    	}
    
    	if (!DeviceIoControl(hDevice, FSCTL_LOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL)) {
    		CloseHandle(hDevice);
    		TRACE("FSCTL_LOCK_VOLUME \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
    		return FALSE;
    	}
    
    	DISK_GEOMETRY Geometry;
    	if (!DeviceIoControl(hDevice, IOCTL_DISK_GET_DRIVE_GEOMETRY, NULL, 0, &Geometry, sizeof(DISK_GEOMETRY), &dwSize, NULL)) {
    		bRet = FALSE;
    		TRACE("IOCTL_DISK_GET_DRIVE_GEOMETRY \\\\.\\PhysicalDrive0 failed. Error=%u\n", GetLastError());
    		goto _out;
    	}
    
    	*pBuffer = (LPVOID)GlobalAlloc(GPTR, Geometry.BytesPerSector);
    	if (*pBuffer) {
    		if (!ReadFile(hDevice, *pBuffer, Geometry.BytesPerSector, &dwOverRead, NULL)) {
    			printf("ReadFile \\\\.\\PhysicalDrive %u bytes failed. Error=%u\n", Geometry.BytesPerSector, GetLastError());
    			bRet = FALSE;
    		}
    	}
    
    _out:
    	DeviceIoControl(hDevice, FSCTL_UNLOCK_VOLUME, NULL, 0, NULL, 0, &dwSize, NULL);
    	CloseHandle(hDevice);
    	return bRet;
    
    }
    
    
    /*
    获取磁盘分区信息
    vDiskNo:磁盘序号
    */
    DWORD CMDiskManager::GetLayoutInfo(DWORD vDiskNo)
    {
    	char diskPath[256];				//磁盘内部路径
    	//生成磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    	HANDLE hDevice;               //硬盘句柄 handle to the drive to be examined
    	BOOL result;                  //结果标志 results flag
    	DWORD readed;                 // discard results
    	  
    	hDevice = CreateFile(
    		diskPath,
    		GENERIC_READ | GENERIC_WRITE,
    		FILE_SHARE_READ | FILE_SHARE_WRITE,
    		NULL,           //default security attributes  
    		OPEN_EXISTING, // disposition  
    		0,              // file attributes  
    		NULL
    		);
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
    		return DWORD(-1);
    	}
    
    	DRIVE_LAYOUT_INFORMATION_EX* dl;
    	DWORD tSize = 0x4000; // sizeof(DRIVE_LAYOUT_INFORMATION_EX) * 10;
    	dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(tSize);
    	if (NULL == dl)
    	{
    		(void)CloseHandle(hDevice);
    		return (WORD)-1;
    	}
    
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_GET_DRIVE_LAYOUT_EX,
    		NULL,
    		0,
    		dl,
    		tSize,
    		&readed,
    		NULL
    		);
    
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_GET_DRIVE_LAYOUT_EX Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	CString tPartitionStyle = "RAW";
    	switch (dl->PartitionStyle){
    	case 0:	
    		tPartitionStyle = "MBR";
    		break; 
    	case 1:
    		tPartitionStyle = "GPT";
    		break;
    	}
    
    	//printf("dl->PartitionCount = %d", dl->PartitionCount);
    	TRACE("dl->PartitionCount = %d, tPartitionStyle:%s", dl->PartitionCount, tPartitionStyle.GetBuffer());
    
    	free(dl);
    	(void)CloseHandle(hDevice);
    
    	return 0;
    }
    
    /*
    初始化磁盘,创建分区
    vDiskNo:磁盘序号,千万要避开系统盘,系统盘一般是0
    vPartNum:分区数,只要1个分区就可以了
    */
    DWORD CMDiskManager::CreateDisk(DWORD vDiskNo, WORD vPartNum)
    {
    	printf("准备CreateDisk, vDiskNo=%d, vPartNum=%d \n", vDiskNo, vPartNum);
    
    	//第0块磁盘是系统盘,不能格式化掉!!!但不排除某些情况下新插入的移动硬盘会是第0块磁盘
    	if (0 == vDiskNo){
    		printf("第0块磁盘是系统盘,不能格式化掉\n");
    		return 0;
    	}
    
    	HANDLE hDevice;               //硬盘句柄 handle to the drive to be examined
    	BOOL result;                  //结果标志 results flag
    	DWORD readed;                 // discard results
    	DWORD ret;
    	WORD i;
    	char diskPath[256];				//磁盘内部路径
    	DISK_GEOMETRY pdg;
    	DWORD sectorSize;			//扇区大小
    	DWORD signature;			//签名
    	LARGE_INTEGER diskSize;		//磁盘大小
    	LARGE_INTEGER partSize;		//分区大小
    	BYTE actualPartNum;			//实际上的分区数
    
    	DWORD layoutStructSize;		//
    	DRIVE_LAYOUT_INFORMATION_EX *dl;	//磁盘分区信息
    	CREATE_DISK newDisk;		//创建磁盘(初始化?)
    
    	//生成磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    
    	actualPartNum = 4;
    	if (vPartNum > actualPartNum)
    	{
    		printf("vPartNum > 4\n");
    		return (WORD)-1;
    	}
    
    	hDevice = CreateFile(
    		diskPath,
    		GENERIC_READ | GENERIC_WRITE,
    		FILE_SHARE_READ | FILE_SHARE_WRITE,
    		NULL,           //default security attributes  
    		OPEN_EXISTING, // disposition  
    		0,              // file attributes  
    		NULL
    		);
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
    		return DWORD(-1);
    	}
    
    	// Create primary partition MBR
    	//创建主分区的MBR
    	printf("创建主分区的MBR\n");
    
    	newDisk.PartitionStyle = PARTITION_STYLE_MBR;
    	signature = (DWORD)time(0);     // 原为time(NULL),   get signature from current time
    	newDisk.Mbr.Signature = signature;
    
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_CREATE_DISK,
    		&newDisk,
    		sizeof(CREATE_DISK),
    		NULL,
    		0,
    		&readed,
    		NULL
    		);
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_CREATE_DISK Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	//fresh the partition table
    	//刷新分区表
    	printf("刷新分区表\n");
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_UPDATE_PROPERTIES,
    		NULL,
    		0,
    		NULL,
    		0,
    		&readed,
    		NULL
    		);
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	//Now create the partitions
    	//现在创建分区
    	ret = GetDriveGeometry(vDiskNo, &pdg);
    	if ((DWORD)-1 == ret)
    	{
    		return ret;
    	}
    
    	//扇区大小
    	sectorSize = pdg.BytesPerSector;
    	diskSize.QuadPart = pdg.Cylinders.QuadPart * pdg.TracksPerCylinder *
    		pdg.SectorsPerTrack * pdg.BytesPerSector;       //calculate the disk size;
    	partSize.QuadPart = diskSize.QuadPart / vPartNum;
    
    	//分区结构大小
    	layoutStructSize = sizeof(DRIVE_LAYOUT_INFORMATION_EX) + (actualPartNum - 1) * sizeof(PARTITION_INFORMATION_EX);
    	dl = (DRIVE_LAYOUT_INFORMATION_EX*)malloc(layoutStructSize);
    	if (NULL == dl)
    	{
    		(void)CloseHandle(hDevice);
    		return (WORD)-1;
    	}
    
    	dl->PartitionStyle = (DWORD)PARTITION_STYLE_MBR;
    	dl->PartitionCount = actualPartNum;
    	dl->Mbr.Signature = signature;
    
    	//clear the unused partitions
    	//清除未用的分区
    	printf("清除未用的分区\n");
    	for (i = 0; i < actualPartNum; i++){
    		dl->PartitionEntry[i].RewritePartition = 1;
    		dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_ENTRY_UNUSED;
    	}
    
    	//set the profile of the partitions
    	for (i = 0; i < vPartNum; i++){
    		dl->PartitionEntry[i].PartitionStyle = PARTITION_STYLE_MBR;
    		dl->PartitionEntry[i].StartingOffset.QuadPart =
    			(partSize.QuadPart * i) + ((LONGLONG)(pdg.SectorsPerTrack) * (LONGLONG)(pdg.BytesPerSector));   //32256
    		dl->PartitionEntry[i].PartitionLength.QuadPart = partSize.QuadPart;
    		dl->PartitionEntry[i].PartitionNumber = i + 1;
    		dl->PartitionEntry[i].RewritePartition = TRUE;
    		dl->PartitionEntry[i].Mbr.PartitionType = PARTITION_IFS;
    		dl->PartitionEntry[i].Mbr.BootIndicator = FALSE;
    		dl->PartitionEntry[i].Mbr.RecognizedPartition = TRUE;
    		dl->PartitionEntry[i].Mbr.HiddenSectors =
    			pdg.SectorsPerTrack + (DWORD)((partSize.QuadPart / sectorSize) * i);
    	}
    	//execute the layout  
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_SET_DRIVE_LAYOUT_EX,
    		dl,
    		layoutStructSize,
    		NULL,
    		0,
    		&readed,
    		NULL
    		);
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_SET_DRIVE_LAYOUT_EX Error: %ld\n", GetLastError());
    		free(dl);
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	//fresh the partition table
    	printf("刷新分区表\n");
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_UPDATE_PROPERTIES,
    		NULL,
    		0,
    		NULL,
    		0,
    		&readed,
    		NULL
    		);
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
    		free(dl);
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	free(dl);
    	(void)CloseHandle(hDevice);
    	printf("CreateDisk完成\n");
    	Sleep(3000);            //wait the operations take effect
    	return 0;
    }
    
    
    //获取磁盘几何信息
    BOOL CMDiskManager::GetDriveGeometry(DWORD vDiskNo, DISK_GEOMETRY *pdg)
    {
    	HANDLE hDevice; // handle to the drive to be examined
    	BOOL bResult; // results flag
    	DWORD junk; // discard results
    
    	char diskPath[256];				//磁盘内部路径
    	sprintf_s(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    
    	hDevice = CreateFile(TEXT(diskPath), // drive
    		0, // no access to the drive
    		FILE_SHARE_READ | // share mode
    		FILE_SHARE_WRITE,
    		NULL, // default security attributes
    		OPEN_EXISTING, // disposition
    		0, // file attributes
    		NULL); // do not copy file attributes
    
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		return (FALSE);
    	}
    
    	bResult = DeviceIoControl(hDevice, // device to be queried
    		IOCTL_DISK_GET_DRIVE_GEOMETRY, // operation to perform
    		NULL, 0, // no input buffer
    		pdg, sizeof(*pdg), // output buffer
    		&junk, // # bytes returned
    		(LPOVERLAPPED)NULL); // synchronous I/O
    
    	CloseHandle(hDevice);
    
    	return (bResult);
    }
    
    
    /******************************************************************************
    * Function: delete the partition layout of the disk
    删除磁盘分区信息(恢复出厂设置)
    * input: disk, disk name
    * output: N/A
    * return: Succeed, 0
    *         Fail, -1
    ******************************************************************************/
    DWORD CMDiskManager::DestroyDisk(DWORD vDiskNo)
    {
    	if (0 == vDiskNo){
    		//系统盘是0号盘,为了安全,不能删除
    		return 0; 
    	}
    
    	HANDLE hDevice;               // handle to the drive to be examined
    	BOOL result;                  // results flag
    	DWORD readed;                 // discard results
    	CHAR diskPath[256];
    
    	sprintf(diskPath, "\\\\.\\PhysicalDrive%d", vDiskNo);
    
    	hDevice = CreateFile(
    		diskPath, // drive to open
    		GENERIC_READ | GENERIC_WRITE,     // access to the drive
    		FILE_SHARE_READ | FILE_SHARE_WRITE, //share mode
    		NULL,             // default security attributes
    		OPEN_EXISTING,    // disposition
    		0,                // file attributes
    		NULL            // do not copy file attribute
    		);
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    	{
    		fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
    		return DWORD(-1);
    	}
    
    	result = DeviceIoControl(
    		hDevice,               // handle to device
    		IOCTL_DISK_DELETE_DRIVE_LAYOUT, // dwIoControlCode
    		NULL,                           // lpInBuffer
    		0,                              // nInBufferSize
    		NULL,                           // lpOutBuffer
    		0,                              // nOutBufferSize
    		&readed,      // number of bytes returned
    		NULL        // OVERLAPPED structure
    		);
    	if (!result)
    	{
    		//fprintf(stderr, "IOCTL_DISK_DELETE_DRIVE_LAYOUT Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	//fresh the partition table
    	result = DeviceIoControl(
    		hDevice,
    		IOCTL_DISK_UPDATE_PROPERTIES,
    		NULL,
    		0,
    		NULL,
    		0,
    		&readed,
    		NULL
    		);
    	if (!result)
    	{
    		fprintf(stderr, "IOCTL_DISK_UPDATE_PROPERTIES Error: %ld\n", GetLastError());
    		(void)CloseHandle(hDevice);
    		return DWORD(-1);
    	}
    
    	(void)CloseHandle(hDevice);
    	return 0;
    }
    
    /******************************************************************************
    * Function:快速格式化某个磁盘,文件系统NTFS,
    如果在CreateDisk()创建磁盘后,磁盘的文件系统是RAW的话,才需要调用该函数
    * input: disk, disk name
    * output: N/A
    * return: Succeed, 0
    *         Fail, 1
    ******************************************************************************/
    DWORD CMDiskManager::FormatVolume(CHAR letter)
    {
    	DWORD ret;
    	CHAR cmd[64];
    	sprintf(cmd, "format %c: /FS:NTFS /Q /Y", letter);
    	ret = (DWORD)system(cmd);
    	return ret;
    }
    
    //获取第dwNum个磁盘的信息
    void CMDiskManager::GetDiskInfo(DWORD &dwNum, CString chDriveInfo[])
    {
    	DWORD DiskCount = 0;
    
    	//利用GetLogicalDrives()函数可以获取系统中逻辑驱动器的数量,函数返回的是一个32位无符号整型数据。  
    	DWORD DiskInfo = GetLogicalDrives();
    
    	//通过循环操作查看每一位数据是否为1,如果为1则磁盘为真,如果为0则磁盘不存在。  
    	while (DiskInfo)
    	{
    		//通过位运算的逻辑与操作,判断是否为1  
    		Sleep(10);
    		if (DiskInfo & 1)
    		{
    			DiskCount++;
    		}
    		DiskInfo = DiskInfo >> 1;//通过位运算的右移操作保证每循环一次所检查的位置向右移动一位。*/  
    	}
    
    	if (dwNum < DiskCount)
    	{
    		return;//实际的磁盘数目大于dwNum  
    	}
    	dwNum = DiskCount;//将磁盘分区数量保存  
    
    
    	//-------------------------------------------------------------------//  
    	//通过GetLogicalDriveStrings()函数获取所有驱动器字符串信息长度  
    	int DSLength = GetLogicalDriveStrings(0, NULL);
    
    	CHAR* DStr = new CHAR[DSLength];
    	memset(DStr, 0, DSLength);
    
    	//通过GetLogicalDriveStrings将字符串信息复制到堆区数组中,其中保存了所有驱动器的信息。  
    	GetLogicalDriveStrings(DSLength, DStr);
    
    	int DType;
    	int si = 0;
    	BOOL fResult;
    	unsigned _int64 i64FreeBytesToCaller;
    	unsigned _int64 i64TotalBytes;
    	unsigned _int64 i64FreeBytes;
    
    	//读取各驱动器信息,由于DStr内部数据格式是A:\NULLB:\NULLC:\NULL,所以DSLength/4可以获得具体大循环范围  
    	for (int i = 0; i<DSLength / 4; ++i)
    	{
    		Sleep(10);
    		CString strdriver = DStr + i * 4;
    		CString strTmp, strTotalBytes, strFreeBytes;
    		DType = GetDriveType(strdriver);//GetDriveType函数,可以获取驱动器类型,参数为驱动器的根目录  
    		switch (DType)
    		{
    		case DRIVE_FIXED:
    		{
    			strTmp.Format(_T("本地磁盘"));
    		}
    			break;
    		case DRIVE_CDROM:
    		{
    			strTmp.Format(_T("DVD驱动器"));
    		}
    			break;
    		case DRIVE_REMOVABLE:
    		{
    			strTmp.Format(_T("可移动磁盘"));
    		}
    			break;
    		case DRIVE_REMOTE:
    		{
    			strTmp.Format(_T("网络磁盘"));
    		}
    			break;
    		case DRIVE_RAMDISK:
    		{
    			strTmp.Format(_T("虚拟RAM磁盘"));
    		}
    			break;
    		case DRIVE_UNKNOWN:
    		{
    			strTmp.Format(_T("虚拟RAM未知设备"));
    		}
    			break;
    		default:
    			strTmp.Format(_T("未知设备"));
    			break;
    		}
    
    		//GetDiskFreeSpaceEx函数,可以获取驱动器磁盘的空间状态,函数返回的是个BOOL类型数据  
    		fResult = GetDiskFreeSpaceEx(strdriver,
    			(PULARGE_INTEGER)&i64FreeBytesToCaller,
    			(PULARGE_INTEGER)&i64TotalBytes,
    			(PULARGE_INTEGER)&i64FreeBytes);
    
    		if (fResult)
    		{
    			strTotalBytes.Format(_T("磁盘总容量%.2fMB"), (float)i64TotalBytes / 1024 / 1024);
    			strFreeBytes.Format(_T("磁盘剩余空间%.2fMB"), (float)i64FreeBytesToCaller / 1024 / 1024);
    		}
    		else
    		{
    			strTotalBytes.Format(_T(""));
    			strFreeBytes.Format(_T(""));
    		}
    		chDriveInfo[i] = strTmp + _T("(") + strdriver + _T("):") + strTotalBytes + ", " +strFreeBytes;
    		si += 4;
    	}
    }
    
    
    /******************************************************************************
    
    * Function: get disk's physical number from its drive letter
    		根据逻辑盘符找到物理硬盘号
    
    *           e.g. C-->0 (C: is on disk0)
    
    * input: letter, drive letter
    
    * output: N/A
    
    * return: Succeed, disk number
    
    *         Fail, -1
    
    ******************************************************************************/
    
    //根据逻辑盘符找到物理硬盘号
    DWORD CMDiskManager::GetPhysicalDriveFromPartitionLetter(CHAR letter)
    {
    	HANDLE hDevice;               // handle to the drive to be examined
    
    	BOOL result;                 // results flag
    
    	DWORD readed;                   // discard results
    
    	STORAGE_DEVICE_NUMBER number;   //use this to get disk numbers
    	
    	CHAR path[256];
    
    	sprintf(path, "\\\\.\\%c:", letter);
    
    	hDevice = CreateFile(path, // drive to open
    
    		GENERIC_READ | GENERIC_WRITE,    // access to the drive
    
    		FILE_SHARE_READ | FILE_SHARE_WRITE,    //share mode
    
    		NULL,             // default security attributes
    
    		OPEN_EXISTING,    // disposition
    
    		0,                // file attributes
    
    		NULL);            // do not copy file attribute
    
    	if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
    
    	{
    
    		fprintf(stderr, "CreateFile() Error: %ld\n", GetLastError());
    
    		return DWORD(-1);
    	}
    	
    	result = DeviceIoControl(
    
    		hDevice,                // handle to device
    
    		IOCTL_STORAGE_GET_DEVICE_NUMBER, // dwIoControlCode
    
    		NULL,                            // lpInBuffer
    
    		0,                               // nInBufferSize
    
    		&number,           // output buffer
    
    		sizeof(number),         // size of output buffer
    
    		&readed,       // number of bytes returned
    
    		NULL      // OVERLAPPED structure
    
    		);
    
    	if (!result) // fail
    	{
    
    		fprintf(stderr, "IOCTL_STORAGE_GET_DEVICE_NUMBER Error: %ld\n", GetLastError());
    
    		(void)CloseHandle(hDevice);
    
    		return (DWORD)-1;
    	}
    
    	//printf("%d %d %d\n\n", number.DeviceType, number.DeviceNumber, number.PartitionNumber);
    	
    	(void)CloseHandle(hDevice);
    	
    	return number.DeviceNumber;
    
    }
    
    /******************************************************************************
    
    * Function: get disk's drive letters from physical number
    获取一个物理硬盘上的所有盘符
    *           e.g. 0-->{C, D, E} (disk0 has 3 drives, C:, D: and E:)
    
    * input: vDiskNo, disk's physical number
    
    * output: letters, letters array
    
    * return: Succeed, the amount of letters
    
    *         Fail, -1
    
    ******************************************************************************/
    
    CString CMDiskManager::GetPartitionLetterFromPhysicalDrive(DWORD vDiskNo)
    {
    	DWORD mask;
    	DWORD driveType;
    	DWORD bmLetters;
    	DWORD diskNumber;
    	CHAR path[256];
    	CHAR letter;
    	DWORD letterNum;
    	WORD i;
    	CHAR *p;
    	CString tRet = ""; 
    
    	bmLetters = GetLogicalDrives();
    
    	if (0 == bmLetters)
    	{
    		return "";
    	}
    	
    	letterNum = 0;
    
    	for (i = 0; i < sizeof(DWORD) * 8; i++)
    	{
    		mask = 0x1u << i;
    
    		if ((mask & bmLetters) == 0)        //get one letter
    		{
    			continue;
    		}
    
    		letter = (CHAR)(0x41 + i);    //ASCII change
    
    		sprintf(path, "%c:\\", letter);
    
    		driveType = GetDriveType(path);
    
    		if (driveType != DRIVE_FIXED)
    		{
    			bmLetters &= ~mask;     //clear this bit
    			continue;
    		}
    
    		diskNumber = GetPhysicalDriveFromPartitionLetter(letter);
    
    		if (diskNumber != vDiskNo)
    		{
    			bmLetters &= ~mask;     //clear this bit
    
    			continue;
    		}
    
    		letterNum++;
    	}
    	
    	//build the result
    
    	/*letters = (CHAR *)malloc(letterNum);
    	
    	if (NULL == *letters)
    	{
    		return (DWORD)-1;
    	}
    
    	p = *letters;
    	*/
    	CString s;
    	for (i = 0; i < sizeof(DWORD) * 8; i++)
    	{
    		mask = 0x1u << i;
    
    		if ((mask & bmLetters) == 0)
    		{
    			continue;
    		}
    
    		letter = (CHAR)(0x41 + i);    //ASCII change
    		s.Format("%c", letter); 
    		if (!tRet.IsEmpty()){
    			tRet +=  ",";
    		}
    		tRet += s + ":"; 
    		
    	}
    
    	return tRet;
    }
    



    头文件:CMDiskManager.h

    #include <windows.h>
    #include <winioctl.h>
    #include <stdio.h>
    #include "time.h"
    
    #include <stdlib.h>
    #include <tchar.h>
    
    #pragma pack(1)
    
    #define MAX_MBR_PARTITIONS          4
    #define MBR_DISK_SIGNATURE_OFFSET   440
    #define MBR_DISK_PPT_OFFSET         446
    #define MBR_SIGNATURE_OFFSET        510
    
    //
    // MBR Partition Entry
    //
    typedef struct {
    	UINT8  BootIndicator;
    	UINT8  StartHead;
    	UINT8  StartSector;
    	UINT8  StartTrack;
    	UINT8  OSType;
    	UINT8  EndHead;
    	UINT8  EndSector;
    	UINT8  EndTrack;
    	UINT32 StartingLBA;
    	UINT32 SizeInLBA;
    } MBR_PARTITION_RECORD;
    
    //
    // MBR Partition table
    //
    typedef struct {
    	UINT8                 BootCode[440];
    	UINT32                UniqueMbrSignature;
    	UINT16                Unknown;
    	MBR_PARTITION_RECORD  PartitionRecord[MAX_MBR_PARTITIONS];
    	UINT16                Signature;
    } MASTER_BOOT_RECORD;
    
    #pragma pack()
    
    #define MBR_SIGNATURE               0xAA55
    #define EXTENDED_DOS_PARTITION      0x05
    #define EXTENDED_WINDOWS_PARTITION  0x0F
    
    
    class CMDiskManager {
    
    public:
    
    	CMDiskManager(); 
    
    	//获取磁盘几何
    	BOOL GetDriveGeometry(DWORD vDiskNo, DISK_GEOMETRY *pdg);
    	 
    	//获取磁盘大小,单位是MB
    	int GetDiskSize(DWORD vDiskNo);
    
    	/*
    	获取磁盘分区信息
    	vDiskNo:磁盘序号 
    	*/
    	DWORD GetLayoutInfo(DWORD vDiskNo);
    
    	//读MBR信息
    	BOOL ReadMBR(int vDiskNo, LPVOID *pBuffer);
    
    	/*
    	获取磁盘分区个数
    	vDiskNo:磁盘序号
    	*/
    	int GetPartNum(DWORD vDiskNo);
    
    	/*
    	初始化磁盘,创建分区
    	vDiskNo:磁盘序号,千万要避开系统盘,系统盘一般是0
    	vPartNum:分区数,只要1个分区就可以了
    	*/
    	DWORD CreateDisk(DWORD vDiskNo, WORD vPartNum);
    
    	/*
    	回复磁盘到空白状态,删除MBR分区信息
    	*/
    	DWORD DestroyDisk(DWORD vDiskNo);
    
    }; 

    如果CreateDisk之后文件系统格式还是RAW的,那么可以用这个:
    /******************************************************************************
    * Function:快速格式化某个磁盘,文件系统NTFS
    * input: disk, disk name
    * output: N/A
    * return: Succeed, 0
    *         Fail, 1
    ******************************************************************************/
    DWORD CMDiskManager::FormatVolume(CHAR letter)
    {
    	DWORD ret;
    	CHAR cmd[64];
    	sprintf(cmd, "format %c: /FS:NTFS /Q /Y", letter);
    	ret = (DWORD)system(cmd);
    	return ret;
    }







    展开全文
  • Windows 系统中的文件路径格式

    千次阅读 2019-05-17 23:10:00
    title: Windows 系统中的文件路径格式 ms.date: 06/28/2018 ms.technology: dotnet-standard dev_langs: csharp vb helpviewer_keywords: I/O, long paths long paths path formats, Windows author: ...

    System.IO命名空间中很多类型的成员都包括 path 参数,让你可以指定指向某个文件系统资源的绝对路径或相对路径。 此路径随后会传递至 Windows 文件系统 API。 本主题讨论可在 Windows 系统上使用的文件路径格式。

    传统 DOS 路径

    标准的 DOS 路径可由以下三部分组成:

    • 卷号或驱动器号,后跟卷分隔符 (:)。
    • 目录名称。 目录分隔符用来分隔嵌套目录层次结构中的子目录。
    • 可选的文件名。 目录分隔符用来分隔文件路径和文件名。

    如果以上三项都存在,则为绝对路径。 如未指定卷号或驱动器号,且目录名称的开头是目录分隔符,则路径属于当前驱动器根路径上的相对路径。 否则路径相对于当前目录。 下表显示了一些可能出现的目录和文件路径。

    路径说明
    C:\Documents\Newsletters\Summer2018.pdfC: 盘根路径上的绝对文件路径。
    \Program Files\Custom Utilities\StringFinder.exe当前驱动器根路径上的绝对路径。
    2018\January.xlsx指向当前目录的子目录中的文件的相对路径。
    ..\Publications\TravelBrochure.pdf指向当前目录的同级目录中的文件的相对路径。
    C:\Projects\apilibrary\apilibrary.sln指向 C: 盘根路径中的文件的绝对路径。
    C:Projects\apilibrary\apilibrary.slnC: 盘当前目录上的相对路径。

    请注意最后两个路径之间的差异。 两者都指定了可选的卷说明符(均为“C:”),但前者以所指定卷的根开头,而后者不是。 结果,前者表示 C: 盘根目录上的绝对路径,而后者表示 C: 盘当前目录上的相对路径。 应使用前者时使用了后者是涉及 Windows 文件路径的 bug 的常见原因。

    可以通过调用 System.IO.Path.IsPathFullyQualified方法来确定文件路径是否完全限定(即是说,该路径独立于当前目录,且在当前目录更改时不发生变化)。 请注意,如果解析的路径始终指向同样的位置,那么此类路径可以包括相对目录段(...),而同时依然是完全限定的。

    以下示例演示绝对路径和相对路径之间的差异。 假定存在目录 D:\FY2018\,且在运行该示例之前还没有通过命令提示符为 D:\ 设置任何当前目录。

    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Reflection;
    
    public class Example
    {
       public static void Main(string[] args)
       {
          Console.WriteLine($"Current directory is '{Environment.CurrentDirectory}'");
          Console.WriteLine("Setting current directory to 'C:\\'");
          
          Directory.SetCurrentDirectory(@"C:\");
          string path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
          path = Path.GetFullPath(@"D:FY2018");
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          Console.WriteLine("Setting current directory to 'D:\\Docs'");
          Directory.SetCurrentDirectory(@"D:\Docs");
    
          path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
          path = Path.GetFullPath(@"D:FY2018");
    
          // This will be "D:\Docs\FY2018" as it happens to match the drive of the current directory
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          Console.WriteLine("Setting current directory to 'C:\\'");
          Directory.SetCurrentDirectory(@"C:\");
    
          path = Path.GetFullPath(@"D:\FY2018");
          Console.WriteLine($"'D:\\FY2018' resolves to {path}");
    
          // This will be either "D:\FY2018" or "D:\FY2018\FY2018" in the subprocess. In the sub process,
          // the command prompt set the current directory before launch of our application, which
          // sets a hidden environment variable that is considered.
          path = Path.GetFullPath(@"D:FY2018");
          Console.WriteLine($"'D:FY2018' resolves to {path}");
    
          if (args.Length < 1)
          {
             Console.WriteLine(@"Launching again, after setting current directory to D:\FY2018");
             Uri currentExe = new Uri(Assembly.GetExecutingAssembly().GetName().CodeBase, UriKind.Absolute);
             string commandLine = $"/C cd D:\\FY2018 & \"{currentExe.LocalPath}\" stop";
             ProcessStartInfo psi = new ProcessStartInfo("cmd", commandLine); ;
             Process.Start(psi).WaitForExit();
    
             Console.WriteLine("Sub process returned:");
             path = Path.GetFullPath(@"D:\FY2018");
             Console.WriteLine($"'D:\\FY2018' resolves to {path}");
             path = Path.GetFullPath(@"D:FY2018");
             Console.WriteLine($"'D:FY2018' resolves to {path}");
          }
          Console.WriteLine("Press any key to continue... ");
          Console.ReadKey();
       }
    }
    // The example displays the following output:
    //      Current directory is 'C:\Programs\file-paths'
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    //      Setting current directory to 'D:\Docs'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\Docs\FY2018
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    //      Launching again, after setting current directory to D:\FY2018
    //      Sub process returned:
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to d:\FY2018
    // The subprocess displays the following output:
    //      Current directory is 'C:\'
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\FY2018\FY2018
    //      Setting current directory to 'D:\Docs'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\Docs\FY2018
    //      Setting current directory to 'C:\'
    //      'D:\FY2018' resolves to D:\FY2018
    //      'D:FY2018' resolves to D:\FY2018\FY2018
    

    UNC 路径

    通用命名约定 (UNC) 路径,用于访问网络资源,具有以下格式:

    • 一个以 \\ 开头的服务器名或主机名。 服务器名称可以为 NetBIOS 计算机名称或者 IP/FQDN 地址(支持 IPv4 和 IPv6)。
    • 共享名,使用 \ 将其与主机名分隔开。 服务器名和共享名共同组成了卷。
    • 目录名称。目录分隔符(System.IO.Path.DirectorySeparatorChar)用来分隔嵌套目录层次结构中的子目录。
    • 可选的文件名。 目录分隔符用来分隔文件路径和文件名。

    以下是一些 UNC 路径的示例:

    路径说明
    \\system07\C$\system07 上 C: 盘的根目录。
    \\Server2\Share\Test\Foo.txt\\Server2\Share 卷的测试目录中的 Foo.txt 文件。

    UNC 路径必须始终是完全限定的。 它们可以包括相对目录段(...),但是这些目录段必须是完全限定的路径的一部分。 只能通过将 UNC 路径映射至驱动器号来使用相对路径。

    DOS 设备路径

    Windows 操作系统有一个指向所有资源(包括文件)的统一对象模型。 可从控制台窗口访问这些对象路径;并通过旧版 DOSUNC 路径映射到的符号链接的特殊文件,将这些对象路径公开至 Win32 层。 此特殊文件夹可通过 DOS 设备路径语法(以下任一)进行访问:

    \\.\C:\Test\Foo.txt
    \\?\C:\Test\Foo.txt

    从 NET Core 1.1 和 .NET Framework 4.6.2 开始,运行在 Windows 上的 .NET 实现支持 DOS 设备路径语法。

    DOS 设备路径由以下部分组成:

    • 设备路径说明符(\\.\\\?\),它将路径标识为 DOS 设备路径。

      .NET Core 的所有版本以及从 4.6.2 开始的 .NET Framework 版本都支持 \\?\

    • 指向“真正”设备对象(这里是 C:)的符号链接。

      设备路径说明符后的第一个 DOS 设备路径段标识了卷或驱动器。 (例如,\\?\C:\\\.\BootPartition\。)

      UNC 有个特定的链接,很自然地名为 UNC。 例如:

      \\.\UNC\Server\Share\Test\Foo.txt
      \\?\UNC\Server\Share\Test\Foo.txt

      对于设备 UNC,服务器/共享部分构成了卷。 例如,在 \\?\server1\e:\utilities\\filecomparer\ 中,服务器/共享部分是 server1\utilities。 使用相对目录段调用Path.GetFullPath(System.String,System.String)等方法时,这一点非常重要;决不可能越过卷。

    DOS 设备路径通过定义进行完全限定。 不允许使用相对目录段(...)。 也不会包含当前目录。

    示例:引用同一个文件的方法

    以下示例演示了一些方法,以此可在使用System.IO命名空间中的 API 时引用文件。 该示例实例化 System.IO.FileInfo 对象,并使用它的 System.IO.FileInfo.NameFileInfo.Length属性来显示文件名以及文件长度。

    using System;
    using System.IO;
    
    class Program
    {
        static void Main()
        {
            string[] filenames = {
                @"c:\temp\test-file.txt",
                @"\\127.0.0.1\c$\temp\test-file.txt",
                @"\\LOCALHOST\c$\temp\test-file.txt",
                @"\\.\c:\temp\test-file.txt",
                @"\\?\c:\temp\test-file.txt",
                @"\\.\UNC\LOCALHOST\c$\temp\test-file.txt",
                @"\\127.0.0.1\c$\temp\test-file.txt" };
    
            foreach (var filename in filenames)
            {
                FileInfo fi = new FileInfo(filename);
                Console.WriteLine($"file {fi.Name}: {fi.Length:N0} bytes");
            }
        }
    }
    // The example displays output like the following:
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    //      file test-file.txt: 22 bytes
    

    路径规范化

    几乎所有传递至 Windows API 的路径都经过规范化。 规范化过程中,Windows 执行了以下步骤:

    • 识别路径。
    • 将当前目录应用于部分限定(相对)路径。
    • 规范化组件和目录分隔符。
    • 评估相对目录组件(当前目录是 .,父目录是 ..)。
    • 剪裁特定字符。

    这种规范化隐式进行,若想显式进行规范化,可以调用 Path.GetFullPath方法,这会包装对 GetFullPathName() 函数的调用。 还可以使用 P/Invoke 直接调用 Windows GetFullPathName() 函数

    识别路径

    路径规范化的第一步就是识别路径类型。 路径归为以下几个类别之一:

    • 它们是设备路径;就是说,它们的开头是两个分隔符和一个问号或句点(\\?\\.)。
    • 它们是 UNC 路径;就是说,它们的开头是两个分隔符,没有问号或句点。
    • 它们是完全限定的 DOS 路径;就是说,它们的开头是驱动器号、卷分隔符和组件分隔符 (C:\)。
    • 它们指定旧设备(CONLPT1)。
    • 它们相对于当前驱动器的根路径;就是说,它们的开头是单个组件分隔符 (\)。
    • 它们相对于指定驱动器的当前目录;就是说,它们的开头是驱动器号和卷分隔符,而没有组件分隔符 (C:)。
    • 它们相对于当前目录;就是说,它们的开头是上述情况以外的任何内容 (temp\testfile.txt)。

    路径的类型决定是否以某种方式应用当前目录。 还决定该路径的“根”是什么。

    处理旧设备

    如果路径是旧版 DOS 设备(例如 CON``COM1LPT1),则会转换为设备路径(方法是在其前面追加 \\.\)并返回。

    开头为旧设备名的路径始终被 Path.GetFullPath(System.String)方法解释为旧设备。 例如,CON.TXT 的 DOS 设备路径为 \\.\CON,而 COM1.TXT\file1.txt 的 DOS 设备路径为 \\.\COM1

    应用当前目录

    如果路径非完全限定,Windows 会向其应用当前目录。 不会向 UNC 和设备路径应用当前目录。 带有分隔符 C:\\ 的完整驱动器也不会。

    如果路径的开头是单个组件分隔符,则会应用当前目录中的驱动器。 例如,如果文件路径是 \utilities 且当前目录为 C:\temp\,规范化后路径则为 C:\utilities

    如果路径开头是驱动器号和卷分隔符,而没有组件分隔符,则应用从命令行界面为指定驱动器设置的最新当前目录。 如未设置最新当前目录,则只应用驱动器。 例如,如果文件路径为 D:sources,当前目录为 C:\Documents\,且 D: 盘上的最新当前目录为 D:\sources\,则结果为 D:\sources\sources。 这些“驱动器相对”路径是导致程序和脚本逻辑错误的常见原因。 假设以字母和冒号开头的路径不是相对路径,显然是不正确的。

    如果路径不是以分隔符开头的,则应用当前驱动器和当前目录。 例如,如果路径是 filecompare 且当前目录是 C:\utilities\,则结果为 C:\utilities\filecompare\

    相对路径在多线程应用程序(也就是大多数应用程序)中很危险,因为当前目录是分进程的设置。 任何线程都能在任何时候更改当前目录。 从 .NET Core 2.1 开始,可以调用 Path.GetFullPath(System.String,System.String)方法,从想要据此解析绝对路径的相对路径和基础路径(当前目录)获取绝对路径。

    规范化分隔符

    将所有正斜杠 (/) 转换为标准的 Windows 分隔符,也就是反斜杠 (\)。 如果存在斜杠,前两个斜杠后面的一系列斜杠都将折叠为一个斜杠。

    评估相对组件

    处理路径时,会评估所有由一个或两个句点(...)组成的组件或分段:

    • 如果是单句点,则删除当前分段,因为它表示当前目录。

    • 如果是双句点,则删除当前分段和父级分段,因为双句点表示父级目录。

      仅当父级目录未越过路径的根时,才删除父级目录。 路径的根取决于路径的类型。 对于 DOS 路径,根是驱动器 (C:\);对于UNC,根是服务器/共享 (\\Server\Share);对于设备路径,则为设备路径前缀(\\?\\\.\)。

    剪裁字符

    随着分隔符的运行和相对段先遭删除,一些其他字符在规范化过程中也删除了:

    • 如果某段以单个句点结尾,则删除此句点。 (单个或两个句点的段在之前的步骤中已规范化。 三个或更多句点的段未规范化,并且实际上是有效的文件/目录名。)

    • 如果路径的结尾不是分隔符,则删除所有尾随句点和空格 (U+0020)。 如果最后的段只是单个或两个句点,则按上述相对组件规则处理。

      此规则意味着可以创建以空格结尾的目录名称,方法是在空格后添加结尾分隔符。

      请勿创建以空格结尾的目录名或文件名。 如果以空格结尾,则可能难以或者无法访问目录,并且应用程序在尝试处理这样的目录或文件时通常会操作失败。

    跳过规范化

    一般来说,任何传递到 Windows API 的路径都会(有效地)传递到 GetFullPathName 函数并进行规范化。 但是有一种很重要的例外情况:以问号(而不是句点)开头的设备路径。 除非路径确切地以 \\?\ 开头(注意使用的是规范的反斜杠),否则会对它进行规范化。

    为什么要跳过规范化过程? 主要有三方面的原因:

    1. 为了访问那些通常无法访问但合法的路径。 例如名为 hidden. 的文件或目录,这是能访问它的唯一方式。

    2. 为了在已规范化的情况下通过跳过规范化过程来提升性能。

    3. 为了跳过路径长度的 MAX_PATH 检查以允许多于 259 个字符的路径(仅在 .NET Framework 上)。 大多数 API 都允许这一点,也有一些例外情况。

    .NET Core 显式处理长路径,且不执行 MAX_PATH 检查。 MAX_PATH 检查只适用于 .NET Framework。

    跳过规范化和路径上限检查是两种设备路径语法之间唯一的区别;除此以外它们是完全相同的。 请谨慎地选择跳过规范化,因为很容易就会创建出“一般”应用程序难以处理的路径。

    如果将开头为 \\?\ 的路径显式地传递至 GetFullPathName 函数,则依然会对它们进行规范化。

    请注意,可将超过 MAX_PATH 字符数的路径传递至 GetFullPathName,前提是该路径不含 \\?\。 支持任意长度的路径,只要其字符串大小在 Windows 能处理的范围内。

    大小写和 Windows 文件系统

    Windows 文件系统有一个让非 Window 用户和开发人员感到困惑的特性,就是路径和目录名称不区分大小写。 也就是说,目录名和文件名反映的是创建它们时所使用的字符串的大小写。 例如,名为

    Directory.Create("TeStDiReCtOrY");
    

    的方法创建名为 TeStDiReCtOrY 的目录。 如果重命名目录或文件以改变大小写,则目录名或文件名反映的是重命名它们时所使用的字符串的大小写。 例如,以下代码将文件 test.txt 重命名为 Test.txt

    using System.IO;
    
    class Example
    {
       static void Main()
       {
          var fi = new FileInfo(@".\test.txt");
          fi.MoveTo(@".\Test.txt");
       }
    }
    

    但是比较目录名和文件名时不区分大小写。 如果搜索名为“test.txt”的文件,.NET 文件系统 API 会在比较时忽略大小写问题。Test.txt、TEST.TXT、test.TXT 和其他任何大写和小写的字母组合都会成为“test.txt”的匹配项。

    展开全文
  • windows python读取文件路径格式问题

    千次阅读 2020-02-22 16:06:30
    windows python读取文件路径三种格式: ‘D:\Documents\Data.csv’ ——>转义的方式。表示这里\是一个普通\字符,不容易出错 r ‘D:\Documents\Data.csv’ ——>声明字符串。表示不需要转义,因此这里\ ...
  • Windows 创建和格式化硬盘 (12T) 分区 - 失败记录 若要在硬盘上创建分区或卷,必须以管理员身份登录,并且硬盘上必须有未分配的磁盘空间或者在硬盘上的扩展分区内必须有可用空间。 如果没有任何未分配的磁盘空间,则...
  • Windows路径操作API函数

    千次阅读 2015-09-16 19:07:48
    PathRemoveArgs:去除路径的参数;PathRemoveBackslash:去除路径最后的反斜杠“\”;PathAddBackslash:在路径最后加上反斜杠“\”;PathRemoveBlanks:去除路径前后的空格;PathAddExtension:在文件路径后面加上...
  • Windows 路径操作 API

    千次阅读 2015-04-04 12:37:25
    路径截断与合并函数       PathRemoveArgs 去除路径的参数 PathRemoveBackslash 去除路径最后的反斜杠“\” PathAddBackslash  在路径最后加上反...
  • 文件路径提示 —auto filename 1、打开sublime text 3编辑器,开始编写代码,会发现写img src的时候并没有智能提示。这时我们需要安装插件。 2、点开菜单“preferences”——“package control”; 3、在弹出的...
  • windows下使用indent工具格式化代码

    千次阅读 2014-03-27 13:47:45
    在linux下可以用indent格式化c语言代码,本工具是indent的windows移植版本,只需要将含有indent.exe的文件夹放在有环境变量的路径下就可以在命令行下使用。 下载链接; ... 在命令行里面的使用和linux下差不多。...
  • Windows下使用gvim格式化xml文件

    千次阅读 2010-12-27 10:15:00
    2. 配置_vimrc文件Windows下"_vimrc"文件默认保存在gvim安装根目录下。在最后添加au FileType xml exe ":silent 1,$!xmllint % --format --recover"表示使用xmllint打开xml文件。如果xmllint.exe没有加入PATH,$!后...
  • windows路径操作API函数

    千次阅读 2013-11-19 16:30:11
    PathRemoveArgs 去除路径的参数 PathRemoveBackslash 去除路径最后的反斜杠"\" PathAddBackslash 在路径最后加上反斜杠"\" PathRemoveBlanks 去除路径前后的空格 PathAddExtension 在文件路径后面加上扩展名 ...
  • Windows Shell路径处理函数

    千次阅读 2017-05-26 09:59:44
    Windows Shell路径处理函数。以下函数由Shlwapi.dll导出,并在Shlwapi.h和Shlwapi.lib中定义。PathAddBackslash 在字符串的末尾添加反斜杠,以创建路径的正确语法。如果源路径已经有一个尾部反斜杠,则不会添加反...
  • windows 路径相关的shell api

    千次阅读 2013-09-25 14:49:45
    路径截断与合并函数       PathRemoveArgs 去除路径的参数 PathRemoveBackslash 去除路径最后的反斜杠“\” PathAddBackslash  在路径最后加上反...
  • 转载地址:...   windows路径操作API函数 路径截断与合并函数       PathRemoveArgs 去除路径的参数 PathRemoveBackslash 去除路径最
  • java 代码格式化

    千次阅读 2015-10-25 21:02:11
    所以在阅读代码的时候,有一个统一的格式的话就好多了,下面介绍一下使用eclipse代码xml文件来达到格式化文件中的代码的例子,首先我们需要拥有一个统一的格式化代码的xml文件,该文件的地址我已经上传,可以下载: ...
  • vscode vue 格式化 末尾逗号去除

    万次阅读 多人点赞 2020-09-24 18:29:34
    vscode vue项目格式化 vue项目格式化,可以安装vetur插件。 配置文件打开步骤。 ctrl键+逗号键 ; 点击这个图标, 插件完成之后,配置文件,如下 { //配置vscode 的终端为 git,路径是自己的安装路径可以自己找...
  • 路径截断与合并函数       PathRemoveArgs 去除路径的参数 PathRemoveBackslash 去除路径最后的反斜杠“\” PathAddBackslash  在路径最后加上反斜杠“\” PathRemoveBlanks ...
  • Windows7系统设置相对路径快捷方式

    千次阅读 2019-06-13 12:17:10
    Windows系统下,创建快捷方式,默认是绝对路径 坏处:移动目录后,快捷方式无法使用 创建相对路径快捷方式 1、给需创建快捷方式的文件,创建一个快捷方式 2、将D.txt - Shortcut重命名为D,并将其移动...
  • ubuntu下格式化被写保护的U盘

    千次阅读 2017-08-09 14:18:53
    windows系统下没找到直接的格式化被写保护的u盘的方法,要下载专门的格式化工具,但太多软件绑定了而且不一定有效。 所以直接在ubuntu系统下用了两句命令搞定了: 先插入u盘,看u盘的路径是多少,一般为"/...
  • 使用astyle格式化代码

    千次阅读 2015-01-23 13:05:05
    astyle是一款代码格式化工具,它的下载地址是:http://sourceforge.net/projects/astyle 一。...astyle --style=ansi main.cs (ansi/linux:使用ansi/linux风格格式化main.cs) --style=ansi 就...
  • windows常用API函数,用于各种路径名的操作管理。适合在windows环境下开发的初学者使用。
  • Windows文件路径在python的使用

    千次阅读 2018-11-05 12:04:26
    windows读取文件路径可以用\,但是在字符串中\是被当作转义字符来使用, 所以’d:\a.txt’会被转义成’d:\a.txt’这是正确路径,所以不会报错。 而‘C:\Users\FrankYuan\Pictures\CameraRoll\WIN_20161010_08_51_57_...
  • Python中读取文件时的路径格式问题

    万次阅读 2018-07-07 21:35:13
    Python在读取文件内容时的路径问题,值得深究一下.我想讨论的重点还是在绝对路径上面.在这之前我们先看一下1:相对路径.这张图演示了在相对路径下寻找查找指定文件. open('相对路径演示'\'相对路径示例'.txt)打开...
  • VUE在VSCode中的代码格式化设置

    千次阅读 2018-11-16 15:19:31
    VUE在VSCode中的代码格式化设置 { &quot;terminal.integrated.shell.windows&quot;: &quot;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe&quot;, &quot;gitlens.advanced....
  • 【小知识】VScode格式化代码配置及插件

    万次阅读 多人点赞 2019-08-20 02:31:17
    VScode格式化代码配置及插件 学会使用扩展和配置,能让你的vs code生产效率提高百分之二十 ——鲁迅
  • windows上的路径操作函数

    千次阅读 2011-07-06 09:18:52
    路径截断与合并函数 PathRemoveArgs去除路径的参数PathRemoveBackslash去除路径最后的反斜杠“\”PathAddBackslash 在路径最后加上反斜杠“\”PathRemoveBlanks去除路径前后的空格PathAddExt

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 219,152
精华内容 87,660
关键字:

windows路径格式化