dll string parameter

Got a problem you cannot solve? Try here.
Post Reply
Dan Fisher
Posts: 15
Joined: Tue Sep 05, 2006 6:40 am
Location: UK

dll string parameter

Post 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.
Dan
Alex_Ronquillo
Site Admin
Posts: 364
Joined: Mon Jul 30, 2007 11:51 am
Location: USA
Contact:

Post 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
Alejandro Ronquillo
InstallAware
Home of The Next Generation MSI Installer
Get your free copy today - http://www.installaware.com/
Dan Fisher
Posts: 15
Joined: Tue Sep 05, 2006 6:40 am
Location: UK

Post 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?
Dan
elecuyer
Posts: 13
Joined: Thu Jun 28, 2007 9:47 am
Location: Haverhill, MA
Contact:

Post 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.
Dan Fisher
Posts: 15
Joined: Tue Sep 05, 2006 6:40 am
Location: UK

Post 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).
Dan
elecuyer
Posts: 13
Joined: Thu Jun 28, 2007 9:47 am
Location: Haverhill, MA
Contact:

Post 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 :-)
DiVan
Posts: 4
Joined: Tue Jan 15, 2008 9:58 am

Post 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.
DiVan
Posts: 4
Joined: Tue Jan 15, 2008 9:58 am

restriction

Post by DiVan »

Only restriction on buffer (which is not cool) is MAX_PATH... for me it's 260 bytes.
mbond
Posts: 15
Joined: Thu Dec 12, 2013 9:37 am

Re: dll string parameter

Post 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
FrancescoT
Site Admin
Posts: 5361
Joined: Sun Aug 22, 2010 4:28 am

Re: dll string parameter

Post by FrancescoT »

Thanks for sharing it!
Francesco Toscano
InstallAware Software

White Papers (HowTos) - http://www.installaware.com/publication ... papers.htm
Publications - http://www.installaware.com/publications-review.htm
InstallAware Help -F1 anywhere in the InstallAware IDE
Post Reply