Link to home
Start Free TrialLog in
Avatar of eejay
eejay

asked on

Installed app fails to create mscomm control

I am developing an install program for an app that is written in VC++ Ver.5 and MFC using Installshield 5 Professional version. The problem I have is that when I run the install on a virgin machine the app fails to create the MSComm control and exits. It works on 3 other machines that have DevStudio installed. MSComm.ocx is installed to the Windows/System subdirectory as a self-registering DLL with shared and potentialy locked flags.  
Avatar of nietod
nietod

Your application probably uses a Dll that is not available on the machine it fails on.  Most likely it is the MFC dll.
The MFC dll is called MFCXXXX.dll.  The X's specify whethor or not it is a debug version and what version of MFC.

You might also be missing the run-time library if you are using the dll version of the run-time library.
You can use the DumpBin program to see what dlls an exe or dll imports from.
Avatar of eejay

ASKER

The MFC DLLs are present. The program exits at this point:
      if (!m_commctrl.Create(NULL,0,CRect(0,0,0,0),this,ID_COMMCTRL))
      {
            MessageBox("Couldn't Create comm control");
            TRACE0("Failed to create OLE Communications Control\n");
            return -1;      // fail to create
      }

Is see where you say that in your question now.  No the problem is not what I thought it was.  Best reject my answer.  I'm not going to be able to help.
You need to get to work: start debugging!

On the broken machine, step into the Create() call. Figure out why it's not working, and fix the problem.

If you're too lazy to debug, you can use DUMPBIN on the *.OCX file for the comm control you're using to see what it's dependencies are. If you're using MSCOMM32.OCX, the most likely cause is that you have an old version of OLEAUT32.DLL.

.B ekiM

First, execute GetLastError() immediately after the failed call and check the returned number.  Check WINERROR.H for the meaning of the number.
ASKER CERTIFIED SOLUTION
Avatar of lortega
lortega

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
GetLastError() is the wrong way to solve the problem: MFC doesn't set GetLastError().

.B ekiM
Duh!

MFC is a wrapper around Win32 APIs.
Win32 APIs call SetLastError() internally.
==> GetLastError() works for MFC.
QED.

(Unless the friggin MFC layer calls another unpteen APIs after the one that failed)
The wrapped control ends up calling CWnd::CreateControl().  CreateControl() does all the work, which means that it will try to create the control and watch for failures. If a failure happens, it will do work to unwind and recover--which almost always involves calling additional Win32 APIs. You wouldn't want to be forced to do all the cleanup yourself.

But, also, MFC might fail the call for its own reasons.  For example, if MFC detects that OLE hasn't been initialized for the thread where the call is happening, it will implicitly fail the creation call without calling OLE. So, sometimes GetLastError() isn't set because MFC is doing lots of work for you.

Therefore, GetLastError() is the wrong thing to use when calling through MFC's implementation. If you're calling through MFC's wrapper classes, where there's no or little implementation, GetLastError() sometimes works.

Either way, the direct approach to solve the problem is to work with the debugger: figure out what's failing, and remedy it in the setup program. It shouldn't be necessary to do--the control should provide error messages and/or better documentation about its setup dependencies. But it doesn't, and this is what's left.

MFC isn't only "a wrapper around Win32 APIs"; it often provides an _implementation_ based on Win32 APIs. It's your fundamental misunderstanding of MFC's scope that's caused you to reach a bad conclusion in your silly little proof.

.B ekiM

On the machine where the creation fails, is the control successfully registering during setup?  If it isn't, odds are that the machine doens't have OLECAT.DLL correctly installed, or doesn't have a new enough version. As MSCOMM32.OCX registers, it registers itself using OLECAT.DLL to express that it supports several component categories.

On the machine where the creation fails, was MFC42.DLL registered properly? Was it correctly installed?  Where do the GUIDs for the stock property pages point?  For example, does {0BE35200-8F91-11CE-9DE3-00AA004BB851} point at MFC42.DLL, or does it point at OLEPRO.DLL?  Is the DLL appropriately registered and installed?

.B ekiM

Avatar of eejay

ASKER

Unfortunately you are all wrong. The problem was that the MSComm control requires a license string to be passed to Create(). This is described in the following articles on the MS Knowledge Base:
PRB: Dynamic Creation of Redistributable Control Fails [visualc]
 ID: Q151804

 SAMPLE: LICREQST.EXE Requesting a License Key from an Object [visualc]
 ID: Q151771
 
That's interesting: why did it work on some machines and not others?

..B ekiM
Avatar of eejay

ASKER

The machines that it worked on have VC++ installed which licenses the machine to use the redistributable controls that require it. The affected controls are Animated Button Control, Key Status Control, Multimedia MCI Control, MsComm Control,
Masked Edit, Grid Control, and Picture Clip Control. If the machine is not licensed the license key must be specified in the call to Create(). Creating an instance of the controls in a dialog box however will succeed.