请问: 谁有SDK 的最简单的服务程序代码, 给我一个. 立马 200 分送上

realdreamer 2003-02-10 02:03:35
rt
...全文
48 5 打赏 收藏 转发到动态 举报
写回复
用AI写文章
5 条回复
切换为时间正序
请发表友善的回复…
发表回复
benben001 2003-02-10
  • 打赏
  • 举报
回复

void CmdRemoveService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;

schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = OpenService(schSCManager, TEXT(SZSERVICENAME), SERVICE_ALL_ACCESS);

if (schService)
{
// try to stop the service
if ( ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus ) )
{
_tprintf(TEXT("正在停止 %s 服务."), TEXT(SZSERVICEDISPLAYNAME));
Sleep( 1000 );

while( QueryServiceStatus( schService, &ssStatus ) )
{
if ( ssStatus.dwCurrentState == SERVICE_STOP_PENDING )
{
_tprintf(TEXT("."));
Sleep( 1000 );
}
else
break;
}

if ( ssStatus.dwCurrentState == SERVICE_STOPPED )
_tprintf(TEXT("\n%s 已停止.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("\n停止 %s 服务失败.\n"), TEXT(SZSERVICEDISPLAYNAME) );

}

// now remove the service
if( DeleteService(schService) )
_tprintf(TEXT("%s 服务已删除.\n"), TEXT(SZSERVICEDISPLAYNAME) );
else
_tprintf(TEXT("DeleteService 失败 - %s\n"), GetLastErrorText(szErr,256));


CloseServiceHandle(schService);
}
else
_tprintf(TEXT("OpenService 失败 - %s\n"), GetLastErrorText(szErr,256));

CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager 失败 - %s\n"), GetLastErrorText(szErr,256));
}


void CmdInstallService()
{
SC_HANDLE schService;
SC_HANDLE schSCManager;

TCHAR szPath[512];

if ( GetModuleFileName( NULL, szPath, 512 ) == 0 )
{
_tprintf(TEXT("Unable to install %s - %s\n"), TEXT(SZSERVICEDISPLAYNAME), GetLastErrorText(szErr, 256));
return;
}

schSCManager = OpenSCManager(
NULL, // machine (NULL == local)
NULL, // database (NULL == default)
SC_MANAGER_ALL_ACCESS // access required
);
if ( schSCManager )
{
schService = CreateService(
schSCManager, // SCManager database
TEXT(SZSERVICENAME), // name of service
TEXT(SZSERVICEDISPLAYNAME), // name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // service's binary
NULL, // no load ordering group
NULL, // no tag identifier
TEXT(SZDEPENDENCIES), // dependencies
NULL, // LocalSystem account
NULL); // no password

if ( schService )
{
_tprintf(TEXT("%s 已成功安装\n"), TEXT(SZSERVICEDISPLAYNAME) );
CloseServiceHandle(schService);
}
else
{
_tprintf(TEXT("CreateService 失败 - %s\n"), GetLastErrorText(szErr, 256));
}

CloseServiceHandle(schSCManager);
}
else
_tprintf(TEXT("OpenSCManager 失败 - %s\n"), GetLastErrorText(szErr,256));
}



void WriteToFile(LPCTSTR pstr, LPCTSTR pPath)
{
FILE * pf = fopen(pPath, "w+");
fwrite(pstr, lstrlen(pstr), 1, pf);
fclose(pf);
}

realdreamer 2003-02-10
  • 打赏
  • 举报
回复
谢谢
benben001 2003-02-10
  • 打赏
  • 举报
回复
VOID WINAPI service_ctrl(DWORD dwCtrlCode)
{
// Handle the requested control code.
//
switch(dwCtrlCode)
{
// Stop the service.
//
// SERVICE_STOP_PENDING should be reported before
// setting the Stop Event - hServerStopEvent - in
// ServiceStop(). This avoids a race condition
// which may result in a 1053 - The Service did not respond...
// error.
case SERVICE_CONTROL_STOP:
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0);
ServiceStop();
return;

// Update the service status.
//
case SERVICE_CONTROL_INTERROGATE:
break;

// invalid control code
//
default:
break;

}

ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
}



