OLE DB异常"类未注册"仅在运行单元测试时

时间:2018-03-13 11:29:32

标签: c++ com oledb atl

我有一个基于Windows的C ++应用程序/库,它使用Excel环境作为界面。该库从Access数据库中检索信息。

C ++库类基于COM的活动模板库。

当我运行/调试库时,一切正常。负责通过COM从Access数据库检索数据的类函数在设置连接时没有问题。

但是当我运行单元案例(Microsoft C ++单元测试框架)时,它在atldbcli.h中到达函数OpenFromInitializationString时失败。

L"Provider=Microsoft.ACE.OLEDB.12.0;User ID=Admin;Data Source = C:\\Repos\\Xerf\\XerfLib\\XerfData.accdb;Mode = Share Deny None;Extended Properties = \"\";Jet OLEDB:System database=\"\";Jet OLEDB:Registry Path=\"\";Jet OLEDB:Database Password=\"\";Jet OLEDB:Engine Type=6;Jet OLEDB:Database Locking Mode=1;Jet OLEDB:Global Partial Bulk Ops=2;Jet OLEDB:Global Bulk Transactions=1;Jet OLEDB:New Database Password=\"\";Jet OLEDB:Create System Database=False;Jet OLEDB:Encrypt Database=False;Jet OLEDB:Don't Copy Locale on Compact=False;Jet OLEDB:Compact Without Replica Repair=False;Jet OLEDB:SFP=False;Jet OLEDB:Support Complex Data=False;Jet OLEDB:Bypass UserInfo Validation=False;Jet OLEDB:Limited DB Caching=False;Jet OLEDB:Bypass ChoiceField Validation=False"

后者对GetDataSource的调用失败,并在运行单元测试时返回"类未注册"。运行或重新整理整个应用程序/库时,相同的代码成功。 更令人费解的是同一个解决方案在同事计算机上运行,​​包括单元测试和实际应用程序/库。

我正在运行Windows 10 64位和Office 365 ProPlus。我安装了Visual Studio 2017。

如果有人知道发生了什么,我将不胜感激。记住这些。

  • 单元测试不在单独的项目中,而是在主项目中只有一个单独的文件。
  • Oledb32.dll安装在以下位置C:\ Program Files(x86)\ Common Files \ System \ Ole DB \ oledb32.dll(版本10.0.16299.15)

在两种情况下,szInitializationString都是这样的:

#include "stdafx.h"
#include <string.h>

int main()
{
    WCHAR  m_DBInitializationString[1024]{};
    WCHAR  m_DatabasePath[_MAX_PATH]{};
    int iTmp;

    CDataSource db;
    HRESULT hr;

    CoInitialize(NULL);

    size_t wclen = (sizeof m_DBInitializationString) / (sizeof m_DBInitializationString[0]);
    wcscpy_s(m_DatabasePath, _MAX_PATH, L"C:\\Repos\\Xerf\\XerfLib\\XerfData.accdb");

    iTmp = swprintf_s(m_DBInitializationString, wclen, L"%s", L"Provider=Microsoft.ACE.OLEDB.16.0;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"User ID=Admin;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"Data Source = %s;", m_DatabasePath);
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Mode = Share Deny None;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Extended Properties = \"\";");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:System database=\"\";");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Registry Path=\"\";");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Database Password=\"\";");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Engine Type=6;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Database Locking Mode=1;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Global Partial Bulk Ops=2;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Global Bulk Transactions=1;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:New Database Password=\"\";");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Create System Database=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Encrypt Database=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Don't Copy Locale on Compact=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Compact Without Replica Repair=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:SFP=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Support Complex Data=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Bypass UserInfo Validation=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Limited DB Caching=False;");
    iTmp += swprintf_s(&m_DBInitializationString[iTmp], wclen - iTmp, L"%s", L"Jet OLEDB:Bypass ChoiceField Validation=False");

    hr = db.OpenFromInitializationString(m_DBInitializationString);

    return hr;
}

我尝试过创建一个最小的项目并返回相同的错误。这是最小的代码。

#pragma once

#ifndef STRICT
#define STRICT
#endif

#include "targetver.h"

#define m_dwRef                m_dwRefAtl
#define m_pOuterUnknown        m_pOuterUnknownAtl
#define InternalQueryInterface InternalQueryInterfaceAtl
#define InternalAddRef         InternalAddRefAtl
#define InternalRelease        InternalReleaseAtl

