CSDN首页 空间 新闻 论坛 Blog 下载 读书 网摘 搜索 .NET Java 视频 接项目 求职 在线学习 买书 程序员 通知
山寨机中的战斗机! 程序优化工程师到底对IT界有没有贡献
CSDN社区
搜索 收藏 打印 关闭
CSDN社区 >  VC/MFC >  基础类

高分讨论怎样突破“程序只能运行一次”的限制(在线等)

楼主hnic(黑色的上帝)2003-10-03 20:18:27 在 VC/MFC / 基础类 提问

有很多程序现在限制了程序的启动次数,如果有一个程序在运行,当你再次双击时,就会提示比如“该程序已经有一个副本在运行中”之类的,不允许你同时运行两次,这样有时很不方便,谁有解决办法吗?  
  谢了先。 问题点数:100、回复次数:31Top

1 楼heartwell(solever)回复于 2003-10-03 20:26:13 得分 10

没思路,看看别人的想法。如果用的是Guidgen产生的唯一变量来互斥两个进程,不知道怎么办。Top

2 楼ishallwin()回复于 2003-10-03 20:42:32 得分 0

动态跟踪,在调用提示前找到关键代码,修改之,使它跳过提示及退出部分。Top

3 楼heartwell(solever)回复于 2003-10-03 20:47:24 得分 0

想来想去,只有笨办法:找到互斥语句,然后把return或者exit给删了……Top

4 楼dzqsuper(数风流人物-还看打倒日本猪的人(抵制日货))回复于 2003-10-03 21:12:29 得分 0

不懂Top

5 楼Skt32(荒城之月)回复于 2003-10-03 21:13:33 得分 0

 
  改成允许多实例的Top

6 楼aaa2520(沥青)回复于 2003-10-03 21:46:39 得分 0

见到过     好象是设置互斥变量的,具体忘了Top

7 楼xiaonian_3654(你猜猜(我要打光棍,小乔嫁不了))回复于 2003-10-03 21:52:22 得分 0

没有这么复杂呀,  
  懂不懂win32编程?  
  WinMain的四个参数,其中就有一个是你的程序上一个运行实例的句柄呀,  
  判断   这个参数就可以实现这个功能Top

8 楼FAICHEN(CC)回复于 2003-10-03 21:58:49 得分 0

在win32下那个参数已经没有意义了Top

9 楼crybird(寒号鸟)回复于 2003-10-03 22:15:20 得分 20

