Microsoft KB Archive/824459

= PRB: &quot; Is Not a Valid Add-In&quot; Error Message When You Load XLL That Is Rebuilt by Using Visual Studio .NET 2003 =

Article ID: 824459

Article Last Modified on 9/23/2003

-

APPLIES TO


 * Microsoft Visual C++ .NET 2003 Standard Edition
 * Microsoft Excel 2002 Standard Edition
 * Microsoft Excel 97 Standard Edition

-





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:

 is not a valid add-in.



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 &quot;Symptoms&quot; section.



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:   Look at the beginning of your source file.

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

This helps you by reducing the number of changes that you must make in the code of your XLL. static char* g_rgStaticWorksheetFuncs[g_rgWorksheetFuncsRows][10] = {  { &quot; TestArrayFunction&quot;, // Procedure &quot; BK&quot;,              // type_text &quot; TestArrayFunction&quot;,// function_text ...
 * 1) define g_rgWorksheetFuncsRows 4

} }   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. static char* g_rgWorksheetFuncs[g_rgWorksheetFuncsRows][10]; static char* g_rgStaticWorksheetFuncs[g_rgWorksheetFuncsRows][10] = {  { &quot; TestArrayFunction&quot;,              // Procedure &quot; BK&quot;,                                 // type_text &quot; TestArrayFunction&quot;,             // function_text …  } }   In the DllMain function of the XLL, verify that you have code that is similar to the following code.
 * 1) define g_rgWorksheetFuncsRows 4

Note The purpose of this code is to length-prefix all the hard-coded strings. int i,j; for (i=0; i  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; }  } </li> Recompile and then test your XLL.</li></ol>

<div class="moreinformation_section">

MORE INFORMATION
The problem that is mentioned in the &quot;Symptoms&quot; 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.

<div class="references_section">