目录
2022_03_02:一些C语言需要注意的知识
2022_03_14:_findfirst()
2022_03_21:转换FILETIME
2022_03_25 :注册服务时注册成功但是无法打开服务的原因
2022_03_31:需要注意64位系统下system32文件重定向问题
2022_03_02
1.对于无法解析的外部符号_ibo_func处理方法:_CRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
注:对于不同版本的vs对其stdin,stdout,stderr定义不同,导致不同VS之间无法正确调用函数。
2.__cplusplus :识别是C代码还是C++代码
2022_03_03
1.获取硬盘唯一的物理序列号:cmd命令行获取 or C++底层函数获取。
2.devicelocontrol()方法:将控制代码直接发送到指定的设备驱动程序,使相应的设备执行相应的操作。操作成功直接返回一个非零的值;操作失败或者等待,返回零,调用GetLastError()进行获得扩展的错误信息。
2022_03_04
1.IOCTL命令:他是专用于设备输入输出的系统调用,该调用会传入一个跟设备有关的请求码,系统调用功能取决于这个请求码
2.CreatFileA函数:创建或打开文件或 I/O 设备。该函数返回一个句柄,该句柄可用于访问文件或设备的各种类型的 I/O,具体取决于文件或设备以及指定的标志和属性。(参数的详细了解)
3.isalnum()函数:判断一个字符是否是字母或数字
4.加密狗的使用
- SS的托管内存原理:APP利用有效的许可作为凭证,在SS模块内数据加密且数据校验,其内存二进制数据没有明文并且无法非法修改。
2022_03_07
1.无法解析的外部符号imp_iob_func,函数%中引用该符号(解决):
这是因为使用了过期方法造成, VS2015 及以上版本编译失败,提示无法解析的外部符号 __iob_func()。由于编译器版本引起的问题。
#if _MSC_VER>=1900
#include "stdio.h"
_ACRTIMP_ALT FILE* __cdecl __acrt_iob_func(unsigned);
#ifdef __cplusplus
extern "C"
#endif
FILE* __cdecl __iob_func(unsigned i) {
return __acrt_iob_func(i);
}
#endif /* _MSC_VER>=1900 */
2.VS无法打开源文件
我们只需要在他的VC++目录中将我们自己写的头文件的绝对目录包含进来即可。
3.C中的输出类型:
%d整形输出,%ld长整型输出,
%o以八进制数形式输出整数,
%x以十六进制数形式输出整数,
%u以十进制数输出unsigned型数据(无符号数)。
%c用来输出一个字符。
%s用来输出一个字符串,判定结束是按照'\0'来进行判断的。
%f用来输出实数,以小数形式输出,(备注:浮点数是不能定义如的精度的,所以“%6.2f”这种写法是“错误的”!!!)
%e以指数形式输出实数,
%g根据大小自动选f格式或e格式,且不输出无意义的零。
4.C++输出时要进行转换成16进制: cin、cout、printf 默认都是十进制式,如果需要输入或输出十六进制,需要重新指定进制式。对于cin、cout ,其中 oct为八进制,hex为十六进制,dec为十进制。特别注意,一旦指明进制数后,将一直有效,除非重新指定进制数。
5.了解C中常用的库函数:(常用库函数)
2022_03_08
1.链接错误的解决办法(在VS下)
VS20xx:
项目、属性、C/C++、附加包含目录:填写附加头文件所在目录 分号间隔多项
项目、属性、链接器、常规、附加库目录:填写附加依赖库所在目录 分号间隔多项
项目、属性、链接器、输入、附加依赖项:填写附加依赖库的名字.lib 空格或分号间隔多项
2022_03_10
1.在写链表的时候,节点的定义中使用了string类型,如果是使用string类型,它的内存是动态分配的,如下图所示,[11]后面还有很多,根据实例化时确定具体大小。而使用malloc无法进行动态内存分配,只能改为new.
2022_03_14
1._findfirst()
2.完成了将计算机某个目录下的所有文件路径保存在一棵树中,并且实现增删改查的功能。
2022_03_16
1.MD5的简单了解
2022_03_21
1.winAPI访问文件路径
2.转换FILETIME
WIN32_FIND_DATA pNextInfo;//保存文件信息
__int64 creattime = *(__int64*)&(pNextInfo.ftCreationTime);//将FILETIME转换成
__int64 writetime = *(__int64*)&(pNextInfo.ftLastWriteTime);
2022_03_23
1.无法从“WCHAR [260]”转换“std::basic_string<char,std::char_traits<char>,std::allocator<char>>”
解决:
a.在属性->高级->字符集->使用 Unicode 字符集改成使用多字节字符集
b.在#include<windows.h>之前加上#undef UNICODE
2. error C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. Se..........
使用屏蔽警告:#pragma warning(disable:4996);
或者加上_s后缀;
3.服务控制管理器SCM
他管理系统所有的进程。当通过SCM启动某个service进程时(即SCM执行某个service对应的exe程序)SCM会等待此service进程的主线程调用StartServiceCtrlDIispatcher函数。如果StartServiceCtrlDispatcher调用成功,则service进程的主线程就connect到SCM上了。一直到service进程中所有的running services变成SERVICE_STOPPED状态才断开连接。然后service进程的主线程则扮演控制分派器的角色(通过HandlerEX函数发送contral和service start请求)或者分别为每个service创建一个新的线程去执行ServiceMain。
SCM和service进程之间使用communicate通讯其实是按照pipe来实现的。
2022_03_24
1.const char*转换成LPWSTR
LPWSTR ConvertCharToLPWSTR(const char* szString)
{
int dwLen = strlen(szString) + 1;
int nwLen = MultiByteToWideChar(CP_ACP, 0, szString, dwLen, NULL, 0);//算出合适的长度
LPWSTR lpszPath = new WCHAR[dwLen];
MultiByteToWideChar(CP_ACP, 0, szString, dwLen, lpszPath, nwLen);
return lpszPath;
}
2022_03_25
遇到的这个问题当时在网上找了好久都没有解决,最后在Microsoft Docs找到了问题所在。
1.在完成对exe文件进行服务注册时,注册成功后开始启动时发生了错误,查找问题如下:
LPSERVICE_MAIN_FUNCTIONW回调函数:
SCM 在初始化期间锁定服务控制数据库,因此,如果服务在初始化期间尝试调用 StartService,则该调用将被阻止。当服务向 SCM 报告它已成功启动时,它可以调用 StartService。如果服务需要运行其他服务,则该服务应设置所需的依赖项。
此外,在服务初始化期间不应调用任何系统函数。只有在报告SERVICE_RUNNING状态后,服务代码才应调用系统函数。
我在这里出现的错误就是在服务进行初始化期间调用了其他的系统函数,导致服务初始化失败,无法启动服务。
void ServiceMain(int argc, char** argv) {
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwServiceSpecificExitCode = 0;
ServiceStatus.dwCheckPoint = 0;
ServiceStatus.dwWaitHint = 0;
hStatus = RegisterServiceCtrlHandlerA("services_03_18",
(LPHANDLER_FUNCTION)ControlHandler);
//RegisterServiceCtrlHandlerA,注册一个函数返回一个请求
if (hStatus == (SERVICE_STATUS_HANDLE)0) {//注册失败,hStatus会返回0
return;
}
error = InitService();
if (!error) {//初始化失败
//初始化失败,终止服务
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
//退出ServiceMain
return;
}
//如果初始化成功,则向SCM报告状态
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);
//接着启动工作循环,每五秒查询一个可用物理块并存向日志文件中,
//循环服务直到服务状态为SERVICE_RUNNING或者日志文件写入出错为止
MEMORYSTATUS memory;
//服务的工作线程循环
while (ServiceStatus.dwCurrentState == SERVICE_RUNNING) {
char buffer[16] ;
GlobalMemoryStatus(&memory);
sprintf(buffer,"%d",memory.dwAvailPhys);
int result = WriteToLog(buffer);
if (result)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
Sleep(SLEEP_TIME);
}
return;
}
如上面代码,当在处理error = InitService();代码时我的InitService()函数调用了一个系统函数(strcpy()函数),导致初始哈失败,最后改掉后服务成功启动。
2022_03_29
1.客户端与服务端利用管道进行通信,CreateFile()在GetLastRrror()报错error5,无法访问:
因为在进行server端的编写时对CreateNamedPipe()函数中的参数判断错误,因为我的server端是已经注册成以个service,所以无法直接访问,解决:
SECURITY_DESCRIPTOR sd; InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); SetSecurityDescriptorDacl(&sd, true, NULL, false); SECURITY_ATTRIBUTES sa; sa.lpSecurityDescriptor=&sd; sa.bInheritHandle=true;pHandleMailSlot = CreateMailslot("your mail slot path", 0, -1, &sa);
详解链接:GetLastError()5https://blog.csdn.net/weixin_32926649/article/details/113025882
2022_03_31
1.解决了使用winAPI遍历文件路径不全的问题。
在进行文件遍历的过程中,出现了三个问题:一是权限的不足。二是没有意识到64位系统下System32文件会发生重定向。三时在使用strcmp()函数进行比较字符串的时候没有注意当字符串的大小写区分问题,要将strcmp()函数改成stricmp(),这个函数时不区分大小写的。