Home | All Classes | Main Classes | Annotated | Grouped Classes | Functions |

# QAxServer FAQ

- The QAxServer build system
- Typical build problems
  - Compiler errors
    - "No overloaded function takes 2 parameters"
    - "syntax error: bad suffix on number"
  - Linker errors
    - "unresolved external symbol _ucm_instantiate"
    - "_ucm_initialize already defined in ..."
    - "unresolved external symbol _main"
    - "cannot open file ... "
  - Postprocessing and runtime errors
    - The server executable is not a valid Win32 application
    - "Unable to Locate DLL"
    - The Server does not respond
    - The Object cannot be created
- Debugging runtime errors
- Distributing QAxServer binaries
  - Installing stand-alone Servers
  - Installing In-process Servers
  - Distributing Servers over the Internet
- Supported and Unsupported ActiveX clients
  - Supported Clients
  - Unsupported Clients

## The QAxServer build system

To be able to build ActiveX controls with Qt, the build system must be extended to include some additional build steps that are used when the `.pro` file includes `activeqt` in the `CONFIG` settings. The resulting makefile will:

- Link the executable against `qaxserver.lib` instead of `qtmain.lib`
- Call the resulting executable with the `-dumpidl` parameter to generate an IDL description of the ActiveX controls provided by the server.
- Compile the IDL into a type library using the MIDL tool
- Attach the resulting type library as a binary resource to the server executable

Attaching resources to an executable is not supported by Windows 95/98/ME, but a server built on Windows NT/2000/XP will work on those versions.

## Typical build problems

The compiler/linker errors listed are based on those issued by the Microsoft Visual C++ 6.0 compiler.

### Compiler errors

#### "No overloaded function takes 2 parameters"

When the error occurs in code that uses the QAXFACTORY_DEFAULT macro, the widget class had no constructor that can be used by the default factory. Either add a standard widget constructor or implement a custom factory that doesn't require one.

When the error occurs in code that uses the QAXFACTORY_EXPORT macro, the QAxFactory subclass had no appropriate constructor. Provide a public class constructor like

        MyFactory( const QUuid &, const QUuid & );

for your factory class.

#### "syntax error: bad suffix on number"

The unique identifiers have not been passed as strings into the QAXFACTORY_EXPORT or QAXFACTORY_DEFAULT macro.

### Linker errors

#### "unresolved external symbol _ucm_instantiate"

The server does not export an implementation of a QAxFactory. Use the QAXFACTORY_EXPORT macro in one of the project's implementation files to instantiate and export a factory, or use the QAXFACTORY_DEFAULT macro to use the default factory.

#### "_ucm_initialize already defined in ..."

The server exports more than one implementation of a QAxFactory, or exports the same implementation twice. If you use the default factory, the QAXFACTORY_DEFAULT macro must only be used once in the project. Use a custom QAxFactory implementation and the QAXFACTORY_EXPORT macro if the server provides multiple ActiveX controls.

#### "unresolved external symbol _main"

The application does not provide an entry point function `main()`. Implement a standard Qt main function, and use QAxFactory::isServer() to prevent or control stand-alone execution of the application.

        int main( int argc, char **argv )
        {
            QApplication app( argc, argv );

            if ( !QAxFactory::isServer() ) {
                QMessageBox::critical( 0, "Cannot run stand-alone!",
                                          "This executable is a server for ActiveX controls." );
                return -1;
            }

            return app.exec();
        }

Note that even in-process servers must implement a `main()` function to satisfy the linker, although they can use a dummy implementation because it will never be called.

        void main()
        {}

#### "cannot open file ... "

