Windows 服务程序(二)
服务控制管理器 (SCM, Service Control Manager),它在系统启动时自动启动,其主要作用是维护和管理一张服务信息表。
OpenSCManager() 介绍:
功能:建立了一个到服务控制管理器的连接,并打开指定的数据库。
函数原型:SC_HANDLE OpenSCManager(
LPCSTR lpMachineName, // 指向零终止字符串,指定目标计算机的名称。 通常为 NULL。
LPCSTR lpDatabaseName, // 指向零终止字符串,指定将要打开的服务控制管理数据库的名称。通常为 NULL。
DWORD dwDesiredAccess // 指定服务访问控制管理器的权限。通常为 SC_MANAGER_ALL_ACCESS。
);
参数:
lpMachineName
指向零终止字符串,指定目标计算机的名称。
如果该指针为NULL ,或者它指向一个空字符串,那么该函数连接到本地计算机上的服务控制管理器。
lpDatabaseName
指向零终止字符串,指定将要打开的服务控制管理数据库的名称。
此字符串应被置为 SERVICES_ACTIVE_DATABASE。
如果该指针为NULL ,则打开默认的 SERVICES_ACTIVE_DATABASE 数据库。
dwDesiredAccess
指定服务访问控制管理器的权限。
在授予要求的权限前,系统会检查调用进程的权限令牌,该令牌针对与服务控制管理器相关的安全描述符的权限控制列表。
此外,该函数的调用将隐式地指定 SC_MANAGER_CONNECT 的访问权限。
此外,下列服务控制管理器对象的访问类型可以被指定:
SC_MANAGER_ALL_ACCESS 除了所有此表中列出的访问类型,还包括 STANDARD_RIGHTS_REQUIRED。
SC_MANAGER_CONNECT 可以连接到服务控制管理器。
SC_MANAGER_CREATE_SERVICE 使要求的 CreateService 函数创建一个服务对象,并将其添加到数据库中。
SC_MANAGER_ENUMERATE_SERVICE 使要求的 EnumServicesStatus 功能清单的服务,这是在数据库中。
SC_MANAGER_LOCK 使要求的 LockServiceDatabase 功能获得锁定数据库。
SC_MANAGER_QUERY_LOCK_STATUS 使要求的 QueryServiceLockStatus 检索功能锁定状态信息的数据库。
返回值
如果函数成功,返回值是一个指定的服务控制管理器数据库的句柄。如果函数失败,返回值为NULL 。
OpenService() 介绍:
功能:打开一个服务对象。
函数原型:SC_HANDLE OpenService(
SC_HANDLE hSCManager, // 使用 OpenSCManager() 打开后返回的对象句柄。
LPCSTR lpServiceName, // 需要打开的服务的名称,其中不能出现斜杆。
DWORD dwDesiredAccess // 打开权限。通常为 SC_MANAGER_ALL_ACCESS。
);
参数:
lpServiceName
这是在创建服务对象时由 CreateService 函数的 lpServiceName 参数指定的名称,
而不是用户界面应用程序显示的用于标识服务的服务显示名称。
dwDesiredAccess
权限同上。
在授予请求的访问权限之前, 系统将根据与服务对象关联的安全描述符的自由访问控制列表检查调用进程的访问令牌。
返回值:如果函数成功, 则返回值是服务的句柄。如果函数失败,返回值为NULL 。
CreateService() 介绍:
功能:创建一个服务对象,并将其添加到指定的服务控制管理器数据库的函数。
函数原型:SC_HANDLE CreateService(
SC_HANDLE hSCManager, // 服务控制管理器数据库的句柄。
LPCSTR lpServiceName, // 要安装的服务的名称。
LPCSTR lpDisplayName, // 用户界面程序用来标识服务的显示名称。
DWORD dwDesiredAccess, // 对服务的访问权限。通常为 SC_MANAGER_ALL_ACCESS。
DWORD dwServiceType, // 服务类型。 通常为 SERVICE_WIN32_OWN_PROCESS。
DWORD dwStartType, // "服务启动" 选项。通常为 SERVICE_AUTO_START。
DWORD dwErrorControl, // 错误的严重性和所采取的操作。
LPCSTR lpBinaryPathName, // 服务二进制文件的完全限定路径。
LPCSTR lpLoadOrderGroup, // 通常不关心,设置为 NULL。
LPDWORD lpdwTagId, // 通常不关心,设置为 NULL。
LPCSTR lpDependencies, // 通常不关心,设置为 NULL。
LPCSTR lpServiceStartName, // 通常不关心,设置为 NULL。
LPCSTR lpPassword // 通常不关心,设置为 NULL。
);
参数:
hSCManager
服务控制管理器数据库的句柄。此句柄由 OpenSCManager 函数返回,
并且必须具有 SC_MANAGER_CREATE_SERVICE 访问权限。
lpServiceName
要安装的服务的名称。最大字符串长度为256个字符。
服务控制管理器数据库保留字符的大小写, 但服务名称比较始终不区分大小写。正斜杠 (/) 和反斜线 () 不是有效的服务名称字符。
lpDisplayName
用户界面程序用来标识服务的显示名称。此字符串的最大长度为256个字符。
该名称在服务控制管理器中保留为 case。显示名称比较始终不区分大小写。
dwDesiredAccess
对服务的访问。在授予请求的访问权限之前, 系统将检查调用进程的访问令牌。值同 OpenSCManager() 的该参数。
dwServiceType
服务类型
| 值 | 含义 |
| SERVICE_FILE_SYSTEM_DRIVER | 文件系统驱动程序服务。 |
| SERVICE_KERNEL_DRIVER | 驱动程序服务。 |
| SERVICE_WIN32_OWN_PROCESS | 在其自己的进程中运行的服务。(常用的值) |
| SERVICE_USER_OWN_PROCESS | 该服务在登录用户帐户下在其自己的进程中运行。 |
dwStartType
"服务启动" 选项
| 值 | 含义 |
| SERVICE_AUTO_START | 在系统启动期间, 服务控制管理器自动启动服务。(常用的值) |
| SERVICE_BOOT_START | 由系统加载器启动的设备驱动程序。此值仅对驱动程序服务有效。 |
| SERVICE_DEMAND_START | 当进程调用 StartService 函数时, 由服务控制管理器启动的服务。 |
| SERVICE_DISABLED | 无法启动的服务。尝试启动服务会导致错误代码 ERROR_SERVICE_DISABLED。 |
| SERVICE_SYSTEM_START | 由 IoInitSystem 函数启动的设备驱动程序。此值仅对驱动程序服务有效。 |
dwErrorControl
错误的严重性和所采取的操作
| 值 | 含义 |
| SERVICE_ERROR_CRITICAL | 如果可能, 启动程序会在事件日志中记录错误。如果正在启动最后一次已知良好的配置, 则启动操作将失败。否则, 系统将以最后一次正确的配置重新启动。 |
| SERVICE_ERROR_IGNORE | 启动程序忽略错误并继续启动操作。 |
| SERVICE_ERROR_NORMAL | 启动程序在事件日志中记录错误, 但继续启动操作。 |
| SERVICE_ERROR_SEVERE | 启动程序在事件日志中记录错误。如果正在启动最后一次已知良好的配置, 则启动操作将继续进行。否则, 系统将以上次已知良好的配置重新启动。 |
lpBinaryPathName
服务二进制文件的完全限定路径。如果路径包含空格, 则必须引用它以使其正确解释。
该路径还可以包含自动启动服务的参数。例如, "d:\myshare\myservice.exe arg1 arg2"。这些参数被传递到服务入口点。
如果在另一台计算机上指定路径, 则该共享必须由本地计算机的计算机帐户访问, 因为这是远程调用中使用的安全上下文。
但是, 此要求允许远程计算机中的任何潜在漏洞影响本地计算机。因此, 最好使用本地文件。
返回值:如果函数成功, 则返回值是服务的句柄。如果函数失败, 返回值为 NULL。
StartService() 介绍:
功能:启动服务。
函数原型:BOOL StartService(
SC_HANDLE hService,
//此句柄由 OpenService 或 CreateService 函数返回, 并且必须具有 SERVICE_START 访问权限。
DWORD dwNumServiceArgs, // 通常不关心,设置为 NULL。
LPCSTR *lpServiceArgVectors // 通常不关心,设置为 NULL。
);
返回值:非零表示成功,零表示失败。
QueryServiceStatus() 介绍:
功能:检索指定服务的当前状态。
函数原型:BOOL QueryServiceStatus(
SC_HANDLE hService,
// 此句柄由 OpenService 或 CreateService 函数返回, 并且必须具有 SERVICE_START 访问权限。
LPSERVICE_STATUS lpServiceStatus // 指向接收状态信息的 SERVICE_STATUS 结构的指针。
);
返回值:非零表示成功,零表示失败。
ControlService() 介绍:
功能:向服务发送控制代码。
函数原型:BOOL ControlService(
SC_HANDLE hService,
// 此句柄由 OpenService 或 CreateService 函数返回, 并且必须具有 SERVICE_START 访问权限。
DWORD dwControl, // 控制代码。
LPSERVICE_STATUS lpServiceStatus // 指向接收最新服务状态信息的 SERVICE_STATUS 结构的指针。
);
参数
dwControl
| 控制代码 | 含义 |
| SERVICE_CONTROL_CONTINUE | 通知暂停的服务应恢复。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_INTERROGATE | 通知服务应将其当前状态信息报告给服务控制管理器。hService 句柄必须具有 SERVICE_INTERROGATE 访问权限。 |
| SERVICE_CONTROL_NETBINDADD | 通知网络服务有一个用于绑定的新组件。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_NETBINDDISABLE | 通知网络服务其中一个绑定已被禁用。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_NETBINDENABLE | 通知网络服务已启用已禁用的绑定。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_NETBINDREMOVE | 通知网络服务已删除绑定的组件。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_PARAMCHANGE | 通知服务其启动参数已更改。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_PAUSE | 通知服务应暂停。hService 句柄必须具有 SERVICE_PAUSE_CONTINUE 访问权限。 |
| SERVICE_CONTROL_STOP | 通知服务应停止。hService 句柄必须具有 SERVICE_STOP 访问权限。 |
返回值:非零表示成功,零表示失败。
DeleteService() 介绍:
功能:将指定的服务标记为从服务控制管理器数据库中删除。
函数原型:BOOL DeleteService(
SC_HANDLE hService // 此句柄由 OpenService 或 CreateService 函数返回, 并且必须具有 "删除" 访问权限。
);
返回值:非零表示成功,零表示失败。
CloseServiceHandle() 介绍:
功能:关闭服务控制管理器或服务对象的句柄。
函数原型:BOOL CloseServiceHandle(
SC_HANDLE hSCObject // 要关闭的服务控件管理器对象或服务对象的句柄。
);
参数
hSCObject
要关闭的服务控件管理器对象或服务对象的句柄。
服务控制管理器对象的句柄由 OpenSCManager 函数返回, 并且服务对象的句柄由 OpenService 或 CreateService 函数返回。
返回值:非零表示成功,零表示失败。
DemoCode:
#include<stdio.h>
#include<Windows.h>
#include<winsock.h>
#pragma comment(lib, "Advapi32")
#pragma comment(lib,"ws2_32")
#define MYPORT 1234
#define BACKLOG 10
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
SC_HANDLE SCManager;
SC_HANDLE SCService;
void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv);
void WINAPI ServiceHandler(DWORD fdwControl);
void InstallService();
void StartService0();
void StopService();
void UnInstallService();
void MyWork(); // 自定义特定功能的函数。本打算用线程调用完成的,简单起见就这样吧。
//DWORD WINAPI MyWork(LPVOID lpParam); 该函数涉及到线程,先放这里。
int main(void)
{
SERVICE_TABLE_ENTRY ServTable[];
ServTable[].lpServiceName = (LPSTR)"Test";
ServTable[].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServTable[].lpServiceName = NULL;
ServTable[].lpServiceProc = NULL;
StartServiceCtrlDispatcher(ServTable);
InstallService();
StartService0();
return ;
} void WINAPI ServiceMain(DWORD dwArgc, LPSTR *lpszArgv)
{
ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP |
SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;
ServiceStatus.dwWin32ExitCode = ;
ServiceStatus.dwCheckPoint = ;
ServiceStatus.dwServiceSpecificExitCode = ;
ServiceStatus.dwWaitHint = ;
hStatus = RegisterServiceCtrlHandler("BackDoor",
(LPHANDLER_FUNCTION)ServiceHandler);
if (!hStatus)
{
printf("Register Service Error!\n");
system("pause");
return;
}
SetServiceStatus(hStatus, &ServiceStatus);
if (GetLastError() != NO_ERROR)
{
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = ;
ServiceStatus.dwWaitHint = ;
SetServiceStatus(hStatus, &ServiceStatus);
printf("Start Error!\n");
system("pause");
return;
}
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
ServiceStatus.dwCheckPoint = ;
ServiceStatus.dwWaitHint = ;
SetServiceStatus(hStatus, &ServiceStatus);
// 从这里开始可以放入你想服务为你做的事情。
/*
HANDLE hThread = CreateThread(NULL, 0, MyWork, NULL, 0, NULL);
if (hThread = NULL)
return;
*/
MyWork();
return;
} void WINAPI ServiceHandler(DWORD fdwControl)
{
switch (fdwControl)
{
case SERVICE_CONTROL_PAUSE:
ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwCheckPoint = ;
ServiceStatus.dwWaitHint = ;
SetServiceStatus(hStatus, &ServiceStatus);
StopService();
UnInstallService();
return;
default:
break;
}
SetServiceStatus(hStatus, &ServiceStatus);
return;
} void InstallService()
{
char PathName[MAX_PATH];
char SysName[MAX_PATH];
GetModuleFileName(NULL, PathName, MAX_PATH);
GetSystemDirectory(SysName, MAX_PATH);
wsprintf(SysName, "%s\\Test.exe", SysName);
if (!MoveFile(PathName, SysName))
{
printf(" Move File Error!\n");
system("pause");
return;
}
SCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (SCManager == NULL)
{
printf("OpenSCManager Error!\n");
system("pause");
return;
}
SCService = CreateService(
SCManager,
"BackDoor",
"Service32",
SC_MANAGER_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,
SysName,
NULL, NULL, NULL, NULL, NULL);
if (SCService == NULL)
{
printf("CreateService Error!\n");
CloseServiceHandle(SCManager);
system("pause");
return;
}
printf("Create Service Succeed!\n");
CloseServiceHandle(SCService);
CloseServiceHandle(SCManager);
return;
} void StartService0()
{
SCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (SCManager == NULL)
{
printf("OpenSCManager Error!\n");
system("pause");
return;
}
SCService = OpenService(SCManager, "BackDoor", SC_MANAGER_ALL_ACCESS);
if(SCService == NULL)
{
printf("OpenService Error!\n");
CloseServiceHandle(SCManager);
system("pause");
return;
}
if (StartService(SCService, NULL, NULL))
{
while (QueryServiceStatus(SCService,&ServiceStatus))
{
if (ServiceStatus.dwCurrentState == SERVICE_RUNNING)
break;
else
Sleep();
}
printf("Service Start Succeed!\n");
}
CloseServiceHandle(SCService);
CloseServiceHandle(SCManager);
return;
} void StopService()
{
SCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (SCManager == NULL)
{
printf("OpenSCManager Error!\n");
system("pause");
return;
}
SCService = OpenService(SCManager, "BackDoor", SC_MANAGER_ALL_ACCESS);
if (SCService == NULL)
{
printf("Open Service Error!\n");
CloseServiceHandle(SCManager);
system("pause");
return;
}
if (ControlService(SCService, SERVICE_CONTROL_STOP, &ServiceStatus))
{
while (QueryServiceStatus(SCService, &ServiceStatus))
{
if (ServiceStatus.dwCurrentState == SERVICE_STOPPED)
break;
else
Sleep();
}
printf("Service Stop Succeed!\n");
}
CloseServiceHandle(SCService);
CloseServiceHandle(SCManager);
return;
} void UnInstallService()
{
SCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (SCManager == NULL)
{
printf("OpenSCManager Error!\n");
system("pause");
return;
}
SCService = OpenService(SCManager, "BackDoor", SC_MANAGER_ALL_ACCESS);
if (SCService == NULL)
{
printf("Open Service Error!\n");
CloseServiceHandle(SCManager);
system("pause");
return;
}
if (DeleteService(SCService))
printf("Uninstall Service Succeed!\n");
else
printf("Unistall Service Error!\n");
CloseServiceHandle(SCService);
CloseServiceHandle(SCManager);
return;
} void MyWork()
{
SOCKET sockfd, new_fd;
struct sockaddr_in my_addr;
struct sockaddr_in their_addr;
int sin_size = sizeof(struct sockaddr_in);
WSADATA ws;
if (WSAStartup(MAKEWORD(, ), &ws) != )
{
printf("WSAStart up Error!\n");
WSACleanup();
system("pause");
exit();
}
if ((sockfd = socket(AF_INET, SOCK_STREAM, )) == INVALID_SOCKET)
{
printf("Socket Error!\n");
system("pause");
exit();
}
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(MYPORT);
my_addr.sin_addr.S_un.S_addr = INADDR_ANY;
if (bind(sockfd, (struct sockaddr*)&my_addr, sizeof(struct sockaddr)) == -)
{
printf("Bind Error!\n");
closesocket(sockfd);
system("pause");
exit();
}
if (listen(sockfd, BACKLOG) == SOCKET_ERROR)
{
printf("Listen Error!\n");
closesocket(sockfd);
system("pause");
exit();
}
if ((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == INVALID_SOCKET)
{
printf("Accept Error!\n");
closesocket(sockfd);
exit();
}
closesocket(sockfd);
closesocket(new_fd);
WSACleanup();
return;
} /*
DWORD WINAPI MyWork(LPVOID lpParam)
{
return 0;
}
*/
这个程序需要用管理员身份运行,运行结果如下图:

Windows 服务程序(二)的更多相关文章
- Windows服务二:测试新建的服务、调试Windows服务
一.测试Windows服务 为了使Windows服务程序能够正常运行,我们需要像创建一般应用程序那样为它创建一个程序的入口点.像其他应用程序一样,Windows服务也是在Program.cs的Main ...
- Windows服务程序和安装程序制作
转:http://www.cr173.com/html/15350_1.html 本文介绍了如何用C#创建.安装.启动.监控.卸载简单的Windows Service 的内容步骤和注意事项. 一.创建 ...
- .net Windows服务程序和安装程序制作图解 及 VS 2010创建、安装、调试 windows服务(windows service)
.net Windows服务程序和安装程序制作 最近项目中用到window服务程序,以前没接触过,比较陌生,花了两天的时间学习了下,写了个简单的服务,但在制作安装程序的时候,参照网上很多资料,却都制作 ...
- 创建一个Windows服务程序与实现定时器效果
1.创建一个Windows服务程序 一. 新建Window服务项目 二. 添加安装程序 三. 配置服务属性 四. 编写定时器代码 publicpartialclassService1 ...
- 如何在Windows服务程序中添加U盘插拔的消息
研究了下这个问题,主要要在一般的windows服务程序中修改两个地方: 一.调用RegisterServiceCtrlHandlerEx VOID WINAPI SvcMain( DWORD dwAr ...
- 用Visual C#创建Windows服务程序
一.Windows服务介绍: Windows服务以前被称作NT服务,是一些运行在Windows NT.Windows 2000和Windows XP等操作系统下用户环境以外的程序.在以前,编写Wind ...
- .NET 跨平台RPC框架DotNettyRPC Web后台快速开发框架(.NET Core) EasyWcf------无需配置,无需引用,动态绑定,轻松使用 C# .NET 0配置使用Wcf(半成品) C# .NET Socket 简单实用框架 C# .NET 0命令行安装Windows服务程序
.NET 跨平台RPC框架DotNettyRPC DotNettyRPC 1.简介 DotNettyRPC是一个基于DotNetty的跨平台RPC框架,支持.NET45以及.NET Standar ...
- 用C/C++创建windows服务程序
转载:https://blog.csdn.net/chenyujing1234/article/details/8023816 一.演示过程下方代码演示了如何使用vs(C/C++)创建windows服 ...
- WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)
上接 WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...
随机推荐
- NOIP2012 D2 T3 疫情控制 洛谷P1084
题目链接:https://www.luogu.org/problemnew/show/P1084 算法:倍增,二分答案,贪心 + 瞎搞.. 背景:上学长的数论课啥也听不懂,于是前去提高组找安慰.不巧碰 ...
- Java位运算实现加减乘除四则运算
本文是继<一文了解有趣的位运算>的第二篇文章. 我们知道,计算机最基本的操作单元是字节(byte),一个字节由8个位(bit)组成,一个位只能存储一个0或1,其实也就是高低电平.无论多么复 ...
- js-数据交互--AJAX
一:介绍 今天跟下大家简单的介绍一下,在前端开发中,前后端数据交互的一种手段,我们都知道,在前端往后端传送数据的话,利用get,post方法即可向后端发送数据,后端将数据接受,链接到数据库,进行数据库 ...
- Oracle之select
坚持
- 遗传编程(GA,genetic programming)算法初探,以及用遗传编程自动生成符合题解的正则表达式的实践
1. 遗传编程简介 0x1:什么是遗传编程算法,和传统机器学习算法有什么区别 传统上,我们接触的机器学习算法,都是被设计为解决某一个某一类问题的确定性算法.对于这些机器学习算法来说,唯一的灵活性体现在 ...
- [转载 ]五种常见的 PHP 设计模式
五种常见的 PHP 设计模式 策略模式 策略模式是对象的行为模式,用意是对一组算法的封装.动态的选择需要的算法并使用. 策略模式指的是程序中涉及决策控制的一种模式.策略模式功能非常强大,因为这个设计模 ...
- Ubuntu+docker+gitlab安装和使用
以前自己写的代码都是在本地,因为都是自己一个人维护,现在交给团队维护了,所以想着搭建一个gitlab 1,拉镜像 安装非常简单 docker search gitlab 搜索镜像 docker pu ...
- 基于WeChat的消息存储备份、远程控制、小功能项目开源分享计划
WeChat+ 关于该项目 起源 该项目的起因是一个比较程(老)序(油)猿(条)的理由,有一天我发现我下班时间比较早,有点尴尬,但是又不想没事干还坐在公司,那么如何解决我的问题呢,初步想法是远程控制电 ...
- mysql初识笔记
一.初始mysql mysql介绍: mysql版本: 版本号=3个数字+1个后缀 mysql-5.0.9-beta 5 0 9 Beta 主版本号 发行级别 发行稳定级别 发行系列 发行系列的版本号 ...
- MongoDB入门系列之科普篇
目录 背景 对比 MongoDB的数据存储格式 背景 最近公司扩展了很多国外客户,那么一个很严重的问题就是翻译,对于国外客户来说,肯定看不懂中文,那就要项目中提供切换各自国家语言的功能. 由于每个 ...