CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Apr 2002
    Location
    Quebec City, Qc
    Posts
    2

    How to create an exe that work on every Windows machine

    I made an (MFC)application (with some use of CORBA). When I run it on my computer it works. But when I try to run it on other Windows machines (without Visual Studio installed), it doesn't work (can't find MSCV...dll). What can I do ? Is it possible to make a "package and deployment file" like Visual Basic.

    Thx


  2. #2
    Join Date
    Jul 2001
    Location
    Florida, USA
    Posts
    107

    Re: How to create an exe that work on every Windows machine

    Did you build it with the debug configuration or the Release configuration?

    To distribute it you need to build it with the Release configuration. To change this in Microsoft Visual C++ select the Build menu and then Set Active Configuration. Select the Release one and then rebuild it. The .exe will now be in the Release folder, not the Debug folder.

    Hope this helps.


  3. #3
    Join Date
    Aug 2001
    Location
    North Bend, WA
    Posts
    1,947

    Re: How to create an exe that work on every Windows machine

    I found this article on MSDN by dyping "redist" into the index.

    Applications built with Microsoft Visual C++ may require a number of supporting dynamic-link libraries (DLLs), depending on the way the application was built. The conditions under which you may or may not redistribute these files are described in the separate License Agreement included in the Visual C++ product. This article details the DLLs that must be redistributed with different types of applications.

    Visual C++ redistributable files are located in several directories on the Visual C++ CD-ROM. See the file REDISTRB.WRI in the \OS\System directory on the Visual C++ CD-ROM for the locations of the redistributable files. These files are not installed by Visual C++ Setup in a separate directory on your hard disk. However, depending on the setup options you choose, Visual C++ Setup may install some of these files in your Windows System directory. When you redistribute any of these files, you should copy them from the CD to your own distribution disk image, rather than from your hard disk, to make sure you are redistributing the correct version of the files.

    What do you want to know more about?
    Categories of redistributable files


    Version checking of redistributable files


    MFC/other DLL files


    ODBC files



  4. #4
    Join Date
    Mar 2002
    Posts
    9

    Re: How to create an exe that work on every Windows machine

    vc6redistsetup.exe or something like that... You found it in microsoft www-sites. It contains those needed dlls. Least i hope so..


  5. #5
    Join Date
    Feb 2002
    Posts
    3,788

    Re: How to create an exe that work on every Windows machine

    If I get it right the answer could be very simple:
    When building use MFC as a statically link library
    "Project Settings->General : Use MFC in a Static Library"


  6. #6
    Join Date
    Feb 2002
    Posts
    53

    Release vs Debug

    What is the difference between the Release built and the Debug built ?


  7. #7
    Join Date
    Jul 2001
    Location
    Florida, USA
    Posts
    107

    Re: Release vs Debug

    Here is a link to a page in MSDN which gives some good differences and explains some problems you might have when changing your build from debug to release.

    http://msdn.microsoft.com/library/de...ease_build.asp


  8. #8
    Join Date
    May 2000
    Location
    KY, USA
    Posts
    18,652

    Re: How to create an exe that work on every Windows machine

    You can link the MFC dll statically as suggested but I don't like this thing very much since it blows up your application file etc. Usually I suggest building a custom-based installation file (you can use InstallShield for example) which installs your application and all necessary dll's on the target system even with version checking...

    Updating system dll's is always a tricky thing to do. But nevertheless sometimes your software requires changing some of the system dll's.

    In this context it is important to install a newer version of a file and not an older one. For example, you will want to install a newer version of a system DLL on top of an older version, but not an older version on top of a newer version. Typically, version checking is the responsibility of the setup program. If you write your own custom setup program, you must manually check the version when installing redistributable files.

    First of all you need to find out which dll's needs to be redistributed to make sure that your application will run independent of the installed dll's on the target system. For an overview of the dependicies of your application you have two possibilities:

    1. Use the 'Dependency Walker' (depends.exe)

    2. Use 'Dumpbin' (dumpbin.exe) with the parameter /DEPENDENTS

    Both methods will show you a list of dll's that are linked to your application - either statically or dynamically. To find out which dll's are dynamically loaded you need to use the profiling feature of the 'Dependeny Walker'.

    Be always aware that a dll might have dependicies to other dll's or even a version of a specific dll. If you have installed your application on a target system and it won't run you can again use the 'Dependency Walker'. Run it on the target machine and it will report which dll's are either missing or present with an incorrect version. Dll's should always overwrite the existing dll's to avoid multiple instances of the dll on the system.

    If your application needs MFC support and you don't want to link it statically to your application (which I normally not recommend) you need to distribute it as well. MFC dll's are shared components therefore they will be placed within the system directory. You can get the system directory by a call to the API function

    UINT GetSystemDirectory(LPTSTR lpBuffer, UINT uSize)



    Again, installations within the system directory needs to be done carefully. NEVER overwrite a newer dll since other applications may rely on the specific version. To check the version of a dll Windows provides several API functions (Version API).

    Your setup application needs to place needed files in the correct locations and prompt the user if the setup application notice some significantly difference like different language version or you try to overwrite a newer file with the older one. Therefore you will need some information on those files like name and location of the source and destination file and much more important the sharing status of the file (only used by one application or shared between multiple applications).

    Regarding the location and the sharing status you can use the function

    DWORD VerFindFile(DWORD dwFlags,
    LPTSTR szFileName,
    LPTSTR szWinDir,
    LPTSTR szAppDir,
    LPTSTR szCurDir,
    PUINT lpuCurDirLen,
    LPTSTR szDestDir,
    PUINT lpuDestDirLen)



    This function will return several error codes whether the file is currently used by the system etc. Depending on the error code your setup program must react in a proper way.

    To install the source file you should use the function

    DWORD VerInstallFile(DWORD uFlags,
    LPTSTR szSrcFileName,
    LPTSTR szDestFileName,
    LPTSTR szSrcDir,
    LPTSTR szDestDir,
    LPTSTR szCurDir,
    LPTSTR szTmpFile,
    PUINT lpuTmpFileLen)



    since it will do some work for you. It copies the source file to a temporary file within the destination directory - if necessary it will expand a compressed file. After that an automatic comparison of the version information of the temporary and the destination file will be done. Again, your setup program should react to the returned error codes in a proper way. This function can be called multiple times with different flags. For example, if the first call returned an error indicating a version conflict you can force the installation disregarding the conflict by calling this function again with the 'VIFF_FORCEINSTALL' flag. On the other side your setup program needs to take care of the created temporary file by deleting them properly.

    To retrieve the version information your setup program can use the following functions

    DWORD GetFileVersionInfoSize(LPTSTR lptstrFilename, LPDWORD lpdwHandle)

    BOOL GetFileVersionInfo(LPTSTR lptstrFilename,
    DWORD dwHandle,
    DWORD dwLen,
    LPVOID lpData)

    BOOL VerQueryValue(const LPVOID pBlock,
    LPTSTR lpSubBlock,
    LPVOID *lplpBuffer,
    PUINT puLen)

    DWORD VerLanguageName(DWORD wLang, LPTSTR szLang, DWORD nSize)



    'GetFileVersionInfoSize()' returns the size of the version information. 'GetFileVersionInfo()' uses information retrieved by 'GetFileVersionInfoSize()' to retrieve a structure that contains the version information. 'VerQueryValue()' retrieves a specific member from that structure. Your setup program needs to call those function depending on the error code returned by e.g. 'VerInstallFile()'.

    The following is an example to get the product version...

    #include <string>
    #include <sstream>
    #include <malloc.h>
    #include <memory.h>
    #include <windows.h>

    using std::string;
    using std::stringstream;

    struct Language
    {
    WORD m_wLanguage;
    WORD m_wCodePage;
    };

    int main()
    {
    Language *pLanguageInfo = NULL;
    LPVOID pvResourceData = NULL;

    // Allocate language structure
    pLanguageInfo = new Language;
    if(pLanguageInfo)
    {
    // Clear structure
    memset(pLanguageInfo, 0, sizeof(Language));

    // Get version info
    DWORD dwHandle = 0;

    DWORD dwResourceSize = ::GetFileVersionInfoSize("Name of application", &dwHandle);
    if(dwResourceSize)
    {
    pvResourceData = malloc(dwResourceSize);
    if(pvResourceData)
    if(::GetFileVersionInfo("Name of application", 0, dwResourceSize, pvResourceData) != FALSE)
    {
    UINT uiSize = 0;

    // Get language information
    if(::VerQueryValue(pvResourceData, "\\VarFileInfo\\Translation", reinterpret_cast<LPVOID *>(&pLanguageInfo), &uiSize) == FALSE)
    return -1;
    }
    }
    }

    // Get specific info
    UINT uiSize = 0;
    stringstream strsQueryString;
    LPVOID pvValue = NULL;

    // Build query string
    strsTemp << "\\StringFileInfo\\" << setw(4) << setfill('0') << hex << pLanguageInfo->m_wLanguage
    << setw(4) << pLanguageInfo->m_wCodePage << "\\ProductVersion";

    if(::VerQueryValue(pvResourceData,
    const_cast<LPTSTR>(strsTemp.str().c_str()),
    static_cast<LPVOID *>(&pvValue),
    &uiSize) != FALSE)
    {
    // Convert product version
    string strProductVersion = static_cast<LPTSTR>(pvValue);

    string::size_type pos = 0;

    while((pos = strProductVersion.find(",", pos)) < string::npos)
    {
    strProductVersion.replace(pos, 1, ".");
    ++pos;
    }

    cout << strProductVersion;
    }

    return 0;
    }



    This of course is only a 'crash-course' in version management. But I hope it gives you at least a basic understanding how you can proceed with your setup application...

    Ciao, Andreas

    "Software is like sex, it's better when it's free." - Linus Torvalds

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured