Qt案例 使用WINDOWS API的VDS.H库查询/修改 WINDOWS系统中硬盘分区/盘符信息(二)

简单介绍使用vds.h中的类和方法操作修改硬件/盘符的一些常使用的结构和函数,包括获取格式、删除、创建分区,设置磁盘文件类型,格式化卷等;
值得注意的是即使在vds.h库中像格式化卷这种都有多个方法,需要根据实际需求选择合适的方法。

目录导读

    • 提示
    • VDS服务是否能使用
    • 磁盘操作
      • 打开使用 CreateFile 函数创建磁盘对象的句柄
      • 获取磁盘设计大小
      • 格式分区
      • 创建分区
        • 使用 IOCTL_DISK_SET_DRIVE_LAYOUT_EX 创建分区(推荐)
        • 使用 IVdsCreatePartitionEx 接口 创建分区
    • 卷操作
      • 获取卷列表
      • 打开使用 CreateFile 函数创建卷对象的句柄
      • 获取卷关联的磁盘
      • 获取卷的驱动器号
      • 获取卷名称或文件系统名称
      • 获取卷上剩余空间/卷大小等信息
      • 格式化卷

提示

在对磁盘和卷进行处理时,建议简单了解他们之间的关系,可以参考
【Windows系统】磁盘、Partition和Volume的联系与区别
本文涉及的部分类和函数,优先参考
Qt案例 使用WINDOWS API的VDS.H库查询/修改 WINDOWS系统中硬盘分区/盘符信息(一)
一文中的IVdsDisk 接口IVdsVolume 接口的声明基础上使用,
注意不要用有重要数据的磁盘/分区来进行测试。容易造成数据丢失!

VDS服务是否能使用

在部分精简系统或者阉割系统中是不会包含vds服务,需要简单判断是否支持vds服务,以便于后续操作。

bool IsVDSAvailable()
{IVdsService* pService = NULL;IVdsServiceLoader* pLoader = NULL;HRESULT hr = CoCreateInstance(CLSID_VdsLoader, NULL, CLSCTX_LOCAL_SERVER | CLSCTX_REMOTE_SERVER,IID_IVdsServiceLoader, (void**)&pLoader);if (hr != S_OK) {qDebug("Notice: Disabling VDS (Could not create VDS Loader Instance: %s)", WindowsError::GetVdsError(hr));goto out;}hr = pLoader->LoadService( L"", &pService);if (hr != S_OK) {qDebug("Notice: Disabling VDS (Could not load VDS Service: %s)", WindowsError::GetVdsError(hr));goto out;}out:if (pService != NULL)pService->Release();if (pLoader != NULL)pLoader->Release();return (hr == S_OK);
}

磁盘操作

打开使用 CreateFile 函数创建磁盘对象的句柄

通过VDS_DISK_PROP结构可以获取pwszName,打开磁盘操作对象句柄;

//pwszName : \\?\PhysicalDrive2HANDLE hDrive = INVALID_HANDLE_VALUE;hDrive = CreateFileW(prop.pwszName, GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);if(hDrive==INVALID_HANDLE_VALUE){continue;}

获取磁盘设计大小

使用 DISK_GEOMETRY_EX 结构 (描述磁盘设备和介质的扩展几何结构)获取磁盘设计大小。
可用获取 DISK_GEOMETRY 结构 获取磁盘的 Cylinders(柱面数)。
磁盘设计大小:柱面数*每个柱面的轨道数*每个轨道的扇区数*每个扇区字节数
DiskSize =Cylinders*TracksPerCylinder*SectorsPerTrack*BytesPerSector

 BYTE geometry[256] = {0};PDISK_GEOMETRY_EX DiskGeometry = (PDISK_GEOMETRY_EX)(void*)geometry;DWORD size=0;if(!DeviceIoControl(hDrive, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,NULL, 0, geometry, sizeof(geometry), &size, NULL)||size==0){CloseHandle(hDrive);continue;}//qDebug()<<"柱面数量: "<<QString::number(DiskGeometry->Geometry.Cylinders.QuadPart,10);

格式分区

