无法让程序处理 WM_POWERBROADCAST 消息
Cannot get program to process WM_POWERBROADCAST message
我有一个程序,我想在收到 WM_POWERBROADCAST
消息时自动终止。然而,出于某种原因,当我让计算机进入睡眠状态时,它并没有终止。程序应该有足够的时间来响应这个调用,但我认为程序根本没有在处理消息。我认为这主要是因为程序在计算机恢复时也不会终止,并且消息至少应该在 window 的队列中。
我做错了什么导致我的程序无法处理这条消息?
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Set title of program
//SetConsoleTitleA("Star");
//FreeConsole();
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &UserProf);
const wchar_t* EndProf = L"\AppData\UserUpdates";
wcsncat(UserProf, EndProf, 23);
wstring ws(UserProf);
string wstr(ws.begin(), ws.end());
//cout << wstr << endl;
SetCurrentDirectoryA(wstr.c_str());
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
RegisterClass(&WindowClass);
HWND hWnd = CreateWindow(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_HIDE);
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
Hunter:
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket" << endl;
return 0;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
int connCounter = 0;
//Constantly attempts to connect to server
do {
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR) {
connCounter = 0;
closesocket(sock);
WSACleanup();
goto Hunter;
}
else {
connCounter = 1;
}
} while (connCounter == 0);
char buf[1024]; //Where message from server will be stored
char* pbuf{ buf };
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
string accRun = "#777 The account is currently running! ~(^.^)~\n";
string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
int loopCounter = 0;
//int on = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)TRUE, sizeof(TRUE));
MSG Msg = { 0 };
do {
ZeroMemory(buf, 1024);
u_long block = 0;
ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
int bytesReceived = recv(sock, buf, 1024, 0);
if (bytesReceived > 0) {
//Check to see if it equals one of the strings above
if (strstr(pbuf, CreateAccount)) {
//Run program to create account
int accountSuccess;
accountSuccess = accountCreation(sock);
if (accountSuccess == 0) {
int sendResult = send(sock, accInfoSuccess.c_str(), accInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, accInfoProblem.c_str(), accInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, Settings)) {
int settingsSuccess;
settingsSuccess = settingsCreation(sock);
if (settingsSuccess == 0) {
int sendResult = send(sock, settingsInfoSuccess.c_str(), settingsInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, settingsInfoProblem.c_str(), settingsInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, CheckStatus)) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else if (accountSuccess == 1){
int sendResult = send(sock, accNoRun.c_str(), accNoRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Info)) {
//Read text file containing account info and send to server
int infoChecker = checkInfo(sock);
if (infoChecker != 0) {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Run)) {
//Runs the account running program
int running = runProg();
if (running == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accRunErr.c_str(), accRunErr.size() + 1, 0);
}
}
else if (strstr(pbuf, Kill)) {
//Kills this program
WSACleanup();
return 0;
}
else {
//Send back to server that the wrong thing was inputted
int sendResult = send(sock, TryAgain.c_str(), TryAgain.size() + 1, 0);
ZeroMemory(buf, 1024);
loopCounter = 0;
}
}
else {
//Check to make sure bot is running
int vroom = isRunning();
if (vroom == 1) {
//runProg();
loopCounter = 0;
}
else {
loopCounter = 0;
}
}
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
} while (loopCounter == 0);
WSACleanup();
return 0;
}
显示的代码有很多问题,但让我们从影响您的消息问题的最重要的问题开始 - 所有这些 thread-blocking 套接字代码确实根本不属于您的WinMain()
,更不用说您的消息循环本身了。这就是为什么您处理 window 消息(例如 WM_POWERBROADCAST
) 运行 如此缓慢的原因。
您需要重构您的代码。或者:
将套接字代码移动到工作线程,让它随心所欲地阻塞该线程。
使用异步套接字 I/O(通过 WSAAsyncSelect()
等),您可以在 WindowProc
内部进行处理。或者使用重叠 I/O。无论哪种方式,都不需要线程或阻塞操作。
无论你做什么,都不要阻塞 WinMain()
的消息循环。
也就是说,您的代码存在的其他问题包括:
SHGetKnownFolderPath(..., &UserProf); wcsncat(UserProf, EndProf, 23);
是 未定义的行为 。 SHGetKnownFolderPath()
没有为您分配足够的内存来追加任何内容。您需要分配另一个足够大的缓冲区以将 UserProf
复制到其中并将 EndProf
附加到其中。或者,只需先将 UserProf
转换为 std::wstring
,然后将 EndProf
附加到其末尾(无论哪种方式,不要忘记在完成后释放 UserProf
它 - 你目前正在泄漏它)。
您不应将自定义 UserUpdates
子文件夹 直接 添加到用户的 AppData
文件夹本身。使用 FOLDERID_LocalAppData/Low
、FOLDERID_RoamingAppData
或 FOLDERID_ProgramData
来获取更合适的文件夹来添加您的东西。
string wstr(ws.begin(), ws.end());
不是将 std::wstring
转换为 std::string
的正确方法。请改用 std::wstring_convert
、WideCharToMultiByte()
或其他类似的转换。或者,根本不转换,而是使用 std::wcout
和 SetCurrentDirectoryW()
。
你误用了 SO_REUSEADDR
。在 bind()
/connect()
之后就没用了,而且你甚至都没有正确启用它。
recv()
不会像您期望的那样 return 空终止数据。您可能会在尝试匹配接收到的字符串的代码中遇到意外的副作用,如果不是正常崩溃的话。 TCP 是面向流的,而不是像您认为的那样是面向消息的。 Whosebug 上有许多帖子展示了正确 处理 I/O over TCP 的方法。
综上所述,试试这样的东西:
HWND hMyWnd = NULL;
HANDLE hThread = NULL;
bool stopThread = false;
int readString(SOCKET sock, char *buf, int buflen, string &str)
{
str.clear();
char ch, *pbuf = buf;
int len = 0, bytesReceived;
do {
if (stopThread)
return -2;
bytesReceived = recv(sock, &ch, 1, 0);
if (bytesReceived == -1) {
if ((WSAGetLastError() != WSAETIMEDOUT) || !str.empty()) {
//cerr << "Can't read from socket, Err#" << WSAGetLastError() << endl;
return -1;
}
return 1;
}
if (bytesReceived == 0) {
//cerr << "Socket disconnected by server" << endl;
return 0;
}
if (ch == '[=10=]')
break;
*pbuf++ = ch;
len += bytesReceived;
if (len == buflen) {
str.append(buf, len);
pbuf = buf;
len = 0;
}
}
while (true);
if (len > 0)
str.append(buf, len);
return 1;
}
int sendString(SOCKET sock, const string &str)
{
const char *pbuf = str.c_str();
int len = str.length() + 1, bytesSent;
do {
if (stopThread)
return -2;
bytesSent = send(sock, pbuf, len, 0);
if (bytesSent == -1) {
//cerr << "Can't send to socket, Err#" << WSAGetLastError() << endl;
return -1;
}
pbuf += bytesSent;
len -= bytesSent;
}
while (len > 0);
return 1;
}
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
//Things to send
const string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
const string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
const string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
const string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
const string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
const string accRun = "#777 The account is currently running! ~(^.^)~\n";
const string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
const string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
const string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
SOCKET sock = INVALID_SOCKET;
char buf[1024]; //Where message from server will be stored
string str;
while (!stopThread) {
//attempt to connect to server
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket, Err#" << WSAGetLastError() << endl;
break;
}
//BOOL on = TRUE;
//setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
//u_long block = 0;
//ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
wsResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (wsResult != SOCKET_ERROR) {
do {
wsResult = readString(sock, buf, sizeof(buf), str);
if (wsResult <= 0)
break;
if (!str.empty()) {
//Check to see if it equals one of the strings above
if (str == CreateAccount) {
//Run program to create account
if (accountCreation(sock) == 0) {
wsResult = sendString(sock, accInfoSuccess);
}
else {
wsResult = sendString(sock, accInfoProblem);
}
}
else if (str == Settings) {
if (settingsCreation(sock) == 0) {
wsResult = sendString(sock, settingsInfoSuccess);
}
else {
wsResult = sendString(sock, settingsInfoProblem);
}
}
else if (str == CheckStatus) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
wsResult = sendString(sock, accRun);
}
else if (accountSuccess == 1){
wsResult = sendString(sock, accNoRun);
}
else {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Info) {
//Read text file containing account info and send to server
if (checkInfo(sock) != 0) {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Run) {
//Runs the account running program
if (runProg() == 0) {
wsResult = sendString(sock, accRun);
}
else {
wsResult = sendString(sock, accRunErr);
}
}
else if (str == Kill) {
//Kills this program
PostMessage(hMyWnd, WM_CLOSE, 0, 0);
stopThread = true;
break;
}
else {
//Send back to server that the wrong thing was inputted
wsResult = sendString(sock, TryAgain);
}
}
else {
//Check to make sure bot is running
if (isRunning() == 1) {
//runProg();
}
}
}
while (!stopThread);
}
closesocket(sock);
sock = INVALID_SOCKET;
if (!stopThread)
Sleep(5000);
}
WSACleanup();
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
return 0;
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
if (hThread) {
stopThread = true;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
}
PostQuitMessage(0);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &UserProf) == S_OK) {
wstring wstr = wstring(UserProf) + L"\UserUpdates";
//wcout << wstr << endl;
SetCurrentDirectoryW(wstr.c_str());
CoTaskMemFree(UserProf);
}
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
if (!RegisterClassW(&WindowClass)) {
//cerr << "Can't register window class, Err#" << GetLastError() << endl;
return 0;
}
hMyWnd = CreateWindowW(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
if (!hMyWnd) {
//cerr << "Can't create window, Err#" << GetLastError() << endl;
return 0;
}
ShowWindow(hMyWnd, SW_HIDE);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}
我有一个程序,我想在收到 WM_POWERBROADCAST
消息时自动终止。然而,出于某种原因,当我让计算机进入睡眠状态时,它并没有终止。程序应该有足够的时间来响应这个调用,但我认为程序根本没有在处理消息。我认为这主要是因为程序在计算机恢复时也不会终止,并且消息至少应该在 window 的队列中。
我做错了什么导致我的程序无法处理这条消息?
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_CLOSE:
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Set title of program
//SetConsoleTitleA("Star");
//FreeConsole();
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
SHGetKnownFolderPath(FOLDERID_Profile, 0, NULL, &UserProf);
const wchar_t* EndProf = L"\AppData\UserUpdates";
wcsncat(UserProf, EndProf, 23);
wstring ws(UserProf);
string wstr(ws.begin(), ws.end());
//cout << wstr << endl;
SetCurrentDirectoryA(wstr.c_str());
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
RegisterClass(&WindowClass);
HWND hWnd = CreateWindow(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, SW_HIDE);
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
Hunter:
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
SOCKET sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket" << endl;
return 0;
}
sockaddr_in hint;
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
int connCounter = 0;
//Constantly attempts to connect to server
do {
int connResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (connResult == SOCKET_ERROR) {
connCounter = 0;
closesocket(sock);
WSACleanup();
goto Hunter;
}
else {
connCounter = 1;
}
} while (connCounter == 0);
char buf[1024]; //Where message from server will be stored
char* pbuf{ buf };
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
string accRun = "#777 The account is currently running! ~(^.^)~\n";
string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
int loopCounter = 0;
//int on = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)TRUE, sizeof(TRUE));
MSG Msg = { 0 };
do {
ZeroMemory(buf, 1024);
u_long block = 0;
ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
int bytesReceived = recv(sock, buf, 1024, 0);
if (bytesReceived > 0) {
//Check to see if it equals one of the strings above
if (strstr(pbuf, CreateAccount)) {
//Run program to create account
int accountSuccess;
accountSuccess = accountCreation(sock);
if (accountSuccess == 0) {
int sendResult = send(sock, accInfoSuccess.c_str(), accInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, accInfoProblem.c_str(), accInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, Settings)) {
int settingsSuccess;
settingsSuccess = settingsCreation(sock);
if (settingsSuccess == 0) {
int sendResult = send(sock, settingsInfoSuccess.c_str(), settingsInfoSuccess.size() + 1, 0);
}
else {
int sendResult = send(sock, settingsInfoProblem.c_str(), settingsInfoProblem.size() + 1, 0);
}
}
else if (strstr(pbuf, CheckStatus)) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else if (accountSuccess == 1){
int sendResult = send(sock, accNoRun.c_str(), accNoRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Info)) {
//Read text file containing account info and send to server
int infoChecker = checkInfo(sock);
if (infoChecker != 0) {
int sendResult = send(sock, accNoInfo.c_str(), accNoInfo.size() + 1, 0);
}
}
else if (strstr(pbuf, Run)) {
//Runs the account running program
int running = runProg();
if (running == 0) {
int sendResult = send(sock, accRun.c_str(), accRun.size() + 1, 0);
}
else {
int sendResult = send(sock, accRunErr.c_str(), accRunErr.size() + 1, 0);
}
}
else if (strstr(pbuf, Kill)) {
//Kills this program
WSACleanup();
return 0;
}
else {
//Send back to server that the wrong thing was inputted
int sendResult = send(sock, TryAgain.c_str(), TryAgain.size() + 1, 0);
ZeroMemory(buf, 1024);
loopCounter = 0;
}
}
else {
//Check to make sure bot is running
int vroom = isRunning();
if (vroom == 1) {
//runProg();
loopCounter = 0;
}
else {
loopCounter = 0;
}
}
if (PeekMessage(&Msg, NULL, 0, 0, PM_REMOVE) != 0) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
} while (loopCounter == 0);
WSACleanup();
return 0;
}
显示的代码有很多问题,但让我们从影响您的消息问题的最重要的问题开始 - 所有这些 thread-blocking 套接字代码确实根本不属于您的WinMain()
,更不用说您的消息循环本身了。这就是为什么您处理 window 消息(例如 WM_POWERBROADCAST
) 运行 如此缓慢的原因。
您需要重构您的代码。或者:
将套接字代码移动到工作线程,让它随心所欲地阻塞该线程。
使用异步套接字 I/O(通过
WSAAsyncSelect()
等),您可以在WindowProc
内部进行处理。或者使用重叠 I/O。无论哪种方式,都不需要线程或阻塞操作。
无论你做什么,都不要阻塞 WinMain()
的消息循环。
也就是说,您的代码存在的其他问题包括:
SHGetKnownFolderPath(..., &UserProf); wcsncat(UserProf, EndProf, 23);
是 未定义的行为 。SHGetKnownFolderPath()
没有为您分配足够的内存来追加任何内容。您需要分配另一个足够大的缓冲区以将UserProf
复制到其中并将EndProf
附加到其中。或者,只需先将UserProf
转换为std::wstring
,然后将EndProf
附加到其末尾(无论哪种方式,不要忘记在完成后释放UserProf
它 - 你目前正在泄漏它)。您不应将自定义
UserUpdates
子文件夹 直接 添加到用户的AppData
文件夹本身。使用FOLDERID_LocalAppData/Low
、FOLDERID_RoamingAppData
或FOLDERID_ProgramData
来获取更合适的文件夹来添加您的东西。string wstr(ws.begin(), ws.end());
不是将std::wstring
转换为std::string
的正确方法。请改用std::wstring_convert
、WideCharToMultiByte()
或其他类似的转换。或者,根本不转换,而是使用std::wcout
和SetCurrentDirectoryW()
。你误用了
SO_REUSEADDR
。在bind()
/connect()
之后就没用了,而且你甚至都没有正确启用它。recv()
不会像您期望的那样 return 空终止数据。您可能会在尝试匹配接收到的字符串的代码中遇到意外的副作用,如果不是正常崩溃的话。 TCP 是面向流的,而不是像您认为的那样是面向消息的。 Whosebug 上有许多帖子展示了正确 处理 I/O over TCP 的方法。
综上所述,试试这样的东西:
HWND hMyWnd = NULL;
HANDLE hThread = NULL;
bool stopThread = false;
int readString(SOCKET sock, char *buf, int buflen, string &str)
{
str.clear();
char ch, *pbuf = buf;
int len = 0, bytesReceived;
do {
if (stopThread)
return -2;
bytesReceived = recv(sock, &ch, 1, 0);
if (bytesReceived == -1) {
if ((WSAGetLastError() != WSAETIMEDOUT) || !str.empty()) {
//cerr << "Can't read from socket, Err#" << WSAGetLastError() << endl;
return -1;
}
return 1;
}
if (bytesReceived == 0) {
//cerr << "Socket disconnected by server" << endl;
return 0;
}
if (ch == '[=10=]')
break;
*pbuf++ = ch;
len += bytesReceived;
if (len == buflen) {
str.append(buf, len);
pbuf = buf;
len = 0;
}
}
while (true);
if (len > 0)
str.append(buf, len);
return 1;
}
int sendString(SOCKET sock, const string &str)
{
const char *pbuf = str.c_str();
int len = str.length() + 1, bytesSent;
do {
if (stopThread)
return -2;
bytesSent = send(sock, pbuf, len, 0);
if (bytesSent == -1) {
//cerr << "Can't send to socket, Err#" << WSAGetLastError() << endl;
return -1;
}
pbuf += bytesSent;
len -= bytesSent;
}
while (len > 0);
return 1;
}
//Things to compare
const char* CreateAccount = "create"; //Server tells client to make IG account
const char* CheckStatus = "check"; //Client tells server if account is running or not
const char* Info = "info"; //Client sends Username and Password of account to server
const char* Run = "run"; //Tells client to start running the account
const char* Kill = "kill"; //Kills program on client for around a month
const char* Settings = "settings"; //Server sets settings for account to run on
//Things to send
const string TryAgain = "#13 Not a valid input, either type [check] to check if the account is running, type [create] to create new account, or type [info] for account information\n";
const string accInfoSuccess = "#777 You have successfully entered the information for the account (^.^)\n";
const string settingsInfoSuccess = "#777 You have successfully set the settings for this account (^.^)\n";
const string accInfoProblem = "#13 There was a problem in either saving the information to this account or the account creation program. Type [create] and try again (T.T)\n";
const string settingsInfoProblem = "#13 There was a problem in saving the account settings. Type [settings] and try again (T.T)\n";
const string accRun = "#777 The account is currently running! ~(^.^)~\n";
const string accNoRun = "#13 Sorry the account isn't running, type [run] to run the account (O.o)\n";
const string accNoInfo = "#13 There is no info for an account that can be run. Type [create] to make information (\".\")\n";
const string accRunErr = "#13 There is a problem with opening the main bot program, try again. If this problem persists, there is an issue clientside V(T.T)V\n";
DWORD WINAPI ThreadProc(LPVOID lpParameter)
{
string ipAddress = "10.0.0.201"; //IP address of my computer on local network
int port = 13777;
WSAData data;
WORD ver = MAKEWORD(2, 2);
int wsResult = WSAStartup(ver, &data);
if (wsResult != 0) {
//cerr << "Can't start Winsock, Err#" << wsResult << endl;
return 0;
}
sockaddr_in hint = {};
hint.sin_family = AF_INET;
hint.sin_port = htons(port);
inet_pton(AF_INET, ipAddress.c_str(), &hint.sin_addr);
SOCKET sock = INVALID_SOCKET;
char buf[1024]; //Where message from server will be stored
string str;
while (!stopThread) {
//attempt to connect to server
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == INVALID_SOCKET) {
//cerr << "Can't create socket, Err#" << WSAGetLastError() << endl;
break;
}
//BOOL on = TRUE;
//setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&on, sizeof(on));
//u_long block = 0;
//ioctlsocket(sock, FIONBIO, &block);
DWORD timeout = 500;
setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(timeout));
//setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&timeout, sizeof(timeout));
wsResult = connect(sock, (sockaddr*)&hint, sizeof(hint));
if (wsResult != SOCKET_ERROR) {
do {
wsResult = readString(sock, buf, sizeof(buf), str);
if (wsResult <= 0)
break;
if (!str.empty()) {
//Check to see if it equals one of the strings above
if (str == CreateAccount) {
//Run program to create account
if (accountCreation(sock) == 0) {
wsResult = sendString(sock, accInfoSuccess);
}
else {
wsResult = sendString(sock, accInfoProblem);
}
}
else if (str == Settings) {
if (settingsCreation(sock) == 0) {
wsResult = sendString(sock, settingsInfoSuccess);
}
else {
wsResult = sendString(sock, settingsInfoProblem);
}
}
else if (str == CheckStatus) {
//Check to see if program that runs account is running
int accountSuccess = isRunning();
if (accountSuccess == 0) {
wsResult = sendString(sock, accRun);
}
else if (accountSuccess == 1){
wsResult = sendString(sock, accNoRun);
}
else {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Info) {
//Read text file containing account info and send to server
if (checkInfo(sock) != 0) {
wsResult = sendString(sock, accNoInfo);
}
}
else if (str == Run) {
//Runs the account running program
if (runProg() == 0) {
wsResult = sendString(sock, accRun);
}
else {
wsResult = sendString(sock, accRunErr);
}
}
else if (str == Kill) {
//Kills this program
PostMessage(hMyWnd, WM_CLOSE, 0, 0);
stopThread = true;
break;
}
else {
//Send back to server that the wrong thing was inputted
wsResult = sendString(sock, TryAgain);
}
}
else {
//Check to make sure bot is running
if (isRunning() == 1) {
//runProg();
}
}
}
while (!stopThread);
}
closesocket(sock);
sock = INVALID_SOCKET;
if (!stopThread)
Sleep(5000);
}
WSACleanup();
return 0;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
switch (message) {
case WM_CREATE: {
hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);
return 0;
case WM_POWERBROADCAST:
DestroyWindow(hWnd);
return 0;
case WM_DESTROY:
if (hThread) {
stopThread = true;
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;
}
PostQuitMessage(0);
return 0;
case WM_CLOSE:
DestroyWindow(hWnd);
return 0;
}
return DefWindowProc(hWnd, message, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
//Change the current directory of the program back to the appropriate folder
wchar_t* UserProf;
if (SHGetKnownFolderPath(FOLDERID_LocalAppData, 0, NULL, &UserProf) == S_OK) {
wstring wstr = wstring(UserProf) + L"\UserUpdates";
//wcout << wstr << endl;
SetCurrentDirectoryW(wstr.c_str());
CoTaskMemFree(UserProf);
}
WNDCLASSW WindowClass{CS_NOCLOSE, WindowProc, 0, 0, hInstance, NULL, LoadCursor(nullptr, IDC_ARROW), NULL, NULL, L"chakra"};
if (!RegisterClassW(&WindowClass)) {
//cerr << "Can't register window class, Err#" << GetLastError() << endl;
return 0;
}
hMyWnd = CreateWindowW(L"chakra", L"star", WS_POPUP, 0, 0, 10, 10, NULL, NULL, hInstance, NULL);
if (!hMyWnd) {
//cerr << "Can't create window, Err#" << GetLastError() << endl;
return 0;
}
ShowWindow(hMyWnd, SW_HIDE);
MSG Msg;
while (GetMessage(&Msg, NULL, 0, 0)) {
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return 0;
}