Jump to content


This is a ready-only archive of the InstallSite Forum. You cannot post any new content here. / Dies ist ein Archiv des InstallSite Forums. Hier können keine neuen Beiträge veröffentlicht werden.
Photo

2 custom actions in the same DLL


5 replies to this topic

DeusApprime

DeusApprime
  • Members
  • 73 posts

Posted 13 January 2002 - 14:13

Hi,
I've created 2 custom actions - both point to 2 functions inside the same DLL. They are both immediate actions, put in a DoAction control-event. When there was only one action, everything was fine. It run perfectly. But as soon as I added a call to the second function, I got this error message by the DoAction event:

D:\TEMP\MyDLL.dll can not be found. Make sure the file is on target system or installed already.

So I tried to manually copy MyDLL.dll to %temp%... When I ran Setup again, I noticed that the file was actually DELETED as soon as I got the error message.

What is going on? Any ideas?


Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 13 January 2002 - 17:04

Msi is a liitle inefficient when it handles dll calls.  The DLL is copied out of the binary table and copied to eg. <tempdir>\MSI1234.tmp.  Your action is then called from this file.  When your DLL returns msi1234.tmp is deleted.   When you call a second CA the dll files is copied out again eg. msi1243.tmp and the second function is called.  It is quite normal to have multiple CAs in a single DLL but the implementaion is a little awkward.

Now InstallShield normally creates custom action tables like
Action:  CA_Name1
Type: 1
Source: Binary1
Target: FunctionName1
and
Action:  CA_Name2
Type 1
Source: Binary1
Target: FunctionName2

What are you doing?


DeusApprime

DeusApprime
  • Members
  • 73 posts

Posted 14 January 2002 - 07:28

Well, first of all, I have another DLL CA that I use in the Setup (it's in a different DLL). What I see, is when this function is called, the DLL file appears in %TEMP%. It doesn't have a MSIXXX.TMP name - it appears with its original name.

Second of all, I did not understand your last question. I simply created two custom actions with the CA Wizard. I noticed that the CustomAction table held a foreign key to the ISDLLWrapper table (which held the function call and a key to the binary table).

In the IDE, it looked sth like this (I describe only one action):
Action type: 131136
Source: NewBinary19
Target: void MyDLL::Func(.....)

In the real tables, it looked sth like this:
(CustomAction table):
Type: 65
Source: DLLWRAP.DLL
Target: DLL2

(ISDLLWrapper table):
EntryPoint (key): DLL2
Type: 64
Source: NewBinary19
Target: void MyDLL::Func(...)


Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 14 January 2002 - 10:33

You can see how InstallShield make their so called "Standard" dll.  Your DLL function is a parameter of DLLWRAP.DLL

The reason I wanted you to look carefully at the tables is that I had seen InstallShield mess up the binary table in the past. (When I was experimenting with the options).

Presumably the call to the other CA produces
Type 65
Source DDLWRAP.DLL
Target: DLL3

EntryPoint DLL3
Type 64
Source NewBinary19
Target void MyDLL::Func2(...)

Are you sure you have not made a trivial typing error or perhaps you have not exported the second function.  Make sure capitilisation is consistant.

Now what should be happening.

Do Action
- Msi copies MSI1234.TMP from binary table key DLLWRAP.DLL
- This calls UNIT _stdcall DLL2(MSIHANDLE);
- DLL2 looks up DLL2 in ISDLLWrapperTable.
- DLL2 copies MyDLL.DLL out of NewBinary19 overwriting any version previously stored in %TEMP%
- DLL2 calls Func in MyDLL
- DLL2 ignores the return code (64)
- DLL2 deletes MyDLL.DLL
- DLL2 returns success
- Msi Ignores return code.

DoAction
--
- Msi copies MSI4321.TMP from binary table key DLLWRAP.DLL
- This calls UNIT _stdcall DLL3(MSIHANDLE);
- DLL3 looks up DLL3 in ISDLLWrapperTable.
- DLL3 copies MyDLL.DLL out of NewBinary19 overwriting any version previously stored in %TEMP%
- DLL3 calls Func in MyDLL but can not find it.

I can not see why. sorry.


DeusApprime

DeusApprime
  • Members
  • 73 posts

Posted 15 January 2002 - 12:49

Aha! I found out what is causing the error message. It's the fact that my DLL depends on another DLL, which is nowhere to be found. The only question I have now is: how to I make it available during Setup? I *could* place it in the binary table, but how do I extract it out of there?
I cannot use InstallScript by the way, since my project is MSI-only.
Any ideas?

Ian Blake

Ian Blake
  • Members
  • 483 posts

Posted 15 January 2002 - 13:13

You can use the power editor to edit the Binary table so that ISWI will include your dll when your installation is built.

Heres a sketch of your CA..  Add code to detect errors write the data out., close handles etc.

hActiveDatabase = MsiGetActiveDatabase(hInstaller);
Result = MsiDatabaseOpenView(hActiveDatabase,
  "SELECT * FROM Binary WHERE Name='MyBinary'",
 &hView);
Result = MsiViewExecute(hView, 0);
Result = MsiViewFetch(hView, &hRecord);
Count = MsiRecordDataSize(hRecord, 2);
Result = MsiRecordReadStream(....)

Good luck.