19

从以下电话

Marshal.GetActiveObject("Excel.Application")

我得到一个

操作不可用(HRESULT 异常:0x800401E3 (MK_E_UNAVAILABLE))

我相信当我的应用程序和 excel 之间的用户权限不匹配时会导致此错误。

我想知道是否有一种解决方法,无论如何打开 excel,我都可以如何访问打开的 excel 应用程序,我可以以管理员身份打开我想从中访问 excell 的程序。

另外我想知道如何知道打开了哪些权限进程?我一直在使用 ProcessExplorer 查看 UserProfile(在两个应用程序中都是相同的)和 Owner(也是相同的 BUILTIN\Administrators)

背景 我有一个程序通过调用 NUnit-console-x86 来运行不同的测试。正在测试的应用程序打开一个 excel 表单,这是我要从中读取数据的表单。当我以管理员身份运行程序时,或者没有出现这些错误,我也尝试添加 Process.StartInfo.Verb = "runas"; 到我启动 NUnit 的程序,但我仍然收到这些错误

尽管我不想在每台计算机上都安装 Visual Studio,但安装 Visual Studio 似乎可以解决问题。任何人都可以向我解释这些吗?

4

4 回答 4

7

查看Microsoft Support Information,当 excel(或一般的 office)未处于活动状态或在运行对象表中运行时,似乎会生成 0x800401e3。在调用它之前,您必须打开一份 excel 副本。它要么你还没有在代码中打开 excel,要么它还没有完全注册。这可能是问题吗?

于 2013-11-19T23:20:04.707 回答
2

这是 Visual Studio 和 Excel 之间的权限不匹配的问题。微软文档没有这么说,但肯定是这样。更严重的问题是有时会抛出异常,有时不会通过不知道管理权限的旧版本 Excel (即 2007 版)抛出异常。

发生这种情况时,您应该将权限匹配为管理员管理员或无。即使 Excel 无特权和 Visual Studio 管理员也可能无法工作。

于 2019-01-27T06:00:14.187 回答
2

为了扩展@DylanCorriveau 所说的内容,我发现您需要采用以下方法之一来避免此问题。

方法一

我发现在某些情况下(Excel 2010)首先启动 excel 可以解决这个问题。您需要调整路径并等待适合您的需求和版本。

string pathToTheVersionOfExcel = @"C:\Program Files (x86)\Microsoft Office\Office14\EXCEL.EXE";
System.Diagnostics.Process.Start(pathToTheVersionOfExcel);
Thread.Sleep(5000); //"WaitForInputIdle" waits for way too long, generally it takes 5 seconds to start for me

方法二

我过去采用的另一种方法是以不同的方式调用 Excel:

var oExcelApp = new Microsoft.Office.Interop.Excel.Application();

方法三

最后在我的应用程序中(对于 excel 2010 和 2016),我使用了一些解决方法:

[DllImport("user32.dll")]
private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

//In your method...
string pathToTheVersionOfExcel = @"C:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE";
Application oExcelApp = null;

Process process = new Process();
process.StartInfo.FileName = pathToTheVersionOfExcel;
process.Start();

Thread.Sleep(5000);

//Opening a closing notepad seems to "register" excel 2016, not needed for excel 2010 though...
Process processNotepad = new Process();
processNotepad.StartInfo.FileName = @"C:\Windows\system32\notepad.exe";
processNotepad.Start();

ShowWindow(process.MainWindowHandle, 2); //Minimize
ShowWindow(process.MainWindowHandle, 3); //Maximize

Thread.Sleep(5000);

processNotepad.CloseMainWindow();

oExcelApp = (_Application)Marshal.GetActiveObject("Excel.Application");

如果您在 RDP 会话中在 Excel 2016 中运行此代码,它可能非常挑剔,我发现您需要自定义 RDP 以忽略它的最小化状态。我发现这篇文章很有帮助

如果您尝试通过远程服务器上的某种自动构建/发布平台(例如 TFS/Azure DevOps)调用 excel,则需要使用autologin。我自己还没有那个工作

于 2019-04-10T19:47:41.133 回答
1

仅添加“Microsoft.Office.Interop.Excel.dll”的引用

try
{
    //This requires excel app (excel.exe*32) to be running means any excel sheet should be open. If excel not running then it will throw error.
    excelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
    excelApp.Visible = false;
}
catch
{
    //create new excel instance
    excelApp = new Excel.Application(); 
    excelApp.Visible = false;
}

这对我有用。

优点:无需将 Microsoft.Office.Interop.Excel.dll 复制到您安装的文件夹中。由于安装了 MS excel,它将从 GAC 获取。

我也使用过 Office.dll,但不确定它是否真的需要。

于 2018-04-19T05:46:27.237 回答