我们不如自己写一个映射网络驱动器工具吧

还记得上篇说到的VS创建QT工程并添加到GitHub中吗?
我们当时创建了一个项目,叫NetDrive,是本人闲着打算写的一个小工具,打算做一个网络驱动器的映射的工具
这小东西开源在GitHub中,大家可以在GitHub中fork下来一起玩,参加到这个小项目中,欢迎提交PR哦。
那废话不多说了,我们打开项目

设计界面

先双击ui文件,进入设计界面

从左边拖一些基本的组件进来
把功能和大概要展示出来的关键内容给摆好

创建连接信号槽

emmm,大概设计好这个界面之后
我们就可以将槽函数、按钮什么的,绑定好
在我们的设计器里,点击信号设置

按回车没用的,要点那个 + 号

看到这个按钮绑定到这个函数,就可以了
我们准备写功能去,记得先Ctrl + S 保存好哟

准备功能函数开发

参考了巨硬的这个官方说明样例:https://docs.microsoft.com/zh-cn/windows/desktop/WNet/assigning-a-drive-to-a-share

他们都提供好一个Demo了,这就十分快乐了,代码看起来简单易懂
就施展CV大法了

这个时候,他就报错了。
说,无法从“const char [6]”转换为“TCHAR [32]”

所以,我们就看看TCHAR是什么类型
在TCHAR那里,F12,跟进一下到它声明的地方


看到TCHAR就是WCHAR
再跟一下,看到WCHAR就是wchar_t
是16-bit 的 Unicode的字符,16-bit就是两个字节嘛
所以,在官方demo中,解决这个 const char 无法转到TCHAR的办法就是 加个 L

在字符串前加一个L作用: unicode字符集是两个字节组成的。L告示编译器使用两个字节的 unicode 字符集。

在这里,我随意,打印一个样例出来,加L和不加L的一个字符串所占空间给大家看看
至于为啥MARXCBR七个字符占了8个空间,是因为字符串会自动加一个“/0”
结合上面说的和图里面的数据,相信大家能从中一眼看出差异所在

踩的坑:一

OK,咱们解决了官方demo在本地不适用的情况之后
我们直接运行一下

将我之前搞的那个NAS的账号密码还有本地盘符以及映射路径填好之后

在res那个地方,断个点,看一下,有没能映射回来

嗯,看起来是映射成功了

我们回到资源管理器里面看看

但是,没找到我映射回来的B盘
不对呀,刚才都说连接成功,映射成功了

然后,这就是我踩坑的地方了,嘻嘻嘻。我那时候,找来找去都没到为啥,又跑去说明文档里面去看。
但是都没说到,为啥资源管理器没有显示我的网络驱动器

直到,本人在VS中关掉项目,打算重新打开时,才发现
映射的盘符显示在里面了。。。

然后才醒悟,我的VS是用管理员权限去运行的

所以,写好跑出来的程序,也是用管理员去执行的。那么映射回来盘,就只能有管理员权限才能看到啦。

跑去CMD里面,确认一下,的确是管理员才能看到。

所以,用普通用户权限去执行一下这个程序

资源管理器里面就出来了

那么,官方的demo坑就踩完了

创建函数与前面设计的信号关联

接着,我们要建立一个函数,名字与刚才在设计器里面绑定的函数一样
在点击 “连接” 按钮后,就会自动连接好我们所填参数的网络驱动器

在头文件里面,加入 slots:

1
2
public slots:
void connectDrive();

在cpp里面,写逻辑代码
在这里,我们需要获取用户填入的用户名、密码、他所期待的驱动器号,还有远程映射的路径

但是,这里有个需要提醒的:设计不规格,编码泪两行

如上图所示,如果在designer 里面,没将控件对应的对象名定义好的话
在写代码的时候,你就会连自己也不知道这一堆不明意义的控件默认名称到底哪个是哪个
所以,我们在设计的时候,就要将控件的对象名给确定好


然后,输入对象的名字,回车!
还要记得保存,Ctrl S 一下,否则是不会保存更改的。

我们回到VS里面,重新生成一下
这个时候,再用ui.去找对象,就好找多了

编写网络驱动器映射函数

然后,将刚才的demo,抽出来,搞成一个函数
将需要的参数传过去就好了

然后,在QString转TCHAR的时候,果不其然,还是要出幺蛾子

应使用{…} 来初始化聚合对象
所以,我们给他加了一个{}

然后在网上参考了一下:QString到TCHAR
尝试了几个方案,都不行,最后在某一篇博文中,找到了一段类型转换的宏定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

#ifdef UNICODE

#define QStringToTCHAR(x) (wchar_t*) x.utf16()

#define PQStringToTCHAR(x) (wchar_t*) x->utf16()

#define TCHARToQString(x) QString::fromUtf16((x))

#define TCHARToQStringN(x,y) QString::fromUtf16((x),(y))

#else

#define QStringToTCHAR(x) x.local8Bit().constData()

#define PQStringToTCHAR(x) x->local8Bit().constData()

#define TCHARToQString(x) QString::fromLocal8Bit((x))

#define TCHARToQStringN(x,y) QString::fromLocal8Bit((x),(y))

#endif

//来源:https://blog.csdn.net/w_sx12553/article/details/8514839

QString不能直接转换到TCHAR
好记得上面说的TCHAR是16-bit是字符嘛
恰好QString能直接转成这个 .utf16() 一下

我们可以看到const ushort * 不能转TCHAR
因为TCAHR 是wchar_t
而wchar_t 是 unsigned short
所以,在这里,将UserName[32] 改成 *UserName

提出,ushort * 不能转TCHAR *
所以,直接使用 (wchar_t*)对userName.utf16()进行类型转换

到这里就可以完成参数类型转换并传递了

尝试运行一下下

嗯,刚才输进去的网络驱动器被成功映射回来了

在这里再顺手提一下WNetAddConnection2这个函数
整个磁盘映射函数中核心用到的函数,其实就这个~~~
上面的类型转换也是为了满足他对参数的要求

这是他的定义

1
2
3
4
5
6
DWORD WNetAddConnection2A(
LPNETRESOURCEA lpNetResource,
LPCSTR lpPassword,
LPCSTR lpUserName,
DWORD dwFlags
);

巨硬的说明文档连接在此:https://docs.microsoft.com/en-us/windows/desktop/api/winnetwk/nf-winnetwk-wnetaddconnection2a
详细的参数以及返回码对应的意义,可以在里面找到详细的参考说明

要是感觉不错的话,就留个言评论一下下呀,欢迎各位大哥指正