【问题标题】:Exception from HRESULT: 0x800401E3 (MK_E_UNAVAILABLE) WorkaroundsHRESULT 异常:0x800401E3 (MK_E_UNAVAILABLE)
【发布时间】:2012-10-10 20:54:46
【问题描述】:

来自以下调用

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 似乎可以解决问题。 谁能给我解释一下?

【问题讨论】:

  • 我刚刚经历了 Excel 的权限噩梦,一旦我将 Excel 的兼容模式设置为以管理员身份运行以及调用应用程序以管理员身份运行,一切正常。
  • 这个问题我遇到过很多次了,我发现如果遇到错误,在Skype和Excel之间来回切换,就可以了……

标签: c# ms-office


【解决方案1】:

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

【讨论】:

  • 没有。它正在运行。但不知何故,我以非管理员身份运行 Visual Studio。一旦我以管理员身份重新运行它,一切就开始工作了。
  • 啊啊啊。是的,那也可以。很高兴你能够让它工作。
  • 根据您链接的文章:“当 Office 应用程序启动时,它不会立即注册其运行对象。这优化了应用程序的启动过程。Office 应用程序不是在启动时注册,而是注册其运行对象一旦失去焦点,就在 ROT 中。”我发现你需要专注于不同的窗口来完成这个(只是最小化确实有效......),有点hacky,我想知道是否有更好的方法:(
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    为了扩展@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();
    

    方法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");
    

    如果您在 Excel 2016 中的 RDP 会话中运行此代码可能会非常挑剔,我发现您需要自定义 RDP 以忽略它的最小化状态。我找到了this article quite helpful

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

    【讨论】:

      【解决方案4】:

      仅添加“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,但不确定它是否真的需要。

      【讨论】:

        猜你喜欢
        • 2016-02-06
        • 1970-01-01
        • 2012-07-21
        • 2011-03-02
        • 2012-02-26
        • 2011-07-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多