使用IVdsAdvancedDisk::FormatPartition方法格式化创建好的分区,此方法仅设置 OEM、ESP 和未知分区的格式,如果是其他分区需要根据磁盘分区偏移量,找到对应的卷然后使用 IVdsVolumeMF::FormatIVdsVolumeMF2::FormatEx 方法格式化相应的卷。这样磁盘分区才能正常使用,计算机管理-》磁盘管理才会正常显示分区

/*
//!.hVDS 实现此方法。此方法仅设置 OEM、ESP 和未知分区的格式。对于其他分区,必须使用 IVdsVolumeMF::Format 或 IVdsVolumeMF2::FormatEx 方法格式化相应的卷。请注意,OEM、ESP 和未知分区不会作为卷公开,因此不能使用 Format 或 FormatEx 进行格式化。此方法不能用于格式化可移动媒体。*////  The operation is not supported on removable media/// \brief D_FormatPartition 设置现有 OEM、ESP 或未知分区的格式。/// \param _ullOffset 分区偏移量。/// \param _type [VDS_FST_NTFS、VDS_FST_FAT、VDS_FST_FAT32或VDS_FST_UDF]/// \param _pwszLabel 表示卷标签的字符串。/// \param _dwUnitAllocationSize 文件系统分配单元的大小(以字节为单位)/// \param _bForce  如果为 TRUE,则即使正在使用分区,分区也会格式化/// \param _bQuickFormat  如果为 TRUE,则 VDS 执行快速格式/// \param _bEnableCompression 如果为TRUE,则对新格式化的文件系统启用压缩 不能为 FAT 和 FAT32 文件系统设置压缩/// \return///bool D_FormatPartition( ULONGLONG _ullOffset,VDS_FILE_SYSTEM_TYPE _type,LPWSTR _pwszLabel,DWORD _dwUnitAllocationSize,BOOL _bForce=true,BOOL _bQuickFormat=true,BOOL _bEnableCompression=false);//!.Cpp
bool D_FormatPartition( ULONGLONG _ullOffset,VDS_FILE_SYSTEM_TYPE _type,LPWSTR _pwszLabel,DWORD _dwUnitAllocationSize,BOOL _bForce,BOOL _bQuickFormat,BOOL _bEnableCompression)
{bool result=false;//pAdvancedDisk 是 IVdsAdvancedDisk 接口的具体实例IVdsAsync* pAsync=NULL;ULONG ulPercentCompleted=0;HRESULT hResult =pAdvancedDisk->FormatPartition( _ullOffset, _type, _pwszLabel, _dwUnitAllocationSize,_bForce,_bQuickFormat, _bEnableCompression,&pAsync);ULONG jindu=0;while (SUCCEEDED(hResult)) {if (IS_ERROR(hResult)) {pAsync->Cancel();break;}HRESULT hresult2;hResult = pAsync->QueryStatus( &hresult2, &ulPercentCompleted);if (SUCCEEDED(hResult)) {hResult=hresult2;if (hResult == S_OK)break;if (hResult == VDS_E_OPERATION_PENDING)hResult = S_OK;}if(jindu!=ulPercentCompleted){jindu=ulPercentCompleted;qDebug()<<" schedule : "<<jindu;}if(ulPercentCompleted==100)break;}result=(hResult==S_OK);if(!result)qDebug()<<"pAdvancedDisk  Clean is failed! "<<WindowsError::GetVdsError(hResult);out:return result;
}

创建分区

使用 IOCTL_DISK_SET_DRIVE_LAYOUT_EX 创建分区(推荐)

IOCTL_DISK_SET_DRIVE_LAYOUT_EX 按指定对磁盘进行重新分区。
推荐使用这种方式格式化分区,直接可以同时创建多个分区,唯一需要注意的是
需要简单修改 DRIVE_LAYOUT_INFORMATION_EX 结构体

/*  MinGW is unhappy about accessing partitions beside the first unless we redef */
//! MinGW不喜欢访问第一个分区之外的分区,除非我们重新定义
typedef struct _DRIVE_LAYOUT_INFORMATION_EX4 {DWORD PartitionStyle;DWORD PartitionCount;union {DRIVE_LAYOUT_INFORMATION_MBR Mbr;DRIVE_LAYOUT_INFORMATION_GPT Gpt;} Type;PARTITION_INFORMATION_EX PartitionEntry[16];
} DRIVE_LAYOUT_INFORMATION_EX4, *PDRIVE_LAYOUT_INFORMATION_EX4;