VOID AddToMessageLog(LPTSTR lpszMsg)
{
TCHAR szMsg[256];
HANDLE hEventSource;
LPTSTR lpszStrings[2];


if ( !bDebug )
{
dwErr = GetLastError();

// Use event logging to log the error.
//
hEventSource = RegisterEventSource(NULL, TEXT(SZSERVICENAME));

_stprintf(szMsg, TEXT("%s error: %d"), TEXT(SZSERVICENAME), dwErr);
lpszStrings[0] = szMsg;
lpszStrings[1] = lpszMsg;

if (hEventSource != NULL) {
ReportEvent(hEventSource, // handle of event source
EVENTLOG_ERROR_TYPE, // event type
0, // event category
0, // event ID
NULL, // current user's SID
2, // strings in lpszStrings
0, // no bytes of raw data
(LPCSTR*)lpszStrings, // array of error strings
NULL); // no raw data

(VOID) DeregisterEventSource(hEventSource);
}
}
}



BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
BOOL fResult = TRUE;

if ( !bDebug ) // when debugging we don't report to the SCM
{
if (dwCurrentState == SERVICE_START_PENDING)
ssStatus.dwControlsAccepted = 0;
else
ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;

ssStatus.dwCurrentState = dwCurrentState;
ssStatus.dwWin32ExitCode = dwWin32ExitCode;
ssStatus.dwWaitHint = dwWaitHint;

if ( ( dwCurrentState == SERVICE_RUNNING ) ||
( dwCurrentState == SERVICE_STOPPED ) )
ssStatus.dwCheckPoint = 0;
else
ssStatus.dwCheckPoint = dwCheckPoint++;


// Report the status of the service to the service control manager.
//
if (!(fResult = SetServiceStatus( sshStatusHandle, &ssStatus))) {
AddToMessageLog(TEXT("SetServiceStatus"));
}
}
return fResult;
}



LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize )
{
DWORD dwRet;
LPTSTR lpszTemp = NULL;

dwRet = FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
NULL,
GetLastError(),
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
NULL );

// supplied buffer is not long enough
if ( !dwRet || ( (long)dwSize < (long)dwRet+14 ) )
lpszBuf[0] = TEXT('\0');
else
{
lpszTemp[lstrlen(lpszTemp)-2] = TEXT('\0'); //remove cr and newline character
_stprintf( lpszBuf, TEXT("%s (0x%x)"), lpszTemp, GetLastError() );
}

if ( lpszTemp )
LocalFree((HLOCAL) lpszTemp );

return lpszBuf;
}


BOOL WINAPI ControlHandler ( DWORD dwCtrlType )
{
switch( dwCtrlType )
{
case CTRL_BREAK_EVENT: // use Ctrl+C or Ctrl+Break to simulate
case CTRL_C_EVENT: // SERVICE_CONTROL_STOP in debug mode
_tprintf(TEXT("Stopping %s.\n"), TEXT(SZSERVICEDISPLAYNAME));
ServiceStop();
return TRUE;
break;

}
return FALSE;
}


void CmdDebugService(int argc, char ** argv)
{
DWORD dwArgc;
LPTSTR *lpszArgv;

#ifdef UNICODE
lpszArgv = CommandLineToArgvW(GetCommandLineW(), &(dwArgc) );
#else
dwArgc = (DWORD) argc;
lpszArgv = argv;
#endif

_tprintf(TEXT("Debugging %s.\n"), TEXT(SZSERVICEDISPLAYNAME));

SetConsoleCtrlHandler( ControlHandler, TRUE );

ServiceStart( dwArgc, lpszArgv );
}

benben001 2003-02-10
  • 打赏
  • 举报
回复
try {
TESTHR(obj.CreateInstance(__uuidof(PsyScoreObj)));
if (1!=obj->CreateDataModule(DBServer, DBUser, DBPwd, DBName))
{
AddToMessageLog("CreateDataModule 调用失败. 数据库服务器配置有错, 无法连接数据库");
return 2;
}

TESTHR(obj->put_ConnectionString(ConnStr.GetBSTR()));
TESTHR(prs.CreateInstance(__uuidof(Recordset)));
TESTHR(prs->Open(L"SELECT * FROM CPAI_USER WHERE (AtomTScore22 IS NULL) OR (AtomTScore34 IS NULL) OR (AtomTScore37 IS NULL) OR (AtomGroup5 IS NULL) OR (AtomGroup6 IS NULL)",
ConnStr, adOpenDynamic, adLockReadOnly, 1));

} catch (_com_error& )
{
AddToMessageLog(_T("CPAI Report 计算前的初始化失败"));
if (obj!=NULL)
obj->DestoryDataModule();
if (prs!=NULL)
prs->Close();
return 2;
}

