애플리케이션 관리 개요
모든 애플리케이션은 애플리케이션 구현 및 관리에 적용하는 일반적인 기능 집합을 공유하는 경향이 있습니다. 이 토픽에서는 애플리케이션을 만들고 관리하는 Application 클래스의 기능에 대해 간략하게 설명합니다.
Application 클래스
WPF에서 일반적인 애플리케이션 범위 기능은 Application 클래스에 캡슐화됩니다. Application 클래스는 다음과 같은 기능을 포함하고 있습니다.
애플리케이션 수명 추적 및 상호 작용
명령줄 매개 변수 검색 및 처리
처리되지 않은 예외의 검색 및 응답
애플리케이션 범위 속성 및 리소스 공유
독립 실행형 애플리케이션에서 창 관리
탐색 추적 및 관리
Application 클래스를 사용하여 일반적인 작업을 수행하는 방법
Application 클래스에 대해 자세히 알 필요가 없는 경우 다음 표에 Application의 몇 가지 일반 작업과 이러한 작업을 수행하는 방법이 나열되어 있습니다. 관련 API 및 항목을 확인하여 추가 정보 및 샘플 코드를 찾을 수 있습니다.
Task | 접근 방식 |
---|---|
현재 애플리케이션을 나타내는 개체 가져오기 | Application.Current 속성을 사용합니다. |
애플리케이션에 시작 화면 추가 | WPF 애플리케이션에 시작 화면 추가를 참조하세요. |
애플리케이션 시작 | Application.Run 메서드를 사용합니다. |
애플리케이션 중지 | Application.Current 개체의 Shutdown 메서드를 사용합니다. |
명령줄에서 인수 가져오기 | Application.Startup 이벤트를 처리하고 StartupEventArgs.Args 속성을 사용합니다. 예제를 보려면 Application.Startup 이벤트를 참조하세요. |
애플리케이션 종료 코드 가져오기 및 설정 | Application.Exit 이벤트 처리기에서 ExitEventArgs.ApplicationExitCode 속성을 설정하거나 Shutdown 메서드를 호출하고 정수를 전달합니다. |
처리되지 않은 예외의 검색 및 응답 | DispatcherUnhandledException 이벤트를 처리합니다. |
애플리케이션 범위 리소스 가져오기 및 설정 | Application.Current 속성을 사용합니다. |
애플리케이션 범위 리소스 사전 사용 | 애플리케이션 범위 리소스 사전 사용을 참조하세요. |
애플리케이션 범위 속성 가져오기 및 설정 | Application.Current 속성을 사용합니다. |
애플리케이션 상태 가져오기 및 저장 | 애플리케이션 세션 간의 애플리케이션 범위 속성 유지 및 복원을 참조하세요. |
리소스 파일, 콘텐츠 파일 및 원본 사이트 파일을 포함하여 비코드 데이터 파일 관리 | WPF 애플리케이션 리소스, 콘텐츠 및 데이터 파일을 참조하세요. |
독립 실행형 애플리케이션의 창 관리 | WPF 창 개요를 참조하세요. |
탐색 추적 및 관리 | 탐색 개요를 참조하세요. |
애플리케이션 정의
Application 클래스의 기능을 활용하려면 애플리케이션 정의를 구현해야 합니다. WPF 애플리케이션 정의는 Application에서 파생되는 클래스이며 특수한 MSBuild 설정으로 구성됩니다.
애플리케이션 정의 구현
일반적인 WPF 애플리케이션 정의는 태그 및 코드 숨김을 모두 사용하여 구현됩니다. 따라서 코드 숨김에서 애플리케이션별 동작을 구현하고 이벤트를 처리하는 동시에 태그를 사용하여 애플리케이션 속성과 리소스를 선언적으로 설정하고 이벤트를 등록할 수 있습니다.
다음 예제에서는 태그 및 코드 숨김을 모두 사용하여 애플리케이션 정의를 구현하는 방법을 보여 줍니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App" />
using System.Windows;
namespace SDKSample
{
public partial class App : Application { }
}
Imports System.Windows
Namespace SDKSample
Partial Public Class App
Inherits Application
End Class
End Namespace
태그 파일과 코드 숨김 파일이 함께 작동하도록 하려면 다음이 필요합니다.
태그에서
Application
요소에는x:Class
특성이 포함되어야 합니다. 애플리케이션을 빌드할 때 태그 파일에x:Class
가 있으면 MSBuild는 Application에서 파생되며x:Class
특성에 의해 이름이 지정되는partial
클래스를 만듭니다. 이를 위해서는 XAML 스키마(xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
)의 XML 네임스페이스 선언을 추가해야 합니다.코드 숨김에서 클래스는 태그의
x:Class
특성으로 지정된 이름과 같은 이름을 가진partial
클래스여야 하며 Application에서 파생되어야 합니다. 이를 통해 애플리케이션 빌드 시 태그 파일에 대해 생성되는partial
클래스와 코드 숨김 파일을 연결할 수 있습니다(WPF 애플리케이션 빌드 참조).
참고
Visual Studio를 사용하여 새 WPF 애플리케이션 프로젝트나 WPF 브라우저 애플리케이션 프로젝트를 만들면 애플리케이션 정의가 기본적으로 포함되고 태그와 코드 숨김을 모두 사용하여 정의됩니다.
이 코드는 애플리케이션 정의를 구현하는 데 필요한 최소한의 코드이지만, 애플리케이션을 빌드하고 실행하려면 먼저 애플리케이션 정의에 대해 추가 MSBuild 구성이 이루어져야 합니다.
MSBuild용 애플리케이션 정의 구성
독립 실행형 애플리케이션과 XAML(Extensible Application Markup Language)을 실행하려면 특정 수준의 인프라를 구현해야 합니다. 이 인프라의 가장 중요한 부분은 진입점입니다. 사용자가 애플리케이션을 시작하면 운영 체제에서는 잘 알려진 애플리케이션 시작 함수인 진입점을 호출합니다.
Warning
XBAP를 사용하려면 Internet Explorer, 이전 버전 Firefox와 같은 레거시 브라우저가 작동해야 합니다. 이러한 구형 브라우저는 일반적으로 Windows 10과 Windows 11에서 지원되지 않습니다. 최신 브라우저는 보안 위험으로 인해 XBAP 앱에 필요한 기술을 더 이상 지원하지 않습니다. XBAP를 사용하도록 설정하는 플러그 인은 더 이상 지원되지 않습니다. 자세한 내용은 WPF XBAP(브라우저 호스팅 애플리케이션)에 대한 질문과 대답을 참조하세요.
일반적으로는 기술에 따라 개발자가 직접 이 코드 일부나 전체를 작성해야 합니다. 하지만 다음 MSBuild 프로젝트 파일에서 볼 수 있는 것처럼 애플리케이션 정의의 태그 파일을 MSBuild ApplicationDefinition
항목으로 구성하면 WPF에서 이 코드가 자동으로 생성됩니다.
<Project
DefaultTargets="Build"
xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
...
<ApplicationDefinition Include="App.xaml" />
<Compile Include="App.xaml.cs" />
...
</Project>
코드 숨김 파일에 코드가 들어 있으므로 이 코드는 정상적으로 MSBuild Compile
항목으로 표시됩니다.
애플리케이션 정의의 태그 및 코드 숨김 파일에 이러한 MSBuild 구성을 적용하면 MSBuild에서 다음과 같은 코드가 생성됩니다.
using System;
using System.Windows;
namespace SDKSample
{
public class App : Application
{
public App() { }
[STAThread]
public static void Main()
{
// Create new instance of application subclass
App app = new App();
// Code to register events and set properties that were
// defined in XAML in the application definition
app.InitializeComponent();
// Start running the application
app.Run();
}
public void InitializeComponent()
{
// Initialization code goes here.
}
}
}
Imports System.Windows
Namespace SDKSample
Public Class App
Inherits Application
Public Sub New()
End Sub
<STAThread>
Public Shared Sub Main()
' Create new instance of application subclass
Dim app As New App()
' Code to register events and set properties that were
' defined in XAML in the application definition
app.InitializeComponent()
' Start running the application
app.Run()
End Sub
Public Sub InitializeComponent()
' Initialization code goes here.
End Sub
End Class
End Namespace
결과 코드는 진입점 메서드인 Main
을 포함하는 추가 인프라 코드로 애플리케이션 정의를 보강합니다. STAThreadAttribute 특성은 Main
메서드에 적용되어 WPF 애플리케이션에 대한 기본 UI 스레드가 WPF 애플리케이션에 필요한 STA 스레드임을 나타냅니다. Main
은 호출되면 새 App
인스턴스를 생성한 후 이벤트를 등록하고 태그에서 구현되는 속성을 설정하는 InitializeComponent
메서드를 호출합니다. InitializeComponent
가 자동으로 생성되기 때문에 Page 및 Window 구현에서 하는 것처럼 애플리케이션 정의에서 InitializeComponent
를 명시적으로 호출할 필요가 없습니다. 마지막으로, Run 메서드가 호출되어 애플리케이션을 시작합니다.
현재 애플리케이션 가져오기
Application 클래스의 기능은 애플리케이션 간에 공유되므로 AppDomain 하나당 Application 클래스 인스턴스 하나만 허용됩니다. 이를 강제하기 위해 Application 클래스는 singleton 클래스로 구현됩니다(C#에서 Singleton 구현 참조). singleton 클래스는 자체적인 단일 인스턴스를 만들고 static
Current 속성으로 해당 인스턴스에 대한 공유 액세스를 제공합니다.
다음 코드는 현재 AppDomain의 Application 개체에 대한 참조를 가져오는 방법을 보여줍니다.
// Get current application
Application current = App.Current;
' Get current application
Dim current As Application = App.Current
Current는 Application 클래스의 인스턴스에 대한 참조를 반환합니다. Application 파생 클래스를 참조하려면 다음 예제와 같이 Current 속성 값을 캐스팅해야 합니다.
// Get strongly-typed current application
App app = (App)App.Current;
' Get strongly-typed current application
Dim appCurrent As App = CType(App.Current, App)
Application 개체의 수명 중 언제라도 Current 값을 검사할 수 있습니다. 하지만 이러한 검사를 수행할 때는 주의해야 합니다. Application 클래스가 인스턴스화된 후 Application 개체의 상태가 일치하지 않는 기간이 존재하기 때문입니다. 이 기간 중에는 Application이 애플리케이션 인프라 설정, 속성 설정, 이벤트 등록을 비롯하여 코드를 실행하는 데 필요한 다양한 초기화 작업을 수행합니다. 이 기간 중에 Application 개체를 사용하려고 하면 코드가 예기치 않은 결과를 반환할 수 있습니다. 특히 코드가 설정 중인 다양한 Application 속성에 의해 달라지는 경우에 그렇습니다.
Application이 초기화 작업을 완료하면 실제 수명이 시작됩니다.
애플리케이션 수명
WPF 애플리케이션의 수명은 Application에 의해 발생되는 몇 가지 이벤트로 표시되므로 애플리케이션의 시작 시점, 활성화 및 비활성화 시점, 종료 시점을 알 수 있습니다.
시작 화면
.NET Framework 3.5 SP1부터는 시작 창 또는 시작 화면에 사용할 이미지를 지정할 수 있습니다. SplashScreen 클래스를 사용하면 애플리케이션이 로드되는 동안 손쉽게 시작 창을 표시할 수 있습니다. SplashScreen 창은 Run이 호출되기 전에 만들어져 표시됩니다. 자세한 내용은 애플리케이션 시작 시간 및 WPF 애플리케이션에 시작 화면 추가를 참조하세요.
애플리케이션 시작
Run이 호출되고 애플리케이션이 초기화된 후에는 애플리케이션을 실행할 수 있습니다. 이 시점은 Startup 이벤트가 발생하는 시점입니다.
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
}
}
}
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
' Application is running
'</SnippetStartupCODEBEHIND1>
End Class
End Namespace
'</SnippetStartupCODEBEHIND2>
애플리케이션 수명 중 이 시점에서 가장 일반적으로 수행되는 작업은 UI를 표시하는 것입니다.
사용자 인터페이스 표시
대부분의 독립 실행형 Windows 애플리케이션은 실행이 시작되면 Window를 엽니다. 다음 코드에 나온 것처럼 Startup 이벤트 처리기가 이 작업을 수행할 수 있는 하나의 위치입니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Open a window
MainWindow window = new MainWindow();
window.Show();
}
}
}
Imports System.Windows
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
' Open a window
Dim window As New MainWindow()
window.Show()
End Sub
End Class
End Namespace
참고
독립 실행형 애플리케이션에서 처음 인스턴스화되는 Window가 기본적으로 기본 애플리케이션 창이 됩니다. 이 Window 개체는 Application.MainWindow 속성에서 참조됩니다. 처음 인스턴스화된 Window 대신 다른 창이 주 창이 되어야 하는 경우 MainWindow 속성 값을 프로그래밍 방식으로 변경할 수 있습니다.
XBAP를 처음 시작하면 대부분 Page로 이동합니다. 다음 코드에서 이를 확인할 수 있습니다.
<Application
x:Class="SDKSample.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Startup="App_Startup" />
using System;
using System.Windows;
using System.Windows.Navigation;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
((NavigationWindow)this.MainWindow).Navigate(new Uri("HomePage.xaml", UriKind.Relative));
}
}
}
Imports System.Windows
Imports System.Windows.Navigation
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
CType(Me.MainWindow, NavigationWindow).Navigate(New Uri("HomePage.xaml", UriKind.Relative))
End Sub
End Class
End Namespace
Startup을 처리하여 Window만 열거나 Page로 이동하려는 경우에는 태그에서 StartupUri
특성을 대신 설정하면 됩니다.
다음 예제에서는 독립 실행형 애플리케이션에서 StartupUri를 사용하여 Window를 여는 방법을 보여줍니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="MainWindow.xaml" />
다음 예제에서는 XBAP에서 StartupUri를 사용하여 Page로 이동하는 방법을 보여줍니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
StartupUri="HomePage.xaml" />
이 태그는 창을 여는 이전 코드와 같은 효과를 갖습니다.
참고
탐색에 대한 자세한 내용은 탐색 개요를 참조하세요.
매개 변수 없는 생성자가 아닌 생성자를 사용하여 이벤트를 인스턴스화하거나, 표시하기 전에 해당 속성을 설정하거나 해당 이벤트를 등록해야 하거나, 애플리케이션이 시작될 때 제공된 모든 명령줄 인수를 처리해야 하는 경우 Startup 이벤트를 처리하여 Window를 열어야 합니다.
명령줄 인수 처리
Windows에서는 명령 프롬프트나 바탕 화면에서 독립 실행형 애플리케이션을 시작할 수 있습니다. 두 경우 모두 명령줄 인수를 애플리케이션으로 전달할 수 있습니다. 다음 예제에서는 단일 명령줄 인수 "/StartMinimized"를 사용하여 시작되는 애플리케이션을 보여 줍니다.
wpfapplication.exe /StartMinimized
애플리케이션이 초기화되는 중에 WPF는 StartupEventArgs 매개 변수의 Args 속성을 통해 운영 체제에서 명령줄 인수를 검색하여 Startup 이벤트 처리기로 전달합니다. 다음과 같은 코드를 사용하여 명령줄 인수를 검색하고 저장할 수 있습니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
Startup="App_Startup" />
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_Startup(object sender, StartupEventArgs e)
{
// Application is running
// Process command line args
bool startMinimized = false;
for (int i = 0; i != e.Args.Length; ++i)
{
if (e.Args[i] == "/StartMinimized")
{
startMinimized = true;
}
}
// Create main application window, starting minimized if specified
MainWindow mainWindow = new MainWindow();
if (startMinimized)
{
mainWindow.WindowState = WindowState.Minimized;
}
mainWindow.Show();
}
}
}
Imports System.Windows
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
' Application is running
' Process command line args
Dim startMinimized As Boolean = False
Dim i As Integer = 0
Do While i <> e.Args.Length
If e.Args(i) = "/StartMinimized" Then
startMinimized = True
End If
i += 1
Loop
' Create main application window, starting minimized if specified
Dim mainWindow As New MainWindow()
If startMinimized Then
mainWindow.WindowState = WindowState.Minimized
End If
mainWindow.Show()
End Sub
End Class
End Namespace
코드에서는 Startup을 처리하여 /StartMinimized 명령줄 인수가 제공되었는지 확인합니다. 인수가 제공된 경우 WindowState가 Minimized인 주 창을 엽니다. WindowState 속성은 프로그래밍 방식으로 설정되어야 하므로 기본 Window는 코드에서 명시적으로 열려야 합니다.
XBAP는 ClickOnce 배포를 사용하여 시작되기 때문에 명령줄 인수를 검색하고 처리할 수 없습니다(WPF 애플리케이션 배포 참조). 그러나 XBAP를 시작하는 데 사용되는 URL에서 쿼리 문자열 매개 변수를 검색하고 처리할 수 있습니다.
애플리케이션 활성화 및 비활성화
Windows에서는 사용자가 애플리케이션 간에 전환할 수가 있습니다. 가장 일반적인 방법은 ALT+TAB 키 조합을 사용하는 것입니다. 애플리케이션에 사용자가 선택할 수 있는 Window가 표시되어 있는 경우에만 애플리케이션을 전환할 수 있습니다. 현재 선택된 Window는 활성 창(전경 창이라고도 함)이며 사용자 입력을 받는 Window입니다. 활성 창이 있는 애플리케이션을 활성 애플리케이션(또는 전경 애플리케이션)이라고 합니다. 다음과 같은 경우에 애플리케이션이 활성 애플리케이션이 됩니다.
Application.Activated 이벤트를 처리하면 애플리케이션이 활성화되는 시점을 감지할 수 있습니다.
마찬가지로 다음과 같은 경우에는 애플리케이션이 비활성화됩니다.
사용자가 현재 애플리케이션에서 다른 애플리케이션으로 전환하는 경우
애플리케이션이 종료되는 경우
Application.Deactivated 이벤트를 처리하면 애플리케이션이 비활성화되는 시점을 감지할 수 있습니다.
다음 코드는 Activated 및 Deactivated 이벤트를 처리하여 애플리케이션이 활성화되었는지 확인하는 방법을 보여줍니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Activated="App_Activated"
Deactivated="App_Deactivated" />
using System;
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
bool isApplicationActive;
void App_Activated(object sender, EventArgs e)
{
// Application activated
this.isApplicationActive = true;
}
void App_Deactivated(object sender, EventArgs e)
{
// Application deactivated
this.isApplicationActive = false;
}
}
}
Imports System.Windows
Namespace SDKSample
Partial Public Class App
Inherits Application
Private isApplicationActive As Boolean
Private Sub App_Activated(ByVal sender As Object, ByVal e As EventArgs)
' Application activated
Me.isApplicationActive = True
End Sub
Private Sub App_Deactivated(ByVal sender As Object, ByVal e As EventArgs)
' Application deactivated
Me.isApplicationActive = False
End Sub
End Class
End Namespace
Window도 활성화 및 비활성화할 수 있습니다. 자세한 내용은 Window.Activated 및 Window.Deactivated를 참조하세요.
참고
XBAP는 Application.Activated 및 Application.Deactivated가 발생하지 않습니다.
애플리케이션 종료
다음과 같은 이유로 애플리케이션이 종료되면 애플리케이션 수명이 끝납니다.
애플리케이션 종료를 쉽게 관리할 수 있도록 Application에서는 Shutdown 메서드, ShutdownMode 속성과 SessionEnding 및 Exit 이벤트를 제공합니다.
참고
Shutdown은 UIPermission이 있는 애플리케이션에서만 호출할 수 있습니다. 독립 실행형 WPF 애플리케이션에는 항상 이 권한이 있습니다. 하지만 인터넷 영역의 부분 신뢰 보안 샌드박스에서 실행되는 XBAP에는 이 권한이 없습니다.
종료 모드
대부분의 애플리케이션은 모든 창을 닫거나 주 창을 닫으면 종료됩니다. 하지만 다른 애플리케이션과 관련된 조건이 특정 애플리케이션의 종료 시점을 결정하는 경우가 있습니다. 다음 ShutdownMode 열거형 값 중 하나로 ShutdownMode를 설정하여 애플리케이션이 종료되는 조건을 지정할 수 있습니다.
ShutdownMode의 기본값은 사용자가 애플리케이션의 마지막 창을 닫으면 애플리케이션이 자동으로 종료되는 OnLastWindowClose입니다. 하지만 주 창이 닫힐 때 애플리케이션을 종료해야 하는 경우 ShutdownMode를 OnMainWindowClose로 설정하면 WPF에서 자동으로 이를 수행합니다. 다음 예제에서 이를 확인할 수 있습니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
ShutdownMode="OnMainWindowClose" />
애플리케이션별 종료 조건이 있는 경우ShutdownMode를 OnExplicitShutdown으로 설정합니다. 이 경우 Shutdown 메서드를 호출하여 명시적으로 애플리케이션을 종료하는 것은 사용자의 책임입니다. 그렇지 않으면 모든 창을 닫은 경우에도 애플리케이션이 계속 실행됩니다. ShutdownMode가 OnLastWindowClose 또는 OnMainWindowClose인 경우에는 Shutdown이 암시적으로 호출됩니다.
참고
ShutdownMode는 XBAP에서 설정할 수 있지만 이 설정은 무시됩니다. 브라우저에서 다른 위치로 이동하거나 XBAP를 호스트하는 브라우저가 닫히면 XBAP가 항상 종료됩니다. 자세한 내용은 탐색 개요를 참조하세요.
세션 종료
ShutdownMode 속성으로 설명되는 종료 조건은 애플리케이션과 관련이 있습니다. 하지만 외부 조건에 따라 애플리케이션이 종료되는 경우도 있습니다. 가장 일반적인 외부 조건은 다음과 같은 작업으로 사용자가 Windows 세션을 종료하는 경우에 발생합니다.
로그오프
종료
다시 시작
최대 절전 모드
Windows 세션이 종료되는 시점을 감지하려면 다음 예제처럼 SessionEnding 이벤트를 처리하면 됩니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
SessionEnding="App_SessionEnding" />
using System.Windows;
namespace SDKSample
{
public partial class App : Application
{
void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
// Ask the user if they want to allow the session to end
string msg = string.Format("{0}. End session?", e.ReasonSessionEnding);
MessageBoxResult result = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo);
// End session, if specified
if (result == MessageBoxResult.No)
{
e.Cancel = true;
}
}
}
}
Imports System.Windows
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_SessionEnding(ByVal sender As Object, ByVal e As SessionEndingCancelEventArgs)
' Ask the user if they want to allow the session to end
Dim msg As String = String.Format("{0}. End session?", e.ReasonSessionEnding)
Dim result As MessageBoxResult = MessageBox.Show(msg, "Session Ending", MessageBoxButton.YesNo)
' End session, if specified
If result = MessageBoxResult.No Then
e.Cancel = True
End If
End Sub
End Class
End Namespace
이 예제의 코드는 ReasonSessionEnding 속성을 검사하여 Windows 세션이 종료되는 방식을 결정합니다. 또한 이 값을 사용하여 사용자에게 확인 메시지를 표시합니다. 사용자가 세션이 종료되기를 원하지 않는 경우에는 코드에서 Cancel을 true
로 설정하여 Windows 세션이 종료되지 않게 합니다.
참고
SessionEnding은 XBAP에 대해 발생하지 않습니다.
종료
애플리케이션이 종료될 때 애플리케이션 상태 유지와 같은 몇 가지 최종 처리를 수행해야 할 경우가 있습니다. 이러한 경우 다음 예제의 App_Exit
이벤트 처리기와 마찬가지 방법으로 Exit 이벤트를 처리할 수 있습니다. App.xaml 파일에서 이벤트 처리기로 정의됩니다. 해당 구현은 App.xaml.cs 및 Application.xaml.vb 파일에서 강조 표시됩니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
Startup="App_Startup"
Exit="App_Exit">
<Application.Resources>
<SolidColorBrush x:Key="ApplicationScopeResource" Color="White"></SolidColorBrush>
</Application.Resources>
</Application>
using System.Windows;
using System.IO;
using System.IO.IsolatedStorage;
namespace SDKSample
{
public partial class App : Application
{
string filename = "App.txt";
public App()
{
// Initialize application-scope property
this.Properties["NumberOfAppSessions"] = 0;
}
private void App_Startup(object sender, StartupEventArgs e)
{
// Restore application-scope property from isolated storage
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain();
try
{
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Open, storage))
using (StreamReader reader = new StreamReader(stream))
{
// Restore each application-scope property individually
while (!reader.EndOfStream)
{
string[] keyValue = reader.ReadLine().Split(new char[] {','});
this.Properties[keyValue[0]] = keyValue[1];
}
}
}
catch (FileNotFoundException ex)
{
// Handle when file is not found in isolated storage:
// * When the first application session
// * When file has been deleted
}
}
private void App_Exit(object sender, ExitEventArgs e)
{
// Persist application-scope property to isolated storage
IsolatedStorageFile storage = IsolatedStorageFile.GetUserStoreForDomain();
using (IsolatedStorageFileStream stream = new IsolatedStorageFileStream(filename, FileMode.Create, storage))
using (StreamWriter writer = new StreamWriter(stream))
{
// Persist each application-scope property individually
foreach (string key in this.Properties.Keys)
{
writer.WriteLine("{0},{1}", key, this.Properties[key]);
}
}
}
}
}
Imports System.IO
Imports System.IO.IsolatedStorage
Namespace SDKSample
Partial Public Class App
Inherits Application
Private filename As String = "App.txt"
Public Sub New()
' Initialize application-scope property
Me.Properties("NumberOfAppSessions") = 0
End Sub
Private Sub App_Startup(ByVal sender As Object, ByVal e As StartupEventArgs)
' Restore application-scope property from isolated storage
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForDomain()
Try
Using stream As New IsolatedStorageFileStream(filename, FileMode.Open, storage)
Using reader As New StreamReader(stream)
' Restore each application-scope property individually
Do While Not reader.EndOfStream
Dim keyValue() As String = reader.ReadLine().Split(New Char() {","c})
Me.Properties(keyValue(0)) = keyValue(1)
Loop
End Using
End Using
Catch ex As FileNotFoundException
' Handle when file is not found in isolated storage:
' * When the first application session
' * When file has been deleted
End Try
End Sub
Private Sub App_Exit(ByVal sender As Object, ByVal e As ExitEventArgs)
' Persist application-scope property to isolated storage
Dim storage As IsolatedStorageFile = IsolatedStorageFile.GetUserStoreForDomain()
Using stream As New IsolatedStorageFileStream(filename, FileMode.Create, storage)
Using writer As New StreamWriter(stream)
' Persist each application-scope property individually
For Each key As String In Me.Properties.Keys
writer.WriteLine("{0},{1}", key, Me.Properties(key))
Next key
End Using
End Using
End Sub
End Class
End Namespace
전체 예제는 애플리케이션 세션 간의 애플리케이션 범위 속성 유지 및 복원을 참조하세요.
Exit는 독립 실행형 애플리케이션과 XBAP 모두에서 처리할 수 있습니다. XBAP에서는 다음과 같은 경우에 Exit가 발생합니다.
XBAP가 다른 위치로 이동하는 경우
Internet Explorer에서 XBAP를 호스트하는 탭이 닫히는 경우
브라우저가 닫힌 경우
종료 코드
대부분의 경우 애플리케이션은 운영 체제에서 사용자 요청에 대한 응답으로 시작하게 됩니다. 하지만 다른 애플리케이션에서 일부 특정 작업을 수행하기 위해 애플리케이션을 시작할 수도 있습니다. 시작된 애플리케이션이 종료될 경우 시작하는 애플리케이션에서 시작된 애플리케이션이 종료되는 조건을 알고 싶을 수 있습니다. 이런 경우 Windows에서는 애플리케이션이 종료될 때 애플리케이션 종료 코드를 반환할 수 있습니다. 기본적으로 WPF 애플리케이션은 종료 코드 값으로 0을 반환합니다.
참고
Visual Studio에서 디버깅할 경우 애플리케이션이 종료되면 출력 창에 애플리케이션 종료 코드가 다음과 같은 메시지로 표시됩니다.
The program '[5340] AWPFApp.vshost.exe: Managed' has exited with code 0 (0x0).
보기 메뉴에서 출력을 클릭하여 출력 창을 엽니다.
종료 코드를 변경하려면 정수 인수를 종료 코드로 수락하는 Shutdown(Int32) 오버로드를 호출하면 됩니다.
// Shutdown and return a non-default exit code
Application.Current.Shutdown(-1);
' Shutdown and return a non-default exit code
Application.Current.Shutdown(-1)
Exit 이벤트를 처리하면 종료 코드 값을 검색하고 변경할 수 있습니다. Exit 이벤트 처리기는 ApplicationExitCode 속성이 있는 종료 코드에 대한 액세스를 제공하는 ExitEventArgs를 전달합니다. 자세한 내용은 Exit를 참조하세요.
참고
독립 실행형 애플리케이션 및 XBAP 모두에서 종료 코드를 설정할 수 있습니다. 하지만 XBAP의 경우 종료 코드 값이 무시됩니다.
처리되지 않은 예외
원하지 않는 예외를 throw하는 경우와 같이 애플리케이션이 비정상적인 상황에서 종료되는 경우가 있습니다. 이런 경우에는 애플리케이션에 예외를 검색하고 처리할 코드가 없을 수 있습니다. 이런 형식의 예외가 처리되지 않은 예외이며, 애플리케이션이 닫히기 전에 다음 그림에 표시된 것과 비슷한 알림으로 표시됩니다.
처리되지 않은 예외 알림을 보여주는 스크린샷.
사용자 환경의 관점에서는 애플리케이션에서 다음과 같은 작업의 일부 또는 전부를 수행하여 이러한 기본 동작을 방지하는 것이 바람직합니다.
사용자에게 친숙한 정보 표시
애플리케이션을 실행 상태로 유지
Windows 이벤트 로그에 개발자에게 친숙한 세부적인 예외 정보 기록
이러한 지원을 구현하는 것은 처리되지 않은 예외, 다시 말해 DispatcherUnhandledException 이벤트가 발생하는 원인을 검색할 수 있는지에 따라 달라집니다.
<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.App"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException" />
using System.Windows;
using System.Windows.Threading;
namespace SDKSample
{
public partial class App : Application
{
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
// Process unhandled exception
// Prevent default unhandled exception processing
e.Handled = true;
}
}
}
Imports System.Windows
Imports System.Windows.Threading
Namespace SDKSample
Partial Public Class App
Inherits Application
Private Sub App_DispatcherUnhandledException(ByVal sender As Object, ByVal e As DispatcherUnhandledExceptionEventArgs)
' Process unhandled exception
' Prevent default unhandled exception processing
e.Handled = True
End Sub
End Class
End Namespace
DispatcherUnhandledException 이벤트 처리기는 예외 자체(DispatcherUnhandledExceptionEventArgs.Exception)를 포함하여 처리되지 않은 예외와 관련된 컨텍스트 정보를 포함하는 DispatcherUnhandledExceptionEventArgs 매개 변수를 전달합니다. 이 정보를 사용하여 예외를 처리하는 방법을 결정할 수 있습니다.
DispatcherUnhandledException을 처리할 때는 DispatcherUnhandledExceptionEventArgs.Handled 속성을 true
로 설정해야 합니다. 그러지 않으면 WPF에서 계속해서 예외가 처리되지 않은 것으로 간주하고 이전에 설명한 기본 동작으로 돌아갑니다. 처리되지 않은 예외가 발생하고 DispatcherUnhandledException 이벤트가 처리되지 않거나, 이벤트가 처리되지만 Handled가 false
로 설정된 경우 애플리케이션이 즉시 종료됩니다. 뿐만 아니라 다른 Application 이벤트가 발생하지 않습니다. 따라서 애플리케이션에 애플리케이션이 종료되기 전에 실행되어야 하는 코드가 있는 경우 DispatcherUnhandledException을 처리해야 합니다.
처리되지 않은 예외의 결과로 애플리케이션이 종료될 수는 있지만 애플리케이션은 대개 다음 섹션에서 설명하는 것처럼 사용자 요청에 대한 응답으로 종료됩니다.
애플리케이션 수명 이벤트
독립 실행형 애플리케이션과 XBAP는 수명이 동일하지 않습니다. 다음 그림에서는 독립 실행형 애플리케이션 수명에서의 주요 이벤트와 이러한 이벤트가 발생하는 순서를 보여 줍니다.
독립 실행형 애플리케이션 - 애플리케이션 개체 이벤트ApplicationModelOverview_ApplicationObjectEvents
마찬가지로 다음 그림에서는 XBAP 수명에서의 주요 이벤트와 이러한 이벤트가 발생하는 순서를 보여줍니다.
XBAP - 애플리케이션 개체 이벤트ApplicationModelOverview_ApplicationObjectEvents_xbap
참고 항목
.NET Desktop feedback