Notice: This website is an unofficial Microsoft Knowledge Base (hereinafter KB) archive and is intended to provide a reliable access to deleted content from Microsoft KB. All KB articles are owned by Microsoft Corporation. Read full disclaimer for more details.

PRB: "<XLL Name> Is Not a Valid Add-In" Error Message When You Load XLL That Is Rebuilt by Using Visual Studio .NET 2003


View products that this article applies to.

Symptoms

When you rebuild an Excel-link library (XLL) with Microsoft Visual Studio .NET 2003, and that XLL was originally written in Visual C++ 6.0, Excel cannot recognize the XLL. When you do the rebuild, and then you add in the rebuilt XLL to Excel, you receive the following error message:

<XLL Name> is not a valid add-in.

↑ Back to the top


Cause

For performance reasons in Visual C++ .NET 2003, the string literals in the XLL are written in a read-only section of the XLL. Therefore, when you modify the string literals in XLL, an access violation (AV) occurs, and you receive the error message that is mentioned in the "Symptoms" section.

↑ Back to the top


Workaround

To work around this problem, copy the read-only string to a non-read-only string. Then you must length-prefix the new non-read-only string for Excel. To do this, follow these steps:
  1. Look at the beginning of your source file.

    The declaration of the array of static strings looks similar to the following code:
    #define g_rgWorksheetFuncsRows 4
    static char* g_rgWorksheetFuncs[g_rgWorksheetFuncsRows][10] =
    {
       { " TestArrayFunction",  // Procedure
          " BK",                // type_text
          " TestArrayFunction", // function_text
               ...
        }
    }
    
  2. Rename the array to g_rgStaticWorksheetFuncs.

    This helps you by reducing the number of changes that you must make in the code of your XLL.
    #define g_rgWorksheetFuncsRows 4
    static char* g_rgStaticWorksheetFuncs[g_rgWorksheetFuncsRows][10] =
    {
       { " TestArrayFunction", // Procedure
          " BK",               // type_text
          " TestArrayFunction",// function_text
                ...
    
       }
    }
    
  3. Add a new global variable with the same name as the original array name and with the same signature as the original array signature.

    Make sure that you do not initialize the new global variable with hard-coded values.
    #define g_rgWorksheetFuncsRows 4
    static char* g_rgWorksheetFuncs[g_rgWorksheetFuncsRows][10];
    static char* g_rgStaticWorksheetFuncs[g_rgWorksheetFuncsRows][10] =
    {
       { " TestArrayFunction",              // Procedure
          " BK",                                  // type_text
          " TestArrayFunction",              // function_text
                �
       }
    }
    
  4. In the DllMain function of the XLL, verify that you have code that is similar to the following code.

    Note The purpose of this code is to length-prefix all the hard-coded strings.
       int i,j;
       for (i=0; i<g_rgWorksheetFuncsRows; i++) 
       {
          for (j=0; j<10; j++) 
          {
             BYTE currentVal = (BYTE)strlen(g_rgWorksheetFuncs[i][j]+1);
             g_rgWorksheetFuncs[i][j][0] = currentVal;
          }
       }
    
  5. Rewrite the code in the DllMain function of the XLL so that the code is similar to the following code:

    Note The modified code copies the static string array to an array that is non-read-only. The modified code length-prefixes the copied non-read-only string for use by Excel.
      int i,j;
       for (i=0; i<g_rgWorksheetFuncsRows; i++) 
       {
          for (j=0; j<10; j++) 
          {
             //Get the current length of the static string.
             BYTE currentVal = (BYTE)strlen(g_rgStaticWorksheetFuncs[i][j]+1);
    
             //Create a new non-read-only string and then initialize it.
             g_rgWorksheetFuncs[i][j] = new char[currentVal+2];
             memset( g_rgWorksheetFuncs[i][j], '\0', currentVal+2 );
    
             //Copy the read-only string to the non-read-only string.
             memcpy( g_rgWorksheetFuncs[i][j]+1, g_rgStaticWorksheetFuncs[i][j] + 1,
                currentVal );
    
             //Length-prefix the non-read-only string.
             g_rgWorksheetFuncs[i][j][0] = currentVal;
          }
       }
    
  6. Recompile and then test your XLL.

↑ Back to the top


More information

The problem that is mentioned in the "Symptoms" section occurs when you try to length-prefix the read-only string. The following code is a sample of the code that produces the problem:
   for (i=0; i<g_rgWorksheetFuncsRows; i++) 
   {
      for (j=0; j<10; j++) 
      {
         BYTE currentVal = (BYTE)strlen(g_rgWorksheetFuncs[i][j]+1); // Produces AV.
         g_rgWorksheetFuncs[i][j][0] = currentVal;
      }
   }
The previous code produces an access violation when you try to assign the currentVal variable to the g_rgWorksheetFuncs[i][j][0] byte.

↑ Back to the top


References

For additional information, click the following article number to view the article in the Microsoft Knowledge Base:
178474� HOWTO: Build an Add-in (XLL) for Excel Using Visual C++

↑ Back to the top


Keywords: KB824459, kbaddin, kbdll, kberrmsg, kbprb

↑ Back to the top

Article Info
Article ID : 824459
Revision : 3
Created on : 9/23/2003
Published on : 9/23/2003
Exists online : False
Views : 442