if (prs->EndOfFile) {
prs->Close();
obj->DestoryDataModule();
return 0;
}
while(true)
{
ret = MsgWaitForMultipleObjectsEx(
nCount,
&hServerStopEvent,
calcInterval,
0,
0
);
if (ret == WAIT_TIMEOUT)
{
//调用 VB 组件.
obj->CalcCPAIReport(prs);
try {
//prs->Fields-
prs->MoveNext();
if (prs->EndOfFile)
{
prs->Close();
obj->DestoryDataModule();
return 0;
}
continue;

} catch(_com_error &e) {
AddToMessageLog(e.Description());
obj->DestoryDataModule();
if (prs!=NULL && prs->State==adStateOpen)
prs->Close();
//WriteToFile((char*)e.Source(), "c:\\Source.txt");
//WriteToFile((char*)e.Description(), "c:\\Description.txt");
return 2;
}
} else if (ret == WAIT_OBJECT_0)
{
//服务器停止
obj->DestoryDataModule();
return 1;
} else if (ret == WAIT_FAILED)
{
AddToMessageLog("MsgWaitForMultipleobjectsEx call failed!");
obj->DestoryDataModule();
return 2;
}


}
}

BOOL ServiceInit(DWORD dwArgc, LPTSTR *lpszArgv)
{
if (!InitInternalData())
{
return FALSE;
}

if (!ReportStatusToSCMgr(
SERVICE_START_PENDING,
NO_ERROR,
2000))
{
return FALSE;
}

hServerStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hServerStopEvent==NULL)
{
return FALSE;
}

if (FAILED(CoInitialize(NULL)))
return FALSE;

if (!ReportStatusToSCMgr(
SERVICE_START_PENDING,
NO_ERROR,
1000))
{
return FALSE;
}

return TRUE;
}

void ServiceUninit()
{
ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 3000);
if (hServerStopEvent)
CloseHandle(hServerStopEvent);
CoUninitialize();
}


void Service(DWORD dwArgc, LPSTR *lpszArgv)
{
// DebugBreak();

DWORD ret = 0;
//注册表读取 startInterval 值
const DWORD nCount = 1;
// DebugBreak();
while(true)
{
ret = MsgWaitForMultipleObjectsEx(nCount, &hServerStopEvent, startInterval, 0, 0);
switch (ret)
{
case WAIT_TIMEOUT:
//开始计算 CPAI
ret = CalcCPAI();
switch (ret)
{
case 0:
continue;

case 1:
//服务器停止
return;

case 2:
//出现错误
return;
default:
AddToMessageLog("无效的返回值");
}
continue;

case WAIT_OBJECT_0 + nCount:
//服务器控制消息
MSG msg;
if (!PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
continue;
//WriteToFile("接收到消息", "c:\\test.txt");

case WAIT_OBJECT_0:
//停止服务器
return;


case WAIT_FAILED:
AddToMessageLog(_T("服务器等待失败"));
return;
}
}
}



VOID ServiceStart (DWORD dwArgc, LPTSTR *lpszArgv)
{

//初始化服务数据及资源
if (!ServiceInit(dwArgc, lpszArgv))
{
AddToMessageLog(_T("初始化失败"));
return;
}

//报告运行中
if (!ReportStatusToSCMgr(
SERVICE_RUNNING, // service state
NO_ERROR, // exit code
0)) // wait hint
{
ServiceUninit();
return;
}

Service(dwArgc, lpszArgv);

ServiceUninit();
}


void ShowHelpInfo()
{
printf( "%s -install 安装 CPAI Report Build 服务\n", SZAPPNAME );
printf( "%s -remove 卸载 CPAI Report Build 服务\n", SZAPPNAME );
//printf( "%s -debug <params> to run as a console app for debugging\n", SZAPPNAME );
//printf( "\nStartServiceCtrlDispatcher being called.\n" );
//printf( "This may take several seconds. Please wait.\n" );
}


int _tmain(int argc, _TCHAR* argv[])
{
SERVICE_TABLE_ENTRY dispatchTable[] =
{
{ TEXT(SZSERVICENAME), (LPSERVICE_MAIN_FUNCTION)service_main },
{ NULL, NULL }
};

if ( (argc > 1) &&
((*argv[1] == '-') || (*argv[1] == '/')) && (*(argv[1]+1) != 0))
{
if ( _stricmp( "install", argv[1]+1 ) == 0 )
{
CmdInstallService();
}
else if ( _stricmp( "remove", argv[1]+1 ) == 0 )
{
CmdRemoveService();
}
else if ( _stricmp( "debug", argv[1]+1 ) == 0 )
{
bDebug = TRUE;
CmdDebugService(argc, argv);
}
else if ( _stricmp( "help", argv[1]+1) == 0 )
{
ShowHelpInfo();
}
else if (_stricmp( "?", argv[1]+1) == 0 )
{
ShowHelpInfo();
}
else if (_stricmp( "h", argv[1]+1) == 0 )
{
ShowHelpInfo();
}

return 0;
}

if (!StartServiceCtrlDispatcher(dispatchTable))
AddToMessageLog(TEXT("StartServiceCtrlDispatcher failed."));

//WriteToFile("end", "c:\\test.txt");

}

VOID ServiceStop()
{
if ( hServerStopEvent )
SetEvent(hServerStopEvent);
}




void WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv)
{

sshStatusHandle = RegisterServiceCtrlHandler( TEXT(SZSERVICENAME), service_ctrl);

if (!sshStatusHandle)
goto cleanup;

ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
ssStatus.dwServiceSpecificExitCode = 0;


if (!ReportStatusToSCMgr(
SERVICE_START_PENDING,
NO_ERROR,
1))
goto cleanup;


ServiceStart( dwArgc, lpszArgv );

cleanup:

if (sshStatusHandle)
(VOID)ReportStatusToSCMgr(
SERVICE_STOPPED,
dwErr,
0);
return;
}




