none
CAB Installation fails on device when CAB built in Release mode when using custom Setup DLL (ShellExecuteEx)

    Question

  • Hi,

    I have tried to implement the custom Setup DLL and associated upgrade check as detailed in the following blog post :-

    http://blogs.msdn.com/b/raffael/archive/2009/04/22/programmatically-discriminate-between-upgrade-or-uninstall-of-a-cab-on-windows-mobile.aspx

    Things were going well until I change my solution to Release mode, now the CAB file fails to install.

    I have managed to track down the offending line of code :-

    bRet = ShellExecuteEx(&sei);

    Commenting this line of code allows for successful installation of the CAB file, however on upgrade the code will not function as required.

    The weird thing is that everything works fine when the solution is in Debug mode, no errors when installing the CAB file.

    I have been through the various project properties however I haven't found anything obvious that maybe causing the problem and my lack of C++ experience means I am lost as to why this would be occuring.

    I have tried installing the CAB file on another device however I am presented with the same installation failure.

    I would be really grateful if someone could help me.

    Thank you very much for taking the time to read this.

    Paul Diston

     


    http://www.smartmobiledevice.co.uk/
    Friday, June 11, 2010 4:35 PM

Answers

  • Hi Paul,

    Reading through your code, i can see a possible cause for your error (I'm assuming that the code snippet is the function body and it's not enclosed in a control loop): if the file is not found, you are deleting the string that contains the file name. The break statement only affects the enclosing if (as per my assumption) and the code tries to execute the ShellExecuteEx with an invalid pointer.

    As a side note, you don't need to allocate memory for that string. If your code is not supposed to change it, then:

    LPCWSTR pszFileNameWithPath = TEXT("\\Program Files\\SampleApplication\\SampleApplication.exe"); 

    should be enough for you. The string is statically allocated as a global variable and you don't have to care about releasing it.

    Hope this helps!

     

     


    João Paulo Figueira (Device Application Development MVP)
    Monday, June 14, 2010 8:40 AM
  • Hi,

    I seem to have had some success, thank you so much for your help.

    From your recommendation about allocating the string I have found that the following code now allows for a successful installation :-

    g_hinstModule = (HINSTANCE)hModule;  
    
    //check if UpgCheck.exe is already available on device (1st time it won't, but in any case we don't need it)  
    TCHAR pszFileNameWithPath[MAX_PATH]; 
    memset (&pszFileNameWithPath, 0, sizeof(pszFileNameWithPath));
    
    wcscpy(pszFileNameWithPath, _T("\\Program Files\\SampleApplication\\SampleApplication.exe"));
    
    WIN32_FIND_DATA wfdFindFileData;  
    
    HANDLE hFile = FindFirstFile(pszFileNameWithPath, &wfdFindFileData);  
    
    if(hFile == INVALID_HANDLE_VALUE)  
    {
    	FindClose(hFile);
    }
    else
    {
    	FindClose(hFile);
    
      //Launch external process that will monitor wceload.exe  
    	BOOL bRet;  
    	SHELLEXECUTEINFO sei;
    	memset(&sei, 0, sizeof(SHELLEXECUTEINFO));
    	sei.cbSize = sizeof(sei);  
    	sei.nShow = SW_SHOWNORMAL;  
    	sei.lpFile = pszFileNameWithPath;  
    	sei.lpParameters = TEXT(" "); 
    
    	bRet = ShellExecuteEx(&sei);
    
    	if(!bRet)
    	{
    		TCHAR szMsg[80];
    		wsprintf(szMsg, L"GetLastError = %d", GetLastError());
    		MessageBox(NULL, szMsg, L"Error", MB_OK);
    	}
    }

    There didn't seem to be an error with the ShellExecuteEx, it seemed to be a problem with deleting the string used for the filename.

    Thanks once again for your help.

    Paul Diston


    http://www.smartmobiledevice.co.uk/
    • Edited by Paul Diston Monday, June 14, 2010 4:34 PM
    • Marked as answer by Paul Diston Tuesday, June 15, 2010 8:02 AM
    Monday, June 14, 2010 12:06 PM