下面演示代码是以一个单文档应用程序为例,工程名字是Mutex。  
  1、在应用程序类InitInstance()函数中判断是否已有一个应用程序实例正在运行。  
  BOOL   CMutexApp::InitInstance()  
  {  
  //创建命名信标对象。  
  HANDLE   hSem=CreateSemaphore(NULL,1,1,"xxxxx");  
  if(hSem)   //信标对象创建成功。  
  {  
  //信标对象已经存在,则程序已有一个实例在运行。  
  if(ERROR_ALREADY_EXISTS==GetLastError())  
  {    
  CloseHandle(hSem);   //关闭信号量句柄。    
   
  //获取桌面窗口的一个子窗口。  
  HWND   hWndPrev=::GetWindow(::GetDesktopWindow(),GW_CHILD);    
   
  while(::IsWindow(hWndPrev))  
  {  
  //判断窗口是否有我们预先设置的标记,如有,则是我们寻找的窗口,并将它激活。  
  if(::GetProp(hWndPrev,"xxxxx"))    
  {  
  //如果主窗口已最小化,则恢复其大小。  
  if   (::IsIconic(hWndPrev))    
  ::ShowWindow(hWndPrev,SW_RESTORE);  
   
  //将应用程序的主窗口激活。  
  ::SetForegroundWindow(hWndPrev);  
  return   FALSE;   //退出实例。  
  }  
  //继续寻找下一个窗口。  
  hWndPrev   =   ::GetWindow(hWndPrev,GW_HWNDNEXT);    
  }  
   
  AfxMessageBox("已有一个实例在运行,但找不到它的主窗口!");  
  }  
  }  
  else  
  {  
  AfxMessageBox("创建信标对象失败,程序退出!");  
  return   FALSE;  
  }  
   
  AfxEnableControlContainer();  
   
  //   Standard   initialization  
  //   If   you   are   not   using   these   features   and   wish   to   reduce   the   size  
  //   of   your   final   executable,   you   should   remove   from   the   following  
  //   the   specific   initialization   routines   you   do   not   need.  
   
  #ifdef   _AFXDLL  
  Enable3dControls();   //   Call   this   when   using   MFC   in   a   shared   DLL  
  #else  
  Enable3dControlsStatic();   //   Call   this   when   linking   to   MFC   statically  
  #endif  
   
  //   Change   the   registry   key   under   which   our   settings   are   stored.  
  //   TODO:   You   should   modify   this   string   to   be   something   appropriate  
  //   such   as   the   name   of   your   company   or   organization.  
  SetRegistryKey(_T("Local   AppWizard-Generated   Applications"));  
   
  LoadStdProfileSettings();   //   Load   standard   INI   file   options   (including   MRU)  
   
  //   Register   the   application's   document   templates.   Document   templates  
  //   serve   as   the   connection   between   documents,   frame   windows   and   views.  
   
  CSingleDocTemplate*   pDocTemplate;  
  pDocTemplate   =   new   CSingleDocTemplate(  
  IDR_MAINFRAME,  
  RUNTIME_CLASS(CMutexDoc),  
  RUNTIME_CLASS(CMainFrame),   //   main   SDI   frame   window  
  RUNTIME_CLASS(CMutexView));  
  AddDocTemplate(pDocTemplate);  
   
  //   Parse   command   line   for   standard   shell   commands,   DDE,   file   open  
  CCommandLineInfo   cmdInfo;  
  ParseCommandLine(cmdInfo);  
   
  //   Dispatch   commands   specified   on   the   command   line  
  if   (!ProcessShellCommand(cmdInfo))  
  return   FALSE;  
   
  //   The   one   and   only   window   has   been   initialized,   so   show   and   update   it.  
  m_pMainWnd->ShowWindow(SW_SHOW);  
  m_pMainWnd->UpdateWindow();  
   
  return   TRUE;  
  }  
  2、在框架类的OnCreate()函数中设置查找标记。  
  int   CMainFrame::OnCreate(LPCREATESTRUCT   lpCreateStruct)  
  {  
  if   (CFrameWnd::OnCreate(lpCreateStruct)   ==   -1)  
  return   -1;  
   
  if   (!m_wndToolBar.CreateEx(this,   TBSTYLE_FLAT,   WS_CHILD   |   WS_VISIBLE   |   CBRS_TOP  
  |   CBRS_GRIPPER   |   CBRS_TOOLTIPS   |   CBRS_FLYBY   |   CBRS_SIZE_DYNAMIC)   ||  
  !m_wndToolBar.LoadToolBar(IDR_MAINFRAME))  
  {  
  TRACE0("Failed   to   create   toolbar\n");  
  return   -1;   //   fail   to   create  
  }  
   
  if   (!m_wndStatusBar.Create(this)   ||  
  !m_wndStatusBar.SetIndicators(indicators,  
  sizeof(indicators)/sizeof(UINT)))  
  {  
  TRACE0("Failed   to   create   status   bar\n");  
  return   -1;   //   fail   to   create  
  }  
   
  //   TODO:   Delete   these   three   lines   if   you   don't   want   the   toolbar   to  
  //   be   dockable  
   
  m_wndToolBar.EnableDocking(CBRS_ALIGN_ANY);  
  EnableDocking(CBRS_ALIGN_ANY);  
  DockControlBar(&m_wndToolBar);  
   
   
  //设置查找标记。  
  ::SetProp(m_hWnd,"xxxxx",(HANDLE)1);  
   
  return   0;  
  }  
  3、在程序退出是删除设置的标记,在框架类中响应WM_DESTROY消息,进行处理。  
  void   CMainFrame::OnDestroy()    
  {  
  CFrameWnd::OnDestroy();  
   
  //   TODO:   Add   your   message   handler   code   here  
  //删除所设置的标记。  
  ::RemoveProp(m_hWnd,"xxxxx");  
  }  
  至此,使应用程序只运行一个实例的功能就完成了。  
  Top

10 楼vcforever(累)回复于 2003-10-04 09:56:16 得分 0

最简单的方法就是找到创建互斥体(Mutex)的那几行代码!  
  把他删除就可以了!Top

11 楼tanyaliji(努力学习.net)(★)回复于 2003-10-04 10:00:22 得分 0

