如何从 ROT 获取 progID?
How to get a progID from the ROT?
简介:
我正在尝试遍历 ROT (运行 Object Table) 并搜索 COM object 的特定 progID
。在我的例子中,progID
应该是 Excel.Application
.
例如,如果我有一个 excel 的实例 运行,我会得到 Excel.Application
这样的:
Excel.Application excel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
问题:
如果我有多个实例 运行,这个调用基本上会给我 any 个实例,但我无法识别正确的实例(例如通过 window 标题,...)。所以,我需要一个特定的实例,它可以通过打开 Workbook
或 window 标题来识别。
当前方法:
由于 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
。
- 我无法从
ppunkObject
中识别出正确的 Type
和 GetType()
。
ppszDisplayName
有时给我 excel 文档的路径,有时给我当前打开的工作簿的标题。
问题:
- 有没有办法用这种方法识别正确的 COM object?如果没有,
- 是否有可能一般从 ROT 得到正确的
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);
解法:
似乎无法从 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 COM 对象。
简介:
我正在尝试遍历 ROT (运行 Object Table) 并搜索 COM object 的特定 progID
。在我的例子中,progID
应该是 Excel.Application
.
例如,如果我有一个 excel 的实例 运行,我会得到 Excel.Application
这样的:
Excel.Application excel = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
问题:
如果我有多个实例 运行,这个调用基本上会给我 any 个实例,但我无法识别正确的实例(例如通过 window 标题,...)。所以,我需要一个特定的实例,它可以通过打开 Workbook
或 window 标题来识别。
当前方法:
由于 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
。 - 我无法从
ppunkObject
中识别出正确的Type
和GetType()
。 ppszDisplayName
有时给我 excel 文档的路径,有时给我当前打开的工作簿的标题。
问题:
- 有没有办法用这种方法识别正确的 COM object?如果没有,
- 是否有可能一般从 ROT 得到正确的
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);
解法:
似乎无法从 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 COM 对象。