WPF 应用第一次加载带有窗口的插件,但第二次无法显示窗口

WPF app loads a plugin with a window well first time, but fails to show the window second time

提问人:Alex Netkachov 提问时间:11/12/2023 更新时间:11/12/2023 访问量:39

问:

该应用通过加载程序集来实现插件。插件可以多次加载,而且工作非常简单,直到我从插件中显示一个窗口。它第一次工作,但第二次不会打开窗口。

主机应用

Host.csproj(主机.csproj)

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <LangVersion>default</LangVersion>
    <TargetFramework>net48</TargetFramework>
    <OutputType>WinExe</OutputType>
    <UseWPF>true</UseWPF>
    <StartupObject>Host.MainModule</StartupObject>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
  </PropertyGroup>
  <ItemGroup>
    <ApplicationDefinition Include="MainModule.xaml">
      <Generator>MSBuild:Compile</Generator>
      <SubType>Designer</SubType>
    </ApplicationDefinition>
  </ItemGroup>
</Project>

MainModule.xaml

<Application x:Class="Host.MainModule"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/>

MainModule.xaml.cs

using System;
using System.IO;
using System.Reflection;
using System.Windows;

namespace Host;

public partial class MainModule
{
  protected override void OnStartup(StartupEventArgs e)
  {
      base.OnStartup(e);

      LoadAndRun(@"..\..\..\..\..\Service\bin\x64\Debug\net48\Service.dll");
      LoadAndRun(@"..\..\..\..\..\Service\bin\x64\Debug\net48\Service.dll");

      MessageBox.Show("ok");

      Shutdown();
  }

  private static void LoadAndRun(string path) {
    var folder = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
    var assembly = Assembly.LoadFile(Path.GetFullPath(Path.Combine(folder, path)));
    var provider = assembly.GetType("Service.Provider");
    var instance = Activator.CreateInstance(provider);
    var method = provider.GetMethod("Run");
    method.Invoke(instance, null);
  }
}

服务库

服务.csproj

<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <LangVersion>default</LangVersion>
    <TargetFramework>net48</TargetFramework>
    <OutputType>library</OutputType>
    <UseWPF>true</UseWPF>
    <DebugType>full</DebugType>
    <DebugSymbols>true</DebugSymbols>
    <DefineConstants>TRACE</DefineConstants>
  </PropertyGroup>
</Project>

提供程序.cs

using System;
using System.Diagnostics;
using Microsoft.SqlServer.Server;

namespace Service;

public sealed class Provider {
  public void Run() {
    var form = new Form();
    var sw = Stopwatch.StartNew();
    form.ShowDialog();
    Console.WriteLine($"{nameof(Provider)}.{nameof(Run)}: form was opened for {sw.ElapsedMilliseconds} ms");
  }
}

Form.xaml

<Window x:Class="Service.Form"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Form"
        Height="400" Width="200">
</Window>

Form.xaml.cs

using System;

namespace Service;

public partial class Form {
  public Form() {
    Console.WriteLine($"{nameof(Form)}.{nameof(Form)}: start");
    InitializeComponent();
    Console.WriteLine($"{nameof(Form)}.{nameof(Form)}: done");
  }
}

启动后,应用会显示一次表单,然后显示一个消息框。

控制台输出为:

Form.Form: start
Form.Form: done
Provider.Run: form was opened for 1159 ms
Form.Form: start
Form.Form: done
Provider.Run: form was opened for 0 ms

如您所见,表单第二次启动,没有例外,但会立即关闭。

我将感谢您在这件事上的帮助。谢谢!

C# WPF Net-4.8

评论


答:

0赞 emoacht 11/12/2023 #1

检查 Application.ShutdownMode。默认值为 OnLastWindowClose,因此应用程序将在第一个窗口关闭时关闭。如果要使应用程序保持运行,请将其更改为 OnExplicitShutdown。

它与从单独的程序集加载 Window 无关。