CustomAction 在开发计算机上成功,在部署计算机上失败

发布于 2024-09-12 04:32:52 字数 1992 浏览 4 评论 0原文

我正在创建一个 WiX 安装程序来安装连接到数据库的程序。为了解决这个问题,我创建了一个 C dll,它检查服务器上是否存在某个 SQL 实例:

extern "C" UINT __stdcall DBConTest(MSIHANDLE hInstaller)

{

FILE *fp;
fp = fopen("dbcontestdll.txt", "w");
_ConnectionPtr pCon;
int iErrCode;
HRESULT hr;
UINT rc;
//init COM

fwprintf(fp, L"entering dbcontest\n");
if(FAILED(hr = CoInitializeEx(NULL,tagCOINIT::COINIT_APARTMENTTHREADED)))
    return ERROR_INVALID_DATA;

fwprintf(fp,L"did coinit\n");
if(FAILED(hr = pCon.CreateInstance(__uuidof(Connection))))
    return ERROR_INVALID_DATA;

fwprintf(fp,L"created instance of connection\n");
TCHAR constr[1024];
DWORD constrlen = sizeof(constr);
rc=MsiGetProperty(hInstaller,TEXT("DBCONNECTIONSTRING"), constr, &constrlen);

fwprintf(fp, L"dbconstring is: %s\n", constr);
TCHAR serverstr[1024];
DWORD serverstrlen = sizeof(serverstr);
rc = MsiGetProperty(hInstaller,TEXT("SQLINSTANCE"),serverstr,&serverstrlen);

fwprintf(fp, L"SQLINSTANCE is: %sl\n",serverstr);
TCHAR finalconstr[2048];
swprintf(finalconstr,L"%s; Data Source=%s;",constr,serverstr);
try{
    hr = pCon->Open(finalconstr,TEXT(""),TEXT(""),adConnectUnspecified);
}
catch(_com_error ce){

    fwprintf(fp, L"%s\n", msg);
    ::MessageBox(NULL,msg,NULL,NULL);
    CoUninitialize();
    MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("0"));
    return ERROR_SUCCESS;

}
if(FAILED(hr)){
    MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("0"));
    return ERROR_SUCCESS;

}
pCon->Close();
CoUninitialize();
MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("1"));
::MessageBox(NULL,TEXT("Successfully connected to the database!"),NULL,NULL);
fwprintf(fp, L"leaving...\n");
fclose(fp);
return ERROR_SUCCESS;

}

现在,当我将此函数构建到 dll 中并将其添加到我的 WiX 项目中时,此代码可以工作在我的开发计算机上(具体来说,安装成功完成,文件“dbcontestdll.txt”存在并且其中包含正确的数据) - 但是,当我在“全新安装”计算机上运行它时,安装失败并显示退出代码第2896章 没有创建“dbcontestdll.txt”。

在 Windows 安装程序中使用基于 C 的 dll(例如 C++ 可再发行组件)是否有先决条件?

I'm creating a WiX installer to install a program which connects to a database. To help with this, I've created a C dll which checks to see if a certain instance of SQL exists on a server:

extern "C" UINT __stdcall DBConTest(MSIHANDLE hInstaller)