//#define _ATL_DEBUG_INTERFACES //Writes, to the output window, any interface leaks that are detected when _Module.Term is called.
//#define _ATL_DEBUG_QI         //Writes all calls to QueryInterface to the output window.
#define _ATL_APARTMENT_THREADED
#define _ATL_NO_AUTOMATIC_NAMESPACE
#define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS  // some CString constructors will be explicit

//#define ATL_NO_ASSERT_ON_DESTROY_NONEXISTENT_WINDOW

#include <atlbase.h>
#include <atlcom.h>
#include <atlctl.h>
#include <AtlConv.h>

// DB access
#include <atldbcli.h>
#include <atldb.h>

using namespace ATL;

此代码包含在预编译头文件stdafx.h

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
<title>Registration Form using jQuery Ajax and PHP MySQL</title>
<!--This is a CDN link to bootstrap 4 CSS-->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css" integrity="sha384-/Y6pD6FV/Vv2HJnA6t+vslU6fwYXjCFtcEpHbNJ0lyAFsXTsjBbfaDjzALeQsN6M" crossorigin="anonymous">
<!--This is a CDN link to the jQuery Library-->
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<!--This is a link to a jQuery script to validate form data-->
<script type="text/javascript" src="js/validation.min.js"></script>
<!--This is a CDN link to bootstrap 4 JS-->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js" integrity="sha384-b/U6ypiBEHpOf/4+1nzFpr53nxSS+GLCkfwBdFNTxtclqqenISfwAzpKaMNFNmj4" crossorigin="anonymous"></script>
<!--This is a CDN link to bootstrap 4 JS-->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js" integrity="sha384-h0AbiXch4ZDo7tp9hKZ4TsHbi047NrKGLO3SEJAg45jXxnGIfYzk4Si90RDIqNm1" crossorigin="anonymous"></script>
<!--This is a link to custom styles within the project-->
<link href="style.css" rel="stylesheet" type="text/css"/>
<!--This is a link to the custom JavaScript within the project-->
<script type="text/javascript" src="js/script.js"></script>
<script type="text/javascript" src="js/main.js"></script>
<script src="https://use.fontawesome.com/ee309940e2.js"></script>
</head>

<body>

<div class="signin-form">

    <div class="container small-container">
       <form action="http://localhost:8080/fvah/rest/Customer" class="form-signin" method="post" id="register-form">
        <h2>Register</h2>
        <hr />
        <div id="error">
        <!-- error will be shown here ! -->
        </div>

        <div class="form-row">
              <div class="form-row">
                    <div class="col">
                        <input type="text" class="form-control" placeholder="First name"name="firstNname" id="firstNname">
                    </div>
                    <div class="col">
                        <input type="text" class="form-control" placeholder="Last name" name="lastName" id="lastNname">
                    </div>
              </div>
        </div>
        <div class="form-row">
              <div class="form-row">
                    <div class="col">
                        <input type="text" class="form-control" placeholder="Company Name" name="companyName" id="company">
                    </div>
                    <div class="col">
                        <input type="text" class="form-control" placeholder="Address1" name="address1" id="address1">
                        <input type="text" class="form-control" placeholder="Address2" name="address2" id="address2">
                        <input type="text" class="form-control" placeholder="City" name="city" id="city">
                        <input type="text" class="form-control" placeholder="County" name="county" id="county">
                        <input type="text" class="form-control" placeholder="Contact No" name="contactNo" id="contactNo">
                    </div>
              </div>
        </div>

        <div class="form-row">
              <div class="form-row">
                    <div class="col">
                        <input type="text" class="form-control" placeholder="Email Address" name="email" id="user_email">
                    </div>
                    <div class="col">
                        <input type="password" class="form-control" placeholder="Password" name="password" id="password">
                        <input type="password" class="form-control" placeholder="ReType Password" name="cpassword" id="cpassword">
                    </div>
              </div>
        </div>

        <hr />

        <div class="form-group">
            <button type="submit" class="btn btn-default" name="btn-save" id="btn-submit">
            <i class="fa fa-user-plus" aria-hidden="true"></i> &nbsp; Create Account
            </button> 
        </div>  

      </form>

    </div>

</div>

</body>
</html>

祝你好运, 约翰

1 个答案:

答案 0 :(得分:0)

这不是解释,但它是解决问题的方法。

安装Microsoft Access 2013 Runtime 32位解决了这个问题。

即使我之前在init字符串中指定Provider=Microsoft.ACE.OLEDB.12.0它没有任何影响,因为安装的唯一ACE提供程序是属于Office 2016套件的ACE提供程序。

我很高兴解释为什么Office 2016 32位ACE提供程序无法正常工作。

这是最小项目https://github.com/jahlqvis/TestOLEDBAccess