|
Thanks for reply.
I have already called this class from the winmain() function. And I hope it executes properly.
From testing my code I have come to the conclusion that the problem is with CloseHandle().because when I run another instance of my appliction then it creates new Mutex again (means that in Task Manager -> Process Tab ,it shows two instances of my application), but it also generates the error ERROR_ALREADY_EXISTS and then it goes to call the CloseHandle() function and it also executes but it does not close handle(means it does not delete instance from the Task Manager).
Is there ny other idea??
Thanks.
|
|
|
|
|
Hai Sarath,
I have a doubt. If i fulfill the same requirement by using CSemaphore as follows...
...
CSemaphore csLock(1,1,"MYSTRING",NULL);
...
BOOL CMyApplication::InitInstance()
{
...
if(csLock.Lock(100))
{
AfxMessageBox("One Instance is already running");
return false;
}
...
}
...
int CMyApplication::ExitInstance()
{
csLock.Unlock();
...
}
Is there anything wrong doing like this?
I would be thankful if you give me suggessions on using this.
Thank you
Saadhinchaali
|
|
|
|
|
Hello,
It's a good idea to make use of available class. There's nothing wrong with the method you have specified. It should work. The idea is only to make use of any named kernel object. CSemaphore is a wrapper which is doing the same operation of CreateSemaphore , WaitForSingleObject and ReleaseSemaphore functions (atleast for the operations you specified).
For the single instance purpose, we only need a mutex. Mutex is really like a binary semaphore (either free/owned state). It's a bad idea to use semaphore as we have mutex (you can also use CMutex instead of win32 APIs ) which is already available. Also you don't have to wait for 100 ms. you can pass 0 to the Lock function which will tests the object's state and returns immediately.
Another thing is advisable to make csLock as the member of App class. Nothing special but just being Object Oriented.
I don't know why Ashish's class is not working as it should work if properly used.
In An MFC App, it can be used as follows
BOOL MyApp::InitInstance()<br />
{<br />
<br />
if( !m_Instance.Init())
return 0;<br />
....<br />
}
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
Thank sarath, for your kind reply.
So the CSemaphore should be used whene we want to allow a certain number of processes or threads to allow to access? is't it?
Saadhinchaali
|
|
|
|
|
The following seems to be the problem with the code LPCWSTR(mutexname).
ashishbhatt wrote: m_mutex = CreateMutex(NULL,FALSE,LPCWSTR(mutexname));
What's the type of mutexname. It's like type casting ASCII string into widestring which may cause unexpected behavior.
Seems this will do. Just try it
LPCTSTR mutexname = _T("MyMutex");
m_mutex = CreateMutex(NULL,FALSE,mutexname);
The following code worked fine for me.
<br />
class RTMPInstanceHandler<br />
{<br />
HANDLE m_mutex;<br />
public:<br />
RTMPInstanceHandler():m_mutex(NULL)<br />
{<br />
}<br />
<br />
~RTMPInstanceHandler()<br />
{<br />
Release();<br />
}<br />
<br />
BOOL Init()<br />
{<br />
m_mutex = CreateMutex(NULL,FALSE,_T("mutexname"));<br />
if(m_mutex == NULL)<br />
{<br />
return FALSE;<br />
}<br />
<br />
if (GetLastError() == ERROR_ALREADY_EXISTS)<br />
{<br />
return FALSE;<br />
}<br />
return TRUE;<br />
}<br />
<br />
DWORD Release()<br />
{<br />
try<br />
{<br />
CloseHandle(m_mutex);<br />
}<br />
catch (...)<br />
{<br />
}<br />
<br />
return GetLastError();<br />
}<br />
};<br />
<br />
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])<br />
{<br />
int nRetCode = 0;<br />
<br />
<br />
RTMPInstanceHandler inst;<br />
if ( !inst.Init())<br />
{<br />
cout<<"instance already exists";<br />
return nRetCode;<br />
}<br />
<br />
cin >> nRetCode;<br />
return nRetCode;<br />
}<br />
-Sarath.
"Great hopes make everything great possible" - Benjamin Franklin
|
|
|
|
|
Thank you very much for taking that too much interest in my problem.
I used your suggetion as you told to do but the same problem exists.
Thanks.
|
|
|
|
|
"And Every time I run application then it shows the message indicating that another Instance is running but CloseHandle() function does not remove process."
I think this is the source of the problem. The CloseHandle API doesn't control the running process. It is used to tell the running process that a previous instance exists and that it should not run. It is not clear from the code snippet that application is terminated when the first instance of the application is detected.
For a MFC CWinApp this text would occur in the InitInstance member function,
BOOL CMyApp::InitInstance()
{
m_hMutex = ::CreateMutex(0, FALSE, "TestApp");
if (::GetLastError() == ERROR_ALREADY_EXISTS) {
TRACE("TestApp: Already running");
::CloseHandle(m_hMutex);
return FALSE;
}
}
A return value of FALSE from CMyApp::InitInstance will terminate the second instance of the program. The important point is that the Mutex is a resource used by the process, not the process itself. When you detect the ERROR_ALREADY_EXISTS condition you must terminate the application yourself. You must close the handle because CreateMutex returned a valid handle.
|
|
|
|
|
Thanks to you.
Sorry For the very late Reply on this htread becaz I do not want to create new thread for the same problem.
As you told in your post to test the code you show ,, I tested it and works fine.But i want to know some more things,, As you told that I have to terminate my application myself but how can I do that???
My problem is that when I run another instance of application then from my code it shows the message that another instance is running and I also close the Mutex Handle,But it creates new entry into the Process list(in TaskManager->Process tab).So how can I remove this entry when one is already running??
Ashish Bhatt,
System Developer,
Avinashi System Pvt. Ltd.
|
|
|
|
|
It is not clear to me which instance of the process you are trying to terminate. I have been assuming you want to terminate the second instance. I'll address that.
First what are the results we are looking for? The test program I use is the MFC program generated by MSVC App Wizard. The produces a program that will run two instances. When you do the Windows task manager will show both instances in the process list. To make the test results easy to see, sort the Task Manager process list by name in order to see the two processes listed together. If you then terminate one instance it will be removed from the process list after it has terminated. This is the result we are seeking. What we want is a way for the second instance of the program to detect the first instance of the program. When the first instance is detected the second program instance should terminate itself, just as if we had done it from the application. As before, the task manager process list will reflect that the second instance of the program terminated and remove it from the process list, leaving just the first instance running.
The way we detect the second instance of the program is to use a mutex object. Each instance of the program tries to create the mutex. This is doen when the application starts during InitInstance().
BOOL CMfctestApp::InitInstance()
{
m_hMutex = ::CreateMutex(0, FALSE, "TestApp");
if (::GetLastError() == ERROR_ALREADY_EXISTS)
{
TRACE("TestApp: Already running");
::CloseHandle(m_hMutex), m_hMutex = 0;
return FALSE;
}
}
Note the use comma sequence operator and the explicit assignment of the mutex handle. A second instance of the application will get a valid handle to the existing mutex. Once we have closed the handle we do not want to use it again. We declare the m_hMutex handle as a private member variable in the application class,
class CMfctestApp : public CWinApp
{
private:
HANDLE m_hMutex;
};
Finally, we insure that the first instance of the application will properly release the mutex when the application terminates. This is done in ExitInstance()
int CMfctestApp::ExitInstance()
{
if (m_hMutex)
::CloseHandle(m_hMutex);
return CWinApp::ExitInstance();
}
The first instance of the program will have a valid, non null mutex handle and will close it. All other instances will have handle of 0.
If now run the program outside of the debugger and look at the Task Manager process list and you will see the first instance running. In the MSVC IDE place a breakpoint in the InitInstance member function and run the program under the debugger. When the breakpoint is hit look at the process list in the Task Manager and you will see both instances running. Let the second instance of the program, in the debugger, continue and you should see the process get removed from the task list.
|
|
|
|
|
Hi, i follow your way to create the program, so far is okay.
but i try to add the code below in
ExitInstance()
{
if(m_hMutex)
{
::CloseHandle(m_hMutex);
ReleaseMutex(m_hMutex);
}
if(m_hMutex)
{
::CloseHandle(m_hMutex);
ReleaseMutex(m_hMutex);
}
return CWinApp::ExitInstance();
|
|
|
|
|
The CreateMutex does not work on Win 7 32 bit. Even if the application already exists it returns a success..
Any thought?
Thanks..
|
|
|
|
|
Hi Experts,
Hi have 2 view(both ListView) in my application. One conataind the full path of files. I want to drag drop a file in other ListView from first ListView.
How can I do this ?
Thanx in advance.
|
|
|
|
|
Did you search on the codeproject?
|
|
|
|
|
Hi..all's
I am making a program. I need to fetch record from Oracle database and
print these record to .txt file . I write a program for this . Although
i fetch record from database and store these record to result set .
Now i can exteract these record from object of CRecordset class and how can i write these record to .txt file although . I have create file successfully. My code is written below.
CDatabase *Dbase = new CDatabase();
CRecordset rs;
int count=0;
if(!Dbase->Open("aixmmapping_72",FALSE,FALSE,"ODBC;DSN=aixmmapping_72;UID=aixmmapping_72;PWD=aixmmapping_72"))
{
MessageBox(" Can Not Connect With Database");
}else
{
rs.Open(CRecordset::dynaset,_T("Select * from vor"));
while(!rs.IsEOF())
{
rs.MoveNext();
}
CFile obj;
obj.Open( "D:\\Yogi\\Test\\abc.txt", CFile::modeCreate|CFile:: modeReadWrite);
char TextData[800];
strcpy(TextData, "rs");
obj.Write(TextData,800);
MessageBox("File Write Successfully");
rs.Close();
}
Please help me
Regard's
Kaushik
|
|
|
|
|
Refer CRecordset::GetFieldValue[^] and pay particular attention to the Note in the remarks section, which mentions that you should NOT have the ODBC Cursor Library loaded.
|
|
|
|
|
First of all Thanks for reply.....
I can get record from database and can print it to .txt file.
but all the record print in a single line.
Can you told me how can make formatting of file so that each and every row print in a saprate line.
Again Thanks for help
Regard's
Kaushik
|
|
|
|
|
Here is what I get from the code you posted:
Open database
Open a recordset of all fields of table "vor"
Walk through all records in the recordset, doing nothing with each record
Open a file
Write the single string "rs" to the file
close the file
close the recordset
the MSDN article I linked includes a piece of sample code that:
walks through all the records of the recordset
walks each of the fields of each record
what I think you need to do is:
figure out how to write each varValue to the file
include a write to file of a cariage-return line-feed pair before the rs.MoveNext()
|
|
|
|
|
I am trying to do this like
sStr.Empty();
sStr="\n";
strcpy(TextData, sStr);
obj.Write(TextData,sStr.GetLength());
rs.MoveNext();
But its not working....
Can u told me where i am making wrong
Regard's
Kaushik
|
|
|
|
|
My code is runnign fine Thanks for Help
Regard's
Kaushik
|
|
|
|
|
Hello sir,
Although i can print the value of table field in .txt file .
in well manage order but , Now i want to show its field name at top of
its raw
I am trying it using GetFieldName() function but i am unable to fetch field name . Can u please told me how can i do this
Regard's
Kaushik
|
|
|
|
|
Could anyone tell me how to restrict a window from being dragged outside the visible screen of the desktop?
Your help would be much appreciated, thank you.
-> Demsen
|
|
|
|
|
Try handling either of the below...
1. CWnd::OnWindowPosChanged()
or
2. WM_WINDOWPOSCHANGED
Maxwell Chen
|
|
|
|
|
I've used OnWindowPosChanging already and my code looks like this:
void CSnapDialog::OnWindowPosChanging( WINDOWPOS* lpwndpos )
{
int m_EdgeSnapGap = 1;
RECT rcScrn;
SystemParametersInfo (SPI_GETWORKAREA, 0, &rcScrn, 0);
//Snap X axis
if (abs(lpwndpos->x - rcScrn.left) <= m_EdgeSnapGap)
{
lpwndpos->x = rcScrn.left;
//???
//Code is needed here to prevent window from drifting
//outside the left edge of visible screen
}
else if (abs(lpwndpos->x + lpwndpos->cx - rcScrn.right) <= m_EdgeSnapGap)
{
lpwndpos->x = rcScrn.right - lpwndpos->cx;
//???
//Code is needed here to prevent window from drifting
//outside the right edge of the visible screen
}
//Snap Y axis
if (abs(lpwndpos->y - rcScrn.top) <= m_EdgeSnapGap)
{
lpwndpos->y = rcScrn.top;
//???
//Code is needed here to prevent window from drifting
//outside the top edge of the visible screen
}
else if (abs(lpwndpos->y + lpwndpos->cy - rcScrn.bottom) <= m_EdgeSnapGap)
{
lpwndpos->y = rcScrn.bottom - lpwndpos->cy;
//???
//Code is needed here to prevent window from drifting
//outside the bottom edge of the visible screen
}
}
Can anyone help me on what code I should supply to make this work correctly?
<div class="ForumMod">modified on Thursday, December 20, 2007 2:01:10 AM</div>
|
|
|
|
|
Hi,
The program that I am working on uses two external DLL modules.
[program.exe] uses [library.dll]
[library.dll] uses [another_library.dll]
I have stepped through the program line by line, and have used the CRT break on allocation debugging feature. Upon exiting the program in debug mode within visual studio, it reports a lot of memory leaks. However, I believe these messages to be false.
Here is basically what happens.
[program.exe]
-->CMFCApplication
---->Initialise();
------>[library.dll]
-------->AllocateSomeMemory();
---------->[another_library.dll]
------------>AllocateSomeMoreMemory();
When the application closes I have confirmed that the processes exit in the following order:
[library.dll], [another_library.dll], [program.exe].
When [library.dll] exits the 'Output' panel within visual studio indicates that there is a memory leak. The memory is then released by [another_library.dll] after the leak has been reported within the output panel.
All three modules use the /MDd (Debug) /MD (Release) switches for multi-threaded dll, so they each share exactly the same memory manager.
Is there a way which I can force the DLL processes to be terminated in the specific order:
[another_library.dll], [library.dll], [program.exe]? Because I am confident that this will resolve the issue. I understand that it is probably safe for me to ignore this warning output...but future (problemsome) memory leaks will be masked by the fake ones. This could lead to some serious problems.
Any advice would be greatly appreciated...this is driving me nuts!
Lea Hayes
|
|
|
|
|
1. Shouldn't another_library.dll be released first? Library.dll is using another_library.dll , but library.dll dies in the half way. Therefore the system has no clue to release the resources of another_library.dll currently being used by library.dll .
2. Unreleased threads (suspended) can also cause memory leak warnings. Before the program exits, you should let all the threads exit.
Maxwell Chen
modified on Wednesday, December 19, 2007 10:56:20 PM
|
|
|
|