怎么只运行一个实例

时间:2022-01-20 04:42:39
网上找了些帖子
说这样子HWND hWnd = FindWindow(NULL, _T("TestTree"));
if(IsWindow(hWnd))
{
ShowWindow(hWnd, SW_NORMAL);     // 显示
SetForegroundWindow(hWnd);       // 激活
return FALSE;
} 不太明白
放在OnInitDialog()中也没有效果,求大神们讲讲有什么好的办法!!

26 个解决方案

#1


没效果是因为你没把HWND hWnd = FindWindow(NULL, _T("TestTree"));里面改成窗口名字吧?

#2


还可以用CMutex

#3


hWnd = FindWindow(TEXT("653811224"),TEXT("Hello World"));
wc.lpszClassName = TEXT("653811224");
hWnd = CreateWindowEx( 0, TEXT("653811224"), TEXT("Hello World"), 
//以上三句都要书写正确

#4


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}

#5


引用 楼主 yin_yang_yin 的回复:
网上找了些帖子
说这样子HWND hWnd = FindWindow(NULL, _T("TestTree"));
if(IsWindow(hWnd))
{
ShowWindow(hWnd, SW_NORMAL);     // 显示
SetForegroundWindow(hWnd);       // 激活
return FALSE;
} 不太明白
放在OnInitDialog()中也没有效果,求大神们讲讲有什么好的办法!!


_T("TestTree") 应该是你窗口的名字

#6


引用 4 楼 zhao4zhong1 的回复:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



傻吊代码

不说啥


注册消息,

和互斥体

然后postmessage广播消息 即可

#7


引用 6 楼 combobox2013 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



傻吊代码

不说啥


注册消息,

和互斥体

然后postmessage广播消息 即可


此“傻吊代码”抄自MSDN。

#8


遗憾的是有时程序不进行消息处理。

#9


《Windows核心编程》

#10


以MFC对话框程序为例,在App类定义如下变量和函数
//添加的标识只运行一次的属性名
CString  g_szPropName = "MyAppName";   //自己定义一个属性名
HANDLE   g_hValue = (HANDLE)1;               //自己定义一个属性值

BOOL CALLBACK EnumWndProc(HWND hwnd,LPARAM lParam)
{
HANDLE h = GetProp(hwnd,g_szPropName);
if( h == g_hValue)
{
*(HWND*)lParam = hwnd;
return false;
}
return true;
}

在InitInstance()中添加如下代码
	HWND oldHWnd = NULL; 
EnumWindows(EnumWndProc,(LPARAM)&oldHWnd);    //枚举所有运行的窗口 
if(oldHWnd != NULL) 

::ShowWindow(oldHWnd,SW_SHOWNORMAL);          //激活找到的前一个程序 
::SetForegroundWindow(oldHWnd);                //把它设为前景窗口 
return FALSE;                                  //退出本次运行 
}


在主对话框的OnInitDialog()的开头添加
SetProp(m_hWnd,g_szPropName,g_hValue);


g_szPropName,g_hValue自己添加extern扩展一下作用范围

#11


遗憾的是有的程序没有窗口。

#12


引用 4 楼 zhao4zhong1 的回复:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

#13


引用 12 楼 zy_cs_dn_zy 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?

#14


引用 13 楼 zhao4zhong1 的回复:
Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?


这应该算2个实例了。

相当于2台机子运行了。

对于这极端情景,你有何思路来解决?
 

#15


引用 14 楼 combobox2013 的回复:
Quote: 引用 13 楼 zhao4zhong1 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?


这应该算2个实例了。

相当于2台机子运行了。

对于这极端情景,你有何思路来解决?
 

我只是和你抬抬杠而已。说明绝对的单例是不存在的。 怎么只运行一个实例

#16


引用 12 楼 zy_cs_dn_zy 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河

#17


引用 16 楼 combobox2013 的回复:
Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧

#18


引用 17 楼 zy_cs_dn_zy 的回复:
Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?



#19


整个动态密码什么的,开启程序给出一条动态信息,用户需要打电话通过动态信息获得一个动态登录密码,程序结束的时候返回一个动态退出密码,如果用户不把上一次的动态退出密码告诉有关人员,那么该用户是得不到下一次的动态运行密码的...

以上  纯属瞎掰 怎么只运行一个实例

#20


引用 18 楼 combobox2013 的回复:
Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行

#21


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行


那应该有其他办法的吧,

#22


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行



再次阅读你的回复:

这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

前提是一台机子上, 就算你在Administrators组里开发的程序,程序又管理权限,

