高分讨论怎样突破“程序只能运行一次”的限制(在线等)
有很多程序现在限制了程序的启动次数,如果有一个程序在运行,当你再次双击时,就会提示比如“该程序已经有一个副本在运行中”之类的,不允许你同时运行两次,这样有时很不方便,谁有解决办法吗?
谢了先。
问题点数: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




