다른 앱에서 WPF 시스템 트레이 응용 프로그램을 닫는 방법은 무엇입니까?

괴롭히다

Philipp Sumi의 훌륭한 NotifyIcon사용 하는 창없는 WPF 응용 프로그램이 있습니다. 이전 WinForms 기반 버전을 기꺼이 교체하고 있지만 한 가지 문제가 있습니다.

내 앱에는 실행 파일을 제거하기 전에 트레이 응용 프로그램을 닫는 제거 프로그램이 있습니다. 닫기 작업은 트레이 응용 프로그램 프로세스에 WM_CLOSE 메시지를 보내는 것으로 완료됩니다. 그러나 WinForms를 사용하여 이러한 메시지를 듣는 것은 비교적 쉽습니다. WPF를 사용하여 수행하는 방법, 그리고 다시 WPF 트레이 응용 프로그램을 종료하도록 원격으로 알리는 더 좋은 방법이 있을까요? 내 말은, 또 뭐가 있지? 파이프?

이것은 중복이 아닙니다. 내 앱에 "메인 창"이 없습니다. 따라서 주 창을 참조하는 것은 작동하지 않습니다.

시스템이 다시 시작하거나 종료하는 경우 앱이 자동으로 종료되도록 지시하는 방법이 있어야한다고 생각합니다. 그렇기 때문에 "이 앱이 응답하지 않습니다. 종료 하시겠습니까?"또는 이와 유사한 메시지가 표시되는 이유입니다.

내 순진한 접근 방식은 다음과 같습니다.

