You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

ClickOnce应用更新后变更日志无法显示的问题求助

ClickOnce更新完成后无法触发变更日志显示的问题

我基于WPF和.NET 4.8开发ClickOnce应用,目前应用运行正常,更新通知功能正常,但实现更新完成后自动弹出变更日志时遇到问题。

我尝试订阅UpdateCompleted事件,在事件处理程序中调用MainWindow的ShowChangelog()方法,但该方法并未生效。


相关代码

App.xaml.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Deployment.Application;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace internaltesting
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);

            // Subscribe to the UpdateCompleted event
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                ApplicationDeployment.CurrentDeployment.UpdateCompleted += UpdateCompletedEventHandler;
            }
        }

        private void UpdateCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
        {
            if (e.Error == null)
            {
                Application.Current.Dispatcher.Invoke(() =>
                {
                    if(Application.Current.MainWindow is  MainWindow mainWindow)
                    {
                        mainWindow.ShowChangelog();
                    }
                });
            }
        }
    }
}

MainWindow.xaml.cs

public void ShowChangelog()
{
    changelogRichTextBox.Visibility = Visibility.Visible;
    okayButton.Visibility = Visibility.Visible;
}
private void UpdatesButton_Click(object sender, RoutedEventArgs e)
{
    var contextMenu = new ContextMenu();
    
    var menuItemLatestUpdates = new MenuItem { Header = "Latest Updates" };
    
    menuItemLatestUpdates.Click += LatestUpdates_Click;
    menuItemLatestUpdates.Cursor = Cursors.Hand;
    
    contextMenu.Items.Add(menuItemLatestUpdates);

    contextMenu.IsOpen = true;
}

private void LatestUpdates_Click(object sender, RoutedEventArgs e)
{
    try
    {
        ShowChangelog();
    }
    catch (Exception ex)
    {
        MessageBox.Show("Error reading changelog: " + ex.Message, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
    }
}

private void OkayButton_Click(object sender, RoutedEventArgs e)
{
    changelogRichTextBox.Visibility = Visibility.Collapsed;
    okayButton.Visibility = Visibility.Collapsed;
}

MainWindow.xaml

<Button Content="Updates" Click="UpdatesButton_Click" Cursor="Hand"  HorizontalAlignment="Left"  VerticalAlignment="Top" Margin="540,0,0,0" Width="100" >
    <Button.ContextMenu>
        <ContextMenu>
            <MenuItem Header="Latest Updates" Click="LatestUpdates_Click" Cursor="Hand" />
        </ContextMenu>
    </Button.ContextMenu>
</Button>

<Grid>
    <RichTextBox x:Name="changelogRichTextBox" HorizontalAlignment="Stretch" VerticalAlignment="Center" Width="450" Height="300" Visibility="Collapsed" >
        <FlowDocument>
            <Paragraph>
                <!-- Use Inlines to style the content -->
                <Bold FontSize="20">Changelog</Bold>
            </Paragraph>
            <Paragraph>
                <Bold FontSize="16">Version 1.0.0.4</Bold>
            </Paragraph>
            <Paragraph>
                <Bold>Modifications:</Bold>
            </Paragraph>
            <List MarkerStyle="Disc">
                <ListItem>
                    <Paragraph>Added Initialize button and Force initalize button.</Paragraph>
                </ListItem>
                <ListItem>
                    <Paragraph>Show Dialog with changes made on the program.</Paragraph>
                </ListItem>
                <ListItem>
                    <Paragraph>Added a few new sale commands.</Paragraph>
                </ListItem>
                <ListItem>
                    <Paragraph>Added a feedback Textbox.</Paragraph>
                </ListItem>
            </List>
            <Paragraph>
                <Bold>Bug Fixes:</Bold>
            </Paragraph>
            <List MarkerStyle="Disc">
                <ListItem>
                    <Paragraph>Fixed the ebtsf and ebtw ref number not auto generating after completing sale.</Paragraph>
                </ListItem>
            </List>
        </FlowDocument>
    </RichTextBox>

    <Button x:Name="okayButton" Content="Okay" HorizontalAlignment="Center" VerticalAlignment="Bottom" Margin="0,165" Click="OkayButton_Click" Width="50" Background="Silver"  Cursor="Hand" Visibility="Collapsed"/>
</Grid>
</Grid>

问题排查与解决方案

1. 验证UpdateCompleted事件是否触发

ClickOnce的UpdateCompleted事件仅在主动调用UpdateAsync()或用户通过内置提示完成更新时触发。如果是静默更新或未显式触发更新逻辑,事件不会执行。

临时在事件处理程序开头加验证:

private void UpdateCompletedEventHandler(object sender, AsyncCompletedEventArgs e)
{
    MessageBox.Show("UpdateCompleted事件已触发"); // 验证用,之后可删除
    // 原有代码
}

2. 确保MainWindow已完成初始化

OnStartup阶段MainWindow可能未完全加载,导致Application.Current.MainWindow为空。改为在MainWindow的Loaded事件中订阅更新事件:

修改MainWindow.xaml.cs:

protected override void OnLoaded(RoutedEventArgs e)
{
    base.OnLoaded(e);
    if (ApplicationDeployment.IsNetworkDeployed)
    {
        ApplicationDeployment.CurrentDeployment.UpdateCompleted += (s, args) =>
        {
            if (args.Error == null)
            {
                ShowChangelog();
            }
        };
    }
}

3. 检查UI元素父容器状态

确认changelogRichTextBox和okayButton所在的父Grid未被设置为Collapsed/Hidden,或被其他元素遮挡。可在ShowChangelog()中同步设置父容器可见性:

public void ShowChangelog()
{
    // 假设父Grid的x:Name为changelogGrid
    changelogGrid.Visibility = Visibility.Visible;
    changelogRichTextBox.Visibility = Visibility.Visible;
    okayButton.Visibility = Visibility.Visible;
}

4. 处理更新后重启的场景

如果更新完成后应用自动重启,UpdateCompleted事件是在旧版本进程中触发的,新版本启动后不会执行该逻辑。此时可在新版本启动时检查是否为更新后首次运行:

修改App.xaml.cs的OnStartup:

protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    if (ApplicationDeployment.IsNetworkDeployed)
    {
        var currentDeployment = ApplicationDeployment.CurrentDeployment;
        // 判断是否为更新后首次启动
        if (currentDeployment.IsFirstRun)
        {
            Application.Current.Dispatcher.Invoke(() =>
            {
                if (Application.Current.MainWindow is MainWindow mainWindow)
                {
                    mainWindow.ShowChangelog();
                }
            });
        }
    }
}

5. 优化Dispatcher调用

将Dispatcher.Invoke改为BeginInvoke并指定优先级,确保UI线程正确处理:

Application.Current.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal, () =>
{
    if(Application.Current.MainWindow is MainWindow mainWindow)
    {
        mainWindow.ShowChangelog();
    }
});

内容的提问来源于stack exchange,提问作者Moshe

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 21:08:10