调用:

  LONGLONG ullSize=1215277056;///设置后方分区大小LONGLONG ullSize=2373588*prop.ulBytesPerSector;LONGLONG ullOffset=DiskUllSize-ullSize;CREATE_DISK CreateDisk = {PARTITION_STYLE_MBR, {{0}}};CreateDisk.PartitionStyle=PARTITION_STYLE_MBR;CreateDisk.Mbr.Signature=(DWORD)GetTickCount64();DRIVE_LAYOUT_INFORMATION_EX4 DriveLayoutEx = {0};DriveLayoutEx.PartitionStyle=PARTITION_STYLE_MBR;DriveLayoutEx.PartitionCount=2;DriveLayoutEx.PartitionEntry[0].PartitionStyle=PARTITION_STYLE_MBR;DriveLayoutEx.PartitionEntry[0].StartingOffset.QuadPart=ullOffset;DriveLayoutEx.PartitionEntry[0].PartitionLength.QuadPart=ullSize;DriveLayoutEx.PartitionEntry[0].PartitionNumber=1;DriveLayoutEx.PartitionEntry[0].RewritePartition=TRUE;DriveLayoutEx.PartitionEntry[0].Mbr.BootIndicator=TRUE;DriveLayoutEx.PartitionEntry[0].Mbr.PartitionType=0xef;DriveLayoutEx.PartitionEntry[0].Mbr.RecognizedPartition=TRUE;//设置中间间隔LONGLONG Offset=(2048*prop.ulBytesPerSector);//设置分区大小LONGLONG OffullSize=DiskUllSize-ullSize-Offset;DriveLayoutEx.PartitionEntry[1].PartitionStyle=PARTITION_STYLE_MBR;DriveLayoutEx.PartitionEntry[1].StartingOffset.QuadPart=Offset;DriveLayoutEx.PartitionEntry[1].PartitionLength.QuadPart=OffullSize;DriveLayoutEx.PartitionEntry[1].PartitionNumber=2;DriveLayoutEx.PartitionEntry[1].RewritePartition=TRUE;DriveLayoutEx.PartitionEntry[1].Mbr.BootIndicator=TRUE;DriveLayoutEx.PartitionEntry[1].Mbr.PartitionType=0xef;DriveLayoutEx.PartitionEntry[1].Mbr.RecognizedPartition=TRUE;DriveLayoutEx.Type.Mbr.Signature = CreateDisk.Mbr.Signature;//hDrive 磁盘对象句柄DWORD size = sizeof(CreateDisk);//!如果不调用IOCTL_DISK_CREATE_DISK, IOCTL_DISK_SET_DRIVE_LAYOUT_EX调用将失败bool r = DeviceIoControl(hDrive, IOCTL_DISK_CREATE_DISK, (BYTE*)&CreateDisk, size, NULL, 0, &size, NULL);if (!r) {qDebug()<<"Could not reset disk: %s"<< GetError();return ;}RefreshDriveLayout();size=sizeof(DriveLayoutEx);r = DeviceIoControl(hDrive, IOCTL_DISK_SET_DRIVE_LAYOUT_EX, (BYTE*)&DriveLayoutEx,  size, NULL, 0, &size, NULL);if (!r) {qDebug()<<"Could not set drive layout: "<< GetError();return ;}RefreshDriveLayout();
使用 IVdsCreatePartitionEx 接口 创建分区

IVdsCreatePartitionEx 接口 在基本磁盘上创建分区。
IVdsCreatePartitionEx::CreatePartitionEx 在基本磁盘上创建分区。
IVdsCreatePartitionEx 接口实例需要通过IVdsDisk 接口获取。

  • 初始化实例:
   IVdsCreatePartitionEx*  pCreatePartition=NULL;//判断 IVdsDisk 接口 接口实例是否有效//IFNULL_GOTO(pDisk,"pDisk No instantiation!",out);HRESULT hResult= pDisk->QueryInterface(IID_IVdsCreatePartitionEx,(void **)&pCreatePartition);if (hResult != S_OK){qDebug("Could not initialize_pCreatePartition : %s", GetLastError());pCreatePartition=NULL;}
  • 创建分区:
///  如果起始分区不在第一柱形内,分区后的分区偏移量会发生偏适用于创建一个分区差/// \brief 在基本磁盘上创建分区。  [此方法取代 IVdsAdvancedDisk::CreatePartition 方法。]///  *当调用方同时指定 ullOffset 和 ulAlign 参数时,偏移量必须位于第一个柱形内*。/// \param _ullOffset 分区偏移量/// \param _ullSize 新分区的大小(以字节为单位)/// \param _ulAlign 对齐大小(以字节为单位)。/// \param para  gpt/mbr/// \return///bool CreatePartitionEx(ULONGLONG _ullOffset,ULONGLONG _ullSize,ULONG _ulAlign,CREATE_PARTITION_PARAMETERS *para);
 bool result=false;//判断IVdsCreatePartitionEx 接口是否有效 //IFNULL_INIT_ISNULL_GOTO(pCreatePartition,initialize_pCreatePartition(),"pCreatePartition No instantiation! ",out);IVdsAsync* pAsync=NULL;ULONG ulPercentCompleted;HRESULT hResult =pCreatePartition->CreatePartitionEx(_ullOffset,_ullSize,_ulAlign,para,&pAsync);ULONG jindu=0;while (SUCCEEDED(hResult)) {if (IS_ERROR(hResult)) {pAsync->Cancel();break;}HRESULT hresult2;hResult = pAsync->QueryStatus( &hresult2, &ulPercentCompleted);if (SUCCEEDED(hResult)) {hResult=hresult2;if (hResult == S_OK)break;if (hResult == VDS_E_OPERATION_PENDING)hResult = S_OK;}if(jindu!=ulPercentCompleted){jindu=ulPercentCompleted;qDebug()<<" schedule : "<<jindu;}if(ulPercentCompleted==100)break;}result=(hResult==S_OK);///if(!result)///     qDebug()<<"pCreatePartition CreatePartitionEx is failed! "<<WindowsError::GetVdsError(hResult);

注意:如果起始分区偏移量不在第一柱形内,分区后的分区偏移量会发生偏移
一般磁盘的一个扇区512字节,一个柱面有255个轨道,每个轨道63个扇区;
所以第一个分区的起始偏移量不能超过 1*255*63*512 字节
发生偏移后,就没办法准确获取对应的卷进行格式化,不推荐使用。

卷操作

获取卷列表

通过FindFirstVolume 扫描计算机的卷。
FindFirstVolume 函数打开卷搜索句柄,并返回有关在计算机上找到的第一个卷的信息。 建立搜索句柄后,可以使用 FindNextVolume 函数搜索其他卷。 如果不再需要搜索句柄,请使用 FindVolumeClose 函数将其关闭。

HANDLE hDrive = INVALID_HANDLE_VALUE, hVolume = INVALID_HANDLE_VALUE;
wchar_t * volume_name[MAX_PATH], path[MAX_PATH];for(uint32_t i=0; true; i++){if (i == 0) {hVolume = FindFirstVolumeW((LPWSTR)volume_name, sizeof(volume_name));if (hVolume == INVALID_HANDLE_VALUE) {qDebug("Could not access first GUID volume");goto out;}} else {if (!FindNextVolumeW(hVolume, (LPWSTR)volume_name, sizeof(volume_name))) {if (GetLastError() != ERROR_NO_MORE_FILES) {qDebug("Could not access next GUID volume");}qDebug()<<"FindNextVolumeW is failed!";break;}}QString volume_d=QString::fromWCharArray((LPCWSTR)volume_name);qDebug()<<"[volume_d] "<<volume_d;
}

打开使用 CreateFile 函数创建卷对象的句柄

通过 volume_name 打开卷对象句柄
[volume_d] "\\\\?\\Volume{2efb2ac5-6828-4320-8848-041647908928}\\"

  QString volume_d=QString::fromWCharArray((LPCWSTR)volume_name);hDrive = CreateFileW((LPCWSTR)volume_d.mid(0,volume_d.length()-1).toStdWString().c_str(), GENERIC_READ|FILE_READ_ATTRIBUTES|SYNCHRONIZE|FILE_TRAVERSE,FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL, NULL);if (hDrive == INVALID_HANDLE_VALUE) {qDebug("Could not open GUID volume '%s'", volume_name);continue;}

获取卷关联的磁盘

VOLUME_DISK_EXTENTS 结构
表示磁盘上的物理位置,可通过此结构获取卷对应的磁盘。经常使用。