{

FILE *fp;
fp = fopen("dbcontestdll.txt", "w");
_ConnectionPtr pCon;
int iErrCode;
HRESULT hr;
UINT rc;
//init COM

fwprintf(fp, L"entering dbcontest\n");
if(FAILED(hr = CoInitializeEx(NULL,tagCOINIT::COINIT_APARTMENTTHREADED)))
    return ERROR_INVALID_DATA;

fwprintf(fp,L"did coinit\n");
if(FAILED(hr = pCon.CreateInstance(__uuidof(Connection))))
    return ERROR_INVALID_DATA;

fwprintf(fp,L"created instance of connection\n");
TCHAR constr[1024];
DWORD constrlen = sizeof(constr);
rc=MsiGetProperty(hInstaller,TEXT("DBCONNECTIONSTRING"), constr, &constrlen);

fwprintf(fp, L"dbconstring is: %s\n", constr);
TCHAR serverstr[1024];
DWORD serverstrlen = sizeof(serverstr);
rc = MsiGetProperty(hInstaller,TEXT("SQLINSTANCE"),serverstr,&serverstrlen);

fwprintf(fp, L"SQLINSTANCE is: %sl\n",serverstr);
TCHAR finalconstr[2048];
swprintf(finalconstr,L"%s; Data Source=%s;",constr,serverstr);
try{
    hr = pCon->Open(finalconstr,TEXT(""),TEXT(""),adConnectUnspecified);
}
catch(_com_error ce){

    fwprintf(fp, L"%s\n", msg);
    ::MessageBox(NULL,msg,NULL,NULL);
    CoUninitialize();
    MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("0"));
    return ERROR_SUCCESS;

}
if(FAILED(hr)){
    MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("0"));
    return ERROR_SUCCESS;

}
pCon->Close();
CoUninitialize();
MsiSetProperty(hInstaller,TEXT("DBCONNECTIONVALID"),TEXT("1"));
::MessageBox(NULL,TEXT("Successfully connected to the database!"),NULL,NULL);
fwprintf(fp, L"leaving...\n");
fclose(fp);
return ERROR_SUCCESS;

}

Now, when I build this function into a dll and add it to my WiX project, this code works on my development machine (specifically, the installation successfully finishes and the file "dbcontestdll.txt" exists and has the correct data in it)--but, when I run it on a "fresh install" machine, the installation fails with exit code 2896 and the "dbcontestdll.txt" is not created.

Are there prerequisites to using C-based dlls in a Windows Installer, such as the C++ redistributable?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

陈年往事 2024-09-19 04:32:53

对于自定义操作,我强烈建议静态链接到 C 运行时。自定义 aciton DLL 最终会更大一些,但您对自定义操作之外的文件的依赖性会减少。

For custom actions, I highly recommend statically linking to the C run time. The custom aciton DLL ends up a little bigger but you'll have one less dependency on files outside the custom action.

巴黎盛开的樱花 2024-09-19 04:32:53

是的,您可能需要 Visual C 运行时。 Dependency Walker 可能会帮助查找所需的 dll。

查看此示例,了解如何使用 Bootstrapper。这样您就可以在运行 msi 之前安装运行时。我使用以下引导程序行:

<BootstrapperFile Include="Microsoft.Visual.C++.9.0.x86">
  <ProductName>Visual C++ 2008 Runtime Libraries (x86)</ProductName>
</BootstrapperFile>

此包通常存储在 C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\vcredist_x86 目录中。

Yes you probably need the visual c runtime. Dependency Walker might assist finding the required dlls.

Look at this example how to use a Bootstrapper. This way you can install the runtime before the msi will be run. I use the following bootstrapper line:

<BootstrapperFile Include="Microsoft.Visual.C++.9.0.x86">
  <ProductName>Visual C++ 2008 Runtime Libraries (x86)</ProductName>
</BootstrapperFile>

This package is normally stored in the C:\Program Files\Microsoft SDKs\Windows\v6.0A\Bootstrapper\Packages\vcredist_x86 directory.

雨的味道风的声音 2024-09-19 04:32:53

我也有这个问题。我有一个默认情况下动态链接的 MFC DLL,但我忘记在包中包含 MSVCR100.DLL。当然,它在开发机器上运行良好,甚至在大多数客户的机器上运行良好,但在旧的 Vista PC 上却失败了。我切换到静态链接。

I had this problem also. I had an MFC DLL that was dynamically linking by default, and I forgot to include MSVCR100.DLL in the package. Of course it worked fine on the development machine, it even worked on most customers' machines, but it failed on an old Vista PC. I switched to statically linked.

南街女流氓 2024-09-19 04:32:52

您可能不希望自己陷入必须引导 C++ redist 才能运行自定义操作的情况。您是否尝试过使用文件 |新 | WiX 附带的 C++ 自定义操作对象?您可以使用它来删除您的 CA,然后将代码复制并粘贴到其中。这应该为您提供避免此问题所需的所有编译器和链接器设置。

You probably don't want to get yourself into the situation where you have to bootstrap C++ redists just to run a Custom Action. Have you tried using the File | New | C++ Custom Action probject that comes with WiX? You can use that to stub out your CA and then copy and paste your code into it. That should give you all the compiler and linker settings that you need to avoid this problem.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文