c#编写的软件如何多开

author author     2023-04-28     309

关键词:

c#编写的软件,本身不能多开,如何实现多开?

可以多开的。不知道你具体指哪种情况。

windows系统下,程序防止多开的几种常见方法:
1)使用FindWindow API函数。
通过查找窗口标题(或/和类名)来判断程序是否正在运行。如果找到了,表明程序正在运行,这时可退出程序,达到不重复运行的效果;反之表明程序是第一次运行。
这种方法不适用于以下情况,程序的标题是动态变化的、系统中运行了相同标题(或/和类名)的程序

2)Mutex/Event/Semaphore
通过互斥对象/信号量/事件等线程同步对象来确定程序是否已经运行。最常用的函数如:CreateMutexA(注意:QQ堂、QQ游戏大厅就是采用这样方法来限制程序多开的)

3)内存映射文件(File Mapping)
通过把程序实例信息放到跨进程的内存映射文件中,也可以控制程序多开。

4)DLL全局共享区
DLL全局共享区在映射到各个进程的地址空间时仅被初始化一次,且是在第一次被windows加载时,所以利用该区数据就能对程序进行多开限制。

5)全局Atom
将某个特定字符串通过GlobalAddAtom加入全局原子表(Global Atom Table),程序运行时检查该串是否存在来限制程序多开。(该Atom不会自动释放,程序退出前必须调用GlobalDeleteAtom来释放Atom)

6)检查窗口属性
将某些数据通过SetProp加入到指定窗口的property list,程序运行时枚举窗口并检查这些数据是否存在来限制多开。

以上只列举了最常见的几种方法,具体应用中可以有n种选择,或综合运用多种方法来限制。

上面说过,QQT采用CreateMutex函数来限制多开,那么我怎么知道是使用这个函数来限制的呢?
答案就是跟踪程序,查找程序是使用哪种方法来限制的。比如先看看是否使用CreateMutex来限制,如果不是,再看看是不是使用FindWindow,以此类推,直到找到方法为止。当然,有些程序也会综合使用多种方法来限制多开,方法也是一样的,只是麻烦点而已。

下面讲一讲使用CreateMutex函数来限制多开的方法:
CreateMutex函数声明如下(具体请查阅相关资料,如MSDN)
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,// pointer to security attributes
BOOL bInitialOwner, // flag for initial ownership
LPCTSTR lpName// pointer to mutex-object name
);

以下是使用CreateMutex函数来限制多开的典型delphi代码
hMutex:=CreateMutex(nil,TRUE,'qqtang');//建立互斥量
// 调用失败? 已经存在?
if(hMutex=0) or (GetLastError=ERROR_ALREADY_EXISTS)then
begin
//程序第二(或以上)次运行时,GetLastError会返回ERROR_ALREADY_EXISTS,表明互斥量已存在
//可以在这里编写退出代码
end;
该段代码首先调用CreateMutex函数创建一名为 qqtang 的互斥对象,如果调用CreateMutex函数失败(hMutex=nil)或互斥对象早已存在(GetLastError=ERROR_ALREADY_EXISTS),则退出程序。

好了,明白上面的内容后,我们进入修改实战:
下载OllyDbg V1.1,解压到任何目录即可使用。
启动OllyDbg,打开QQT目录下的Core.dll文件,按[是]载入DLL文件。
按Ctrl+N打开API调用列表,找到CreateMutexA后按回车,在弹出的窗口里双击第一行来到CPU窗口,反汇编代码如下:

10002FB9 . 51 push ecx ; /MutexName = "qqtang"
10002FBA . 6A 01 push 1 ; |InitialOwner = TRUE
10002FBC . 6A 00 push 0 ; |pSecurity = NULL
10002FBE . FF15 60E40010 call dword ptr [<&KERNEL32.CreateMutexA>] ; \CreateMutexA 建立互斥量
10002FC4 . 8B95 D4FEFFFF mov edx,dword ptr [ebp-12C]
10002FCA . 8902 mov dword ptr [edx],eax
10002FCC . 8B85 D4FEFFFF mov eax,dword ptr [ebp-12C]
10002FD2 . 8338 00 cmp dword ptr [eax],0 ; 检查CreateMutexA函数是否调用失败
10002FD5 . 0F84 CD000000 je Core.100030A8 ; 把je改为jmp即可
10002FDB . FF15 5CE40010 call dword ptr [<&KERNEL32.GetLastError>] ; [GetLastError
10002FE1 . 3D B7000000 cmp eax,0B7 ; 检查对象是否已存在
10002FE6 . 0F85 BC000000 jnz Core.100030A8 ; (也可以在这里把jnz改为jmp)
10002FEC . 8B8D D4FEFFFF mov ecx,dword ptr [ebp-12C]
10002FF2 . C701 00000000 mov dword ptr [ecx],0
10002FF8 . 6A 00 push 0 ; /Title = NULL
10002FFA . 68 5CC60010 push Core.1000C65C ; |Class = "QQTangWinClass"
10002FFF . 6A 00 push 0 ; |hAfterWnd = NULL
10003001 . 6A 00 push 0 ; |hParent = NULL
10003003 . FF15 40E70010 call dword ptr [<&USER32.FindWindowExA>] ; \FindWindowExA 查找QQT窗口

选中这行:
10002FD5 . 0F84 CD000000 je Core.100030A8
然后按空格,在弹出的窗口中把“je 100030A8”修改为“jmp 100030A8”,按[汇编]。
右键单击CPU窗口,在弹出菜单中选“复制到可执行文件”-》“所有改动”,选[全部复制]。右键单击弹出的窗口,选“保存文件”保存即可。
参考技术A 挺复杂的 C#做软件这方面还不成熟 C++好 但有点难

windows系统下,程序防止多开的几种常见方法:
1)使用FindWindow API函数。
通过查找窗口标题(或/和类名)来判断程序是否正在运行。如果找到了,表明程序正在运行,这时可退出程序,达到不重复运行的效果;反之表明程序是第一次运行。
这种方法不适用于以下情况,程序的标题是动态变化的、系统中运行了相同标题(或/和类名)的程序

2)Mutex/Event/Semaphore
通过互斥对象/信号量/事件等线程同步对象来确定程序是否已经运行。最常用的函数如:CreateMutexA(注意:QQ堂、QQ游戏大厅就是采用这样方法来限制程序多开的)

3)内存映射文件(File Mapping)
通过把程序实例信息放到跨进程的内存映射文件中,也可以控制程序多开。

4)DLL全局共享区
DLL全局共享区在映射到各个进程的地址空间时仅被初始化一次,且是在第一次被windows加载时,所以利用该区数据就能对程序进行多开限制。

5)全局Atom
将某个特定字符串通过GlobalAddAtom加入全局原子表(Global Atom Table),程序运行时检查该串是否存在来限制程序多开。(该Atom不会自动释放,程序退出前必须调用GlobalDeleteAtom来释放Atom)

6)检查窗口属性
将某些数据通过SetProp加入到指定窗口的property list,程序运行时枚举窗口并检查这些数据是否存在来限制多开。

以上只列举了最常见的几种方法,具体应用中可以有n种选择,或综合运用多种方法来限制。

上面说过,QQT采用CreateMutex函数来限制多开,那么我怎么知道是使用这个函数来限制的呢?
答案就是跟踪程序,查找程序是使用哪种方法来限制的。比如先看看是否使用CreateMutex来限制,如果不是,再看看是不是使用FindWindow,以此类推,直到找到方法为止。当然,有些程序也会综合使用多种方法来限制多开,方法也是一样的,只是麻烦点而已。

下面讲一讲使用CreateMutex函数来限制多开的方法:
CreateMutex函数声明如下(具体请查阅相关资料,如MSDN)
HANDLE CreateMutex(
LPSECURITY_ATTRIBUTES lpMutexAttributes,// pointer to security attributes
BOOL bInitialOwner, // flag for initial ownership
LPCTSTR lpName// pointer to mutex-object name
);

以下是使用CreateMutex函数来限制多开的典型delphi代码
hMutex:=CreateMutex(nil,TRUE,'qqtang');//建立互斥量
// 调用失败? 已经存在?
if(hMutex=0) or (GetLastError=ERROR_ALREADY_EXISTS)then
begin
//程序第二(或以上)次运行时,GetLastError会返回ERROR_ALREADY_EXISTS,表明互斥量已存在
//可以在这里编写退出代码
end;
该段代码首先调用CreateMutex函数创建一名为 qqtang 的互斥对象,如果调用CreateMutex函数失败(hMutex=nil)或互斥对象早已存在(GetLastError=ERROR_ALREADY_EXISTS),则退出程序。

好了,明白上面的内容后,我们进入修改实战:
下载OllyDbg V1.1,解压到任何目录即可使用。
启动OllyDbg,打开QQT目录下的Core.dll文件,按[是]载入DLL文件。
按Ctrl+N打开API调用列表,找到CreateMutexA后按回车,在弹出的窗口里双击第一行来到CPU窗口,反汇编代码如下:

10002FB9 . 51 push ecx ; /MutexName = "qqtang"
10002FBA . 6A 01 push 1 ; |InitialOwner = TRUE
10002FBC . 6A 00 push 0 ; |pSecurity = NULL
10002FBE . FF15 60E40010 call dword ptr [<&KERNEL32.CreateMutexA>] ; \CreateMutexA 建立互斥量
10002FC4 . 8B95 D4FEFFFF mov edx,dword ptr [ebp-12C]
10002FCA . 8902 mov dword ptr [edx],eax
10002FCC . 8B85 D4FEFFFF mov eax,dword ptr [ebp-12C]
10002FD2 . 8338 00 cmp dword ptr [eax],0 ; 检查CreateMutexA函数是否调用失败
10002FD5 . 0F84 CD000000 je Core.100030A8 ; 把je改为jmp即可
10002FDB . FF15 5CE40010 call dword ptr [<&KERNEL32.GetLastError>] ; [GetLastError
10002FE1 . 3D B7000000 cmp eax,0B7 ; 检查对象是否已存在
10002FE6 . 0F85 BC000000 jnz Core.100030A8 ; (也可以在这里把jnz改为jmp)
10002FEC . 8B8D D4FEFFFF mov ecx,dword ptr [ebp-12C]
10002FF2 . C701 00000000 mov dword ptr [ecx],0
10002FF8 . 6A 00 push 0 ; /Title = NULL
10002FFA . 68 5CC60010 push Core.1000C65C ; |Class = "QQTangWinClass"
10002FFF . 6A 00 push 0 ; |hAfterWnd = NULL
10003001 . 6A 00 push 0 ; |hParent = NULL
10003003 . FF15 40E70010 call dword ptr [<&USER32.FindWindowExA>] ; \FindWindowExA 查找QQT窗口

选中这行:
10002FD5 . 0F84 CD000000 je Core.100030A8
然后按空格,在弹出的窗口中把“je 100030A8”修改为“jmp 100030A8”,按[汇编]。
右键单击CPU窗口,在弹出菜单中选“复制到可执行文件”-》“所有改动”,选[全部复制]。右键单击弹出的窗口,选“保存文件”保存即可。

http://zhidao.baidu.com/question/91932874.html
参考技术B 从开始菜单中启动vs2005,再用vs2005打开文件,每次重复操作就行了,就可以实现多开了!(打开第一个文件可以直接打开)本回答被提问者采纳 参考技术C

我晕,楼上居然说怎么限制多开,答非所问。

你说不能多开,我有点疑问,我也使用C#写的程序,开N个都没问题呀,是不是你用了什么特别的技术,你拿出来晒晒吧。

参考技术D 使用C#开发软件,开发工具一般是VS系列,都是可以双开或者多开的。
但是比较占用内存。

c#编写一个小巧快速的windows动态桌面软件

开源自己前段时间使用C#编写的Windows动态桌面软件,在接下来的博客我将描写一些技术细节和遇到的一些坑。这个软件可以把视频设置成桌面背景播放,不仅如此而且还可以把网页或一个网页文件设置成桌面背景播放。支持.NETFr... 查看详情

如何使用沙盘多开流量精灵,流量精灵多开有用吗

1下载并安装沙盘软件.然后创建若干个沙盘. ?2从网上下载流量精灵并预备好要刷流量的网址,先不要开始刷.注意我把流量精灵复制了若干份,现在打开第一个,可以刷两个网址,我填入网址,但不开启分享。如果此时运行2.exe是... 查看详情

如何从托管 C# 代码跟踪 CRT 调试内存泄漏输出的来源?

...:2020-01-2214:44:14【问题描述】:我正在运行一个用C#(WPF)编写的软件,该软件使用了大量本机遗留代码。当我关闭软件时,调试器会继续运行,并且我的调试输出屏幕会打印以下内容:Detectedmemoryleaks 查看详情

如何在 C# 中编写我自己的包装器?

】如何在C#中编写我自己的包装器?【英文标题】:HowtowritemyownwrapperinC#?【发布时间】:2009-04-1421:58:14【问题描述】:在我的另一个问题中,我一直在努力寻找知道在哪里可以找到C#的免费开源OCR库的人。但是,似乎只有C++库,... 查看详情

如何使用 C# 在 android 中编写推送通知的代码?

】如何使用C#在android中编写推送通知的代码?【英文标题】:Howtocodeforpushnotificationinandroidusingc#?【发布时间】:2015-03-1605:49:46【问题描述】:我是android应用程序开发的新手,我需要为具有推送通知功能的应用程序编写代码,我... 查看详情

如何将软件转换为DLL?

...描述】:我有一个软件,它提供了一些用C++语言VisualStudio编写的功能。我想在我用C#编写的asp.netWeb应用程序中使用它。所以我决定将软件转换为DLL,以便我可以将DLL包含在我的Web应用程序中以使用该功能。如何将软件转换成DLL?... 查看详情

如何在 C# 中编写 JSON 文件?

】如何在C#中编写JSON文件?【英文标题】:HowtowriteaJSONfileinC#?【发布时间】:2013-05-3101:47:13【问题描述】:我需要在C#中使用JSON格式将以下数据写入文本文件。括号对于它是有效的JSON格式很重要。["Id":1,"SSN":123,"Message":"whatever","I... 查看详情

ASP C# 如何编写整洁的 GUI 代码

】ASPC#如何编写整洁的GUI代码【英文标题】:ASPC#HowtoprogramneatGUIcode【发布时间】:2009-04-0609:49:58【问题描述】:大约几个月以来,我正在编写ASPC#。我总是在事件中编写很多代码,在加载事件中我检查查询字符串是否有有效数据... 查看详情

如何从用 C# 编写的抽象基类继承

】如何从用C#编写的抽象基类继承【英文标题】:HowtoinheritfromanabstractbaseclasswritteninC#【发布时间】:2017-02-0105:41:40【问题描述】:我正在尝试使用Python.NET(2.1.0)从Python(2.7)中的抽象.NET基类继承。我是Pythonn00b,但据我了解……这是... 查看详情

如何编写 C++ 代码来处理 C# 代码中引发的事件

】如何编写C++代码来处理C#代码中引发的事件【英文标题】:howtowriteC++codetohandleaneventraisedinC#code【发布时间】:2010-12-1521:58:27【问题描述】:我想知道如何在C++代码中接收并处理从C#代码引发的事件。我有一个C#WinFormsUI模块,它... 查看详情

如何在 C# 中编写实现给定接口的通用容器类?

】如何在C#中编写实现给定接口的通用容器类?【英文标题】:HowcanIwriteagenericcontainerclassthatimplementsagiveninterfaceinC#?【发布时间】:2010-10-2506:30:34【问题描述】:上下文:.NET3.5,VS2008。我不确定这个问题的标题,所以也可以对标... 查看详情

如何在 C# 中高效地编写大型文本文件?

】如何在C#中高效地编写大型文本文件?【英文标题】:HowtoefficientlywritealargetextfileinC#?【发布时间】:2011-03-2508:20:09【问题描述】:我正在C#中创建一个方法,它为GoogleProductFeed生成一个文本文件。提要将包含超过30,000条记录,... 查看详情

c#脚本编写经验总结

...个“C#解释器”,当然它并不是解释执行的。完了以后,编写了一些C#脚本,在此期间发现了一些在IDE中编程会忽略的知识,下面一一列举一下。STAThread一次编写脚本时,发现FolderBrowserDialog好像失效了,不能正常弹出。后来发现... 查看详情

现在一般的软件是用啥语言编写的?

...对于驱动程序的开发,操作系统,这些大多数是用C语言编写的,少数是用汇编语言。而对于网络方面的,比如网站开发等,这些基本上是用java,c#等编写的。 参考技术B如果是用于网络那就是JAVA了(安全性佳)其它就啥子都有... 查看详情

单击时,如何使使用 C# 编写的 ActiveX 控件在 JavaScript 中引发事件?

】单击时,如何使使用C#编写的ActiveX控件在JavaScript中引发事件?【英文标题】:HowcanImakeanActiveXcontrolwrittenwithC#raiseeventsinJavaScriptwhenclicked?【发布时间】:2009-09-2116:58:49【问题描述】:我已经在SO上看到了一些与此相关的问题,但... 查看详情

如何使用基于 SQL Query 的连接在 C# 中编写 LINQ?

】如何使用基于SQLQuery的连接在C#中编写LINQ?【英文标题】:HowtowriteLINQinC#withjoinsbasedonSQLQuery?【发布时间】:2021-08-1518:35:34【问题描述】:我需要根据以下查询编写一个linq。在SQLServer中,selectEXID,ID,NAMEfromTable1AjoinTable2BonA.BXID=B.BI... 查看详情

C#编写文件[关闭]

】C#编写文件[关闭]【英文标题】:C#Writingafile[closed]【发布时间】:2014-08-3119:10:29【问题描述】:我有一个简单的问题:我知道如何编写文件,但是在不作为文本文件读取的情况下将数据存储在文件中的最佳方法是什么?【问题... 查看详情

我应该如何编写 .i 文件以在 Java 或 C# 中包装回调

】我应该如何编写.i文件以在Java或C#中包装回调【英文标题】:HowshouldIwritethe.ifiletowrapcallbacksinJavaorC#【发布时间】:2012-08-3106:42:38【问题描述】:我的C程序使用定期调用的回调函数。我希望能够处理Java或C#程序中的回调函数。... 查看详情