删除那几行就可以了,   严重同意楼上的Top

12 楼chinacao(多多指教)回复于 2003-10-04 10:06:56 得分 0

同意楼上的Top

13 楼dzqsuper(数风流人物-还看打倒日本猪的人(抵制日货))回复于 2003-10-04 10:36:50 得分 0

国庆来了,我不打算送你们太多,只想送你们六千万:千万要快乐,千万要健康,千万要平安,千万要知足,千万不要忘记我,千万要给我分!Top

14 楼hnic(黑色的上帝)回复于 2003-10-04 14:46:59 得分 0

对不起,我可能没有把我的问题表述清楚。  
  首先,我用的是别人的   应用程序,手上没有代码,找到创建互斥体(Mutex)的那几行代码,好像不是很好找吧!  
   
  为了说得更清楚我举个例子吧,比如说“联众”,当你运行了一个副本了以后,如果想要再次运行,肯定是不被允许的,否则,在一台机器上login两个账号,岂不是可以作弊?  
   
  我要的就是同的外加程序的方法,使得该程序可以运行多次。  
  谢谢了,望达人指点。Top

15 楼SpringStart(SpringStart)回复于 2003-10-04 15:20:26 得分 20

做一个程序在后台监视.  
  1.用FindWindow()函数得到窗口的hwnd  
  2.将全局变量blnFindWindow设置为true,并保存得到的hwnd  
  3.继续用FindWindow()函数得到窗口的hwnd,如果blnFindWindow为true则用postmessage发送quit的消息Top

16 楼flinming(flinming)回复于 2003-10-04 15:22:08 得分 30

app最开始运行中  
  //此程序只能运行一次,用互斥量来判断程序是否已运行  
          HANDLE   m_hMutex=CreateMutex(NULL,TRUE,   m_pszAppName);    
          if(GetLastError()==ERROR_ALREADY_EXISTS)   {   return   FALSE;   }Top

17 楼flinming(flinming)回复于 2003-10-04 15:22:50 得分 0

m_pszAppName这个可以自己设置一个字符串。。Top

18 楼fbmsf(FBM)回复于 2003-10-06 12:19:31 得分 0

HOOK   API:CreateMutex   ,FindWindowTop

19 楼keiven()回复于 2003-10-06 13:09:46 得分 0

upTop

20 楼jiajie828(班迪特)回复于 2003-10-06 13:51:23 得分 0

MarkTop

21 楼85125(柠檬色的天空)回复于 2003-10-06 14:17:34 得分 0

不如在机器上装一个虚似机,如果你非要在一个环境下运行两个实例,它的解决方法可能就不属于这个版的问题了,涉及破解(用SOFTICE,TWD,IDA,Uedit32等工具,先分析,再跟踪,最后修改EXE文件,去除防重复运行功能)Top

22 楼rtdb(东临碣石)回复于 2003-10-06 14:33:25 得分 0

而且,一般来说,不让运行多个实例,往往是系统限制,  
  例如通信时端口只有一个。  
   
  就算你破解成功,运行时也会出错。Top

23 楼mfc168(子非鱼)回复于 2003-10-06 15:13:36 得分 0

程序运行的时候,在任务管理器中可以看到运行实例名,如:QQ等,而只运行一个实例,就是与这个名有关,每次运行的时候程序会查找该名,如果存在,则只能运行一次,所以问题的关键是改变程序运行时的实例名,这需要特别熟悉PE结构,具体可查PE结构信息,通过相关软件来修改Top

24 楼85125(柠檬色的天空)回复于 2003-10-06 16:52:35 得分 0

也是,如果跟端口联系紧密,事必冲突,这个方法可行性不高,但从表面上看来似乎没有行之有效的解决办法  
   
  关注中。。Top

25 楼fbmsf(FBM)回复于 2003-10-06 17:15:27 得分 0

首先要知道为什么别人只让你运行一个。  
  其次,他是怎么实现的,  
  比较常用的方法是CreateMutex   ,FindWindow  
  Top

26 楼venursa()回复于 2003-10-06 17:24:07 得分 0

楼上说的有道理!  
   
  Top

27 楼romanticist(桃花岛主--杭州)回复于 2003-10-06 18:42:47 得分 20