///重构结构体
typedef struct _VOLUME_DISK_EXTENTS_OverDide {DWORD       NumberOfDiskExtents;// Set ANYSIZE_ARRAY = 8DISK_EXTENT Extents[8];
} VOLUME_DISK_EXTENTS_OverDide;
 VOLUME_DISK_EXTENTS_OverDide DiskExtents;DWORD size=0;//hDrive 卷对象句柄bool r = DeviceIoControl(hDrive, IOCTL_VOLUME_GET_VOLUME_DISK_EXTENTS, NULL, 0,&DiskExtents, sizeof(DiskExtents), &size, NULL);if ((!r) || (size == 0)) {qDebug("Could not get Disk Extents: (empty data)!");if(hDrive!=NULL)CloseHandle(hDrive);continue;}if (DiskExtents.NumberOfDiskExtents == 0) {qDebug("Ignoring volume '%s' because it has no extents...", volume_name);continue;}if (DiskExtents.NumberOfDiskExtents != 1) {// If we have more than one extent for a volume, it means that someone// is using RAID-1 or something => Stay well away from such a volume!qDebug("Ignoring volume '%s' because it has more than one extent (RAID?)...", volume_name);continue;}
// DiskExtents.Extents[0].DiskNumber 磁盘索引//if (DiskExtents.Extents[0].DiskNumber != Deive_item.DeviceNumber)// Not on our disk//    continue;

获取卷的驱动器号

getVolumePathNamesForVolumeNameW 函数 检索指定卷的驱动器号和装载的文件夹路径的列表。

  DWORD  CharCount = MAX_PATH + 1;PWCHAR Names = (PWCHAR) new BYTE [CharCount * sizeof(WCHAR)];bool Success = GetVolumePathNamesForVolumeNameW((LPCWSTR)volume_name, Names, CharCount, &CharCount);if ( !Success )continue;
//        qDebug()<<"[Names] : "<<QString::fromWCharArray(Names);

获取卷名称或文件系统名称

getVolumeInformationByHandleW 函数
检索与指定文件关联的文件系统和卷的相关信息。

   LPCWSTR lpRootPathName=(LPCWSTR)Names;DWORD   nVolumeNameSize=MAX_PATH+1;LPWSTR  lpVolumeNameBuffer=(LPWSTR)new BYTE [nVolumeNameSize * sizeof(WCHAR)];LPDWORD lpVolumeSerialNumber=0;LPDWORD lpMaximumComponentLength=0;LPDWORD lpFileSystemFlags=0;DWORD   nFileSystemNameSize=MAX_PATH+1;LPWSTR  lpFileSystemNameBuffer=(LPWSTR)new BYTE [nFileSystemNameSize * sizeof(WCHAR)];BOOL ishave= GetVolumeInformationByHandleW(hDrive,lpVolumeNameBuffer,nVolumeNameSize,lpVolumeSerialNumber,lpMaximumComponentLength,lpFileSystemFlags,lpFileSystemNameBuffer,nFileSystemNameSize);if(!ishave)continue;qDebug()<<"[lpVolumeNameBuffer] : "<<QString::fromWCharArray(lpVolumeNameBuffer);qDebug()<<"[lpFileSystemNameBuffer] : "<<QString::fromWCharArray(lpFileSystemNameBuffer);

获取卷上剩余空间/卷大小等信息

getDiskFreeSpaceExA 函数 检索有关磁盘卷上可用空间量的信息,即空间总量、可用空间总量以及与调用线程关联的用户可用空间总量。
参数 驱动器根路径,比如“D:”