当你的程序在User组机子上运行, 首先机子创建了一个内核对象。

开始运行。。。。。。。。。。

然后你双击了另一个实例,实例发现如果操作系统中存在这个明明的内核对象,然后就退出程序。

你就觉得矛盾吗? 你双击的另一个实例,此时也是User组权限,

两个User组权限, 居然会。。。。

你懂我要说什么



#23


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行

为什么不限定只能由某个用户启动呢?发现其它用户启动直接退出或MessageBox后退出。

#24


引用 22 楼 combobox2013 的回复:
Quote: 引用 20 楼 zy_cs_dn_zy 的回复:

Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行



再次阅读你的回复:

这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

前提是一台机子上, 就算你在Administrators组里开发的程序,程序又管理权限,

当你的程序在User组机子上运行, 首先机子创建了一个内核对象。

开始运行。。。。。。。。。。

然后你双击了另一个实例,实例发现如果操作系统中存在这个明明的内核对象,然后就退出程序。

你就觉得矛盾吗? 你双击的另一个实例,此时也是User组权限,

两个User组权限, 居然会。。。。

你懂我要说什么





这越来越长了.....
服务启动程序后,程序就成了一个系统进程,即任务管理器的用户名是SYSTEM,而双击打开的程序是当前登录用户的进程,这样是不是能理解了

#25


个人意见:两个不同用户启动同一个exe后系统中的两个进程不是同一个实例。

#26


学习了,三位大神。。。

#1


没效果是因为你没把HWND hWnd = FindWindow(NULL, _T("TestTree"));里面改成窗口名字吧?

#2


还可以用CMutex

#3


hWnd = FindWindow(TEXT("653811224"),TEXT("Hello World"));
wc.lpszClassName = TEXT("653811224");
hWnd = CreateWindowEx( 0, TEXT("653811224"), TEXT("Hello World"), 
//以上三句都要书写正确

#4


int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}

#5


引用 楼主 yin_yang_yin 的回复:
网上找了些帖子
说这样子HWND hWnd = FindWindow(NULL, _T("TestTree"));
if(IsWindow(hWnd))
{
ShowWindow(hWnd, SW_NORMAL);     // 显示
SetForegroundWindow(hWnd);       // 激活
return FALSE;
} 不太明白
放在OnInitDialog()中也没有效果,求大神们讲讲有什么好的办法!!


_T("TestTree") 应该是你窗口的名字

#6


引用 4 楼 zhao4zhong1 的回复:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



傻吊代码

不说啥


注册消息,

和互斥体

然后postmessage广播消息 即可

#7


引用 6 楼 combobox2013 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



傻吊代码

不说啥


注册消息,

和互斥体

然后postmessage广播消息 即可


此“傻吊代码”抄自MSDN。

#8


遗憾的是有时程序不进行消息处理。

#9


《Windows核心编程》

#10


以MFC对话框程序为例,在App类定义如下变量和函数
//添加的标识只运行一次的属性名
CString  g_szPropName = "MyAppName";   //自己定义一个属性名
HANDLE   g_hValue = (HANDLE)1;               //自己定义一个属性值

BOOL CALLBACK EnumWndProc(HWND hwnd,LPARAM lParam)
{
HANDLE h = GetProp(hwnd,g_szPropName);
if( h == g_hValue)
{
*(HWND*)lParam = hwnd;
return false;
}
return true;
}

在InitInstance()中添加如下代码
	HWND oldHWnd = NULL; 
EnumWindows(EnumWndProc,(LPARAM)&oldHWnd);    //枚举所有运行的窗口 
if(oldHWnd != NULL) 

::ShowWindow(oldHWnd,SW_SHOWNORMAL);          //激活找到的前一个程序 
::SetForegroundWindow(oldHWnd);                //把它设为前景窗口 
return FALSE;                                  //退出本次运行 
}


在主对话框的OnInitDialog()的开头添加
SetProp(m_hWnd,g_szPropName,g_hValue);


g_szPropName,g_hValue自己添加extern扩展一下作用范围

#11


遗憾的是有的程序没有窗口。

#12


引用 4 楼 zhao4zhong1 的回复:
int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

#13


引用 12 楼 zy_cs_dn_zy 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?

#14


引用 13 楼 zhao4zhong1 的回复:
Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?


这应该算2个实例了。

相当于2台机子运行了。

对于这极端情景,你有何思路来解决?
 

#15


引用 14 楼 combobox2013 的回复:
Quote: 引用 13 楼 zhao4zhong1 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

