-
Notifications
You must be signed in to change notification settings - Fork 15
fix: stabilize PPT slideshow state sync on transient COM states #394
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -67,6 +67,7 @@ public bool IsConnected | |
| private readonly object _lockObject = new object(); | ||
| private bool _disposed; | ||
| private static bool IsPptBusyHResult(uint hr) => hr == 0x80010001 || hr == 0x8001010A; | ||
| private static bool IsNoActivePresentationOrWindowHResult(uint hr) => hr == 0x80048240; | ||
| #endregion | ||
|
|
||
| #region Constructor & Initialization | ||
|
|
@@ -537,7 +538,7 @@ private void SafeReleaseComObject(object comObject, string objectName) | |
| } | ||
| } | ||
|
|
||
| private void UpdateCurrentPresentationInfo() | ||
| private void UpdateCurrentPresentationInfo(bool preferSlideShowWindow = false, SlideShowWindow knownSlideShowWindow = null) | ||
| { | ||
| object activePresentation = null; | ||
| object slideShowWindows = null; | ||
|
|
@@ -553,7 +554,7 @@ private void UpdateCurrentPresentationInfo() | |
| { | ||
| try | ||
| { | ||
| activePresentation = PPTApplication.ActivePresentation; | ||
| activePresentation = TryGetActivePresentation(knownSlideShowWindow); | ||
| if (activePresentation != null) | ||
| { | ||
| SafeReleaseComObject(CurrentPresentation, "CurrentPresentation"); | ||
|
|
@@ -583,21 +584,30 @@ private void UpdateCurrentPresentationInfo() | |
| try | ||
| { | ||
| slideShowWindows = PPTApplication.SlideShowWindows; | ||
| if (IsInSlideShow && slideShowWindows != null) | ||
| var shouldUseSlideShowWindow = preferSlideShowWindow || IsInSlideShow; | ||
| if (shouldUseSlideShowWindow && slideShowWindows != null) | ||
| { | ||
| dynamic ssw = slideShowWindows; | ||
| if (ssw.Count > 0) | ||
| if (knownSlideShowWindow != null) | ||
| { | ||
| slideShowWindow = ssw[1]; | ||
| if (slideShowWindow != null) | ||
| slideShowWindow = knownSlideShowWindow; | ||
| } | ||
| else | ||
| { | ||
| dynamic ssw = slideShowWindows; | ||
| if (ssw.Count > 0) | ||
| { | ||
| dynamic sswObj = slideShowWindow; | ||
| view = sswObj.View; | ||
| if (view != null) | ||
| { | ||
| dynamic viewObj = view; | ||
| slideShowWindow = ssw[1]; | ||
| } | ||
| } | ||
|
|
||
| if (slideShowWindow != null) | ||
| { | ||
| dynamic sswObj = slideShowWindow; | ||
| view = sswObj.View; | ||
| if (view != null) | ||
| { | ||
| dynamic viewObj = view; | ||
| CurrentSlide = viewObj.Slide as Slide; | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
@@ -633,7 +643,7 @@ private void UpdateCurrentPresentationInfo() | |
| catch (COMException comEx) | ||
| { | ||
| var hr = (uint)comEx.HResult; | ||
| if (hr != 0x8001010E && hr != 0x80004005) | ||
| if (hr != 0x8001010E && hr != 0x80004005 && !IsNoActivePresentationOrWindowHResult(hr)) | ||
| { | ||
| LogHelper.WriteLogToFile($"获取当前幻灯片失败: {comEx.Message}", LogHelper.LogType.Warning); | ||
| } | ||
|
|
@@ -655,7 +665,7 @@ private void UpdateCurrentPresentationInfo() | |
| catch (COMException comEx) | ||
| { | ||
| var hr = (uint)comEx.HResult; | ||
| if (hr == 0x8001010E || hr == 0x80004005) | ||
| if (hr == 0x8001010E || hr == 0x80004005 || IsNoActivePresentationOrWindowHResult(hr)) | ||
| { | ||
| CurrentPresentation = null; | ||
| CurrentSlides = null; | ||
|
|
@@ -698,6 +708,61 @@ private void UpdateCurrentPresentationInfo() | |
| } | ||
| } | ||
| } | ||
|
|
||
| private object TryGetActivePresentation(SlideShowWindow knownSlideShowWindow) | ||
| { | ||
| try | ||
| { | ||
| return PPTApplication.ActivePresentation; | ||
| } | ||
| catch (COMException comEx) | ||
| { | ||
| var hr = (uint)comEx.HResult; | ||
| if (!IsNoActivePresentationOrWindowHResult(hr)) | ||
| { | ||
| throw; | ||
| } | ||
| } | ||
|
|
||
| try | ||
| { | ||
| if (knownSlideShowWindow != null) | ||
| { | ||
| return knownSlideShowWindow.Presentation; | ||
| } | ||
|
|
||
| var slideShowWindows = PPTApplication.SlideShowWindows; | ||
| if (slideShowWindows == null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| dynamic ssw = slideShowWindows; | ||
| if (ssw.Count == 0) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| var slideShowWindow = ssw[1]; | ||
| if (slideShowWindow == null) | ||
| { | ||
| return null; | ||
| } | ||
|
|
||
| dynamic sswObj = slideShowWindow; | ||
| return sswObj.Presentation; | ||
|
Comment on lines
+752
to
+753
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
The fallback path in Useful? React with 👍 / 👎. |
||
| } | ||
| catch (COMException comEx) | ||
| { | ||
| var hr = (uint)comEx.HResult; | ||
| if (!IsNoActivePresentationOrWindowHResult(hr)) | ||
| { | ||
| throw; | ||
| } | ||
| } | ||
|
|
||
| return null; | ||
| } | ||
| #endregion | ||
|
|
||
| #region Event Handlers | ||
|
|
@@ -734,7 +799,7 @@ private void OnSlideShowBegin(SlideShowWindow wn) | |
| _cachedIsInSlideShow = true; | ||
| try | ||
| { | ||
| UpdateCurrentPresentationInfo(); | ||
| UpdateCurrentPresentationInfo(preferSlideShowWindow: true, knownSlideShowWindow: wn); | ||
| SlideShowBegin?.Invoke(wn); | ||
| } | ||
| catch (Exception ex) | ||
|
|
@@ -747,7 +812,7 @@ private void OnSlideShowNextSlide(SlideShowWindow wn) | |
| { | ||
| try | ||
| { | ||
| UpdateCurrentPresentationInfo(); | ||
| UpdateCurrentPresentationInfo(preferSlideShowWindow: true, knownSlideShowWindow: wn); | ||
| SlideShowNextSlide?.Invoke(wn); | ||
| } | ||
| catch (Exception ex) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When
knownSlideShowWindowis provided, this branch stores the caller-owned event argument inslideShowWindow, andUpdateCurrentPresentationInfolater callsSafeReleaseComObject(slideShowWindow)infinally. InOnSlideShowBegin/OnSlideShowNextSlide, that meanswncan be released beforeSlideShowBegin?.Invoke(wn)orSlideShowNextSlide?.Invoke(wn), so handlers that access COM members likewn.Viewmay hitInvalidComObjectExceptionduring normal slideshow events.Useful? React with 👍 / 👎.