我正在Vista上创建一个应用程序,其中包括一个服务和一个控制台应用程序。在同一个用户帐户中运行
在服务中我正在创建一个事件并等待该事件。在控制台应用程序中,我打开相同的事件(问题从这里开始)并调用 SetEvent 函数。我无法在控制台应用程序中打开事件(获取错误5,访问被拒绝)。我在网络中搜索并看到有关完整性级别的内容(我不确定问题是否与完整性级别有关)。它告诉该服务和应用程序的完整性水平不同。
这是代码的一部分,IPC发生了
服务
DWORD
WINAPI IpcThread(LPVOID lpParam)
{
HANDLE ghRequestEvent = NULL ;
ghRequestEvent = CreateEvent(NULL, FALSE,
FALSE, "Global\\Event1") ; //creating the event
if(NULL == ghRequestEvent)
{
//error
}
while(1)
{
WaitForSingleObject(ghRequestEvent, INFINITE) //waiting for the event
//here some action related to event
}
}
控制台应用
在应用程序中,打开事件并设置事件
unsigned int
event_notification()
{
HANDLE ghRequestEvent = NULL ;
ghRequestEvent = OpenEvent(SYNCHRONIZE|EVENT_MODIFY_STATE, FALSE, "Global\\Event1") ;
if(NULL == ghRequestEvent)
{
//error
}
SetEvent(ghRequestEvent) ;
}
我正在运行具有管理权限的应用程序(服务器和控制台应用程序)(我以管理员身份登录并通过右键单击并使用“以管理员身份运行”选项运行控制台应用程序)。
我在控制台应用程序(我正在打开事件)中获得的错误是错误5(访问被拒绝。)。
如果您告诉如何在Vista中的服务和应用程序之间进行IPC,那将非常有用
提前致谢
Navaneeth
答案 0 :(得分:3)
服务和应用程序是否作为具有不同完整性级别的同一用户运行,还是作为不同的用户运行?
如果是前者,那么本文来自MSDN which talks about integrity levels might help。他们有一些示例代码用于降低文件的完整性级别。我不确定这可能与事件相关。
#include <sddl.h>
#include <AccCtrl.h>
#include <Aclapi.h>
void SetLowLabelToFile()
{
// The LABEL_SECURITY_INFORMATION SDDL SACL to be set for low integrity
#define LOW_INTEGRITY_SDDL_SACL_W L"S:(ML;;NW;;;LW)"
DWORD dwErr = ERROR_SUCCESS;
PSECURITY_DESCRIPTOR pSD = NULL;
PACL pSacl = NULL; // not allocated
BOOL fSaclPresent = FALSE;
BOOL fSaclDefaulted = FALSE;
LPCWSTR pwszFileName = L"Sample.txt";
if (ConvertStringSecurityDescriptorToSecurityDescriptorW(
LOW_INTEGRITY_SDDL_SACL_W, SDDL_REVISION_1, &pSD;, NULL))
{
if (GetSecurityDescriptorSacl(pSD, &fSaclPresent;, &pSacl;,
&fSaclDefaulted;))
{
// Note that psidOwner, psidGroup, and pDacl are
// all NULL and set the new LABEL_SECURITY_INFORMATION
dwErr = SetNamedSecurityInfoW((LPWSTR) pwszFileName,
SE_FILE_OBJECT, LABEL_SECURITY_INFORMATION,
NULL, NULL, NULL, pSacl);
}
LocalFree(pSD);
}
}
如果是后者,您可以查看suggests creating a NULL ACL这个链接并将其与对象关联(在示例中它是一个命名管道,但对于我确定的事件,方法类似:< / p>
BYTE sd[SECURITY_DESCRIPTOR_MIN_LENGTH];
SECURITY_ATTRIBUTES sa;
sa.nLength = sizeof(sa);
sa.bInheritHandle = TRUE;
sa.lpSecurityDescriptor = &sd;
InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION);
SetSecurityDescriptorDacl(&sd, TRUE, (PACL) 0, FALSE);
CreateNamedPipe(..., &sa);
答案 1 :(得分:1)
我注意到您正在“全局”命名空间中创建对象,但正尝试在本地命名空间中打开它。是否在公开呼叫帮助中向名称添加“Global \”?
另外,在//错误区域,有没有什么可以让你知道它没有被创建?
答案 2 :(得分:0)
首先,从概念上理解需要什么是很重要的。一旦理解了,我们就可以从中获取它。
在服务器上,它看起来应该类似于:
{
HANDLE hEvent;
hEvent = CreateEvent(null, true, false, TEXT("MyEvent"));
while (1)
{
WaitForSingleObject (hEvent);
ResetEvent (hEvent);
/* Do something -- start */
/* Processing 1 */
/* Processing 2 */
/* Do something -- end */
}
}
在客户端:
{
HANDLE hEvent;
hEvent = OpenEvent(0, false, TEXT("MyEvent"));
SetEvent (hEvent);
}
需要注意以下几点:
答案 3 :(得分:0)
@Navaneeth:
优秀的反馈。由于您的错误是拒绝访问,因此我会将您真正不需要的EVENT_ALL_ACCESS所需的访问权限更改为
(SYNCHRONIZE | EVENT_MODIFY_STATE)
SYNCHRONIZE让你等待事件,EVENT_MODIFY_STATE允许你调用SetEvent,ResetEvent和PulseEvent。
您可能需要更多访问权限,但这非常不寻常。
答案 4 :(得分:0)
“1800 INFORMATION”是对的 - 这是一个UIPI问题;不管怎样,不要在新代码中使用事件,如果事件中的目标阻塞恰好在用户模式APC代码中被触发,则事件信号可能会丢失。 Win32编写服务/应用程序的规范方法是使用RPC调用来跨越UIPI边界。