benben001 2003-02-10
  • 打赏
  • 举报
回复
// CPAIService.cpp : 定义控制台应用程序的入口点。
//


#include <windows.h>
#include <ole2.h>
#include <tchar.h>

//////////////////////////////////////////////////////////////////////////////
//// todo: change to desired strings
////
// name of the executable
#define SZAPPNAME "CPAI Report Build"
// internal name of the service
#define SZSERVICENAME "CPAIReportBuild"
// displayed name of the service
#define SZSERVICEDISPLAYNAME "CPAI Report Build"
// list of service dependencies - "dep1\0dep2\0\0"
#define SZDEPENDENCIES ""
//////////////////////////////////////////////////////////////////////////////




// internal variables
SERVICE_STATUS ssStatus; // current status of the service
SERVICE_STATUS_HANDLE sshStatusHandle;
DWORD dwErr = 0;
BOOL bDebug = FALSE;
TCHAR szErr[256];
HANDLE hServerStopEvent = NULL;

// internal function prototypes
VOID WINAPI service_ctrl(DWORD dwCtrlCode);
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv);
VOID CmdInstallService();
VOID CmdRemoveService();
VOID CmdDebugService(int argc, char **argv);
BOOL WINAPI ControlHandler ( DWORD dwCtrlType );
LPTSTR GetLastErrorText( LPTSTR lpszBuf, DWORD dwSize );
BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint);
void AddToMessageLog(LPTSTR lpszMsg);
VOID ServiceStart(DWORD dwArgc, LPTSTR *lpszArgv);
VOID ServiceStop();
void ShowHelpInfo();
BOOL RegQueryAndSetStringW(HKEY hSubKey, LPCWSTR lpszValueName, _bstr_t* pOutValue);
void WriteToFile(LPCTSTR pstr, LPCTSTR pPath);
void ServiceUninit();
BOOL ServiceInit(DWORD, LPTSTR*);
void Service(DWORD, LPSTR* );

inline void TESTHR(HRESULT x) {if FAILED(x) _com_issue_error(x);};


//需要从注册表读取的值
//默认为一小时启动运行一次
DWORD startInterval = 1000 * 60 * 60;
//默认为每三秒处理一条记录
DWORD calcInterval = 1000 * 3 * 1;


_bstr_t DBServer(L"dev");
_bstr_t DBUser(L"yongzhi.wu");
_bstr_t DBPwd(L" ");
_bstr_t DBName(L"PSYCHCN_TEST_CENTER");
_bstr_t ConnStr = "Provider=SQLOLEDB;Data Source=" + DBServer + ";Initial Catalog=" + DBName + ";User Id=" + DBUser + ";Password=" + DBPwd + ";";

const HKEY hRootKey = HKEY_LOCAL_MACHINE;
const TCHAR* lpszSubKey = "SOFTWARE\\Psychcn\\TestCenter\\Cpai";
const TCHAR* lpszStartIntervalValueName = "StartInterval";
const TCHAR* lpszCalcIntervalValueName = "ScoreInterval";
const WCHAR* lpszDBServerValueName = L"DBServer";
const WCHAR* lpszDBUserValueName = L"DBUser";
const WCHAR* lpszDBPwdValueName = L"DBPwd";
const WCHAR* lpszDBNameValueName= L"DBName";

