Files
community/Ink Canvas/Helpers/COMPPTManager.cs
T
2026-02-06 16:38:33 +08:00

1257 lines
46 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using Microsoft.Office.Interop.PowerPoint;
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Timers;
using System.Windows.Threading;
using Application = System.Windows.Application;
using Timer = System.Timers.Timer;
namespace Ink_Canvas.Helpers
{
/// <summary>
/// 基于 COM 的 PPT 联动管理器
/// </summary>
public class ComPPTManager : IPPTLinkManager
{
#region Events
public event Action<object> SlideShowBegin;
public event Action<object> SlideShowNextSlide;
public event Action<object> SlideShowEnd;
public event Action<object> PresentationOpen;
public event Action<object> PresentationClose;
public event Action<bool> PPTConnectionChanged;
public event Action<bool> SlideShowStateChanged;
#endregion
#region Properties
public Microsoft.Office.Interop.PowerPoint.Application PPTApplication { get; private set; }
object IPPTLinkManager.PPTApplication => PPTApplication;
public Presentation CurrentPresentation { get; private set; }
public Slides CurrentSlides { get; private set; }
public Slide CurrentSlide { get; private set; }
public int SlidesCount { get; private set; }
public bool IsConnected
{
get
{
try
{
if (PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false;
// 尝试访问一个简单的属性来验证连接是否有效
var _ = PPTApplication.Name;
return true;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
// 如果COM对象已失效,返回false
if (hr == 0x8001010E || hr == 0x80004005 || hr == 0x800706B5)
{
return false;
}
return false;
}
catch
{
return false;
}
}
}
public bool IsInSlideShow
{
get
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
try
{
if (PPTApplication == null || !Marshal.IsComObject(PPTApplication)) return false;
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows == null) return false;
dynamic ssw = slideShowWindows;
if (ssw.Count == 0) return false;
try
{
slideShowWindow = ssw[1];
if (slideShowWindow == null) return false;
dynamic sswObj = slideShowWindow;
view = sswObj.View;
if (view == null) return false;
return true;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
return false;
}
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"检查PPT放映状态失败: {comEx.Message} (HR: 0x{hr:X8})", LogHelper.LogType.Warning);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"检查PPT放映状态时发生意外错误: {ex}", LogHelper.LogType.Warning);
return false;
}
finally
{
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
}
/// <summary>
/// 是否尝试支持 WPS(通过 COM 接口 kwpp.Application
/// </summary>
public bool IsSupportWPS { get; set; } = false;
#endregion
#region Private Fields
private Timer _connectionCheckTimer;
private Timer _slideShowStateCheckTimer;
private bool _isModuleUnloading = false;
private bool _lastSlideShowState;
private readonly object _lockObject = new object();
private bool _disposed;
#endregion
#region Constructor & Initialization
public ComPPTManager()
{
InitializeConnectionTimer();
}
private void InitializeConnectionTimer()
{
_connectionCheckTimer = new Timer(500);
_connectionCheckTimer.Elapsed += OnConnectionCheckTimerElapsed;
_connectionCheckTimer.AutoReset = true;
_slideShowStateCheckTimer = new Timer(1000);
_slideShowStateCheckTimer.Elapsed += OnSlideShowStateCheckTimerElapsed;
_slideShowStateCheckTimer.AutoReset = true;
}
public void StartMonitoring()
{
if (!_disposed)
{
_connectionCheckTimer?.Start();
_slideShowStateCheckTimer?.Start();
LogHelper.WriteLogToFile("ComPPTManager: PPT监控已启动", LogHelper.LogType.Trace);
}
}
public void StopMonitoring()
{
_connectionCheckTimer?.Stop();
_slideShowStateCheckTimer?.Stop();
DisconnectFromPPT();
LogHelper.WriteLogToFile("ComPPTManager: PPT监控已停止", LogHelper.LogType.Trace);
}
#endregion
#region Connection Management
private void OnConnectionCheckTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
if (!_isModuleUnloading)
{
CheckAndConnectToPPT();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: PPT连接检查失败: {ex}", LogHelper.LogType.Error);
}
}
private void OnSlideShowStateCheckTimerElapsed(object sender, ElapsedEventArgs e)
{
try
{
if (!_isModuleUnloading && IsConnected)
{
CheckSlideShowState();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: PPT放映状态检查失败: {ex}", LogHelper.LogType.Error);
}
}
private void CheckAndConnectToPPT()
{
if (_isModuleUnloading) return;
lock (_lockObject)
{
try
{
if (_isModuleUnloading) return;
// 尝试连接到PowerPoint
var pptApp = TryConnectToPowerPoint();
if (pptApp == null && IsSupportWPS)
{
// 如果PowerPoint连接失败且支持WPS,尝试连接WPS
pptApp = TryConnectToWPS();
}
if (pptApp != null && !IsConnected)
{
// 有可用的PPT/WPS应用程序且当前未连接,建立连接
ConnectToPPT(pptApp);
}
else if (pptApp == null && IsConnected)
{
// 没有可用的PPT/WPS应用程序但当前显示已连接,断开连接
DisconnectFromPPT();
}
else if (pptApp == null && PPTApplication != null)
{
// PPT/WPS应用程序不可用但PPTApplication对象仍存在,清理无效连接
DisconnectFromPPT();
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: PPT连接检查异常: {ex}", LogHelper.LogType.Error);
if (PPTApplication != null)
{
DisconnectFromPPT();
}
}
}
}
private void CheckSlideShowState()
{
try
{
if (!IsConnected) return;
var currentSlideShowState = IsInSlideShow;
if (currentSlideShowState != _lastSlideShowState)
{
_lastSlideShowState = currentSlideShowState;
SlideShowStateChanged?.Invoke(currentSlideShowState);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 检查PPT放映状态异常: {ex}", LogHelper.LogType.Error);
}
}
private Microsoft.Office.Interop.PowerPoint.Application TryConnectToPowerPoint()
{
try
{
var pptApp = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("PowerPoint.Application");
if (pptApp != null && Marshal.IsComObject(pptApp))
{
var _ = pptApp.Name;
return pptApp;
}
return null;
}
catch
{
return null;
}
}
private Microsoft.Office.Interop.PowerPoint.Application TryConnectToWPS()
{
try
{
var wpsApp = (Microsoft.Office.Interop.PowerPoint.Application)Marshal.GetActiveObject("kwpp.Application");
if (wpsApp != null && Marshal.IsComObject(wpsApp))
{
var _ = wpsApp.Name;
return wpsApp;
}
return null;
}
catch
{
return null;
}
}
private void ConnectToPPT(Microsoft.Office.Interop.PowerPoint.Application pptApp)
{
try
{
PPTApplication = pptApp;
// 在主线程中注册事件,确保COM对象在正确的线程中
Application.Current?.Dispatcher?.Invoke(() =>
{
try
{
PPTApplication.PresentationOpen += OnPresentationOpen;
PPTApplication.PresentationClose += OnPresentationClose;
PPTApplication.SlideShowBegin += OnSlideShowBegin;
PPTApplication.SlideShowNextSlide += OnSlideShowNextSlide;
PPTApplication.SlideShowEnd += OnSlideShowEnd;
LogHelper.WriteLogToFile("ComPPTManager: PPT事件注册成功", LogHelper.LogType.Trace);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: PPT事件注册失败: {ex}", LogHelper.LogType.Error);
throw; // 重新抛出异常,让外层处理
}
}, DispatcherPriority.Normal, default, TimeSpan.FromSeconds(2));
// 获取当前演示文稿信息
UpdateCurrentPresentationInfo();
// 停止连接检查定时器,避免重复连接
_connectionCheckTimer?.Stop();
// 触发连接成功事件
PPTConnectionChanged?.Invoke(true);
LogHelper.WriteLogToFile("ComPPTManager: 成功连接到PPT应用程序", LogHelper.LogType.Event);
if (IsInSlideShow && PPTApplication.SlideShowWindows.Count > 0)
{
OnSlideShowBegin(PPTApplication.SlideShowWindows[1]);
}
else if (CurrentPresentation != null)
{
OnPresentationOpen(CurrentPresentation);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 连接PPT应用程序失败: {ex}", LogHelper.LogType.Error);
PPTApplication = null;
}
}
private void DisconnectFromPPT()
{
try
{
if (PPTApplication != null)
{
// 取消事件注册
try
{
if (Marshal.IsComObject(PPTApplication))
{
Application.Current?.Dispatcher?.Invoke(() =>
{
try
{
PPTApplication.PresentationOpen -= OnPresentationOpen;
PPTApplication.PresentationClose -= OnPresentationClose;
PPTApplication.SlideShowBegin -= OnSlideShowBegin;
PPTApplication.SlideShowNextSlide -= OnSlideShowNextSlide;
PPTApplication.SlideShowEnd -= OnSlideShowEnd;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 取消PPT事件注册时发生异常: {ex}", LogHelper.LogType.Warning);
}
}, DispatcherPriority.Normal, default, TimeSpan.FromSeconds(1));
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 取消PPT事件注册失败: {ex}", LogHelper.LogType.Warning);
}
SafeReleaseComObject(CurrentSlide);
SafeReleaseComObject(CurrentSlides);
SafeReleaseComObject(CurrentPresentation);
if (PPTApplication != null && Marshal.IsComObject(PPTApplication))
{
try
{
Marshal.FinalReleaseComObject(PPTApplication);
}
catch
{
try
{
int refCount = Marshal.ReleaseComObject(PPTApplication);
while (refCount > 0)
{
refCount = Marshal.ReleaseComObject(PPTApplication);
}
}
catch { }
}
}
}
PPTApplication = null;
CurrentPresentation = null;
CurrentSlides = null;
CurrentSlide = null;
SlidesCount = 0;
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
_isModuleUnloading = true;
_connectionCheckTimer?.Stop();
_slideShowStateCheckTimer?.Stop();
// 触发连接断开事件
PPTConnectionChanged?.Invoke(false);
LogHelper.WriteLogToFile("ComPPTManager: 已断开PPT连接", LogHelper.LogType.Event);
ThreadPool.QueueUserWorkItem(_ =>
{
try
{
Thread.Sleep(2000);
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Thread.Sleep(1000);
_isModuleUnloading = false;
_connectionCheckTimer?.Start();
_slideShowStateCheckTimer?.Start();
LogHelper.WriteLogToFile("ComPPTManager: PPT联动模块已重新加载", LogHelper.LogType.Trace);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 重新加载PPT联动模块失败: {ex}", LogHelper.LogType.Error);
_isModuleUnloading = false;
}
});
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 断开PPT连接失败: {ex}", LogHelper.LogType.Error);
_isModuleUnloading = false;
}
}
private void SafeReleaseComObject(object comObject)
{
try
{
if (comObject != null && Marshal.IsComObject(comObject))
{
Marshal.ReleaseComObject(comObject);
}
}
catch { }
}
private void UpdateCurrentPresentationInfo()
{
object activePresentation = null;
object slideShowWindows = null;
object slideShowWindow = null;
object activeWindow = null;
object view = null;
object selection = null;
object slideRange = null;
try
{
if (PPTApplication != null && Marshal.IsComObject(PPTApplication))
{
try
{
activePresentation = PPTApplication.ActivePresentation;
if (activePresentation != null)
{
SafeReleaseComObject(CurrentPresentation);
CurrentPresentation = activePresentation as Presentation;
CurrentSlides = CurrentPresentation.Slides;
try
{
var slideCount = CurrentSlides.Count;
SlidesCount = slideCount > 0 ? slideCount : 0;
}
catch
{
SlidesCount = 0;
}
try
{
slideShowWindows = PPTApplication.SlideShowWindows;
if (IsInSlideShow && slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
if (ssw.Count > 0)
{
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
CurrentSlide = viewObj.Slide as Slide;
}
}
}
}
else
{
activeWindow = PPTApplication.ActiveWindow;
if (activeWindow != null)
{
dynamic aw = activeWindow;
selection = aw.Selection;
if (selection != null)
{
dynamic sel = selection;
slideRange = sel.SlideRange;
if (slideRange != null)
{
dynamic sr = slideRange;
int slideNumber = sr.SlideNumber;
if (slideNumber > 0 && slideNumber <= SlidesCount)
{
CurrentSlide = CurrentSlides[slideNumber];
}
}
}
}
if (CurrentSlide == null && SlidesCount > 0)
{
CurrentSlide = CurrentSlides[1];
}
}
}
catch
{
if (SlidesCount > 0)
{
CurrentSlide = CurrentSlides[1];
}
}
}
else
{
CurrentPresentation = null;
CurrentSlides = null;
CurrentSlide = null;
SlidesCount = 0;
}
}
catch
{
CurrentPresentation = null;
CurrentSlides = null;
CurrentSlide = null;
SlidesCount = 0;
}
}
else
{
CurrentPresentation = null;
CurrentSlides = null;
CurrentSlide = null;
SlidesCount = 0;
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 更新演示文稿信息失败: {ex}", LogHelper.LogType.Error);
CurrentPresentation = null;
CurrentSlides = null;
CurrentSlide = null;
SlidesCount = 0;
}
finally
{
SafeReleaseComObject(slideRange);
SafeReleaseComObject(selection);
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(activeWindow);
SafeReleaseComObject(slideShowWindows);
if (activePresentation != null && !ReferenceEquals(activePresentation, CurrentPresentation))
{
SafeReleaseComObject(activePresentation);
}
}
}
#endregion
#region Event Handlers
private void OnPresentationOpen(Presentation pres)
{
try
{
UpdateCurrentPresentationInfo();
PresentationOpen?.Invoke(pres);
LogHelper.WriteLogToFile($"ComPPTManager: 演示文稿已打开: {pres?.Name}", LogHelper.LogType.Event);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 处理演示文稿打开事件失败: {ex}", LogHelper.LogType.Error);
}
}
private void OnPresentationClose(Presentation pres)
{
try
{
PresentationClose?.Invoke(pres);
DisconnectFromPPT();
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 处理演示文稿关闭事件失败: {ex}", LogHelper.LogType.Error);
}
}
private void OnSlideShowBegin(SlideShowWindow wn)
{
try
{
UpdateCurrentPresentationInfo();
SlideShowBegin?.Invoke(wn);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 处理幻灯片放映开始事件失败: {ex}", LogHelper.LogType.Error);
}
}
private void OnSlideShowNextSlide(SlideShowWindow wn)
{
try
{
UpdateCurrentPresentationInfo();
SlideShowNextSlide?.Invoke(wn);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 处理幻灯片切换事件失败: {ex}", LogHelper.LogType.Error);
}
}
private void OnSlideShowEnd(Presentation pres)
{
try
{
SlideShowEnd?.Invoke(pres);
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"处理幻灯片放映结束事件失败: {ex}", LogHelper.LogType.Error);
}
}
#endregion
#region Public Navigation APIs
public bool TryNavigateToSlide(int slideNumber)
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
object windows = null;
object window = null;
object windowView = null;
try
{
if (!IsConnected || PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false;
if (IsInSlideShow)
{
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
if (ssw.Count >= 1)
{
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
viewObj.GotoSlide(slideNumber);
return true;
}
}
}
}
}
else if (CurrentPresentation != null)
{
windows = CurrentPresentation.Windows;
if (windows != null)
{
dynamic win = windows;
if (win.Count >= 1)
{
window = win[1];
if (window != null)
{
dynamic winObj = window;
windowView = winObj.View;
if (windowView != null)
{
dynamic viewObj = windowView;
viewObj.GotoSlide(slideNumber);
return true;
}
}
}
}
}
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 跳转到幻灯片{slideNumber}失败: {comEx.Message}", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 跳转到幻灯片{slideNumber}失败: {ex}", LogHelper.LogType.Error);
return false;
}
finally
{
SafeReleaseComObject(windowView);
SafeReleaseComObject(window);
SafeReleaseComObject(windows);
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
public bool TryNavigateNext()
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
try
{
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false;
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
sswObj.Activate();
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
viewObj.Next();
return true;
}
}
}
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 切换到下一页失败: {comEx.Message}", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 切换到下一页失败: {ex}", LogHelper.LogType.Error);
return false;
}
finally
{
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
public bool TryNavigatePrevious()
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
try
{
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false;
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
sswObj.Activate();
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
viewObj.Previous();
return true;
}
}
}
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 切换到上一页失败: {comEx.Message}", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 切换到上一页失败: {ex}", LogHelper.LogType.Error);
return false;
}
finally
{
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
public bool TryEndSlideShow()
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
try
{
if (!IsConnected || !IsInSlideShow || PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication)) return false;
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
viewObj.Exit();
return true;
}
}
}
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 结束幻灯片放映失败: {comEx.Message}", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 结束幻灯片放映失败: {ex}", LogHelper.LogType.Error);
return false;
}
finally
{
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
public bool TryStartSlideShow()
{
try
{
if (!IsConnected || CurrentPresentation == null || PPTApplication == null) return false;
if (!Marshal.IsComObject(PPTApplication) || !Marshal.IsComObject(CurrentPresentation)) return false;
CurrentPresentation.SlideShowSettings.Run();
return true;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 开始幻灯片放映失败: {comEx.Message}", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 开始幻灯片放映失败: {ex}", LogHelper.LogType.Error);
return false;
}
}
public object GetCurrentActivePresentation()
{
try
{
if (!IsConnected || PPTApplication == null) return null;
if (!Marshal.IsComObject(PPTApplication)) return null;
if (IsInSlideShow && PPTApplication.SlideShowWindows.Count > 0)
{
try
{
var slideShowWindow = PPTApplication.SlideShowWindows[1];
if (slideShowWindow?.View != null)
{
return (Presentation)slideShowWindow.View.Slide.Parent;
}
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x80048240)
{
return null;
}
throw;
}
}
if (PPTApplication.ActiveWindow?.Presentation != null)
{
return PPTApplication.ActiveWindow.Presentation;
}
return CurrentPresentation;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 获取当前活跃演示文稿失败: {comEx.Message}", LogHelper.LogType.Warning);
return CurrentPresentation;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 获取当前活跃演示文稿失败: {ex}", LogHelper.LogType.Error);
return CurrentPresentation;
}
}
public int GetCurrentSlideNumber()
{
object slideShowWindows = null;
object slideShowWindow = null;
object view = null;
object activeWindow = null;
object selection = null;
object slideRange = null;
try
{
if (!IsConnected || PPTApplication == null) return 0;
if (!Marshal.IsComObject(PPTApplication)) return 0;
if (IsInSlideShow)
{
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
if (ssw.Count > 0)
{
slideShowWindow = ssw[1];
if (slideShowWindow != null)
{
dynamic sswObj = slideShowWindow;
view = sswObj.View;
if (view != null)
{
dynamic viewObj = view;
return viewObj.CurrentShowPosition;
}
}
}
}
}
activeWindow = PPTApplication.ActiveWindow;
if (activeWindow != null)
{
dynamic aw = activeWindow;
selection = aw.Selection;
if (selection != null)
{
dynamic sel = selection;
slideRange = sel.SlideRange;
if (slideRange != null)
{
dynamic sr = slideRange;
int slideNumber = sr.SlideNumber;
if (slideNumber > 0)
{
return slideNumber;
}
}
}
}
if (CurrentSlide != null && Marshal.IsComObject(CurrentSlide))
{
return CurrentSlide.SlideNumber;
}
return 0;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
return 0;
}
catch
{
return 0;
}
finally
{
SafeReleaseComObject(slideRange);
SafeReleaseComObject(selection);
SafeReleaseComObject(view);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
SafeReleaseComObject(activeWindow);
}
}
public string GetPresentationName()
{
try
{
if (CurrentPresentation == null || !Marshal.IsComObject(CurrentPresentation)) return "";
return CurrentPresentation.Name ?? "";
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 获取演示文稿名称失败: {comEx.Message}", LogHelper.LogType.Warning);
return "";
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 获取演示文稿名称失败: {ex}", LogHelper.LogType.Error);
return "";
}
}
public string GetPresentationPath()
{
try
{
if (CurrentPresentation == null || !Marshal.IsComObject(CurrentPresentation)) return "";
return CurrentPresentation.FullName ?? "";
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 获取演示文稿路径失败: {comEx.Message}", LogHelper.LogType.Warning);
return "";
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 获取演示文稿路径失败: {ex}", LogHelper.LogType.Error);
return "";
}
}
public bool TryShowSlideNavigation()
{
object slideShowWindows = null;
object slideShowWindow = null;
object slideNavigation = null;
try
{
LogHelper.WriteLogToFile($"ComPPTManager: 尝试显示幻灯片导航 - 连接状态: {IsConnected}, 放映状态: {IsInSlideShow}", LogHelper.LogType.Trace);
if (!IsConnected || !IsInSlideShow || PPTApplication == null)
{
LogHelper.WriteLogToFile("ComPPTManager: PPT未连接或未在放映状态", LogHelper.LogType.Warning);
return false;
}
if (!Marshal.IsComObject(PPTApplication))
{
LogHelper.WriteLogToFile("ComPPTManager: PPT应用程序COM对象无效", LogHelper.LogType.Warning);
return false;
}
slideShowWindows = PPTApplication.SlideShowWindows;
if (slideShowWindows != null)
{
dynamic ssw = slideShowWindows;
slideShowWindow = ssw[1];
if (slideShowWindow == null)
{
LogHelper.WriteLogToFile("ComPPTManager: 幻灯片放映窗口为空", LogHelper.LogType.Warning);
return false;
}
try
{
dynamic sswObj = slideShowWindow;
slideNavigation = sswObj.SlideNavigation;
if (slideNavigation != null)
{
dynamic sn = slideNavigation;
sn.Visible = true;
LogHelper.WriteLogToFile("ComPPTManager: 成功显示幻灯片导航(PowerPoint模式)", LogHelper.LogType.Event);
return true;
}
LogHelper.WriteLogToFile("ComPPTManager: SlideNavigation对象为空,可能是WPS不支持此功能", LogHelper.LogType.Warning);
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x80020006)
{
LogHelper.WriteLogToFile("ComPPTManager: WPS不支持SlideNavigation功能", LogHelper.LogType.Warning);
return false;
}
throw;
}
}
return false;
}
catch (COMException comEx)
{
var hr = (uint)comEx.HResult;
if (hr == 0x8001010E || hr == 0x80004005)
{
DisconnectFromPPT();
}
LogHelper.WriteLogToFile($"ComPPTManager: 显示幻灯片导航COM异常: {comEx.Message} (HRESULT: 0x{hr:X8})", LogHelper.LogType.Error);
return false;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ComPPTManager: 显示幻灯片导航失败: {ex}", LogHelper.LogType.Error);
return false;
}
finally
{
SafeReleaseComObject(slideNavigation);
SafeReleaseComObject(slideShowWindow);
SafeReleaseComObject(slideShowWindows);
}
}
#endregion
#region Dispose
public void Dispose()
{
if (!_disposed)
{
StopMonitoring();
_connectionCheckTimer?.Dispose();
_slideShowStateCheckTimer?.Dispose();
_disposed = true;
}
}
#endregion
}
}