MFC使用Windows API实现U盘插拔检测,获取U盘容量,U盘内容移动删除,开启和关闭U盘以及获取盘符
文章目录
- 前言
- 一、利用OS API实现对U盘的管理
- 二、项目到底长啥样
- 三、实例代码
- 1.实时判断U盘插入与拔出
- 2.能够显示U盘的总容量、使用容量和剩余容量
- 3.能够将某个目录上的文件或整个目录复制到U盘上
- 4. 删除U盘上文件
- 5.禁止U盘的使用及开启U盘的使用
- 6.尝试读取PCB信息
- 四、总结
前言
MFC实现对U盘的管理并用图形化界面展示出来。
项目下载地址
MFC教程
一、利用OS API实现对U盘的管理
- 能够判断U盘是否存在
- 能够显示U盘的总容量、使用容量和剩余容量;
- 能够将某个目录上的文件或整个目录复制到U盘上;
- 可以删除U盘上文件;
- 禁止U盘的使用及开启U盘的使用;
- 推荐使用C# winform,也可以使用其它语言;
- 体会OS的API的作用; 尝试读取PCB信息;
- 其它创意。 项目最终能以图形界面的形式完成。
二、项目到底长啥样
三、实例代码
本项目主要采用MFC(微软基础类库)开发一个Windows窗体程序,实现对U盘的管理。项目第一个功能以及使用MFC开发的idea源自一位学长。其余功能由自己通过网上查阅资料实现。
项目传送门:
https://blog.csdn.net/qq_39861376/article/details/102678582
1.实时判断U盘插入与拔出
OnDeviceChange(UINT nEventType, DWORD dwData):
首先设置消息映射:
afx_msg BOOL OnDeviceChange(UINT nEventType, DWORD dwData);
BEGIN_MESSAGE_MAP(CMFCUSBDlg, CDialogEx)ON_WM_SYSCOMMAND()ON_WM_PAINT()ON_WM_QUERYDRAGICON()ON_BN_CLICKED(IDC_BUTTON1, &CMFCUSBDlg::OnBnClickedButton1)//ON_WM_ACTIVATE()ON_WM_DEVICECHANGE()
END_MESSAGE_MAP()
注册USB设备消息,不注册消息处理函数无法响应, 只有注册了该设备,OnDeviceChange才能获得详细的信息,否则收到的nEventType参数都是0007,dwData无数据。
BOOL CMFCUSBDlg::OnInitDialog()// 注意向OnInitDialog中添加如下代码;DEV_BROADCAST_DEVICEINTERFACE Filter;ZeroMemory(&Filter, sizeof(Filter));Filter.dbcc_size = sizeof(Filter); // size gets set to 29 with 1-byte packing or 32 with 4- or 8-byte packingFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;Filter.dbcc_classguid = {0xA5DCBF10,0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } };//DEVICE_NOTIFY_ALL_INTERFACE_CLASSES //关注所有设备事件RegisterDeviceNotification(this->m_hWnd, &Filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES);if (NULL == RegisterDeviceNotification(this->m_hWnd, &Filter, DEVICE_NOTIFY_ALL_INTERFACE_CLASSES))TRACE("RegisterDeviceNotification failed!!");
常见的GUID:
GUID:
https://blog.csdn.net/diyu122222/article/details/79791073
C/C++ code
static const GUID GUID_DEVINTERFACE_LIST[] =
{// GUID_DEVINTERFACE_USB_DEVICE{ 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } },// GUID_DEVINTERFACE_DISK{ 0x53f56307, 0xb6bf, 0x11d0, { 0x94, 0xf2, 0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b } },// GUID_DEVINTERFACE_HID, { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } },// GUID_NDIS_LAN_CLASS{ 0xad498944, 0x762f, 0x11d0, { 0x8d, 0xcb, 0x00, 0xc0, 0x4f, 0xc3, 0x35, 0x8c } }GUID_DEVINTERFACE_COMPORT//{ 0x86e0d1e0, 0x8089, 0x11d0, { 0x9c, 0xe4, 0x08, 0x00, 0x3e, 0x30, 0x1f, 0x73 } },GUID_DEVINTERFACE_SERENUM_BUS_ENUMERATOR//{ 0x4D36E978, 0xE325, 0x11CE, { 0xBF, 0xC1, 0x08, 0x00, 0x2B, 0xE1, 0x03, 0x18 } },GUID_DEVINTERFACE_PARALLEL//{ 0x97F76EF0, 0xF883, 0x11D0, { 0xAF, 0x1F, 0x00, 0x00, 0xF8, 0x00, 0x84, 0x5C } },GUID_DEVINTERFACE_PARCLASS//{ 0x811FC6A5, 0xF728, 0x11D0, { 0xA5, 0x37, 0x00, 0x00, 0xF8, 0x75, 0x3E, 0xD1 } }
};
接受设备变更消息:
BOOL CMFCUSBDlg::OnDeviceChange(UINT nEventType, DWORD dwData)
{//const int DBT_DEVICEARRIVAL = 0x8000; // system detected a new device//public const int DBT_DEVICEQUERYREMOVE = 0x8001; // Preparing to remove (any program can disable the removal)//const int DBT_DEVICEREMOVECOMPLETE = 0x8004; // removed //const int DBT_DEVTYP_VOLUME = 0x00000002;//DEV_BROADCAST_DEVICEINTERFACE * dbd = (DEV_BROADCAST_DEVICEINTERFACE*)dwData;//CString str;//str.Format(_T("U disk in !"));//SetDlgItemText(IDC_BUTTON1, str);第一个短点,判断是否接收到设备变动的信息CString detectMsg;char m_decDriver;PDEV_BROADCAST_HDR lpdb = (PDEV_BROADCAST_HDR)dwData;switch (nEventType){case DBT_DEVICEARRIVAL:{//第二个断点,判断nEventType传来的值是0007还是0X8000if (lpdb->dbch_devicetype==DBT_DEVTYP_VOLUME)//逻辑卷{PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;switch (lpdbv->dbcv_flags){case 0://U盘{m_decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);detectMsg.Format(_T("检测到U盘:[%c]插入!"),m_decDriver);MessageBox(detectMsg);}break;case DBTF_MEDIA://光盘break;}}}break;case DBT_DEVICEREMOVECOMPLETE:// Handle device removal{if (lpdb->dbch_devicetype == DBT_DEVTYP_VOLUME)//逻辑卷{PDEV_BROADCAST_VOLUME lpdbv = (PDEV_BROADCAST_VOLUME)lpdb;switch (lpdbv->dbcv_flags){case 0: //U盘{m_decDriver = FirstDriveFromMask(lpdbv->dbcv_unitmask);//detectMsg.Format(_T("检测到U盘:[%s]拔出!"), m_decDriver/*.GetBuffer(0)*/);detectMsg.Format(_T("检测到U盘:[%c]拔出!"),m_decDriver);MessageBox(detectMsg);}break;case DBTF_MEDIA: //光盘break;}}}break;}//CString str;//str.Format(_T("U disk in !"));//SetDlgItemText(IDC_BUTTON1, str);return TRUE;
}
获取单元掩码:
char FirstDriveFromMask(ULONG unitmask)
{char i;for (i = 0; i < 26; ++i){if (unitmask & 0x1)break;unitmask = unitmask >> 1;}return(i + 'A');
}
2.能够显示U盘的总容量、使用容量和剩余容量
按钮事件:
void CMFCUSBDlg::OnBnClickedButton1()
{CString m_decDriver = GetDiskLetter();// 获取盘符INT_PTR nRes;CTipDlg tipDlg; // 构造对话框类CTipDlg的实例 nRes = tipDlg.DoModal(); // 弹出对话框 //从这里开始UpdateData(true);ULARGE_INTEGER nFreeBytesAvailable;ULARGE_INTEGER nTotalNumberOfBytes;ULARGE_INTEGER nTotalNumberOfFreeBytes;//lpDirectoryName 是驱动器的名称。//lpFreeBytesAvailableToCaller 是用户可用的磁盘空间。//lpTotalNumberOfBytes 是磁盘总共的空间。//lpTotalNumberOfFreeBytes 是磁盘空闲的空间。以上都是字节为单位。if (GetDiskFreeSpaceEx(m_decDriver + ":", &nFreeBytesAvailable, &nTotalNumberOfBytes, &nTotalNumberOfFreeBytes)){CString str;str.Format(_T("用户可用的磁盘空间:%.2fGB\n磁盘总空间:%.2fGB\n磁盘空闲空间:%.2fGB\n"), (GB(nFreeBytesAvailable)), (GB(nTotalNumberOfBytes)), (GB(nTotalNumberOfFreeBytes)));MessageBox(str, _T("磁盘信息"), MB_OK);}UpdateData(false);
}
获取盘符:
CString GetDiskLetter()
{CString strDiskLetter = _T("");LPTSTR lpDrives = new TCHAR[MAX_PATH];DWORD dwLen = ::GetLogicalDriveStrings(MAX_PATH, lpDrives);CString sDrives[26];for (DWORD nIndex = 0; nIndex < dwLen / 4; nIndex++){if (::GetDriveType(lpDrives + nIndex * 4) == DRIVE_REMOVABLE){sDrives[nIndex] += (CString)(lpDrives + nIndex * 4);if (sDrives[nIndex] != _T("A://") && sDrives[nIndex] != _T("B://")){CString usbPath = sDrives[nIndex];strDiskLetter = usbPath.Left(1);//AfxMessageBox(strDiskLetter);break;}}}delete lpDrives;return strDiskLetter;
}
字节与GB转化:
float GB(ULARGE_INTEGER TotalNumberOfBytes) {int iTotal = (TotalNumberOfBytes.u.HighPart << 12) + (TotalNumberOfBytes.u.LowPart >> 20);return iTotal / 1024.0;
}
3.能够将某个目录上的文件或整个目录复制到U盘上
获取文件路径:
void CMFCUSBDlg::OnBnClickedButtonfile()
{CString strFile = _T("");CFileDialog dlgFile(TRUE, NULL, NULL, OFN_HIDEREADONLY, _T("Describe Files (*.jpg)|*.jpg|All Files (*.*)|*.*||"), NULL);if (dlgFile.DoModal()){strFile = dlgFile.GetPathName();}SetDlgItemText(EditFile, strFile);// TODO: 在此添加控件通知处理程序代码
}
获取目录路径:
void CMFCUSBDlg::OnBnClickedButtondir()
{TCHAR szFolderPath[MAX_PATH] = { 0 };CString strFolderPath = TEXT("");BROWSEINFO sInfo;::ZeroMemory(&sInfo, sizeof(BROWSEINFO));sInfo.pidlRoot = 0;sInfo.lpszTitle = _T("请选择处理结果存储路径");sInfo.ulFlags = BIF_RETURNONLYFSDIRS | BIF_EDITBOX | BIF_DONTGOBELOWDOMAIN;sInfo.lpfn = NULL;// 显示文件夹选择对话框 LPITEMIDLIST lpidlBrowse = ::SHBrowseForFolder(&sInfo);if (lpidlBrowse != NULL){// 取得文件夹名 if (::SHGetPathFromIDList(lpidlBrowse, szFolderPath)){strFolderPath = szFolderPath;}}if (lpidlBrowse != NULL){::CoTaskMemFree(lpidlBrowse);}CString strFile;GetDlgItemText(EditFile, strFile);string dirname = Replace(strFile);string filename;int flag;for (int i = dirname.length() - 1; i >= 0; i--){if (dirname[i] == '/') {flag = i;break;}}for (int i = flag + 1; i < dirname.length(); i++) {filename += dirname[i];}//strFolderPath = strFolderPath + filename;CString cstrTest;cstrTest = CA2T(filename.c_str());SetDlgItemText(EditDir, strFolderPath+cstrTest);//return strFolderPath
}
复制文件:
void CMFCUSBDlg::OnBnClickedButtoncopy()
{//string Ef= "C:/masm/usb/usb.txt";//string Nf = "D:/1usb.txt";CString Ef; GetDlgItemText(EditFile, Ef);CString Nf; GetDlgItemText(EditDir, Nf);CString str;//str.Format(_T("请选择要复制的文件"));if (Replace(Ef)=="") {//cout << 1;str.Format(_T("请选择要复制的文件"));MessageBox(str); }else if (Replace(Nf) == ""){str.Format(_T("请选择文件复制位置"));MessageBox(str);}else{ wstring stempEf = s2ws(Replace(Ef));wstring stempNf = s2ws(Replace(Nf));LPCWSTR resultEf = stempEf.c_str();LPCWSTR resultNf = stempNf.c_str();// TODO: 在此添加控件通知处理程序代码CString str;str.Format(_T("复制失败,请检查您的文件路径"));if (!CopyFile(resultEf, resultNf, FALSE)){MessageBox(str);} else {str.Format(_T("Copy successfully!"));MessageBox(str);}}
}
替换函数:
//把\替换成/
string Replace(CString str) {string strTest;//CString转换为StringstrTest = CT2A(str.GetString());for (int i = 0; i < strTest.length(); i++) {if (str[i] == '\\') {strTest = strTest.replace(i, 1, "/");}}return strTest;
}
类型转换函数(string转化为wstring再转换为LPCTSTR):
//string到wstring类型转换,wstring可以转换为LPCTSTR文件
wstring s2ws(const std::string& s) {int len;int slength = (int)s.length() + 1;len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);wchar_t* buf = new wchar_t[len];MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);std::wstring r(buf);delete[] buf;return r.c_str();}
第二种类型转换的方法:
LPCWSTR stringToLPCWSTR(std::string orig)
{size_t origsize = orig.length() + 1;const size_t newsize = 100;size_t convertedChars = 0;wchar_t *wcstring = (wchar_t *)malloc(sizeof(wchar_t)*(orig.length() - 1));mbstowcs_s(&convertedChars, wcstring, origsize, orig.c_str(), _TRUNCATE);return wcstring;
}
第三种类型转化:
直接强转(LPCTSTR)string
4. 删除U盘上文件
获取文件路径:同复制操作
删除文件:
void CMFCUSBDlg::OnBnClickedButtondelete()
{CString Nf;GetDlgItemText(EditFile, Nf);wstring stempNf = s2ws(Replace(Nf));LPCWSTR resultNf = stempNf.c_str();BOOL del = DeleteFile(resultNf);if (del){MessageBox(_T("删除成功"), _T("提示信息"), MB_OK);}else{DWORD error_rus = GetLastError();MessageBox( _T("删除失败"), _T("提示信息"), MB_OK);}}
5.禁止U盘的使用及开启U盘的使用
这里采用更改注册表的方式达到禁用与开启的效果,详情可以见:
https://blog.csdn.net/weixin_44627672/article/details/109430607
void CMFCUSBDlg::OnBnClickedCloseu()
{long lRet;HKEY hKey;lRet = RegCreateKey(HKEY_LOCAL_MACHINE,_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"),&hKey);DWORD KeyValue = 4;if (lRet == ERROR_SUCCESS){//MessageBox(_T("right"), _T("Prompt"), MB_OK);lRet = RegSetKeyValue(HKEY_LOCAL_MACHINE,_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"),_T("Start"),REG_DWORD,(LPBYTE)&KeyValue,sizeof(DWORD));if (lRet == ERROR_SUCCESS){MessageBox(_T("禁用成功"), _T("Prompt"), MB_OK);}else{MessageBox(_T("禁用失败,请检查您的权限"), _T("Prompt"), MB_OK);}RegCloseKey(hKey);}else {MessageBox(_T("权限不足"), _T("Prompt"), MB_OK);RegCloseKey(hKey);}//open+query查询值/*TCHAR tchData[64];DWORD dwSize;DWORD dwValue, dwType;DWORD dwBufLen = 255;DWORD dwRet;dwSize = sizeof(data);lRet = RegOpenKeyEx(HKEY_LOCAL_MACHINE, // handle to open key_T("SYSTEM\\CurrentControlSet\\Services\\USBSTOR"), // subkey name0, // reservedKEY_QUERY_VALUE, // security access mask&hKey // handle to open key);假设start说存储的数据是REG_SZlRet = RegQueryValueEx(hKey, // handle to key_T("Start"), // value namesNULL, // reservedNULL, // type buffer(LPBYTE)tchData, // data buffer&dwSize // size of data buffer);if (RegQueryValueEx(hKey, _T("Start"), NULL, &dwType, (LPBYTE)&dwValue, &dwBufLen) == ERROR_SUCCESS){if (dwType == REG_DWORD)dwRet = dwValue;}else {MessageBox(_T("234"));}RegCloseKey(hKey);*/
}
6.尝试读取PCB信息
这里只获取了PID
//获取PCB信息如PID
void CMFCUSBDlg::OnBnClickedButtonpcb()
{CString str;DWORD csPid;csPid = GetCurrentProcessId();str.Format(_T("PID:%u"), csPid);//SetDlgItemText(IDC_EDIT1, _T("PID:[]"));SetDlgItemText(IDC_EDIT1, str);
}
四、总结
做完这个项目将近三天,因为自己基础不好实现起来不是很容易,好在终于解决了;主要还是提高了自己的文献检索能力(如何快速的从网上获得自己所需要的东西,这点很重要)、以及独立解决问题的能力(一个复杂的问题是如何一步一步解决的。从毫无思路到知道大概思路再到具体实现,不断发现问题解决问题,最后走到终点。)
就像海里航行的船,没有指南针,到处都没有路,也可以说到处都是路,如何走到终点这是一个很重要的问题。
最后感谢以下大佬的博客:
1.VS2017加装MFC以及创建第一个MFC程序
https://blog.csdn.net/qq_35987486/article/details/94456910
https://blog.csdn.net/qq_39861376/article/details/102678582
2.为什么找不到标志符
https://blog.csdn.net/taotaoah/article/details/46333983
三.判断U盘是否拔出与插入
1.如何进行消息映射
https://blog.csdn.net/eqiang8271/article/details/24477001?utm_medium=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-BlogCommendFromMachineLearnPai2-1.channel_param
2.USB GUID
https://blog.csdn.net/phenixyf/article/details/48783271
3.判断U盘插入拔出程序
https://blog.csdn.net/qq_39861376/article/details/102678582
4.各个函数的使用以及导入外部库(windows.h,dbt.h)
MSDN
四.判断U盘容量
lpDirectoryName 是驱动器的名称。
lpFreeBytesAvailableToCaller 是用户可用的磁盘空间。
lpTotalNumberOfBytes 是磁盘总共的空间。
lpTotalNumberOfFreeBytes 是磁盘空闲的空间。以上都是字节为单位。
1.GB与bytes转换:
https://blog.csdn.net/qq_41786318/article/details/80969881
2.获取盘符
忘了记录
3.判断U盘容量程序
https://blog.csdn.net/qq_39861376/article/details/102678582
4.如何用MFC框架生成模态对话框弹出式的程序(跟C#、VB,类似)
鸡啄米http://www.jizhuomi.com/software/160.html
五、复制文件操作
1.copyfile函数的使用
MSDN
https://www.jb51.net/article/190834.htm
2.如何查找文件路径
https://blog.csdn.net/wuhenyouyuyouyu/article/details/78521092
3.string中的replace函数
https://blog.csdn.net/qq_40968179/article/details/104380460
4.Cstring与string之间的相互转换
https://blog.csdn.net/Gordon_Wei/article/details/90443677
5.string如何转换成LPCTSTR类型
https://www.cnblogs.com/qinguoyi/p/7249561.html?utm_source=itdadao&utm_medium=referral
六、删除U盘上的文件
1.deleteFile函数等使用
MSDN
七、停止U盘的使用与终止U盘的使用
如何通过注册表禁用U盘
https://jingyan.baidu.com/article/e2284b2b892cd7e2e6118dbb.html
对注册表的操作
https://www.cnblogs.com/zhaoyixiang/p/12983823.html
如何修改REG_DWORD类型的start值
https://zhidao.baidu.com/question/1046050784719513299.html
八、尝试读取PCB的信息
VC如何获取当前自身PID:
https://blog.csdn.net/sunnysab/article/details/9367077?utm_medium=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param&depth_1-utm_source=distribute.pc_relevant.none-task-blog-BlogCommendFromMachineLearnPai2-3.channel_param
MFC使用Windows API实现U盘插拔检测,获取U盘容量,U盘内容移动删除,开启和关闭U盘以及获取盘符相关推荐
- linux U盘插拔检测
因为最终要在tiny210上实现此功能,最终选择了hotplug. http://hi.baidu.com/hdy5200075/item/7751f48647f3d12a100ef3f6这里是hot ...
- 教程一:windows api(c mfc vs2017)实现U盘插拔检测,获取U盘容量,U盘内容移动,开启和关闭U盘以及获取盘符等
c++是大二下学期的专业课,大家可能都学过,这里主要介绍U盘这个小项目要用到没学过的知识.(踩坑合集) U盘完整项目源代码下载地址:https://download.csdn.net/download ...
- android u盘挂载监听,Android SD卡及U盘插拔状态监听及内容读取
本篇是通过系统方法来对sd卡及U盘插拔监听及数据获取,Android盒子端开发,有系统权限,当然,这个比较简单,知道具体方法,可以通过反射来实现. 先贴上效果图: 获取外置存储设备并监听插拔状态 获取 ...
- Android SD卡及U盘插拔状态监听和内容读取
本篇是通过系统方法来对sd卡及U盘插拔监听及数据获取,Android盒子端开发,有系统权限,当然,这个比较简单,知道具体方法,可以通过反射来实现. 先贴上效果图: 获取外置存储设备并监听插拔状态 获取 ...
- Python:dbus监控U盘插拔
本文主要介绍在PyQt5中,使用dbus监控U盘插拔. 测试环境:python3 + dbus + pyqt5 当无法引入dbus.mainloop.pyqt5时,安装对应的包即可: sudo apt ...
- VB中简便的检测U盘插拔的方法(DriveListBox)
我在网上找了很多资料,实现检测U盘插拔的方法基本上都是监测WM_DEVICECHANGE.这种方法不但臃肿,而且效率不高,很容易出错.于是我摸索出了一种新的方法,以下就是实现过程. 首先在窗体中添加一 ...
- 耳机驱动调试(插拔检测与按键检测)
耳机驱动调试(插拔检测与按键检测) 小白一枚,欢各位大佬指出错误 耳机类型判断 三段和四段.欧标和美标 现在许多设备的耳机接口都采用3.5mm的耳机接口,其中终端就是,终端可以兼容三段和四段耳机:三段 ...
- mtk充电器插拔检测
以mt6357 pmic为例,充电器插拔检测和类型检测在mt6357-charger-type.c下完成: 一.首先从pmic的probe开始分析: static int mt6357_charger ...
- windows快捷键失效 - 重启无效 - 插拔键盘解决
被windows快捷键失效问题折磨了很久,快捷键都失效了,包括: windows + e windows + r windows + l 等等,尝试修复注册表,尝试设置"关闭Windows键 ...
最新文章
- MLIR算子量化Quantization
- hyperopt中文文档:Parallelizing-Evaluations-During-Search-via-MongoDB
- 11. 盛最多水的容器 golang
- [美团 CodeM 初赛 Round A]最长树链
- 史上最经典CAP讲解
- 越狱解决iphone4s外放无声音
- 梦幻粉色空间手机背景素材,爱梦想的设计师
- 苏州科技学院计算机组成原理考试,苏州科技学院计算机组成原理复习提纲.doc...
- Visual Studio Code for DBA的介绍
- SNS类游戏cache server设计浅析
- Centos 7忘记密码,如何重置
- win10隐藏桌面功能
- 揭密360急速免杀系列教程
- 手机刷入面具_【手机改造计划】搞机助手 - 小白刷机必备工具,搞机一条龙:解锁、root、刷面具、刷xposed框架、模块下载安装、自动救砖...
- vue实现登录验证码
- 编译原理 --- 正规式和有限自动机
- 计算机无法复制大文件格式,U盘复制文件电脑提示文件过大无法复制怎么解决?...
- 树莓派安装MPlayer播放器
- 鸽巢排序Pigeonhole sort
- 微型计算机中什么是小随机储存器,随机存取存储器
热门文章
- java 发送邮件添加附件,Java实现带附件的邮件发送功能
- mac wordcloud 字体设置
- 调试MCP2515驱动时遇到的问题 CAN控制器和CAN收发器之间的TX和RX引脚接反,导致无法正常收发数据
- 客户主数据知识点总结
- VMware Workstation 与 Device/Credential Guard 不兼容解决方案
- win7打不开计算机网络连接,win7电脑网络连接正常打不开网页怎么解决
- resulful规范_resultful风格接口
- 爬虫+可视化——链家杭州二手房房源信息
- 张景明:方剂【方歌】——清热剂
- SLCP验厂辅导,工厂进行社会劳工整合项目(SLCP认证)验证的具体步骤