bool InitInternalData()
{
//DebugBreak();
LONG ret;
DWORD dwRet=0;
DWORD type=0;
DWORD size=0;
//DWORD lasterror = 0;
HKEY hParaKey = NULL;
ret = RegCreateKeyEx(hRootKey, lpszSubKey, 0, "",
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS, NULL,
&hParaKey, &dwRet);

if (ret != ERROR_SUCCESS)
{
AddToMessageLog(_T("打开注册表失败"));
return false;
}

type =REG_DWORD;
size = sizeof(DWORD);
ret = RegQueryValueEx(hParaKey, lpszStartIntervalValueName, NULL,
&type, (LPBYTE)&startInterval, &size);
if (ret != ERROR_SUCCESS)
{

if (ERROR_FILE_NOT_FOUND==ret)
{
ret = RegSetValueEx(hParaKey, lpszStartIntervalValueName, NULL, REG_DWORD,
(LPBYTE)&startInterval, sizeof(DWORD));
if (ret != ERROR_SUCCESS)
{
RegCloseKey(hParaKey);
return false;
}
}
else
{
RegCloseKey(hParaKey);
return false;
}
//if (lasterror==
}

ret = RegQueryValueEx(hParaKey, lpszCalcIntervalValueName, NULL,
&type, (LPBYTE)&calcInterval, &size);
if (ret != ERROR_SUCCESS)
{
if (ERROR_FILE_NOT_FOUND==ret)
{
ret = RegSetValueEx(hParaKey, lpszCalcIntervalValueName, NULL, REG_DWORD,
(LPBYTE)&calcInterval, sizeof(DWORD));
if (ret != ERROR_SUCCESS)
{
RegCloseKey(hParaKey);
return false;
}
}
else
{
RegCloseKey(hParaKey);
return false;
}
}

//DebugBreak();
if (!RegQueryAndSetStringW(hParaKey, lpszDBServerValueName, &DBServer))
{
AddToMessageLog("初始化错误, 无法访问注册表");
return FALSE;
}

if (!RegQueryAndSetStringW(hParaKey, lpszDBUserValueName, &DBUser))
{
AddToMessageLog("初始化错误, 无法访问注册表");
return FALSE;
}

if (!RegQueryAndSetStringW(hParaKey, lpszDBPwdValueName, &DBPwd))
{
AddToMessageLog("初始化错误, 无法访问注册表");
return FALSE;
}

if (!RegQueryAndSetStringW(hParaKey, lpszDBNameValueName, &DBName))
{
AddToMessageLog("初始化错误, 无法访问注册表");
return FALSE;
}

ConnStr = "Provider=SQLOLEDB;Data Source=" + DBServer + ";Initial Catalog=" + DBName + ";User Id=" + DBUser + ";Password=" + DBPwd + ";";

RegCloseKey(hParaKey);

return true;
}

BOOL RegQueryAndSetStringW(HKEY hSubKey, LPCWSTR lpszValueName, _bstr_t* pOutValue)
{
LONG ret;
DWORD type= REG_SZ;
DWORD size = 0;
LPBYTE pData= (LPBYTE)(WCHAR*)(*pOutValue);
ret = RegQueryValueExW(hSubKey, lpszValueName, NULL, &type, NULL, &size);

if (ERROR_FILE_NOT_FOUND == ret)
{
//注册默认值.
size = pOutValue->length() * 2;
ret = RegSetValueExW(hSubKey, lpszValueName, NULL, REG_SZ, pData, size);

return (ret==ERROR_SUCCESS);
}

if (type!=REG_SZ)
{
return FALSE;
}

WCHAR * pstr = (WCHAR*)malloc(size);
if (pstr == NULL)
return FALSE;

ZeroMemory(pstr, size);
ret = RegQueryValueExW(hSubKey, lpszValueName, NULL, &type, (LPBYTE)pstr, &size);
if (ERROR_SUCCESS != ret)
{
free(pstr);
return FALSE;
}

//pOutValue->
*pOutValue = pstr;
free(pstr);

return TRUE;
}

//DWORD Calc(_RecordsetPtr prs)
//{
//
//
//}

//返回 0 , 无错误 (go on running)
//返回 1 , 服务器停止 (stop)
//返回 2 , 发生错误 (stop<error>)

DWORD CalcCPAI()
{
//DebugBreak();
DWORD ret;
DWORD nCount = 1;
char str[256] = {0};
//wsprintf(str, "%u", hServerStopEvent);
//_bstr_t bstrEvent(str);
//str[0] = 0;
//wsprintf(str, "%u", calcInterval);
//_bstr_t bstrCalcInterval(str);

//从注册表读取 calcInterval 值
_RecordsetPtr prs = NULL;
_PsyScoreObjPtr obj = NULL;

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