BOOL   CExecInApp::InitInstance()  
  {  
   
  //deny running   application     second      
  /* AfxEnableControlContainer();  
   
  ::CreateMutex(NULL,   TRUE,   m_pszExeName);    
          if(ERROR_ALREADY_EXISTS   ==   GetLastError())    
          {    
  try{  
  ::SetForegroundWindow(::FindWindow(NULL,   "Main"));  
  }  
  catch(...)  
  {  
  AfxMessageBox("Application   Error!Please   close   it!");  
  }  
  return   false;  
  }  
  */    
  AfxEnableControlContainer();  
   
  ::CreateMutex(NULL,   TRUE,   m_pszExeName);    
  if(ERROR_ALREADY_EXISTS   ==   GetLastError())    
  {  
                CWnd*   pPrevHwnd   =   CWnd::GetDesktopWindow()->GetWindow(GW_CHILD);    
  //CWnd*   pPrevHwnd   =   CWnd::FindWindow(NULL,m_pszExeName);  
  //AfxMessageBox(m_pszExeName);  
                while(pPrevHwnd)    
                  {    
  //AfxMessageBox("4");  
   
                        if(::GetProp(pPrevHwnd->m_hWnd   ,   m_pszExeName))    
                        {    
  AfxMessageBox("3");  
                                  if(pPrevHwnd->IsIconic())    
                                  {    
  AfxMessageBox("3");  
                                          pPrevHwnd->ShowWindow(SW_RESTORE);    
                                  }    
  //pPrevHwnd->ShowWindow(SW_RESTORE);  
                                pPrevHwnd->SetForegroundWindow();    
                                pPrevHwnd->GetLastActivePopup()->SetForegroundWindow();    
                                  return   FALSE;    
                          }    
                          pPrevHwnd   =   pPrevHwnd->GetWindow(GW_HWNDNEXT);    
                  }    
                  TRACE("Could   not   fond   frevious   instance   main   window   !");    
                  return   FALSE;    
  }  
  ::CreateMutex(NULL,   TRUE,   m_pszExeName);   创建一个互坼量  
  Top

28 楼nie173(不酷不帅)回复于 2003-10-06 18:58:53 得分 0

反编译它,找出他检测是否有自己的副本在运行的部分代码,重新定位指针,跳过去。  
  说的容易,做的难,最不容易的就是怎么发现他的检测部分,一般你可以跟踪他Top

29 楼VCPP_Hunter(独角兽)回复于 2003-10-06 19:04:38 得分 0

我只知道3种方法:  
      1.写一个DLL,输出一个共享数据,初始值为0,在DLL的入口函数处改变它的计数器。  
      2.在InitApplication()函数中创建一个同步对象,如果GetLastError()调用返回ERROR_ALREADY_EXISTS表明已经有一个实例了!  
      3.利用共享数据段实现!  
  我这也是看的,有不足请指出!Top

30 楼cui(蚊子王)回复于 2003-10-06 19:39:38 得分 0

用IDA反汇编,找到相应的代码,一个JMP跳过就是了。Top

31 楼constructor(我还活着)回复于 2003-10-08 15:50:54 得分 0

upTop

相关问题

  • 程序运行后如何限制鼠标移出窗体?
  • 怎样限制一个程序运行的个数?
  • 如何限制程序运行时间和次数??
  • 高分请教如何限制程序运行的方法?
  • 怎么限制只程序只能运行一次
  • PB中调用API函数限制程序多次运行
  • 如何限制程序只运行一次
  • 如何限制程序只能运行一个
  • 如何限制程序只能运行一个
  • *** 帮忙破解一有运行时间限制小程序!!! *****

关键词

  • 函数
  • 应用程序
  • 代码
  • 运行
  • hwndprev
  • pprevhwnd
  • 程序
  • 实例
  • 互斥
  • pszexename

得分解答快速导航

  • 帖主:hnic
  • heartwell
  • crybird
  • SpringStart
  • flinming
  • romanticist

相关链接

  • Visual C++类图书
  • Visual C++类源码下载

广告也精彩

反馈

请通过下述方式给我们反馈
反馈
提问
网站简介|广告服务|VIP资费标准|银行汇款帐号|网站地图|帮助|联系方式|诚聘英才|English|问题报告
北京创新乐知广告有限公司 版权所有, 京 ICP 证 070598 号
世纪乐知(北京)网络技术有限公司 提供技术支持
Copyright © 2000-2008, CSDN.NET, All Rights Reserved
GongshangLogo