那我问问在虚拟机中起一个实例,在虚拟机外起一个实例,算不算两个实例?


这应该算2个实例了。

相当于2台机子运行了。

对于这极端情景,你有何思路来解决?
 

我只是和你抬抬杠而已。说明绝对的单例是不存在的。 怎么只运行一个实例

#16


引用 12 楼 zy_cs_dn_zy 的回复:
Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河

#17


引用 16 楼 combobox2013 的回复:
Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧

#18


引用 17 楼 zy_cs_dn_zy 的回复:
Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?



#19


整个动态密码什么的,开启程序给出一条动态信息,用户需要打电话通过动态信息获得一个动态登录密码,程序结束的时候返回一个动态退出密码,如果用户不把上一次的动态退出密码告诉有关人员,那么该用户是得不到下一次的动态运行密码的...

以上  纯属瞎掰 怎么只运行一个实例

#20


引用 18 楼 combobox2013 的回复:
Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行

#21


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行


那应该有其他办法的吧,

#22


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行



再次阅读你的回复:

这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

前提是一台机子上, 就算你在Administrators组里开发的程序,程序又管理权限,

当你的程序在User组机子上运行, 首先机子创建了一个内核对象。

开始运行。。。。。。。。。。

然后你双击了另一个实例,实例发现如果操作系统中存在这个明明的内核对象,然后就退出程序。

你就觉得矛盾吗? 你双击的另一个实例,此时也是User组权限,

两个User组权限, 居然会。。。。

你懂我要说什么



#23


引用 20 楼 zy_cs_dn_zy 的回复:
Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行

为什么不限定只能由某个用户启动呢?发现其它用户启动直接退出或MessageBox后退出。

#24


引用 22 楼 combobox2013 的回复:
Quote: 引用 20 楼 zy_cs_dn_zy 的回复:

Quote: 引用 18 楼 combobox2013 的回复:

Quote: 引用 17 楼 zy_cs_dn_zy 的回复:

Quote: 引用 16 楼 combobox2013 的回复:

Quote: 引用 12 楼 zy_cs_dn_zy 的回复:

Quote: 引用 4 楼 zhao4zhong1 的回复:

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow) {
//...
#ifdef SINGLE_INSTANCE
    HANDLE hMutex;
    hMutex = CreateMutex(NULL, FALSE, "MySigleInstance" );
    if ( WaitForSingleObject(hMutex, 1000) == WAIT_TIMEOUT ) {
        // There is another instance out there, but it is taking to long to
        // locate, just exit
        return FALSE;
    }
    if ( GetLastError() == ERROR_ALREADY_EXISTS ) {
        ReleaseMutex(hMutex);
        return FALSE;
    }
#endif
//...
#ifdef SINGLE_INSTANCE
    ReleaseMutex(hMutex);
    CloseHandle(hMutex);
#endif
    return 0;
}



这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。 但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。



这是真的假的,别信口开河



这是做项目的时候发现的,大家可以去验证一下,普通用户不能获取管理员用户的内核对象好像也很可以理解吧



你的意思是,如果开发程序的时候, 程序员所用的机子是管理员权限,windows下的:Administrators组的成员,那么你的程序就是管理员权限了。

如果是非管理员组的成员, 如:Users组,,那么程序最后的权限就是User组!!

是否是这个意思?




我们的软件是使用服务启动的,是管理员权限,有一天测试人员手动双击打开,发现两个实例同时运行



再次阅读你的回复:

这是MSDN推荐的用法,即创建一个命名的内核对象,每次启动时检查此内核对象是否已经创建,如果已创建了说明已有一个运行实列。但是使用时请注意普通用户执行的程序无法获取管理员身份执行程序创建的内核对象,即如果分别以普通用户和管理员用户启动程序,会有两个实例同时运行。

前提是一台机子上, 就算你在Administrators组里开发的程序,程序又管理权限,

当你的程序在User组机子上运行, 首先机子创建了一个内核对象。

开始运行。。。。。。。。。。

然后你双击了另一个实例,实例发现如果操作系统中存在这个明明的内核对象,然后就退出程序。

你就觉得矛盾吗? 你双击的另一个实例,此时也是User组权限,

两个User组权限, 居然会。。。。

你懂我要说什么





这越来越长了.....
服务启动程序后,程序就成了一个系统进程,即任务管理器的用户名是SYSTEM,而双击打开的程序是当前登录用户的进程,这样是不是能理解了

#25


个人意见:两个不同用户启动同一个exe后系统中的两个进程不是同一个实例。

#26


学习了,三位大神。。。