-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathInstanceChecker.cpp
More file actions
executable file
·148 lines (122 loc) · 4.01 KB
/
InstanceChecker.cpp
File metadata and controls
executable file
·148 lines (122 loc) · 4.01 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
/**
* This file is a part of IC Login (c) Daniel Bratell 2000
*
* That the source code is publicized on Internet does not mean that
* it's free to use. You are allowed to be inspired by it, but if you
* do patches of your own you must submit them to the original author.
*
* Also, you mustn't redistribute the source code. If you want to
* make other people see it, point them to
*
* http://www.lysator.liu.se/~bratell/iclogin/
*
* Original Author: Daniel Bratell <bratell@lysator.liu.se>
*/
#include "stdafx.h"
#include "InstanceChecker.h"
#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#define new DEBUG_NEW
#endif
///////////////////////////////// Implementation //////////////////////////////
//struct which is put into shared memory
struct CWindowInstance
{
HWND hMainWnd;
};
//Class which be used as a static to ensure that we
//only close the file mapping at the very last chance
class _INSTANCE_DATA
{
public:
_INSTANCE_DATA() { hInstanceData = NULL; }
~_INSTANCE_DATA() { hInstanceData ? ::CloseHandle(hInstanceData) : NULL; }
private:
HANDLE hInstanceData;
friend class CInstanceChecker;
};
static _INSTANCE_DATA instanceData;
#if 0
CInstanceChecker::CInstanceChecker()
{
}
CInstanceChecker::~CInstanceChecker()
{
}
#endif
/** Track the first instance of our App.
* Call this after LoadFrame() in InitInstance(). Call PreviousInstanceRunning() first
* and only call this if it returns false.
*
* @return TRUE on success, else FALSE - another instance is already running.
*/
bool CInstanceChecker::SetOurselfAsRunning()
{
//Create the MMF
int nMMFSize = sizeof(CWindowInstance);
instanceData.hInstanceData = ::CreateFileMapping((HANDLE)INVALID_HANDLE_VALUE,
NULL, PAGE_READWRITE, 0, nMMFSize, MakeMMFFilename());
if(!instanceData.hInstanceData) //Creating the MMF should work
{
return false;
}
//Open the MMF
CWindowInstance* pInstanceData = (CWindowInstance*) ::MapViewOfFile(instanceData.hInstanceData, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, nMMFSize);
ASSERT(pInstanceData != NULL); //Opening the MMF should work
ASSERT(AfxGetMainWnd() != NULL); //Did you forget to set up the mainfrm in InitInstance ?
ASSERT(AfxGetMainWnd()->GetSafeHwnd() != NULL);
pInstanceData->hMainWnd = AfxGetMainWnd()->GetSafeHwnd();
::UnmapViewOfFile(pInstanceData);
return true;
}
/** Returns true if a previous instance of the App is running.
*/
bool CInstanceChecker::AlreadyRunning()
{
bool return_value = false;
//Try to open the MMF first to see if we are the second instance
HANDLE hPrevInstance = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MakeMMFFilename());
if(hPrevInstance)
return_value = true;
::CloseHandle(hPrevInstance);
return return_value;
}
CString CInstanceChecker::MakeMMFFilename()
{
//MMF name is taken from MFC's AfxGetAppName
CString appname(AfxGetAppName());
ASSERT(!appname.IsEmpty());
return appname+_T("_running");
}
/** Activate the Previous Instance of our Application.
* @note Call PreviousInstanceRunning() before calling this function.
* @return hWnd of the previous instance's MainFrame if successful, else NULL.
*/
HWND CInstanceChecker::ActivateOtherInstance()
{
HANDLE hPrevInstance = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, MakeMMFFilename());
ASSERT(hPrevInstance != NULL); //Whats happened to my handle !
// Open up the MMF
int nMMFSize = sizeof(CWindowInstance);
CWindowInstance* pInstanceData = (CWindowInstance*) ::MapViewOfFile(hPrevInstance, FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, nMMFSize);
if (pInstanceData != NULL) //Opening the MMF should work
{
//activate the old window
HWND other_instance = pInstanceData->hMainWnd;
::ShowWindow(other_instance, SW_SHOWNORMAL);
::SetForegroundWindow(other_instance);
//Unmap the MMF we were using
::UnmapViewOfFile(pInstanceData);
//Close the file handle now that we
::CloseHandle(hPrevInstance);
return other_instance;
}
else
{
ASSERT(false); //Somehow MapViewOfFile failed.
}
//Close the file handle now that we
::CloseHandle(hPrevInstance);
return NULL;
}