using (var process = Process.GetProcessesByName("MyApp").FirstOrDefault()) {
    const uint WM_SYSCOMMAND = 0x0112;
    const uint SC_CLOSE = 0xF060;
    const uint WM_CLOSE = 0x0010;
    var hwnd = process.MainWindowHandle;
    NativeMethods.SendMessage(hwnd, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
    foreach (ProcessThread thread in process.Threads) {
        NativeMethods.PostThreadMessage(
            (uint)thread.Id,
            WM_SYSCOMMAND, 
            (IntPtr)SC_CLOSE,
            IntPtr.Zero
        );
    }
} 

작동하지 않습니다. 물론 hwnd는 항상 IntPtr.Zero입니다. 창을 만들지 않으면 창을 만들고 싶지 않습니다. 응용 프로그램 스레드는 SC_CLOSE를 무시하므로 여기서도 기쁨이 없습니다.

네, 보이지 않는 창을 만들려고했습니다. 이 방법은 창에 ShowInTaskBar가 true로 설정된 경우 작동합니다. 안좋다.

그런 다음 System.Windows.Forms.NativeWindow에서 스폰지 창을 만들었습니다.

물론 보이지 않는 창은 WM_CLOSE 및 기타 메시지를 완벽하게 수신 할 수 있지만 프로세스 기본 창으로 설정되어 있지 않으므로 제거 앱으로 대상을 지정할 수 없습니다.

현재 나는 아이디어가 없습니다.

괴롭히다

대부분의 경우 나는 스스로 알아 내야했다. 방법은 다음과 같습니다.

첫째, 프로세스가 있습니다. 이 프로세스에는 주 창이없고 창도 전혀 없으므로 창과의 모든 통신은 테이블에서 벗어납니다. 그러나 프로세스에는 스레드가 있습니다. 스레드에는 메시지 큐가 있지만 Win32 API로 액세스 할 수 있습니다.

그래서 여기에 수신 끝이 있습니다.

/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application {

    // (...)

    /// <summary>
    /// Sent as a signal that a window or an application should terminate.
    /// </summary>
    const uint WM_CLOSE = 0x0010;

    /// <summary>
    /// Retrieves a message from the calling thread's message queue. The function dispatches incoming sent messages until a posted message is available for retrieval.
    /// </summary>
    /// <param name="lpMsg">MSG structure that receives message information from the thread's message queue.</param>
    /// <param name="hWnd">A handle to the window whose messages are to be retrieved. The window must belong to the current thread. Use <see cref="IntPtr.Zero"/> to retrieve thread message.</param>
    /// <param name="wMsgFilterMin">The integer value of the lowest message value to be retrieved.</param>
    /// <param name="wMsgFilterMax">The integer value of the highest message value to be retrieved.</param>
    /// <returns>Non-zero for any message but WM_QUIT, zero for WM_QUIT, -1 for error.</returns>
    [DllImport("user32.dll")]
    static extern int GetMessage(out MSG lpMsg, IntPtr hWnd, uint wMsgFilterMin, uint wMsgFilterMax);

    /// <summary>
    /// Waits indefinitely for a specific thread message.
    /// </summary>
    /// <param name="signal">Signal, message value.</param>
    private void WaitForSignal(uint signal) => GetMessage(out var msg, IntPtr.Zero, signal, signal);

    /// <summary>
    /// WPF application startup.
    /// </summary>
    /// <param name="e">Event arguments.</param>
    protected override async void OnStartup(StartupEventArgs e) {
        base.OnStartup(e);
        // ... initialization code ...
        await Task.Run(() => WaitForSignal(WM_CLOSE));
        Shutdown();
    }

    // (...)

}

보내는 끝 :

/// <summary>
/// Demo.
/// </summary>
class Program {

    /// <summary>
    /// Sent as a signal that a window or an application should terminate.
    /// </summary>
    const uint WM_CLOSE = 0x0010;

    /// <summary>
    /// Posts a message to the message queue of the specified thread. It returns without waiting for the thread to process the message.
    /// </summary>
    /// <param name="threadId">The identifier of the thread to which the message is to be posted.</param>
    /// <param name="msg">The type of message to be posted.</param>
    /// <param name="wParam">Additional message-specific information.</param>
    /// <param name="lParam">Additional message-specific information.</param>
    /// <returns></returns>
    [return: MarshalAs(UnmanagedType.Bool)]
    [DllImport("user32.dll", SetLastError = true)]
    public static extern bool PostThreadMessage(uint threadId, uint msg, IntPtr wParam, IntPtr lParam);

    /// <summary>
    /// Closes a windowless application pointed with process name.
    /// </summary>
    /// <param name="processName">The name of the process to close.</param>
    static void CloseWindowless(string processName) {
        foreach (var process in Process.GetProcessesByName(processName)) {
            using (process) {
                foreach (ProcessThread thread in process.Threads) PostThreadMessage((uint)thread.Id, WM_CLOSE, IntPtr.Zero, IntPtr.Zero);
            }
        }
    }

    /// <summary>
    /// Main application entry point.
    /// </summary>
    /// <param name="args">Command line arguments.</param>
    static void Main(string[] args) => CloseWindowless("MyAppName");

}

그리고 뒤에있는 부두 마술 : P / Invoke 부분은 꽤 분명합니다. 더 흥미로운 것은 WPF Application입니다. OnStartup무시 동작.

메서드가 동기적이고 종료되지 않으면 응용 프로그램이 중단됩니다. 그러나 비동기로 표시된 경우 종료 할 필요가 없습니다. 기다릴 수있는 모든 것을 무기한 기다립니다. Shutdown()메인 UI 스레드에서만 호출 할 수 있기 때문에 이것이 정확히 필요한 것 입니다. 해당 스레드를 차단할 수 없으므로 다른 스레드에서 메시지를 기다려야합니다. 우리는 WM_CLOSE를 모든 프로세스 스레드로 보내서 그것을 얻을 것입니다. 종료되면 Shutdown메서드는 메인 스레드에서 호출됩니다.

이 솔루션에서 가장 좋은 것은 System.Windows.Forms 참조가 필요하지 않습니다.

이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.

침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제

에서 수정
0

몇 마디 만하겠습니다

0리뷰
로그인참여 후 검토

관련 기사

분류에서Dev

WPF 창 및 시스템 트레이 아이콘으로 명령 줄 / Windows 서비스 응용 프로그램을 만드는 방법은 무엇입니까?

분류에서Dev

ApplicationWindow 개체에서 닫을 때 응용 프로그램을 시스템 트레이로 최소화하는 방법은 무엇입니까?

분류에서Dev

Ubuntu에서 응용 프로그램에 대한 트레이 아이콘을 다시 활성화하는 방법은 무엇입니까?

분류에서Dev

Ubuntu에서 응용 프로그램에 대한 트레이 아이콘을 다시 활성화하는 방법은 무엇입니까?

분류에서Dev

내 컨트롤이 내 wpf 응용 프로그램에서 다르게 표시되도록하는 방법은 무엇입니까?

분류에서Dev

다른 응용 프로그램에서 Chrome 창을 닫는 방법은 무엇입니까?

분류에서Dev

다른 응용 프로그램의 사전 빌드 프로세스에서 cmd 응용 프로그램을 호출하는 방법은 무엇입니까?

분류에서Dev

다른 작업 공간에서 응용 프로그램을 시작하는 방법은 무엇입니까?

분류에서Dev

한 콘솔 응용 프로그램에서 텍스트 파일을 읽은 다음 다른 파일에 쓰는 방법은 무엇입니까?

분류에서Dev

각도 응용 프로그램이 다른 응용 프로그램에서 각도 모듈을 지연로드하는 방법은 무엇입니까?

분류에서Dev

내 응용 프로그램에서 다른 응용 프로그램의 숨겨진 창을 표시하는 방법은 무엇입니까?

분류에서Dev

다른 응용 프로그램에서 시작된 응용 프로그램을 디버깅하는 방법은 무엇입니까? (VB6)

분류에서Dev

한 시스템에서 실행중인 응용 프로그램을 다른 시스템으로 이동하는 방법이 있습니까?

분류에서Dev

한 시스템에서 실행중인 응용 프로그램을 다른 시스템으로 이동하는 방법이 있습니까?

분류에서Dev

두 개의 Silverlight 클라이언트 응용 프로그램에서 사용자 정의 컨트롤을 다시 사용하는 방법은 무엇입니까?

분류에서Dev

다른 레거시 Windows 응용 프로그램에 대해 다른 ANSI 코드 페이지를 설정하는 방법은 무엇입니까?

분류에서Dev

다른 응용 프로그램이 macOS에서 마우스 이벤트를 수신하지 못하도록 방지하는 방법은 무엇입니까?

분류에서Dev

응용 프로그램 창 표시에서 응용 프로그램 아이콘 표시로 Alt + Tab 동작을 되 돌리는 방법은 무엇입니까?

분류에서Dev

WPF에서 다른 프로젝트의 리소스를 사용하는 방법은 무엇입니까?

분류에서Dev

실행중인 시스템에서 루트 파일 시스템을 다른 파티션으로 마이그레이션하는 방법은 무엇입니까?

분류에서Dev

bash 스크립트에서 루프를 사용하여 다른 인수로 프로그램을 여러 번 실행하는 방법은 무엇입니까?

분류에서Dev

동일한 프로그램 내에서 충돌시 Qt 응용 프로그램을 자동으로 다시 시작하는 방법은 무엇입니까?

분류에서Dev

응용 프로그램이 시작될 때 서랍을 여는 방법은 무엇입니까?

분류에서Dev

Windows 7 시스템 아이콘 트레이에서 응용 프로그램의 순서를 결정하는 것은 무엇입니까?

분류에서Dev

WPF 다중 창 응용 프로그램에서 사용자 설정을 동적으로로드하고 저장하는 방법은 무엇입니까?

분류에서Dev

다른 프로그램이 닫힌 후 powershell을 사용하여 프로그램을 닫는 방법은 무엇입니까?

분류에서Dev

엔터프라이즈 Java 응용 프로그램에서 스레드를 만드는 올바른 방법은 무엇입니까?

분류에서Dev

WPF에서 응용 프로그램의 다양한 상태에 대한 신호등 색상을 구현하는 가장 좋은 방법은 무엇입니까?

분류에서Dev

응용 프로그램에서만 원숭이 테스트를 실행하는 방법은 무엇입니까?

Related 관련 기사

  1. 1

    WPF 창 및 시스템 트레이 아이콘으로 명령 줄 / Windows 서비스 응용 프로그램을 만드는 방법은 무엇입니까?

  2. 2

    ApplicationWindow 개체에서 닫을 때 응용 프로그램을 시스템 트레이로 최소화하는 방법은 무엇입니까?

  3. 3

    Ubuntu에서 응용 프로그램에 대한 트레이 아이콘을 다시 활성화하는 방법은 무엇입니까?

  4. 4

    Ubuntu에서 응용 프로그램에 대한 트레이 아이콘을 다시 활성화하는 방법은 무엇입니까?

  5. 5

    내 컨트롤이 내 wpf 응용 프로그램에서 다르게 표시되도록하는 방법은 무엇입니까?

  6. 6

    다른 응용 프로그램에서 Chrome 창을 닫는 방법은 무엇입니까?

  7. 7

    다른 응용 프로그램의 사전 빌드 프로세스에서 cmd 응용 프로그램을 호출하는 방법은 무엇입니까?

  8. 8

    다른 작업 공간에서 응용 프로그램을 시작하는 방법은 무엇입니까?

  9. 9

    한 콘솔 응용 프로그램에서 텍스트 파일을 읽은 다음 다른 파일에 쓰는 방법은 무엇입니까?

  10. 10

    각도 응용 프로그램이 다른 응용 프로그램에서 각도 모듈을 지연로드하는 방법은 무엇입니까?

  11. 11

    내 응용 프로그램에서 다른 응용 프로그램의 숨겨진 창을 표시하는 방법은 무엇입니까?

  12. 12

    다른 응용 프로그램에서 시작된 응용 프로그램을 디버깅하는 방법은 무엇입니까? (VB6)

  13. 13

    한 시스템에서 실행중인 응용 프로그램을 다른 시스템으로 이동하는 방법이 있습니까?

  14. 14

    한 시스템에서 실행중인 응용 프로그램을 다른 시스템으로 이동하는 방법이 있습니까?

  15. 15

    두 개의 Silverlight 클라이언트 응용 프로그램에서 사용자 정의 컨트롤을 다시 사용하는 방법은 무엇입니까?

  16. 16

    다른 레거시 Windows 응용 프로그램에 대해 다른 ANSI 코드 페이지를 설정하는 방법은 무엇입니까?

  17. 17

    다른 응용 프로그램이 macOS에서 마우스 이벤트를 수신하지 못하도록 방지하는 방법은 무엇입니까?

  18. 18

    응용 프로그램 창 표시에서 응용 프로그램 아이콘 표시로 Alt + Tab 동작을 되 돌리는 방법은 무엇입니까?

  19. 19

    WPF에서 다른 프로젝트의 리소스를 사용하는 방법은 무엇입니까?

  20. 20

    실행중인 시스템에서 루트 파일 시스템을 다른 파티션으로 마이그레이션하는 방법은 무엇입니까?

  21. 21

    bash 스크립트에서 루프를 사용하여 다른 인수로 프로그램을 여러 번 실행하는 방법은 무엇입니까?

  22. 22

    동일한 프로그램 내에서 충돌시 Qt 응용 프로그램을 자동으로 다시 시작하는 방법은 무엇입니까?

  23. 23

    응용 프로그램이 시작될 때 서랍을 여는 방법은 무엇입니까?

  24. 24

    Windows 7 시스템 아이콘 트레이에서 응용 프로그램의 순서를 결정하는 것은 무엇입니까?

  25. 25

    WPF 다중 창 응용 프로그램에서 사용자 설정을 동적으로로드하고 저장하는 방법은 무엇입니까?

  26. 26

    다른 프로그램이 닫힌 후 powershell을 사용하여 프로그램을 닫는 방법은 무엇입니까?

  27. 27

    엔터프라이즈 Java 응용 프로그램에서 스레드를 만드는 올바른 방법은 무엇입니까?

  28. 28

    WPF에서 응용 프로그램의 다양한 상태에 대한 신호등 색상을 구현하는 가장 좋은 방법은 무엇입니까?

  29. 29

    응용 프로그램에서만 원숭이 테스트를 실행하는 방법은 무엇입니까?

뜨겁다태그

보관