Output CString type with std::cout and printf

CString is a MFC class and it’s under unicode.

When using standard stream to output it, use std::wcout instead of std::cout becuase it’s wide charaters. Also, use cstr.GetBuffer() instead of cstr. Or LPCTSTR(cstr) should work the same.
Example:


CString str1, str2;
std::wcout << “str1: “ << str1.GetBuffer() << std::endl << “str2: “ << str2.GetBuffer() << std::endl;



When using printf, use %S instead of %s should do the job.
2016/2/13 22:05

Different between type bool, BOOL, boolean and BOOLEAN in C/C++

For bool, it can only be used in C++. (For C, there is only _Bool in C99 standard. ) It could be either true or false. It’s only true if it’s not 0.

For BOOL, it’s actually int as typedef int BOOL; and can be ither TRUE or FALSE. It’s only true if it equals 1.

For BOOLEAN, it’s actually byte as typedef BYTE BOOLEAN and only 2 bytes long.

For boolean, it’s not a formal type in C/C++.

Usually, bool is the most common one we use and takes 4 bytes. BOOLEAN is a better solution with less memory cost. But it’s still recommended to use bool in that I am already familiar with it.

When binding sockets to server, which address to choose

Usually when binding a socket to the server, the ip binded could be any of the ips the server keeps including the loopback address, the local area network address, the public Internet address or a preserved address 0.0.0.0.

For loopback address or 127.0.0.1, only local connection to localhost will be recieved. It’s useful in debugging or when using a Reverse Proxy like ngrok.

For the local area networks adress like 192.168.7.7 or public Internet address like 1.2.3.4, only external access to the mechine will be recieved which is most of the server need.

There is an ultimate solution which is a preserved address 0.0.0.0. It includes both three address above and any other unknown addresses. Using it makes sure that all the connections are listen.

Unknown problem...

From: http://blog.csdn.net/creazyapple/article/details/7459875
Deal with this:


1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _inet_ntoa@4,该符号在函数 “public: void thiscall InfoSenser::printNetInfo(void)” (?printNetInfo@InfoSenser@@QAEXXZ) 中被引用
1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _gethostbyname@4,该符号在函数 “public:
thiscall InfoSenser::InfoSenser(void)” (??0InfoSenser@@QAE@XZ) 中被引用
1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _gethostname@8,该符号在函数 “public: thiscall InfoSenser::InfoSenser(void)” (??0InfoSenser@@QAE@XZ) 中被引用
1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _WSAStartup@8,该符号在函数 “public:
thiscall InfoSenser::InfoSenser(void)” (??0InfoSenser@@QAE@XZ) 中被引用
1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _WSACleanup@0,该符号在函数 “public: thiscall InfoSenser::~InfoSenser(void)” (??1InfoSenser@@QAE@XZ) 中被引用
1>InfoSenser.obj : error LNK2019: 无法解析的外部符号 _WSAGetLastError@0,该符号在函数 “public:
thiscall InfoSenser::InfoSenser(void)” (??0InfoSenser@@QAE@XZ) 中被引用
1>D:\netbeans-java\CraftPlugins\ClientCtl\ClientCtl\Debug\ClientCtl.exe : fatal error LNK1120: 6 个无法解析的外部命令

Add #pragma comment(lib,"ws2_32.lib")right after the inclusion of header files in the .cpp file could previent this.
==Still need to find out how does this work. It statically load a dll which I don’t know what it is.==
2017/2/9 23:15

A bad but useable way to deal with _TCHAR* argv[] parameter

from: http://stackoverflow.com/questions/19301538/converting-tchar-to-char
==Warning: this is a temporary solution and shouldn’t be used as a long-term solution. ==


Instead of using the original one, just use int main(int argc, char *argv[]) instead. The new type _TCHAR is actually a macro of a longer char that allows more kinds of characters (char is 128 which is not enough) just for compatible purpose. Since I don’t need internalizations now anyways, I think it’s safe to do that.

How to create a windows services program to run background on start up and how to register it

