小赖子的英国生活和资讯

避免同一台 Windows 服务器上多个用户同时使用同一软件

阅读 桌面完整版

比如你卖软件, 非常贵的软件但又非常好用. 一套一套卖, 每一套指明说是只能同时一个人用(一台机器), 当然你可以写在合同里, 大公司则会去遵守, 但是一些小公司则可能想着, 装在性能较好的 Windows 服务器上, 那么, 多个用户可以同时登陆并启动相同的软件. 这样你就亏大了, 得限制.

同时, 你又想让同一用户可以同时启动相同软件, 因为这样可以方便同时处理多个工程.

最简单的方法就是调用 Win32 API 来在 Global 命名空间下 创建 Mutex 对象. 这个API就是 CreateMutex (CreateMutexAANSI版本, CreateMutexW Unicode版本).

下面的C++代码就能够实现这么一个功能. 注意的是不要使用这个GUID, 因为别人也可能会用到, 最好是自己在 Visual Studio – Tools – Create GUID 生成一个新的GUID.

create-guid-visual-studio-tools

1
2
3
4
5
6
7
8
9
10
11
int _tmain(int argc, _TCHAR* argv[]) {
    if ( ::CreateMutexW( NULL, FALSE, L"Global\\F4CD32D1-3B3B-4AA0-AB76-273FFA455E1B" ) != NULL ) {
        std::wcout << L"Mutex acquired. GLE = " << GetLastError() << std::endl;
        // Continue execution
    } else {
        std::wcout << "Mutex not acquired. GLE = " << GetLastError() << std::endl;
        // Exit application
    }
    _getch();
    return 0;
}
int _tmain(int argc, _TCHAR* argv[]) {
    if ( ::CreateMutexW( NULL, FALSE, L"Global\\F4CD32D1-3B3B-4AA0-AB76-273FFA455E1B" ) != NULL ) {
        std::wcout << L"Mutex acquired. GLE = " << GetLastError() << std::endl;
        // Continue execution
    } else {
        std::wcout << "Mutex not acquired. GLE = " << GetLastError() << std::endl;
        // Exit application
    }
    _getch();
    return 0;
}

第一个参数是结构属性, 第二个参数指明了 Ownership, 第三个参数就是 Mutex 对象的名称. 下面是 .NET 托管的 C# 代码.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
using System.Runtime.InteropServices;
public class HelloACM
{
        [StructLayout(LayoutKind.Sequential)]
        public class SECURITY_ATTRIBUTES
        {
            public int nLength;
            public int lpSecurityDescriptor;
            public int bInheritHandle;
        } 
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern int CreateMutex(SECURITY_ATTRIBUTES lpMutexAttributes, bool bInitialOwner, string lpName); 
 
        public static int Main(string[] args)
        {
            // Avoid Multiple Instances of Different Users BUT Allow Multiple Instances on Single User Session
            if (CreateMutex(null, false, "Global\\F4CD32D1-3B3B-4AA0-AB76-273FFA455E1B") == 0)
            {
                // Multiple Instances from One Single User are Allowed.
                MessageBox.Show("The Software is already running in other sessions.");
                return -1;
            }
        }
}
using System.Runtime.InteropServices;
public class HelloACM
{
        [StructLayout(LayoutKind.Sequential)]
        public class SECURITY_ATTRIBUTES
        {
            public int nLength;
            public int lpSecurityDescriptor;
            public int bInheritHandle;
        } 
        [System.Runtime.InteropServices.DllImport("kernel32.dll")]
        private static extern int CreateMutex(SECURITY_ATTRIBUTES lpMutexAttributes, bool bInitialOwner, string lpName); 

        public static int Main(string[] args)
        {
            // Avoid Multiple Instances of Different Users BUT Allow Multiple Instances on Single User Session
            if (CreateMutex(null, false, "Global\\F4CD32D1-3B3B-4AA0-AB76-273FFA455E1B") == 0)
            {
                // Multiple Instances from One Single User are Allowed.
                MessageBox.Show("The Software is already running in other sessions.");
                return -1;
            }
        }
}

这也是软件保护的一种.

参考文献

1. StackOverflow: http://stackoverflow.com/questions/28240354/how-to-avoid-multiple-instances-of-different-users-but-allow-multiple-instances
2. CreateMutex API MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/ms682411.aspx
3. Kernel Object NameSpace MSDN: https://msdn.microsoft.com/en-us/library/windows/desktop/aa382954.aspx

英文同步: https://helloacm.com/disallow-multiple-instance-of-applications-on-the-same-machine-windows-server-by-other-user-sessions-both-c-and-c-solution/

强烈推荐

微信公众号: 小赖子的英国生活和资讯 JustYYUK

阅读 桌面完整版
Exit mobile version