LPCSTR pszDrive;
DWORD64 qwFreeBytesToCaller, qwTotalBytes, qwFreeBytes;
DWORD dwSectPerClust, dwBytesPerSect, dwFreeClusters,  dwTotalClusters;
BOOL bResult;//使用GetDiskFreeSpaceEx获取磁盘信息并打印结果bResult = GetDiskFreeSpaceExA (pszDrive,(PULARGE_INTEGER)&qwFreeBytesToCaller,(PULARGE_INTEGER)&qwTotalBytes,(PULARGE_INTEGER)&qwFreeBytes);if(bResult){printf("使用GetDiskFreeSpaceEx获取磁盘空间信息\n");printf("可获得的空闲空间(字节): \t%I64d\n", qwFreeBytesToCaller);printf("空闲空间(字节): \t%I64d\n", qwFreeBytes);printf("磁盘总容量(字节): \t%I64d\n", qwTotalBytes);}//使用GetDiskFreeSpace获取磁盘信息并打印结果
bResult = GetDiskFreeSpaceA (pszDrive,&dwSectPerClust,&dwBytesPerSect,&dwFreeClusters,&dwTotalClusters);if(bResult)
{printf("\n使用GetDiskFreeSpace获取磁盘空间信息\n");printf("空闲的簇数量 : \t%d\n",dwFreeClusters);printf("总簇数量 : \t%d\n",dwTotalClusters);printf("每簇的扇区数量 : \t%d\n",dwSectPerClust);printf("每扇区的容量(字节): \t%d\n",dwBytesPerSect);printf("空闲空间(字节): \t%I64d\n",(DWORD64)dwFreeClusters*(DWORD64)dwSectPerClust*(DWORD64)dwBytesPerSect);printf("磁盘总容量(字节): \t%I64d\n",(DWORD64)dwTotalClusters*(DWORD64)dwSectPerClust*(DWORD64)dwBytesPerSect);
}

格式化卷

IVdsVolumeMF3::FormatEx2 方法 格式化分区上的文件系统卷。 此方法与 IVdsVolumeMF2::FormatEx 方法相同,只是使用 Options 参数指定格式设置选项。

  • IVdsVolumeMF3接口通过 IVdsVolume接口实例获取:
 	IVdsVolumeMF3 * pVolumeMF3=NULL;//判断 IVdsVolume 接口实例是否有效//IFNULL_GOTO(pVolume,"pVolume No instantiation!",out);HRESULT hResult= pVolume->QueryInterface(IID_IVdsVolumeMF3,(void **)&pVolumeMF3);if (hResult != S_OK){qDebug("Could not initialize_pVolumeMF3 : %s", GetLastError());pVolumeMF3=NULL;}
  • FormatEx2 格式化分区:
// The following should match VDS_FSOF_FLAGS as much as possible
#define FP_FORCE                            0x00000001
#define FP_QUICK                            0x00000002LPWSTR _pwszFileSystemTypeName=(LPWSTR)L"NTFS";
USHORT _usFileSystemRevision=NULL;
ULONG _ulDesiredUnitAllocationSize=NULL;
LPWSTR _pwszLabel=(LPWSTR)L"数据分区"
DWORD _Options=FP_FORCE|FP_QUICKbool result=false;
//判断pVolumeMF3实例是否有效
//IFNULL_INIT_ISNULL_GOTO(pVolumeMF3,initialize_pVolumeMF3(),"IVdsAdvancedDisk No instantiation! ",out);
IVdsAsync* pAsync=NULL;
ULONG ulPercentCompleted=0;
HRESULT hResult =pVolumeMF3->FormatEx2( _pwszFileSystemTypeName, _usFileSystemRevision, _ulDesiredUnitAllocationSize,_pwszLabel, _Options,&pAsync);
ULONG jindu=0;
while (SUCCEEDED(hResult)) {if (IS_ERROR(hResult)) {pAsync->Cancel();break;}HRESULT hresult2;hResult = pAsync->QueryStatus( &hresult2, &ulPercentCompleted);if (SUCCEEDED(hResult)) {hResult=hresult2;if (hResult == S_OK)break;if (hResult == VDS_E_OPERATION_PENDING)hResult = S_OK;}if(jindu!=ulPercentCompleted){jindu=ulPercentCompleted;qDebug()<<" schedule : "<<jindu;}if(ulPercentCompleted==100)break;
}
result=(hResult==S_OK);
if(!result)qDebug()<<"pVolumeMF3 FormatEx2 is failed! "<<WindowsError::GetVdsError(hResult);

需要注意的是,在格式化分区后都需要根据分区偏移量获取对应的卷,在指定文件格式类型格式化卷。否则创建的卷将不可用,无法识别!

  • 测试时注意保存重要数据!
  • 在修改操作卷时需要注意操作流程:
    更改卷文件系统:
    打开卷。
    锁定卷。
    设置卷的格式。
    卸载卷。
    解锁卷。
    关闭卷柄。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/661258.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Node: opensslErrorStack: [ ‘error:03000086:digital envelope routines::initialization error‘ ]异常处理

