从以下电话
Marshal.GetActiveObject("Excel.Application")
我得到了
操作不可用(HRESULT异常:0x800401E3(MK_E_UNAVAILABLE))
我相信当我的应用程序和excel之间的用户权限不匹配时会导致此错误。
我想知道是否有关于如何访问打开的Excel应用程序的解决方法,无论excel如何打开,我都可以以管理员身份打开我想要访问的程序。
另外我想知道如何判断打开了哪些权限进程?我一直在使用ProcessExplorer来查看UserProfile(在两个应用程序中都是相同的)和Owner(也是相同的BUILTIN \ Administrators)
背景我有一个程序通过调用NUnit-console-x86来运行不同的测试。正在测试的应用程序打开了一个excel表单,这是我想要从中读取数据的表单。当我以管理员身份运行我的程序时,或者我没有得到这些错误,我也尝试添加Process.StartInfo.Verb =“runas”;到我启动NUnit的程序,但我仍然遇到这些错误
虽然我不想在每台计算机上安装visual studio,但看起来安装visual studio解决了这个问题。任何人都可以向我解释这些吗?
看看Microsoft Support Information,当excel(或一般办公室)未激活或在运行对象表中运行时,似乎会生成0x800401e3。在打电话之前,您必须打开excel的副本。它要么你尚未在代码中打开excel,要么尚未完全注册。这可能是问题吗?
这是Visual Studio和Excel之间不匹配的问题。微软文件没有说,但它肯定是。更严重的问题是有时会抛出异常,有时不会通过不知道管理优势的旧版本的Excel,即版本2007。
如果发生这种情况,您应该以administrator-administrator或none-none匹配权限。即使Excel无权限和Visual Studio管理员也可能无法正常工作。
仅添加“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,但不确定它是否真的需要。
为了扩展@DylanCorriveau所说的内容,我发现你需要采取以下方法之一来避免这个问题。
方法1
我发现在某些情况下(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
方法2
我过去采用的另一种方法是以不同的方式调用Excel:
var oExcelApp = new Microsoft.Office.Interop.Excel.Application();
方法3
最后在我的应用程序中(对于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以忽略它的最小化状态。我找到了this article quite helpful。
如果您尝试通过远程服务器(例如TFS / Azure DevOps)上的某种自动构建/发布平台调用excel,则需要使用autologin。我自己没有那个working yet。