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

MsiViewModify failes with ERROR_FUNCTION_FAILED


Best Answer deramor , 09 July 2014 - 23:30

Putting this here for everyone.  I fixed it.

The problem was the following call:

hRec = MsiCreateRecord(nCount);

 

In this case, nCount is variable.  This was the number of Ethernet adapters in the system.  This is what my ComboBox was displaying.

MsiCreateRecord sets up the number of records or "columns" in the table entry.  For the ComboBox table, this number is 4.

 

The reason I had issues reproducing the problem on some systems was that I had a system with 3 NICs.  Other people had 2 or 1.

In this case, 3 NICs would create 3 "columns" in the table.  In the ComboBox table, the 4th column is not needed. (optional)

Therefore, the implementation worked for me.  For those with less than 3 NICs, the ComboBox was blank since the calls to MsiRecordSetString would try to set a record that I didn't ask to be created.  It also happened to fail on the required values/entries.  This meant the entry in the table was invalid which caused errors when writing the entire line to the table.

 

For anyone who looked at this and gave it some thought, thank you.

 

I hope this will help people with similar problems.

Go to the full post


2 replies to this topic

deramor

deramor
  • Full Members
  • 187 posts

Posted 09 July 2014 - 17:32

Hello-

 

I am creating an installation dialog with a dynamically populated combobox on it.

On most systems the combo box populates just fine. 

 

I generate a string list of values then:

 

i=0;
    hDatabase = MsiGetActiveDatabase(hMSI);

    sQuery = "SELECT * FROM ComboBox WHERE Property='COMBOBOXPROP'";
    nResult = MsiDatabaseOpenView(hDatabase, sQuery, hCBOView);
    
    // Allocate space to hold the properties of a combobox row...
    hRec = MsiCreateRecord(nCount);
   
    nResult = ListGetFirstString (listIPAddresses, svString);                      

    // Loop while list items continue to be retrieved.      
    while (nResult != END_OF_LIST)
        ret = MsiRecordSetString    (hRec, 1, 'COMBOBOXPROP');     // Combobox name. Must be unique with MSI
        
        MsiRecordSetInteger    (hRec, 2, i);   // Position of the line in the combo 
        
        MsiRecordSetString    (hRec, 3, svString);         // Key String - a string related to the line    
        
        MsiRecordSetString    (hRec, 4, svString);         // String to be displayed 
        
        // Write the updated row
        ret = MsiViewModify(hCBOView, MSIMODIFY_INSERT_TEMPORARY, hRec);
       
        nResult = ListGetNextString (listIPAddresses, svString);
        i++;      
    endwhile;
    
    // Select the first item in the list as default.
    nResult = ListGetFirstString (listIPAddresses, svString);
    MsiSetProperty(hMSI, "COMBOBOXPROP", svString);
    
    // Close handles
    MsiCloseHandle(hRec);
    MsiViewClose (hView);

 

My problem is that on some systems, the call to MsiViewModify fails with the ever so descriptive error code: ERROR_FUNCTION_FAILED

 

Some things I've tried thus far:

I thought that the text I was entering into the value fields was too long so I set the ComboBox Max Length to 256 which should be more than enough.  This did not help.

 

I thought that perhaps the value I was assigning to the position in the call: MsiRecordSetInteger(hRec, 2, i); was incorrect so I started the iterator (i) at 1 rather than 0.  This also did not help.  However when I add a line to the ComboBox table manually in Installshield, I get an error about putting a zero there so maybe that is part of the problem except it works on many PCs with a 0 iterator start.

 

An off-hand question about SQL Queries...Does there need to be any SQL database software installed in order for these functions to succeed?  I am guessing no since the dependencies for these functions on MSDN is only msi.dll.  At this point I feel like no question is a silly question.

 

I will continue to poke and prod at it but I am running out of ideas.  I was hoping someone else could offer some input.

 

Many thanks.



deramor

deramor
  • Full Members
  • 187 posts

Posted 09 July 2014 - 17:44

Apologies.  After reading the post after I posted, I noticed that I was not checking 3 return codes.

I made the edit and ran my debugging steps again.

 

There is a failed called to MsiRecordSetString before the View is modified.

The failing call: ret = MsiRecordSetString    (hRec, 4, svString); This returns with ERROR_INVALID_PARAMETER.

 

I can only assume the following:

The passed handle is correct since it is the same as the previous 3 calls and those passed.

 

The remaining parameters are the iField and value.

 

The value is just string data.  In fact the same string data passed to the call just prior to the failing one.  Do they have to be different?  Is there a buffer that needs to be flushed?

 

The iField is more curious.

http://msdn.microsof...3(v=vs.85).aspx

The MSDN article for the function says this parameter is:

Field [in]

Specifies the field of the record to set.

So great... There is no description of what that should be.

I am doing what I am doing because of another helpful thread on this forum which explained how to do exactly what I wanted.

It seemed to work for me so I went with it.  The jump up here is that I really don't know why I am choosing values 1, 2, 3, and 4 for each of these function calls for the "iField"



deramor

deramor
  • Full Members
  • 187 posts

Posted 09 July 2014 - 23:30   Best Answer

Putting this here for everyone.  I fixed it.

The problem was the following call:

hRec = MsiCreateRecord(nCount);

 

In this case, nCount is variable.  This was the number of Ethernet adapters in the system.  This is what my ComboBox was displaying.

MsiCreateRecord sets up the number of records or "columns" in the table entry.  For the ComboBox table, this number is 4.

 

The reason I had issues reproducing the problem on some systems was that I had a system with 3 NICs.  Other people had 2 or 1.

In this case, 3 NICs would create 3 "columns" in the table.  In the ComboBox table, the 4th column is not needed. (optional)

Therefore, the implementation worked for me.  For those with less than 3 NICs, the ComboBox was blank since the calls to MsiRecordSetString would try to set a record that I didn't ask to be created.  It also happened to fail on the required values/entries.  This meant the entry in the table was invalid which caused errors when writing the entire line to the table.

 

For anyone who looked at this and gave it some thought, thank you.

 

I hope this will help people with similar problems.