目录 一、问题描述二、问题分析三、解决方案方案一&#xff1a;你可以按照以下步骤来删除 NODE_OPTIONS 环境变量中的 --openssl-legacy-provider 选项&#xff1a;方案二&#xff1a;在package.json更改scripts方案三&#xff1a;降级 Node.js 版本 在进行前端项目开发时&…

Linux+服务器后台运行程序

在Linux服务器直接运行程序&#xff0c;程序运行的时间较长&#xff0c;程序经常会因为网络连接问题异常终止&#xff0c;一直盯着程序运行又费时费力&#xff0c;这时后台运行程序是更好的解决方式。But&#xff0c;如果服务器重启了&#xff0c;那所有进程都断掉了&#xff0…

关于v8垃圾回收机制以及与其相关联的知识点--还没整理版本

对于值类型b来说&#xff0c;就直接释放了其占用的内存&#xff0c;对于引用类型obj来说&#xff0c;销毁的只是变量obj对堆内存地址 1001 的引用&#xff0c;obj的值 { c: 3 } 依然存在于堆内存中。那么堆内存中的变量如何进行回收呢&#xff1f; V8的垃圾回收策略主要是基于…

2024年美国大学生数学建模竞赛思路与源代码【2024美赛D题】

B站账号&#xff0c;提前关注&#xff0c;会有直播&#xff1a;有为社的个人空间-有为社个人主页-哔哩哔哩视频 (bilibili.com) 题目 待定 问题一 思路 待定 模型 待定 程序 待定 问题二 待定 思路 待定 模型 待定 程序 待定

【Java 数据结构】栈和队列

栈和队列 1. 栈(Stack)1.1 概念1.2 栈的使用1.3 栈的模拟实现1.4 栈的应用场景1.5 概念区分 2. 队列(Queue)2.1 概念2.2 队列的使用2.3 队列模拟实现2.4 循环队列 3. 双端队列 (Deque)4. 面试题 1. 栈(Stack) 1.1 概念 栈&#xff1a;一种特殊的线性表&#xff0c;其只允许在…

自然语言处理,基于预训练语言模型的方法,车万翔,引言部分

文章目录 自然语言处理应用任务1. 信息抽取2. 情感分析3. 问答系统4. 机器翻译5. 对话系统 自然语言处理应用任务 1. 信息抽取 信息抽取&#xff08;Information Extraction, IE&#xff09;&#xff0c;是从非结构化的文本中&#xff0c;抽取出结构化信息的过程&#xff0c;…

C++ 单一附合导线平差程序

一、以下图附合导线为例&#xff0c;图形如下&#xff1a; 二、第一步&#xff0c;读取测量数据&#xff0c;读取界面设计如下&#xff1a; 读取数据文本文件格式如下&#xff1a; &#xff08;1&#xff09;已知点坐标数据格式&#xff1a; &#xff08;2&#xff09;角度观测…

【C++杂货铺】详解类和对象 [下]

个人博客&#xff1a;代码菌-CSDN博客 专栏&#xff1a;C杂货铺_代码菌的博客-CSDN博客 目录 &#x1f308;前言&#x1f308; &#x1f4c1; 初始化列表&#xff08;灰常重要&#xff09; &#x1f4c2; 引入 &#x1f4c2; 概念 &#x1f4c2; 特性 &#x1f4c1; 拓展构…

51单片机编程应用(C语言):数码管

目录 1.数码管原理 一位数码管引脚定义&#xff1a; 四位一体数码管&#xff1a; 多个数码管同时显示不同数字 51单片机的数码管的原理图 51单片机实现静态显示和动态显示 静态显示&#xff1a; 动态显示&#xff1a; 1.数码管原理 一位数码管引脚定义&#xff1a; 数码…

外包干了10个月,技术退步明显...

先说一下自己的情况&#xff0c;大专生&#xff0c;18年通过校招进入武汉某软件公司&#xff0c;干了接近4年的功能测试&#xff0c;今年年初&#xff0c;感觉自己不能够在这样下去了&#xff0c;长时间呆在一个舒适的环境会让一个人堕落! 而我已经在一个企业干了四年的功能测…

【代码随想录】LC 349. 两个数组的交集