All replies

  • I would guess that you are not properly initializing the SHELLEXECUTEINFO structure. Can you please show the code you are using?


    João Paulo Figueira (Device Application Development MVP)
    Friday, June 11, 2010 9:29 PM
  • Hi,

    Thank you very much for your reply.

    The code I am using is as follows :-

    //check if UpgCheck.exe is already available on device (1st time it won't, but in any case we don't need it)  
    LPCWSTR pszFileNameWithPath = new TCHAR[MAX_PATH];  
    pszFileNameWithPath = TEXT("\\Program Files\\SampleApplication\\SampleApplication.exe");  
    WIN32_FIND_DATA wfdFindFileData;  
    HANDLE hFile = FindFirstFile(pszFileNameWithPath, &wfdFindFileData);  
    if(hFile == INVALID_HANDLE_VALUE)  
    { 
    	DELETE_STR(pszFileNameWithPath);    
    	break;  
    }  
    FindClose(hFile);
    
    //Launch external process that will monitor wceload.exe  
    BOOL bRet;  
    SHELLEXECUTEINFO sei = {0};  
    //
    sei.cbSize = sizeof(sei);  
    sei.nShow = SW_SHOWNORMAL;  
    sei.lpFile = pszFileNameWithPath;  
    sei.lpParameters = TEXT(" ");
    bRet = ShellExecuteEx(&sei);  
    			
    //if (!bRet)  
    // MessageBox(NULL, TEXT("Could not launch UpgCheck"), TEXT("Test"), MB_OK);  
    			
    DELETE_STR(pszFileNameWithPath); 

    Thank you.

    Paul Diston


    http://www.smartmobiledevice.co.uk/
    Monday, June 14, 2010 7:52 AM
  • Hi Paul,

    Reading through your code, i can see a possible cause for your error (I'm assuming that the code snippet is the function body and it's not enclosed in a control loop): if the file is not found, you are deleting the string that contains the file name. The break statement only affects the enclosing if (as per my assumption) and the code tries to execute the ShellExecuteEx with an invalid pointer.

    As a side note, you don't need to allocate memory for that string. If your code is not supposed to change it, then:

    LPCWSTR pszFileNameWithPath = TEXT("\\Program Files\\SampleApplication\\SampleApplication.exe"); 

    should be enough for you. The string is statically allocated as a global variable and you don't have to care about releasing it.

    Hope this helps!

     

     


    João Paulo Figueira (Device Application Development MVP)
    Monday, June 14, 2010 8:40 AM
  • Hi,

    Thank you very much for suggestion.

    Would you be able to suggest any changes to the code?

    With regard to usage, the code snippet above is executed in the DLL_PROCESS_ATTACH case statement of the DllMain method as per the code in the original blog post.

     Also, would you have any ideas why this code would function "correctly" under Debug but would fail under Release?

    Thanks

    Paul Diston

     


    http://www.smartmobiledevice.co.uk/

     

    Monday, June 14, 2010 9:42 AM
  • I usually split the cases into separate functions for better encapsulation.

    Please run the code again in Release mode and add a MessageBox to report the value of GetLastError. Something like:

    if(!bRet)
    {
      TCHAR szMsg[80];
      wsprintf(szMsg, L"GetLastError = %d", GetLastError());
      MessageBox(szMsg, L"Error", MB_OK);
    }
    This will help in debugging the error.
    João Paulo Figueira (Device Application Development MVP)
    Monday, June 14, 2010 10:04 AM
  • Hi,

    I have added the MessageBox code as suggested however this message box doesn't appear.

    To try and debug this further I added MessageBoxes in the following fashion however the first message box would display (1.0), however dismissing this messagebox then didn't make any further message boxes appear, the installation just seems to pause with the wait cursor appearing and no further information :-

    MessageBox(NULL, L"1.0", L"Error", MB_OK);
    			
    g_hinstModule = (HINSTANCE)hModule;        
    
    MessageBox(NULL, L"1.1", L"Error", MB_OK);
    
    //check if UpgCheck.exe is already available on device (1st time it won't, but in any case we don't need it)       
    LPCWSTR pszFileNameWithPath = new TCHAR[MAX_PATH];       
    
    MessageBox(NULL, L"1.2", L"Error", MB_OK);

    Thanks

    Paul Diston


    http://www.smartmobiledevice.co.uk/
    Monday, June 14, 2010 11:21 AM
  • Hi,

    I seem to have had some success, thank you so much for your help.

    From your recommendation about allocating the string I have found that the following code now allows for a successful installation :-

    g_hinstModule = (HINSTANCE)hModule;  
    
    //check if UpgCheck.exe is already available on device (1st time it won't, but in any case we don't need it)  
    TCHAR pszFileNameWithPath[MAX_PATH]; 
    memset (&pszFileNameWithPath, 0, sizeof(pszFileNameWithPath));
    
    wcscpy(pszFileNameWithPath, _T("\\Program Files\\SampleApplication\\SampleApplication.exe"));
    
    WIN32_FIND_DATA wfdFindFileData;  
    
    HANDLE hFile = FindFirstFile(pszFileNameWithPath, &wfdFindFileData);  
    
    if(hFile == INVALID_HANDLE_VALUE)  
    {
    	FindClose(hFile);
    }
    else
    {
    	FindClose(hFile);
    
      //Launch external process that will monitor wceload.exe  
    	BOOL bRet;  
    	SHELLEXECUTEINFO sei;
    	memset(&sei, 0, sizeof(SHELLEXECUTEINFO));
    	sei.cbSize = sizeof(sei);  
    	sei.nShow = SW_SHOWNORMAL;  
    	sei.lpFile = pszFileNameWithPath;  
    	sei.lpParameters = TEXT(" "); 
    
    	bRet = ShellExecuteEx(&sei);
    
    	if(!bRet)
    	{
    		TCHAR szMsg[80];
    		wsprintf(szMsg, L"GetLastError = %d", GetLastError());
    		MessageBox(NULL, szMsg, L"Error", MB_OK);
    	}
    }

    There didn't seem to be an error with the ShellExecuteEx, it seemed to be a problem with deleting the string used for the filename.

    Thanks once again for your help.

    Paul Diston


    http://www.smartmobiledevice.co.uk/
    • Edited by Paul Diston Monday, June 14, 2010 4:34 PM
    • Marked as answer by Paul Diston Tuesday, June 15, 2010 8:02 AM
    Monday, June 14, 2010 12:06 PM
  • Hi João,

    Please could you change the quote in your previous reply for the EXE path and filename to be as follows :-

    "\\Program Files\\SampleApplication\\SampleApplication.exe"

    Thanks

    Paul Diston


    http://www.smartmobiledevice.co.uk/
    Monday, June 14, 2010 4:34 PM
  • Hi paul,

     

    currently i am working on win form application and using CAB but i face same issue means when i build my application from Visual studio 2008 in debug mode and run exe from debug folder my application working fine but whenever i build my application in release mode and run the exe file , application not working even i try to add setup project and create project installation msi system give same error as in release mode can u help me to create project installation msi from setup project ...

    I would be really grateful if you help me.

     

    Regards

    Shailesh

    Wednesday, July 07, 2010 9:40 AM