代码如下:
class
SingletonWindow
{
//
注册附加属性
public
static
readonly
DependencyProperty
IsEnabledProperty
=
DependencyProperty
.RegisterAttached(
"IsEnabled"
,
typeof
(
bool
),
typeof
(
SingletonWindow
),
new
FrameworkPropertyMetadata
(OnIsEnabledChanged));
public
static
void
SetIsEnabled(
DependencyObject
element,
Boolean
value)
{
element.SetValue(IsEnabledProperty,
value);
}
public
static
Boolean
GetIsEnabled(
DependencyObject
element)
{
return
(
Boolean
)element.GetValue(IsEnabledProperty);
}
//
根据附加属性的返回值使能单实例模式
public
static
void
OnIsEnabledChanged(
DependencyObject
obj,
DependencyPropertyChangedEventArgs
args)
{
if
((
bool
)args.NewValue !=
true
)
{
return
;
}
Process();
return
;
}
public
static
void
Process()
//
如果不适用附加属性也可以直接使用此函数
{
//
判断单实例的方式有很多,如
mutex
,
process
,文件锁等,这里用的是
process
方式
var
process = GetRunningInstance();
if
(process !=
null
)
{
HandleRunningInstance(process);
Environment
.Exit(0);
}
}
const
int
WS_SHOWNORMAL = 1;
[System.Runtime.InteropServices.
DllImport
(
"User32.dll"
)]
static
extern
bool
ShowWindowAsync(
IntPtr
hWnd,
int
cmdShow);
[System.Runtime.InteropServices.
DllImport
(
"User32.dll"
)]
static
extern
bool
SetForegroundWindow(
IntPtr
hWnd);
[System.Runtime.InteropServices.
DllImport
(
"user32.dll"
)]
static
extern
bool
FlashWindow(
IntPtr
hWnd,
bool
bInvert);
static
System.Diagnostics.
Process
GetRunningInstance()
{
var
current = System.Diagnostics.
Process
.GetCurrentProcess();
var
processes = System.Diagnostics.
Process
.GetProcessesByName(current.ProcessName);
foreach
(
var
process
in
processes)
{
if
(process.Id !=
current.Id)
if
(System.Reflection.
Assembly
.GetExecutingAssembly().Location.Replace(
"/"
,
"\\"
) ==
current.MainModule.FileName)
return
process;
}
return
null
;
}
static
void
HandleRunningInstance(System.Diagnostics.
Process
instance)
{
if
(instance.MainWindowHandle!=
IntPtr
.Zero)
{
for
(
int
i = 0; i
< 2;
i++)
{
FlashWindow(instance.MainWindowHandle,
500);
}
SetForegroundWindow(instance.MainWindowHandle);
ShowWindowAsync(instance.MainWindowHandle,
WS_SHOWNORMAL);
}
else
{
//else
处理有点麻烦,简化如下
MessageBox
.Show(
"
已经有一个实例在运行,无法启动第二个实例
"
);
}
}
static
void
FlashWindow(
IntPtr
hanlde,
int
interval)
{
FlashWindow(hanlde,
true
);
System.Threading.
Thread
.Sleep(interval);
FlashWindow(hanlde,
false
);
System.Threading.
Thread
.Sleep(interval);
}
}
代码其实很简单,前半部分是注册依赖属性,然后根据依赖属性判断是否启用单实例模式;后半部分就是一个传统的单实例模式的功能了。也就不介绍了。
使用这段代码也很简单:
Xaml方式:在主窗口的xaml文件中加入附加属性即可
<
Window
xmlns
:
src
="clr-namespace:WpfApplication1"
src
:
SingletonWindow.IsEnabled
="true"
>
传统方式:直接使用代码中后半部分,和winform下没什么区别。在主窗口的构造函数里面加入这句话。
SingletonWindow
.Process();