log.h
#pragma once
#include "StdAfx.h"
#include <iostream>
class CLog
{
public:
enum LogLevel // Log级别
{
lvInfo = 0, // 一般
lvWarning = 1, // 警告
lvError = 2 // 错误
};
CLog ();
~CLog ();
bool Open(LPCTSTR pszFileName);
void Close(); // 关闭日志记录
void Write(int nLogLevel, LPCTSTR pszFormat, ...); // 格式化写入日志信息
private:
FILE* m_out;
};
log.cpp
#include "stdafx.h"
#include "Log.h"
#include <time.h>
#include <iostream>
#include <queue>
#include <stdarg.h>
#pragma warning(disable:4996)
#ifdef _UNICODE
typedef wchar_t char_t;
typedef std::wstring string_t;
typedef std::wstringstream stringstream_t;
#else
typedef char char_t;
typedef std::string string_t;
typedef std::stringstream stringstream_t;
#endif
// 格式化获取当前日期
static string_t GetTimeStr(LPCTSTR format)
{
time_t t;
time(&t);
tm* time = localtime(&t);
//"2011-07-18 23:03:01 ";
//format = "%Y-%m-%d %H:%M:%S ";
char_t strDate[50];
_tcsftime(strDate, 30, format, time);
return string_t(strDate);
}
// 获取操作系统版本信息
static string_t GetOSName()
{
SYSTEM_INFO info = {0};
ZeroMemory(&info, sizeof(info));
GetSystemInfo(&info);
OSVERSIONINFOEX os;
os.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
if (::GetVersionEx((OSVERSIONINFO*) & os))
{
string_t vname;
// 判断主版本号
switch (os.dwMajorVersion)
{
case 4:
// 判断次版本号
switch (os.dwMinorVersion)
{
case 0:
if (os.dwPlatformId == VER_PLATFORM_WIN32_NT)
// 1996年7月发布
vname = _T("Microsoft Windows NT 4.0");
else if (os.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
vname = _T("Microsoft Windows 95");
break;
case 10:
vname = _T("Microsoft Windows 98");
break;
case 90:
vname = _T("Microsoft Windows Me");
break;
}
break;
case 5:
// 再比较dwMinorVersion的值
switch (os.dwMinorVersion)
{
case 0:
// 1999年12月发布
vname = _T("Microsoft Windows 2000");
break;
case 1:
// 2001年8月发布
vname = _T("Microsoft Windows XP");
break;
case 2:
if (os.wProductType == VER_NT_WORKSTATION
&& info.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64)
vname = _T("Microsoft Windows XP Professional x64 Edition");
else if (GetSystemMetrics(SM_SERVERR2) == 0)
vname = _T("Microsoft Windows Server 2003");
// 2003年3月发布
else if (GetSystemMetrics(SM_SERVERR2) != 0)
vname = _T("Microsoft Windows Server 2003 R2");
break;
}
break;
case 6:
switch (os.dwMinorVersion)
{
case 0:
// VER_NT_WORKSTATION是桌面系统
if (os.wProductType == VER_NT_WORKSTATION)
vname = _T("Microsoft Windows Vista");
else
//服务器版本
vname = _T("Microsoft Windows Server 2008");
break;
case 1:
if (os.wProductType == VER_NT_WORKSTATION)
vname = _T("Microsoft Windows 7");
else
vname = _T("Microsoft Windows Server 2008 R2");
break;
}
break;
default:
vname=_T("未知操作系统");
}
WORD nSpVer = os.wServicePackMajor;
char_t strSpVer[10];
_itow_s(nSpVer, strSpVer, 10, 10);
vname.append(L" SP").append(strSpVer);
return vname;
}
else
return _T("");
}
// 获取操作系统位数
static string_t GetOSBit()
{
SYSTEM_INFO si;
GetNativeSystemInfo(&si);
if (si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_AMD64 ||
si.wProcessorArchitecture == PROCESSOR_ARCHITECTURE_IA64 )
{
return string_t(_T("64位"));
}
else
{
return string_t(_T("32位"));
}
}
// 获取IE浏览器版本
static string_t GetIEVer()
{
char_t strVer[64];
ULONG dwSize = 64;
CRegKey keyVersion;
try
{
LONG lResult = keyVersion.Open(HKEY_LOCAL_MACHINE,
TEXT("SOFTWARE\\Microsoft\\Internet Explorer"), KEY_READ);
if (lResult != ERROR_SUCCESS)
throw L"获取IE版本信息异常";
LONG lResultQuery = keyVersion.QueryStringValue(
TEXT("Version"), strVer, &dwSize);
if (ERROR_SUCCESS != lResultQuery)
return L"查询IE版本信息异常";
}
catch (char_t* ex)
{
std::wcout << ex << std::endl;
}
return string_t(strVer);
}
// 获取磁盘分区信息
static string_t GetDisksStr()
{
string_t strDriv ;
DWORD dw = GetLogicalDriveStrings(0,NULL);
char_t* drivStr = (char_t*)HeapAlloc(
GetProcessHeap(), 0, dw * sizeof(TCHAR));
GetLogicalDriveStringsW(dw,drivStr);
int count = 0;
while (count < 100)
{
if (drivStr[count] == _T(':'))
{
//char_t wc = drivStr[count];
char_t buff[1];
buff[0] = drivStr[count-1];
strDriv.append(buff, 1);
buff[0] = drivStr[count];
strDriv.append(buff, 1);
buff[0] = drivStr[count+1];
strDriv.append(buff, 1);
strDriv.append(L" ");
}
count++;
}
return strDriv;
}
// 获取内存大小
static string_t GetMemSize()
{
string_t strMem;
MEMORYSTATUS memStat; // 内存信息结构体
ZeroMemory(&memStat, sizeof(memStat));
memStat.dwLength = sizeof(memStat);
GlobalMemoryStatus(&memStat);
size_t totalPhys = memStat.dwTotalPhys / (1024*1024); // 总内存大小(MB)
size_t availPhys = memStat.dwAvailPhys / (1024*1024); // 可用内存大小(MB)
char_t strTotal[10];
char_t strAvail[10];
_ui64tow_s(totalPhys, strTotal, 10, 10);
_ui64tow_s(availPhys, strAvail, 10, 10);
strMem.append(_T("总内存大小: ")).append(strTotal).append(_T("M"));
strMem.append(_T(" 可用内存大小: ")).append(strAvail).append(_T("M"));
return strMem;
}
// 获取CPU信息
static string_t GetCpuInfo()
{
string_t strCpu;
HKEY hKey;
#define BUFSIZE 80
char_t szCpuInfo[BUFSIZE];
DWORD szCpuFre = 0;
DWORD dwBufLen = BUFSIZE;
LONG lRet;
lRet = RegOpenKeyEx( HKEY_LOCAL_MACHINE,
_T("HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0"),
0, KEY_QUERY_VALUE, &hKey);
if ( lRet != ERROR_SUCCESS )
{
strCpu = _T("未知CPU类型");
}
else
{
lRet = RegQueryValueExW( hKey, _T("ProcessorNameString"), NULL, NULL,
(LPBYTE)szCpuInfo, &dwBufLen);
if ( (lRet != ERROR_SUCCESS) || (dwBufLen > BUFSIZE) )
{
strCpu = _T("未知CPU类型");
}
else
{
strCpu = szCpuInfo;
lRet = RegQueryValueEx(hKey, _T("~MHz"), NULL, NULL,
(LPBYTE) &szCpuFre, &dwBufLen);
}
}
return strCpu;
}
// 获取当前线程所在路径
static string_t GetProcPath()
{
char_t path[MAX_PATH];
GetModuleFileNameW(NULL, path, MAX_PATH);
return string_t(path);
}
// 获取磁盘使用情况
static string_t GetDisksFreeSpace()
{
_ULARGE_INTEGER freespace, totalspace, userspace;
string_t diskInfo;
string_t strDisks = GetDisksStr();
char_t buff[20] = {0};
_tcscpy(buff, strDisks.c_str());
std::queue <string_t> drivs;
int index = 0;
while (buff[index])
{
char_t driv[3] = {0};
driv[0] = buff[index];
driv[1] = buff[++index];
index += 3;
drivs.push(driv);
}
while (!drivs.empty())
{
string_t driv;
driv = drivs.front();
drivs.pop();
GetDiskFreeSpaceExW(driv.c_str(), &userspace,
&totalspace, &freespace);
LONGLONG gByte = 1024 * 1024 * 1024;
double dTotal = (double)((totalspace.QuadPart) / gByte);
double dUse = (double)((userspace.QuadPart) / gByte);
double dFree = (double)((freespace.QuadPart) / gByte);
char_t drivInfo[100];
swprintf(drivInfo, _T("\t%s 总大小:%4gG 已用:%4gG 可用:%4gG\n"),
driv.c_str(), dTotal, dUse, dFree);
diskInfo.append(drivInfo);
}
return diskInfo;
}
//
// CLog 日志记录类
// 构造函数
CLog::CLog():m_out(NULL) {}
bool CLog::Open(LPCTSTR pszFileName)
{
m_out = _tfopen(pszFileName, _T("a,ccs=UTF-8"));
try
{
if (m_out == NULL)
throw _T("打开log文件出错");
fseek(m_out, 0, SEEK_END);
long fsize = ftell(m_out);
if (fsize <= 10)
{
string_t osName = GetOSName(); // 操作系统名称
string_t osBit = GetOSBit(); // 操作系统位数(32/64)
string_t ieVer = GetIEVer(); // IE版本
string_t partition = GetDisksStr(); // 分区信息
string_t diskInfo = GetDisksFreeSpace(); // 磁盘使用情况
string_t memSize = GetMemSize(); // 内存大小
string_t cpuInfo = GetCpuInfo(); // CPU信息s
DWORD pId = GetCurrentThreadId(); // 当前线程ID
string_t procPath = GetProcPath(); // 当前线程所在路径
char* old_locale = _strdup(setlocale(LC_CTYPE,NULL) );
setlocale(LC_CTYPE, "chs" );//设定
LPCTSTR ex = _T("写日志文件异常!");
if (-1 == _ftprintf(m_out,
L"--------------------------------------------------------------------\n"))
throw ex;
if (-1 == _ftprintf(m_out,
L"%s%s %s\n", _T("[操作系统版本]\n\t"), osName.c_str(), osBit.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[IE版本]\n\t%s%s\n"), _T("Internet Explorer "), ieVer.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[磁盘分区]\n\t%s\n"), partition.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[磁盘使用情况]\n%s"), diskInfo.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[内存使用情况]\n\t%s\n"), memSize.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[CPU信息]\n\t%s\n"), cpuInfo.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[当前进程ID]\n\t%d\n"), pId))
throw ex;
if (-1 == _ftprintf(m_out,
_T("[程序所在路径]\n\t%s\n"), procPath.c_str()))
throw ex;
if (-1 == _ftprintf(m_out,
_T("--------------------------------------------------------------------\n")))
throw ex;
setlocale( LC_CTYPE, old_locale );
free(old_locale);//还原区域设定
}
}
catch (LPCTSTR /*ex*/)
{
//std::wcout << ex << std::endl;
return false;
}
return true;
}
// 格式化写入日志信息 logLevel: 日志级别
void CLog::Write(int logLevel, LPCTSTR format, ...)
{
va_list ap;
va_start(ap, format);
string_t logTime = GetTimeStr(_T("%Y-%m-%d %H:%M:%S"));
try
{
char_t args[256] = {0};
va_start(ap, format);
_vstprintf(args, format, ap);
string_t strLevel;
switch (logLevel)
{
case CLog::lvInfo:
strLevel = _T("Info");
break;
case CLog::lvWarning:
strLevel = _T("Warn");
break;
case CLog::lvError:
strLevel = _T("Error");
break;
}
if (-1 == _ftprintf(m_out,_T("[%s] [%s] %s\n"),
logTime.c_str(), strLevel.c_str(), args))
throw L"写入日志出错!";
va_end(ap);
}
catch (char_t* ex)
{
std::wcout << ex << std::endl;
}
}
// 关闭记录文件
void CLog::Close()
{
if (m_out != NULL)
{
fclose(m_out);
m_out = NULL;
}
}
CLog::~CLog()
{
Close();
}