如何将unicode string / wstring / CStringW从C ++ dll返回到InstallScript?

时间:2015-07-03 23:03:07

标签: c++ string dll installshield installscript

我正在使用InstallShield 2013 Premium。我在Visual Studio 2010中创建了一个C ++ DLL,以提供一些单独使用InstallScript无法实现的功能。在完成大量工作以获取此值之后,我的C ++函数需要向InstallScript返回一个小字符串(用户名)。

在整个C ++中我使用CStringW来表示我的字符串。理想情况下,我想将其作为Unicode返回,但如果这是我唯一的选择,我会满足于ANSI。我尝试了CStringW,std :: wstring,std :: string,LPCTSTR,LPSTR,char *等多种方法。我试过直接返回,并尝试通过引用返回。什么都行不通!

有时dll函数会挂起,有时会抛出异常,最多会返回带有非打印字符的垃圾值。关于此的官方文档似乎不准确(它对我不起作用!)。广泛的谷歌搜索和搜索Flexera板产生了解决同样荒谬问题的其他人的“解决方案”,但是没有那些对我有用...

直到最后我才尝试这个,因为我理所当然地认为你可以很容易地在dll和InstallScript之间传递字符串。回想起来,我应该先从两者之间的接口开始,然后再开发dll功能。

3 个答案:

答案 0 :(得分:1)

感谢帮帮!我终于为自己想出了这个。然而,解决方案有多个方面,我没有在其他地方找到记录或建议。

主要观点

1)从C ++返回WCHAR *

2)使用WSTRING作为InstallScript原型中的相应返回类型

3)将其返回到InstallScript中的常规STRING变量中,并将其视为任何其他

4)保留WCHAR *在静态变量中指向C ++ dll的值,否则显然会被删除而指针变为无效

如果你已经足够发现自己在同一条船上,我可能不需要提供每一个细节,但这里有一大堆示例代码可以帮助你:< / p>

Visual Studio Def文件

LIBRARY MyIsDllHelper
EXPORTS   
   getSomeStringW   @1

C ++标题

#ifdef MYISDLLHELPER_EXPORTS
#define MYISDLLHELPER_API __declspec(dllexport) 
#else
#define MYISDLLHELPER_API __declspec(dllimport) 
#endif

#include <stdexcept>
#include <atlstr.h>

namespace MyIsDllHelper
{
    class MyIsDllHelper
    {
    public:         
    static MYISDLLHELPER_API WCHAR * getSomeStringW();
    };
}

C ++来源

#include "stdafx.h"
#include "MyIsDllHelper.h"

static CStringW someStringRetained;

CStringW getTheString()
{
    CStringW s;
    // do whatever...

    return s;
} 

WCHAR * MyIsDllHelper::MyIsDllHelper::getSomeStringW()
{   
    someStringRetained = getTheString();
    return someStringRetained.GetBuffer( someStringRetained.GetLength() ) + L'\0';
}

的InstallScript

#define HELPER_DLL_FILE_NAME "MyIsDllHelper.dll"
prototype WSTRING MyIsDllHelper.getSomeStringW();

function DoSomething( hMSI )
    STRING svSomeString;    
    STRING svDllPath;   
begin

    // Find the .dll file path. (A custom function)
    GetSupportFilePath( HELPER_DLL_FILE_NAME, TRUE, svDllPath );    

    // Load the .dll file into memory.
    if( UseDLL( svDllPath ) != 0 ) then
        MessageBox ("Could not load dll: " + svDllPath, SEVERE );
        abort;
    endif;

    // Get the string from the dll 
    try         
        svSomeString = MyIsDllHelper.getSomeStringW();
    catch   
        MessageBox( "Could not execute dll function: MyIsDllHelper.getSomeStringW", SEVERE );
        abort;      
    endcatch;       

    // Remove the .dll file from memory.
    if( UnUseDLL( svDllPath ) < 0 ) then
        MessageBox ("Could not unload dll: " + svDllPath, SEVERE );
        abort;
    endif;

    // Use the string
    MessageBox( "svSomeString: [" + svSomeString + "]", INFORMATION );       

end;

答案 1 :(得分:0)

当你可以使用C语言而不是C ++语言时,你最好。匹配函数接口,如GetEnvironmentVariable,函数接受指向缓冲区的指针(以及正确的缓冲区大小),然后写入该缓冲区。只要您可以使用CString中的StringCchCopy之类的内容完成缓冲区,您的大多数实现都不应该更改。

由于您特别提到CStringW和其他Unicode字符串类型,我建议为接口类型选择LPWSTR(而不是LPTSTR)。

然后剩下的就是声明这个以供InstallScript使用。这意味着原型应使用WSTRINGBYREF。如果函数接口与GetEnvironmentVariableW相同,则原型应如下所示:

prototype MyFunc(WSTRING, BYREF WSTRING, NUMBER);

答案 2 :(得分:0)

你可以使用字符串,但我想问题是编码。

看看这里:https://adventuresinscm.wordpress.com/2014/01/12/unicode-files-and-installshield/