In order to create a windows serivice program, a program must have certain content inside to register and respond to actions. Also, it must be registered to the system through the program sc at shell or through editing the registry table which both need adminstrator permission.

In the program:

#Declare three global varible. The name is not important.


SERVICE_TABLE_ENTRY entryTable[2];
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;


#declare 2 global functions as follow which one will be called when the service start and work as the main function of the service in another process and another will be called when there is a control signal like start or restart was issued by the system or users. The name of them is not important.


void WINAPI ctrlHandler(DWORD request);
void WINAPI serviceMain(int argc, char**argv);


#Fill in the created array of the struct SERVICE_TABLE_ENTRY contains two elements in that service information in the first one and put all nulls in the second as follow. Then, use StartServiceCtrlDispatcher(entryTable); to register the service. This step have to be done during founction main.


void initEntryTable(SERVICE_TABLE_ENTRY &templateEnteyTable){
    entryTable[0].lpServiceName = templateEnteyTable.lpServiceName;
    entryTable[0].lpServiceProc = templateEnteyTable.lpServiceProc;
    entryTable[1].lpServiceName = NULL;
    entryTable[1].lpServiceProc = NULL;
    StartServiceCtrlDispatcher(entryTable);
}
I use these codes to initialize a entry table.

        serviceT.lpServiceName = TEXT("testservice");
        serviceT.lpServiceProc = (LPSERVICE_MAIN_FUNCTION)serviceMain;
        initEntryTable(serviceT);


#Now the void WINAPI serviceMain(int argc, char**argv); should contains code like the following to illustrate the property of itself by giving certain value of the variables inside the struct ServiceStatus. Then, register the service and get the handle of it with hStatus = ::RegisterServiceCtrlHandlerW(TEXT("testservice"), ctrlHandler);


    ServiceStatus.dwServiceType = SERVICE_WIN32;

    ServiceStatus.dwCurrentState = SERVICE_START_PENDING;/*This is the state of this service and need to be changed actively.*/

    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; /*This is the types of command your service could recieve*/

    ServiceStatus.dwWin32ExitCode = 0;/*I am still learning this part, leave it 0*/

    ServiceStatus.dwServiceSpecificExitCode = 0;/*I am still learning this part, leave it 0*/

    ServiceStatus.dwCheckPoint = 0;/*I am still learning this part, leave it 0*/

    ServiceStatus.dwWaitHint = 0;/*I am still learning this part, leave it 0*/


    hStatus = ::RegisterServiceCtrlHandlerW(TEXT("testservice"), ctrlHandler);


#Since the serviceMain() founction takes controll of the service status, the state of the service must be change to ServiceStatus.dwCurrentState = SERVICE_RUNNING; and report to the system with SetServiceStatus once it done with initialization or the system will wrongly recognize the service as “going wrong” and get a error of “failed to start, service is not responding”.


ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus(hStatus, &ServiceStatus);


#For the void WINAPI ctrlHandler(DWORD request), it deals with requests like shutdown and the request will be sent as parameter.


#The final step is to register the service officially to the system through sc or the registry table. I use the first step because it’s easier.

Manually: Enter system shell, use sc create testservice binPath="C:\path\to\file.exe" to create a new service. ==(There is a space after all the = symbols which is necessary)==
To configure it like make the service start up on boot, either sc config testservice [configuration] or sc create testservice [configuration works].

InCode: I use the following code the do the job.


std::string filename(argv[0]);
string mycommand = (std::string)”sc create testservice binPath= \””+filename+”\””+” start= auto”;
const char *c = mycommand.data();
std::cout << “Execute: “ << mycommand << “?” << std::endl<


#Now the service should be done and should be shown in the service control manager.
2017/2/9 13:06

A way to avoid duplicate declaration

While there are multiple hear file insertions and there are insertions inside those header files, it’s common that a error of duplicate declaration occurs. To solve that, one way is add a macro #ifndef HEADER_FILE_H after the macro #define <header_file.h> and add #endif at the end of the program could solve the confict in header files.