Page 1 of 1
dll string parameter
Posted: Wed Sep 26, 2007 6:08 am
by Dan Fisher
I am calling a simple Delphi dll from IA6. Can anyone shed some light on why the value of the var param passed to this function isn't changed when it's returned to the installation code? (If I put debug code into the dll method it all seems to be working fine, and the var param is populated as it should be.)
dll code:
procedure GetDecryptedPassword(aEncrypted: PChar; var aDecrypted: PChar); stdcall;
var
Cipher: TCipher;
Decrypted: string;
begin
Cipher := TCipher.Create;
try
Decrypted := Cipher.DecryptedString(cDBKey, string(aEncrypted));
StrLCopy(aDecrypted, PChar(Decrypted), Length(Decrypted) + 1);
finally
Cipher.Free;
end;
end;
IA code:
~InstallAware Clipboard Data~
~Call DLL Function~
~{A67FBE45-E960-42CA-AFE0-E225496F1530}~
~$SUPPORTDIR$\\InstSupt.dll,GetDecryptedPassword,void,,"pointer to string",$ENCPASSWORD$,"allocated string buffer (MAX_PATH length)",$UNENCPASSWORD$,$~
~mIDEFunc.dll\\mEXEFunc.dll~
After which $UNENCPASSWORD$ is the empty string it was initialised to, rather than the value aDecrypted was set to in the dll.
Posted: Wed Sep 26, 2007 4:53 pm
by Alex_Ronquillo
This is a guess, but the problem may be that you are using allocated string buffer for $ENCPASSWORD$, instead of pointer to string. Your dll code requires both arguments to be of the same type. Try it by changing the type
Posted: Fri Sep 28, 2007 8:12 am
by Dan Fisher
Thanks Alex. I've tried your suggestion, but it doesn't work (it's also at odds with all the relevant advice given in this forum). I've also tried using a char array as the parameter, to no avail. I've also tried using an 'out' parameter instead of a var. In all cases the dll procedure is called, it does what it should, and sets the value of the out/var parameter correctly. Back in the IA script, the value is always an empty string.
There are quite a few questions about this in the forum, and I can't see anywhere that anyone says they've succeded in getting string values back from a dll call. Is it the case that this just doesn't work, and I should stop wasting time and take a different approach, or has anyone actually succeded in doing this?
Posted: Mon Dec 03, 2007 3:36 pm
by elecuyer
I'm having the same problem. IA, please help.... At least provide some documentation on getting the "allocated string buffer (MAX_PATH length)" to work.
Posted: Mon Dec 10, 2007 12:20 pm
by Dan Fisher
I gave up on this - wasted too much time on a trivial problem when there are real problems waiting to be fixed. My workaround was to have the dll write the value to a file and then have IA read the values out of the file (actually a list of key-value pairs which are then read in as an ini file).
It's awful, and I hate doing hacks like that and then hoping for the best when it gets released, but I couldn't see another way round it, and IA weren't being much help, as you can see! (A simple "sorry, it doesn't work" would have at least saved valuable time).
Posted: Mon Dec 10, 2007 12:31 pm
by elecuyer
I did the same thing - write, then read from a temporary INI file. I'll give you 3 guesses as to the INI file's name

Posted: Mon Jan 28, 2008 9:54 am
by DiVan
I've succeded actualy...
Code: Select all
~InstallAware Clipboard Data~
~Call DLL Function~
~{2AFB2974-B6D6-4C0F-8264-DD06A94DCB33}~
~BLABLABLABLABLA......"pointer to string",$CREDENTIALS_USERNAME$,"pointer to string",$CREDENTIALS_PASSWORD$,"allocated string buffer (MAX_PATH length)",$CREDENTIALS_ERROR$,$~
~mIDEFunc.dll\\mEXEFunc.dll~
I return Exception.ToString() to the user.
c++ '/clr' code:
Code: Select all
extern "C" __declspec(dllexport) int __stdcall ValidateUser(
//blablabla...
const LPCTSTR username,
const LPCTSTR password,
TCHAR* error)
{
// ...work...
// ...at some point
ExceptionToPStr(ex, error);
return something;
}
void ExceptionToPStr(Exception^ ex, TCHAR* str)
{
...
_tcsncpy(str, MYMESSAGE, _tcslen(str));
...
}
If I understand correct, TCHAR* (or char*) in c++ is like PChar in Delphi.
'var' param isn't changed because "Call Dll Function" holds pointer to that "allocated buffer" and copies it to the IA variable at the end of the function call. So, if you alter the pointer itself, ( in c++ simply by typing
resultString = "something"; in Delphi, by using 'var') it will not return to the IA.
Realy, I don't know, how 'Call Dll Function' works. It just an assumption. But it works.
restriction
Posted: Tue Jan 29, 2008 10:24 am
by DiVan
Only restriction on buffer (which is not cool) is MAX_PATH... for me it's 260 bytes.
Re: dll string parameter
Posted: Wed Jan 08, 2014 8:49 am
by mbond
For those that use Delphi instead of C++, here is how you make it work:
Delphi code (a complete working DLL with a single entry point):
Code: Select all
library MySetupHelper;
uses
SysUtils, Classes, Windows;
{$R *.res}
function MyFunc (someINParam : PAnsiChar; someOUTParam : PAnsiChar; ) LongInt; stdcall;
var
MyINValue : String;
MyOUTValue : String;
begin
result := 1; //success
try
MyINValue := String(someINParam);
//Do some work here to get this value.
MyOUTValue := ''; //Set this value as needed.
StrPCopy(someOUTParam, MyOUTValue);
except on E:Exception do
result := 0; //failure
end;
end;
exports
MyFunc;
begin
end.
IA Code (complete working MSIcode snippet):
Clear Text:
Code: Select all
Set Variable SETUPHELPERFOLDER to
Set Variable DLLRESULT to
Set Variable INPARAM to MyINPARAMValue
Set Variable OUTPARAM to
Comment: Change souce path/file to be functional.
Define File Bag : C:\Temp\SetupHelper.dll, get runtime location of files into variable SETUPHELPERFOLDER
Call DLL Function $SETUPHELPERFOLDER$SetupHelper.dll->MyFunc (get result into variable DLLRESULT)
if Variable DLLRESULT Equals 1
MessageBox: DEBUG, OUTPARAM = $OUTPARAM$
else
MessageBox: DEBUG, DLLRESULT = $DLLRESULT$
end
Clipboard data:
Code: Select all
~InstallAware Clipboard Data~
~Comment~
~{DACF0133-0443-47A1-AECE-88B59B6EF4A2}~
~~
~End~
~{EADA86B3-2658-43A4-96CE-3DB310E4DAA7}~
~MessageBox~
~{23D3BA1B-97BE-4DC4-941A-5E7B1365491E}~
~DEBUG~
~DLLRESULT = $DLLRESULT$~
~0~
~1~
~~
~Else~
~{62D63A2A-E5E6-49D1-B240-3526BBF1FEF5}~
~MessageBox~
~{725BCCC7-9081-4716-9589-75977F094A5B}~
~DEBUG~
~OUTPARAM = $OUTPARAM$~
~0~
~1~
~~
~If~
~{C674B806-8257-4259-BB49-C6365CD5CE9C}~
~DLLRESULT~
~0~
~1~
~FALSE~
~Call DLL Function~
~{0D03DF5D-90FB-48B7-9C2B-4BA193425E24}~
~$SETUPHELPERFOLDER$SetupHelper.dll,MyFunc,long,DLLRESULT,"pointer to string",$INPARAM$,"allocated string buffer (MAX_PATH length)",$OUTPARAM$,$~
~mIDEFunc.dll\mEXEFunc.dll~
~File Bag~
~{0A9F82F2-BA63-49D9-9A48-36092BF72B4C}~
~C:\Temp\SetupHelper.dll|,FALSE,SETUPHELPERFOLDER~
~mFileBagIDE.dll\mFileBagEXE.dll~
~Comment~
~{53F00B30-6B60-4CAF-8651-C5DEFF895F60}~
~Change souce path/file to be functional.~
~Comment~
~{31A7C41B-0C01-4FD2-B8B0-3F759E0287B9}~
~~
~Set Variable~
~{B75A3126-8D18-420A-AE52-BAED9ACCC822}~
~OUTPARAM$MYAH$MYAH$FALSE~
~~
~Set Variable~
~{BC12E82F-4740-4A97-BC27-9377655A121F}~
~INPARAM$MYAH$MYAH$FALSE~
~MyINPARAMValue~
~Set Variable~
~{8E6ED04F-BF4E-4499-862D-84540F40A59B}~
~DLLRESULT$MYAH$MYAH$FALSE~
~~
~Set Variable~
~{0813AAF0-B614-4BD0-9E75-06DA1E5DBB15}~
~SETUPHELPERFOLDER$MYAH$MYAH$FALSE~
~~
Enjoy!
Bond
Re: dll string parameter
Posted: Wed Jan 08, 2014 12:15 pm
by FrancescoT
Thanks for sharing it!