文章目录 前言一、题目1、原题链接2、题目描述 二、解题报告1、思路分析2、时间复杂度3、代码详解 前言 本专栏文章为《代码随想录》书籍的刷题题解以及读书笔记&#xff0c;如有侵权&#xff0c;立即删除。 一、题目 1、原题链接 349. 两个数组的交集 2、题目描述 二、解题报…

C语言实战项目<贪吃蛇>

我们这篇会使用C语言在Windows环境的控制台中模拟实现经典小游戏贪吃蛇 实现基本的功能&#xff1a; 结果如下: 1.一些Win32 API知识 本次实现呢我们会用到一些Win32 API的知识(WIN32 API也就是Microsoft Windows 32位平台的应用程序编程接口): 1)控制窗口大小 我们可以使用…

【Qt学习笔记】(二)信号和槽

信号和槽 1 信号和槽概述2 信号和槽的使用3 可视化生成槽函数4 自定义信号和槽5 带参数的信号和槽6 信号与槽的连接方式7 信号与槽的断开8 使用 Lambda 表达式来定义槽函数 1 信号和槽概述 在Qt中&#xff0c;用户和控件的每次交互过程称为一个事件。比如"用户点击按钮&q…

实时时钟芯片DS1307单片机C语言驱动程序

实时时钟RTC相关索引 1.单片机RTC及时钟芯片的时间到底从哪一年起始&#xff1f; 2.STM32F103单片机内部RTC实时时钟驱动程序 3.实时时钟芯片DS1302单片机C语言驱动程序 4.实时时钟芯片DS1307单片机C语言驱动程序 一、DS1307简介 DS1307是一款非易失性实时时钟&#xff08;R…

代码随想录算法训练营第五十一天 | 309.最佳买卖股票时机含冷冻期、714.买卖股票的最佳时机含手续费

309.最佳买卖股票时机含冷冻期 题目链接&#xff1a;309.最佳买卖股票时机含冷冻期I 给定一个整数数组prices&#xff0c;其中第 prices[i] 表示第 *i* 天的股票价格 。 设计一个算法计算出最大利润。在满足以下约束条件下&#xff0c;你可以尽可能地完成更多的交易&#xf…

【Java程序设计】【C00209】基于SSM个人求职管理系统(论文+PPT)

基于SSM个人求职管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这个一个基于SSM的个人求职管理系统&#xff0c;本系统共分为三种权限&#xff1a;管理员、普通管理员、用户 管理员&#xff1a;首页、个人中心、用户管理、管理…

Day 31 | 贪心算法 理论基础 、455.分发饼干 、 376. 摆动序列 、 53. 最大子序和

理论基础 文章讲解 455.分发饼干 题目 文章讲解 视频讲解 思路&#xff1a;从小饼干开始喂小胃口 class Solution {public int findContentChildren(int[] g, int[] s) {Arrays.sort(g);Arrays.sort(s);int start 0;int count 0;for (int i 0; i < s.length &&a…

go并发编程-介绍与Goroutine使用

1. 并发介绍 进程和线程 A. 进程是程序在操作系统中的一次执行过程&#xff0c;系统进行资源分配和调度的一个独立单位。B. 线程是进程的一个执行实体,是CPU调度和分派的基本单位,它是比进程更小的能独立运行的基本单位。C.一个进程可以创建和撤销多个线程;同一个进程中的多个…

Go语言的100个错误使用场景(11-20)|项目组织和数据类型

前言 大家好&#xff0c;这里是白泽。 《Go语言的100个错误以及如何避免》 是最近朋友推荐我阅读的书籍&#xff0c;我初步浏览之后&#xff0c;大为惊喜。就像这书中第一章的标题说到的&#xff1a;“Go: Simple to learn but hard to master”&#xff0c;整本书通过分析100…

DevSecOps 参考模型介绍

目录 一、参考模型概述 1.1 概述 二、参考模型分类 2.1 DevOps 组织型模型 2.1.1 DevOps 关键特性 2.1.1.1 模型特性图 2.1.1.2 特性讲解 2.1.1.2.1 自动化 2.1.1.2.2 多边协作 2.1.1.2.3 持续集成 2.1.1.2.4 配置管理 2.1.2 DevOps 生命周期 2.1.2.1 研发过程划分…