我正在使用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功能。
答案 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使用。这意味着原型应使用WSTRING和BYREF。如果函数接口与GetEnvironmentVariableW相同,则原型应如下所示:
prototype MyFunc(WSTRING, BYREF WSTRING, NUMBER);
答案 2 :(得分:0)
你可以使用字符串,但我想问题是编码。
看看这里:https://adventuresinscm.wordpress.com/2014/01/12/unicode-files-and-installshield/