- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我遵循了“简单的窗口”tutorial来自 WinProg 网站。
当教程中的代码在没有 C 运行时库的情况下编译时,一切似乎都按预期工作。窗口已创建并向用户可见显示。
如果我通过按关闭按钮关闭窗口,该窗口将被销毁并且进程将退出 - 该进程不再在本地计算机上运行。
但是,当我链接到 WTS 库并添加对 WTSRegisterSessionNotification 函数的调用时,该进程在关闭其相应窗口后继续在本地计算机上运行。
此行为似乎仅在调用 WTSRegisterSessionNotification 后从 WinMain 返回时才会发生。
我的猜测是 WTSRegisterSessionNotification 创建某种永远不会被通知退出的工作线程。从 WinMain 返回似乎不会导致 ExitProcess 调用,可能是因为代码是在没有 C 运行时库的情况下编译的。
从 WinMain 返回之前调用 ExitProcess 可以避免该问题。但这感觉不是处理这种情况的正确方法。
我的问题是:是否有一个我忽略的 WTS API 函数可以/应该在从 WinMain 返回之前调用,以确保进程退出?
代码示例:
#include <windows.h>
#include <wtsapi32.h>
const char g_szClassName[] = "myWindowClass";
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
switch (msg)
{
case WM_WTSSESSION_CHANGE:
if (wParam == WTS_SESSION_LOCK)
OutputDebugString( "current session got locked" );
else if (wParam == WTS_SESSION_UNLOCK)
OutputDebugString( "current session got unlocked" );
break;
case WM_CLOSE:
DestroyWindow( hwnd );
break;
case WM_DESTROY:
WTSUnRegisterSessionNotification( hwnd );
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hwnd, msg, wParam, lParam );
}
return 0;
}
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow )
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
//Step 1: Registering the Window Class
wc.cbSize = sizeof( WNDCLASSEX );
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon( NULL, IDI_APPLICATION );
wc.hCursor = LoadCursor( NULL, IDC_ARROW );
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon( NULL, IDI_APPLICATION );
if (!RegisterClassEx( &wc ))
{
MessageBox( NULL, "Window Registration Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}
// Step 2: Creating the Window
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
g_szClassName,
"The title of my window",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
NULL, NULL, hInstance, NULL );
if (hwnd == NULL)
{
MessageBox( NULL, "Window Creation Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}
if (!WTSRegisterSessionNotification( hwnd, NOTIFY_FOR_THIS_SESSION ))
{
MessageBox( NULL, "Register Session Notification Failed!", "Error!",
MB_ICONEXCLAMATION | MB_OK );
return 0;
}
ShowWindow( hwnd, nCmdShow );
UpdateWindow( hwnd );
// Step 3: The Message Loop
while (GetMessage( &Msg, NULL, 0, 0 ) > 0)
{
TranslateMessage( &Msg );
DispatchMessage( &Msg );
}
return Msg.wParam;
}
编译器命令行:
/GS- /TC /GL /analyze- /W4 /Gy /Zc:wchar_t /Gm- /O1 /Ob2 /Fd"Release\vc100.pdb" /fp:fast /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /errorReport:prompt /WX- /Zc:forScope /GR- /Gd /Oy /Oi /MD /Fa"Release\" /nologo /Zl /Fo"Release\" /Os
链接器命令行:
/OUT:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.exe" /MANIFEST:NO /LTCG /NXCOMPAT /PDB:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.pdb" /DYNAMICBASE:NO "kernel32.lib" "user32.lib" "wtsapi32.lib" /ALLOWISOLATION /MACHINE:X86 /ENTRY:"WinMain" /OPT:REF /INCREMENTAL:NO /PGD:"C:\Users\treintje\Documents\Visual Studio 2015\Projects\sample\Release\sample.pgd" /SUBSYSTEM:WINDOWS /MANIFESTUAC:NO /ManifestFile:"Release\sample.exe.intermediate.manifest" /OPT:ICF /ERRORREPORT:PROMPT /NOLOGO /NODEFAULTLIB /TLBID:1
最佳答案
The problem could be avoided by calling ExitProcess before returningfrom WinMain. But this doesn't feel like the proper way to deal withthe situation.
退出过程必须直接或间接调用ExitProcess
。这是绝对正确的做法,也是强制性的。当您使用CRT
时,WinMain
并不是应用程序的真正入口点 - 它是从WinMainCRTStartup
调用的,而WinMainCRTStartup
又调用了ExitProcess
。如果您不使用CRT
- 您必须直接调用ExitProcess
。
从 Windows 10(确切地说是 1607 版本,但可能是以前的版本)开始,存在一个新功能 - 用于 dll 加载的“并行加载器”。现在,当您的进程中加载任何 dll(ntdll
、kernel32
和 kernelbase
除外)时,系统会创建工作线程来“并行”加载 dll ”。即使您运行一个非常简单的程序 - 例如 WinMain 中的单个 MessageBox - 但不调用 Exitprocess,您的进程不会退出,但仍会存活 30-60 秒 - dll 加载器工作线程(LdrpWorkCallback
) >) 有 30 秒空闲超时,之后将退出。
关于c - WTSRegisterSessionNotification 导致进程挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40854000/
我正在尝试使用 Spark 从 Cassandra 读取数据。 DataFrame rdf = sqlContext.read().option("keyspace", "readypulse
这是代码: void i_log_ (int error, const char * file, int line, const char * fmt, ...) { /* Get erro
我必须调试一个严重依赖 Gtk 的程序。问题是由于某些原因,在使用 GtkWindow 对象时开始出现许多运行时警告。问题是,即使 Gtk 提示严重错误,它也不会因这些错误而中止。我没有代码库的更改历
我正在尝试从已有效编译和链接的程序中检索二进制文件。我已经通过 GL_PROGRAM_BINARY_LENGTH 收到了它的长度。该文档说有两个实例可能会发生 GL_INVALID_OPERATION
我有一个托管在 Azure 环境中的服务。我正在使用控制台应用程序使用该服务。这样做时,我得到了异常: "The requested service, 'http://xxxx-d.yyyy.be/S
我有以下代码,它被 SEGV 信号杀死。使用调试器表明它被 main() 中的第一个 sem_init() 杀死。如果我注释掉第一个 sem_init() ,第二个会导致同样的问题。我试图弄清楚是什么
目前我正在编写一个应用程序(目标 iOS 6,启用 ARC),它使用 JSON 进行数据传输,使用核心数据进行持久存储。 JSON 数据由 PHP 脚本通过 json_encode 从 MySQL 数
我对 Xamarin.Forms 还是很陌生。我在出现的主页上有一个非常简单的功能 async public Task BaseAppearing() { if (UserID
这是我的代码的简化版本。 public class MainActivity extends ActionBarActivity { private ArrayList entry = new Arr
我想弄明白为什么我的两个 Java 库很难很好地协同工作。这是场景: 库 1 有一个类 A,其构造函数如下: public A(Object obj) { /* boilerplate */ } 在以
如果网站不需要身份验证,我的代码可以正常工作,如果需要,则在打印“已创建凭据”后会立即出现 EXC_BAD_ACCESS 错误。我不会发布任何内容,并且此代码是直接从文档中复制的 - 知道出了什么问题
我在使用 NSArray 填充 UITableView 时遇到问题。我确信我正在做一些愚蠢的事情,但我无法弄清楚。当我尝试进行简单的计数时,我得到了 EXC_BAD_ACCESS,我知道这是因为我试图
我在 UITableViewCell 上有一个 UITextField,在另一个单元格上有一个按钮。 我单击 UITextField(出现键盘)。 UITextField 调用了以下方法: - (BO
我有一个应用程序出现间歇性崩溃。崩溃日志显示了一个堆栈跟踪,这对我来说很难破译,因此希望其他人看到了这一点并能为我指出正确的方向。 基本上,应用程序在启动时执行反向地理编码请求,以在标签中显示用户的位
我开发了一个 CGImage,当程序使用以下命令将其显示在屏幕上时它工作正常: [output_view.layer performSelectorOnMainThread:@selector(set
我正在使用新的 EncryptedSharedPreferences以谷歌推荐的方式上课: private fun securePrefs(context: Context): SharedPrefe
我有一个中继器,里面有一些控件,其中一个是文本框。我正在尝试使用 jquery 获取文本框,我的代码如下所示: $("#").click(function (event) {}); 但我总是得到 nu
在以下场景中观察到 TTS 初始化错误,太随机了。 已安装 TTS 引擎,存在语音集,并且可以从辅助功能选项中播放示例 tts。 TTS 初始化在之前初始化和播放的同一设备上随机失败。 在不同的设备(
maven pom.xml org.openjdk.jol jol-core 0.10 Java 类: public class MyObjectData { pr
在不担心冲突的情况下,可以使用 MD5 作为哈希值,字符串长度最多为多少? 这可能是通过为特定字符集中的每个可能的字符串生成 MD5 哈希来计算的,长度不断增加,直到哈希第二次出现(冲突)。没有冲突的
我是一名优秀的程序员,十分优秀!