我正在使用
[DllImport("Oleacc.dll")]
static extern int AccessibleObjectFromWindow(
int hwnd,
uint dwObjectID,
byte[] riid,
ref Excel.Window ptr);Run Code Online (Sandbox Code Playgroud)
使用他的句柄获取Excel实例,我从excel实例的进程ID获取.
这就是我使用这些功能时的样子
const uint OBJID_NATIVEOM = 0xFFFFFFF0;
Guid IID_IDispatch = new Guid("{00020400-0000-0000-C000-000000000046}");
Excel.Window ptr = null;
int hr = AccessibleObjectFromWindow(hwndChild, OBJID_NATIVEOM,
IID_IDispatch.ToByteArray(), ref ptr);
Object objApp = ptr.Application;Run Code Online (Sandbox Code Playgroud)
这种代码安静很有效,但唯一的问题是我必须添加对Office 2003主互操作程序集的引用.
正如你所看到的,函数中的最后一个参数是我需要添加对Pias的引用的原因,所以我的问题是如果有一种方法可以避免使用Interop程序集,我尝试过后期绑定但是也许我一直在做错,因为我无法让它发挥作用.
我需要从我的.Net4应用程序自动化办公文档(Word和Excel).
由于我无法真正强迫我的用户使用特定的Office版本,因此我不使用互操作程序集或tlbimp,因此我的项目不包含任何其他引用,如果未安装Office,整个应用程序也将失败(功能刚赢了)不可用).
相反,我问系统哪个COM服务器可以处理"Word.Application"或"Excel.Application":
dynamic app = Activator.CreateInstance(Type.GetTypeFromProgID("Word.Application"));
app.Foo();
Run Code Online (Sandbox Code Playgroud)
我担心如何在完成后正确处理"app"对象,因为现在我有两个内部管理系统需要担心(COM引用计数和.Net引用跟踪).理想情况下,我应该能够将动态app对象包装到一次性包装器类中,并确保在处理包装器时底层COM对象未被引用.
编辑:此外,我想知道当我完成它时如何正确地使COM对象"活着",因为Word是在一个单独的过程中.我应该能够实例化Word应用程序,自动化它,然后释放我的所有引用,但Word应用程序应该保持打开状态.
我正在使用Office互操作创建一个新的Word实例:
var word = Microsoft.Office.Interop.Word.Application();
word.Visible = true;
word.Activate;
Run Code Online (Sandbox Code Playgroud)
我可以像这样得到一个窗口句柄:
var wordHandle = Process.GetProcessesByName("winword")[0].MainWindowHandle;
Run Code Online (Sandbox Code Playgroud)
问题是代码的工作原理是假设没有其他Word运行实例.如果有多个,则无法保证它返回的句柄是针对我已启动的实例.我GetForegroundWindow在检测WindowActivate到来自我的对象的事件之后尝试使用但是这一切都在WPF应用程序中运行,该应用程序被设置为作为最顶层的窗口运行,所以我只获得了WPF窗口的句柄.有没有其他方法来获取我的单词实例的句柄?