使用Delphi 2007 ...我有一个应用程序,它使用互斥锁来强制执行一个正在运行的实例.在dpr单元中,如果互斥锁已经存在,我得到一个正在运行的实例的句柄FindWindow,到目前为止没问题.第二个实例通常由虚拟打印机驱动程序启动,并引用命令行上的文件名.如果有一个命令行文件引用,那么我想简单地将消息发布到正在运行的实例并暂停新实例.
我正在使用这个......
PostMessage(hwnd,WM_STARTUP_MESSAGE,0,0); //hwnd as returned by FindWindow
Run Code Online (Sandbox Code Playgroud)
WM_STARTUP_MESSAGE 被定义为 WM_APP + 6057
我有一个用户问题WM_STARTUP_MESSAGE是在主线程中没有处理.从dpr单元中的日志记录启动信息中可以看出PostMessage返回的false SysErrorMessage(GetLastError)是:
Zugriff verweigert (his windows german translation is Access Denied).
Run Code Online (Sandbox Code Playgroud)
我有很多这个应用程序的用户,我只有2个这个问题的报告,不能在这里重现.在Windows 10这里至少有一个问题用户,另一个我不确定.
我ChangeWindowMessageFilterEx在主窗体中使用OnCreate允许WM_COPYDATA.我有想法只是简单地包含WM_STARTUP_MESSAGE在那里但由于该函数不喜欢该消息索引值而导致崩溃,所以我认为它是为特定范围的消息值保留的.
有没有人见过这个,可以提供一些指导?
Rem*_*eau 10
根据PostMessage()文件:
当UIPI阻止消息时,使用GetLastError检索的最后一个错误设置为5(拒绝访问).
这也称为UI权限级别隔离(UIPI).
作为Vista中安全启动的一部分,具有UI的应用程序将以三种不同级别的权限运行.应用程序窗口可以与相同或更低级别的其他窗口交互,但不能与更高级别/许可的应用程序交互.
仅当较高权限应用程序明确允许使用调用ChangeWindowMessageFilter()的消息时,较低权限模式才能将消息发送到较高权限的应用程序.较低特权应用程序也只能读取较高特权应用程序拥有的HWND.
Internet Explorer是以最低权限级别运行的示例进程.
用户界面权限隔离(UIPI)在Windows子系统中实施限制,以防止较低权限的应用程序在较高权限的进程中发送窗口消息或安装挂钩.允许更高权限的应用程序将窗口消息发送到较低权限的进程.限制在SendMessage和相关窗口消息功能中实现.并非所有从较低权限进程发送到较高权限进程的窗口消息都被阻止.通常,"读取"类型消息(例如WM_GETTEXT)可以从较低权限发送到较高权限窗口.但是,阻止了写入类型消息,例如WM_SETTEXT.
...
UIPI不会干扰或更改同一特权(或完整性)级别的应用程序之间窗口消息传递的行为.UIPI通过阻止以下行为来防止低权限进程访问更高权限的进程.较低权限的进程不能:
- 对具有更高权限的进程执行窗口句柄验证.
- 将SendMessage或PostMessage用于以更高权限运行的应用程序窗口.这些API返回成功但静默删除窗口消息.
- 使用线程挂钩附加到以更高权限运行的进程.
- 使用日志挂钩来监视以更高权限运行的进程.
- 对运行具有更高权限的进程执行动态链接库(DLL)注入.
很明显,当发生错误时,HWND您发布的属于正在以比发布消息的进程更高的完整性/权限级别运行的进程.您可以使用SysInternals的Process Explorer来检查.
您说您的应用程序的第二个实例由虚拟打印机驱动程序运行,因此驱动程序可能运行的完整性级别低于用户启动的应用程序实例.
ChangeWidowMessageFilter/Ex()对非系统消息ID没有任何限制(某些系统消息无法过滤).它肯定不会在用户定义的消息ID上崩溃.如果您无权更改给定HWND/ MsgID 的消息过滤器,则该函数将简单地返回FALSE,并GetLastError()告诉您原因.
如果您遇到崩溃,则与代码中的其他内容有关.
此外,表格的OnCreate活动不是最好的地方ChangeWindowMessageFilterEx().在程序的生命周期中,表单可能必须HWND动态地重新创建它,甚至可能不止一次.每次HWND创建新内容时,您都必须ChangeWindowMessageFilterEx()再次呼叫.解决这个问题的最好方法是覆盖Form的虚CreateWnd()方法,例如:
type
TMyForm = class(TForm)
protected
procedure CreateWnd; override;
end;
procedure TMyForm.CreateWnd;
begin
inherited;
ChangeWindowMessageFilterEx(Handle, WM_STARTUP_MESSAGE, MSGFLT_ALLOW, nil);
end;
Run Code Online (Sandbox Code Playgroud)