The ActiveX server could not shut down properly when the last client stopped using it. It usually takes about two seconds for the application to terminate, but you might have to use the task manager to kill the process (e.g. when a client doesn't release the controls properly).

### Postprocessing and runtime errors

#### The server executable is not a valid Win32 application

Attaching the type library corrupted the server binary. This is a bug in Windows and happens only with release builds.

The first linking step has to link a dummy type library into the executable that can later be replaced by idc. Add a resource file with a type library to your project as demonstrated in the examples.

#### "Unable to Locate DLL"

The build system needs to run the server executable to generate the interface definition, and to register the server. If a dynamic link library the server links against is not in the path this might fail (e.g. Visual Studio calls the server using the enivronment settings specified in the "Directories" option). Make sure that all DLLs required by your server are located in a directory that is listed in the path as printed in the error message box.

#### The Server does not respond

If the system is unable to start the server (check with the task manager whether the server runs a process), make sure that no DLL the server depends on is missing from the system path (e.g. the Qt DLL!). Use a dependency walker to view all dependencies of the server binary.

If the server runs (e.g. the task manager lists a process), see the following section for information on debugging your server.

#### The Object cannot be created

If the server could be built and registered correctly during the build process, but the object cannot be initiliazed e.g. by the OLE/COM Object Viewer application, make sure that no DLL the server depends on is missing from the system path (e.g. the Qt DLL). Use a dependency walker to view all dependencies of the server binary.

If the server runs, see the following section for information on debugging your server.

## Debugging runtime errors

To debug an in-process server in Visual Studio, set the server project as the active project, and specify a client "executable for debug session" in the project settings (e.g. use the ActiveX Test Container). You can set breakpoints in your code, and also step into ActiveQt and Qt code if you installed the debug version.

To debug an executable server, run the application in a debugger and start with the command line parameter "-activex". Then start your client and create an instance of your ActiveX control. COM will use the existing process for the next client trying to create an ActiveX control.

## Distributing QAxServer binaries

ActiveX servers written with Qt can use Qt either as a shared library, or have Qt linked statically into the binary. Both ways will produce rather large packages (either the server binary itself becomes large, or you have to ship the Qt DLL).

### Installing stand-alone Servers

When your ActiveX server can also run as a stand-alone application, run the server executable with the `-regserver` command line parameter after installing the executable on the target system. After that the controls provided by the server will be available to ActiveX clients.

### Installing In-process Servers

When your ActiveX server is part of an installation package, use the `regsvr32` tool provided by Microsoft to register the controls on the target system. If this tool is not present, load the DLL into your installer process, resolve the `DllRegisterServer` symbol and call the function:

        HMODULE dll = LoadLibrary( "myserver.dll" );
        typedef HRESULT(__stdcall *DllRegisterServerProc)();
        DllRegisterServerProc DllRegisterServer =
            (DllRegisterServerProc)GetProcAddress( dll, "DllRegisterServer" );

        HRESULT res = E_FAIL;
        if ( DllRegisterServer )
            res = DllRegisterServer();
        if ( res != S_OK )
            // error handling

### Distributing Servers over the Internet

If you want to use controls in your server in web-pages you need to make the server available to the browser used to view your page, and you need to specify the location of the server package in your page.

To specify the location of a server, use the CODEBASE attribute in the OBJECT tag of your web-site. The value can point to the server file itself, to an `INF` file listing other files the server requires (e.g. the Qt DLL), or a compressed `CAB` archive.

INF and CAB files are documented in almost every book available about ActiveX and COM programming as well as in the MSDN library and various other Online resources. The examples include INF files that can be used to build CAB archives:

        [version]
            signature="$CHICAGO$"
            AdvancedINF=2.0
         [Add.Code]
            simpleax.exe=simpleax.exe
         [simpleax.exe]
            file-win32-x86=thiscab
            clsid={DF16845C-92CD-4AAB-A982-EB9840E74669}
            RegisterServer=yes

The CABARC tool from Microsoft can easily generate CAB archives:

     cabarc N simpleax.cab simpleax.exe simple.inf

The INF files assume a static build of Qt, so no dependencies to other DLLs are listed in the INF files. To distribute an ActiveX server depending on DLLs you must add the dependencies, and provide the library files with the archive.

## Supported and Unsupported ActiveX clients

The following sections list standard applications that have been reported to work or not work with ActiveX controls developed with ActiveQt.

### Supported Clients

- Internet Explorer
- Microsoft ActiveX Control Test Container
- Microsoft Visual Studio 6.0 (dialog editor)
- Microsoft Visual Basic 6.0 (only in-process controls)
- MFC- and ATL-based containers
- Sybase PowerBuilder
- ActiveQt based containers

### Unsupported Clients

- Visual Studio.NET - Microsoft's unmanged code wrapper is reported to be buggy for C++ controls that don't expose a dual interface.
- Borland Builder, Delphi - don't support C++ COM objects that don't expose a dual interface.
- Microsoft Office Applications - these require aggregation support