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
相关产品推荐
相关产品推荐

