简介:
我正在尝试迭代ROT (运行对象表),并搜索COM对象的特定progID。在我的例子中,progID应该是Excel.Application。
例如,如果我有一个运行excel的实例,就会得到如下所示的Excel.Application:
Excel.Application excel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");问题:
如果我有多个实例正在运行,这个调用基本上会给出任何实例,并且我无法识别正确的实例(例如,通过窗口标题.)。因此,我需要一个特定的实例,它可以通过打开的Workbook或窗口标题来标识。
当前方法:
由于Marshal.GetActiveObject想要一个progID,所以我试着浏览一下ROT,并查找当前存在的所有progID:
public static void Main(string[] args)
{
if (GetRunningObjectTable(0, out IRunningObjectTable pprot) == 0)
{
pprot.EnumRunning(out IEnumMoniker ppenumMoniker);
ppenumMoniker.Reset();
var moniker = new IMoniker[1];
while (ppenumMoniker.Next(1, moniker, IntPtr.Zero) == 0)
{
CreateBindCtx(0, out IBindCtx ppbc);
pprot.GetObject(moniker[0], out object ppunkObject);
moniker[0].GetDisplayName(ppbc, null, out string ppszDisplayName);
moniker[0].GetClassID(out Guid pClassID);
ProgIDFromCLSID(ref pClassID, out string lplpszProgID);
}
}
// Excel excel = (Excel)Marshal.GetActiveObject("Excel.Application");
}我注意到以下几点:
ProgIDFromCLSID()给我打电话file或null。Type和GetType()中识别正确的ppunkObject。ppszDisplayName有时给我提供excel文档的路径,有时提供当前打开的工作簿的标题。问题:
progID?另外,如果有更简单的方法来识别我的实例,请告诉我。
附加代码:
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Excel = Microsoft.Office.Interop.Excel.Application;和
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot);
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
[DllImport("ole32.dll")]
private static extern int ProgIDFromCLSID([In] ref Guid clsid, [MarshalAs(UnmanagedType.LPWStr)] out string lplpszProgID);发布于 2018-03-22 14:11:08
解决方案:
似乎没有办法从ROT中获得适当的progID (而且也没有帮助,因为Excel.Application没有给出特定的实例)。但是,如果您知道文件的存储位置(路径的一部分似乎就足够了),这是可能的。
完整代码(工作示例):
// Microsoft.CSharp, 4.0.30319
// Microsoft.Office.Interop.Excel, 15.0.4420.1017
using System;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Excel = Microsoft.Office.Interop.Excel;
public static void Main(string[] args)
{
object ppunk = null;
if (GetRunningObjectTable(0, out IRunningObjectTable pprot) == 0)
{
pprot.EnumRunning(out IEnumMoniker ppenumMoniker);
ppenumMoniker.Reset();
var moniker = new IMoniker[1];
while (ppenumMoniker.Next(1, moniker, IntPtr.Zero) == 0)
{
CreateBindCtx(0, out IBindCtx ppbc);
moniker[0].GetDisplayName(ppbc, null, out string ppszDisplayName);
Marshal.ReleaseComObject(ppbc);
// Identify by worksheet path
if (ppszDisplayName.ToLower().Contains(".xls") && ppszDisplayName.ToLower().Contains("appdata"))
{
pprot.GetObject(moniker[0], out object ppunkObject);
ppunk = ppunkObject;
}
}
}
if (ppunk != null)
{
Excel.Workbook workbook = ppunk as Excel.Workbook;
Excel.Application excel = workbook.Application;
// Do something
dynamic title = workbook.FullName;
excel.Quit();
}
}
// https://msdn.microsoft.com/en-us/library/windows/desktop/ms684004(v=vs.85).aspx
[DllImport("ole32.dll")]
private static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable pprot);
// https://msdn.microsoft.com/de-de/library/windows/desktop/ms678542(v=vs.85).aspx
[DllImport("ole32.dll")]
private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);多文本,短义:基本上,如果您只知道路径的一部分或工作簿的文件名,这个片段就会给您Excel对象。
https://stackoverflow.com/questions/49406971
复制相似问题