using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using System.Text;
namespace Ink_Canvas.Helpers
{
public static class PPTROTConnectionHelper
{
#region Win32 API Declarations
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
[DllImport("user32.dll")]
private static extern IntPtr GetForegroundWindow();
[DllImport("user32.dll")]
private static extern int GetWindowText(IntPtr hWnd, StringBuilder lpString, int nMaxCount);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
private static extern bool IsWindowVisible(IntPtr hWnd);
[DllImport("user32.dll")]
private static extern bool GetWindowRect(IntPtr hWnd, out RECT lpRect);
[StructLayout(LayoutKind.Sequential)]
private struct RECT
{
public int Left;
public int Top;
public int Right;
public int Bottom;
}
#endregion
#region Constants
private static readonly Guid PowerPointApplicationGuid = new Guid("91493441-5A91-11CF-8700-00AA0060263B");
private static readonly string[] PptLikeExtensions = new[]
{
".pptx", ".pptm", ".ppt",
".ppsx", ".ppsm", ".pps",
".potx", ".potm", ".pot",
".dps", ".dpt"
};
#endregion
#region Public Methods
public static Microsoft.Office.Interop.PowerPoint.Application TryConnectViaROT(bool isSupportWPS = false)
{
try
{
object bestApp = GetAnyActivePowerPoint(null, out int bestPriority, out _);
if (bestApp != null && bestPriority > 0)
{
try
{
Type appType = typeof(Microsoft.Office.Interop.PowerPoint.Application);
Microsoft.Office.Interop.PowerPoint.Application pptApp = null;
if (appType.IsInstanceOfType(bestApp))
{
pptApp = (Microsoft.Office.Interop.PowerPoint.Application)bestApp;
}
if (pptApp != null)
{
try
{
var nameObj = pptApp.GetType().InvokeMember("Name", BindingFlags.GetProperty, null, pptApp, null);
SafeReleaseComObject(nameObj);
return pptApp;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ROT 连接验证 Name 不可用(将依赖 SlideShowWindows): {ex.Message}", LogHelper.LogType.Warning);
return pptApp;
}
}
else
{
SafeReleaseComObject(bestApp);
}
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ROT 连接验证失败: {ex.Message}", LogHelper.LogType.Warning);
SafeReleaseComObject(bestApp);
}
}
else if (bestApp != null)
{
SafeReleaseComObject(bestApp);
}
try
{
var pptApp = (Microsoft.Office.Interop.PowerPoint.Application)OleActiveObject.GetActiveObject("PowerPoint.Application");
if (pptApp != null && Marshal.IsComObject(pptApp))
{
try
{
var _ = pptApp.Name;
}
catch (COMException)
{
}
return pptApp;
}
}
catch (COMException) { }
catch (InvalidCastException) { }
if (isSupportWPS)
{
try
{
var wpsApp = (Microsoft.Office.Interop.PowerPoint.Application)OleActiveObject.GetActiveObject("kwpp.Application");
if (wpsApp != null && Marshal.IsComObject(wpsApp))
{
try
{
var _ = wpsApp.Name;
}
catch (COMException)
{
}
return wpsApp;
}
}
catch (COMException) { }
catch (InvalidCastException) { }
}
return null;
}
catch (Exception ex)
{
LogHelper.WriteLogToFile($"ROT 连接过程发生异常: {ex}", LogHelper.LogType.Error);
return null;
}
}
#endregion
#region Public Methods
///
/// 在系统的运行对象表(ROT)中查找并返回最合适的正在运行的 PowerPoint 应用实例。
///
/// 可选的目标 PowerPoint COM 对象,用于优先比较;传入 null 表示不指定目标。
/// 输出参数:返回找到的最佳实例的优先级(0 表示未找到或无活动演示)。
/// 输出参数:返回与 对应实例的优先级(如果未提供或未命中则为 0)。
/// 最合适的 PowerPoint 应用对象(通常为 COM Application 实例),若未找到则返回 null。
public static object GetAnyActivePowerPoint(object targetApp, out int bestPriority, out int targetPriority)
{
IRunningObjectTable rot = null;
IEnumMoniker enumMoniker = null;
object bestApp = null;
bestPriority = 0;
targetPriority = 0;
int highestPriority = 0;
List