Geeks With Blogs

News

Google My Blog

Catch me at: The List!


My InstallScript Utility Belt My Amazon Wishlist
My Standard Disclaimer


Archives
Chris G. Williams Beware: I mix tech and personal interests here.

This is a little collection of routines I've written to make my life easier when using InstallShield.  Use at your own risk. Modify to your heart's content.  No warranties expressed or implied.  Etc...

//////////////////////////////////////////////////////////////////////////////
//  File Name:   UsefulScripts.rul
//  Description: Reusable Installshield Scripts 
//  Comments:    Scripts that may prove to be handy in other installs
//               would go in this file.   
//            
//////////////////////////////////////////////////////////////////////////////

//////////////////// installation declarations ///////////////////
// ---- script function prototypes -----
 
 // these update the Web.Config
 prototype NUMBER ReadKey(HWND, STRING, STRING, byref STRING);
 prototype UpdateKey(HWND, STRING, STRING, STRING);
 prototype AddKey(HWND, STRING, STRING, STRING);
 prototype UpdateCustomErrors(HWND, STRING, STRING);

 // these help working with legacy (orphaned) installs
 prototype STRING CheckRegistryForPath(STRING);
 prototype STRING CheckRegistryForMSI(STRING);
 prototype NUMBER RemoveLegacyInstall(STRING, STRING, STRING);

 // these help working with Virtual Dirs
 prototype NUMBER CheckIISExists(HWND);
 prototype NUMBER DeleteVirtualDir(HWND, STRING);
 prototype NUMBER CheckVirtualDirExists(HWND, STRING); 

 // these help with file manipulation
 prototype NUMBER ClearReadOnly(HWND, STRING);
 

////////////////////////////////////////////////////////////////////////
// Function: ClearReadOnly
// Purpose: Clear the Read Only attribute on all files in or below the
//          directory passed in
////////////////////////////////////////////////////////////////////////
function NUMBER ClearReadOnly(hmsi, svDirectory)
 NUMBER nFilesResult;
 STRING svMatchingFileName;
 
 begin
  nFilesResult = FindAllFiles(svDirectory, "*.*", svMatchingFileName, RESET);
  while(nFilesResult = 0)
   SetFileInfo(svMatchingFileName, FILE_ATTRIBUTE, FILE_ATTR_NORMAL, "");
   nFilesResult = FindAllFiles(svDirectory,"*.*", svMatchingFileName, CONTINUE);
  endwhile;
  
  return nFilesResult;
 end;


////////////////////////////////////////////////////////////////////////
// Function: ReadKey
// Purpose: Read specific keys in Web.Config, using FileGrep
////////////////////////////////////////////////////////////////////////
function NUMBER ReadKey(hmsi, svFilePath, svFindEntry, svReturnValue)
 NUMBER nResult, nvLineNumber;
 STRING WebConfigFile, svReturnLine;

 begin
  // build the path to the Web.Config    
  WebConfigFile = svFilePath ^ "web.config";

  // search the Web.Config for the entry we specify
  nResult = FileGrep( WebConfigFile, svFindEntry, svReturnLine, nvLineNumber, RESTART );
  switch(nResult)
   case 0:
    // Since this line normally appears twice in our web.config file, we're
    // checking for the existence of a 2nd match and reading it instead.
    // If there is no 2nd match, go ahead and read the one we find.
    if ( svFindEntry = "ConnectionString" ) then
     nResult = FileGrep( WebConfigFile, "<add key=\"" + svFindEntry + "\"", svReturnLine, nvLineNumber, CONTINUE );
     if ( nResult < 0 ) then
      FileGrep( WebConfigFile, "<add key=\"" + svFindEntry + "\"", svReturnLine, nvLineNumber, RESTART );
     endif;
    endif;
   
    svReturnValue = svReturnLine;
    return 0;
   
   case -2:
    // File Not Found
    MessageBox( "Web.Config file not found.", SEVERE );
    return nResult;
   case -4:
    // EOF reached
    MessageBox( svFindEntry + " key not found.", SEVERE );
    return nResult;
   default:
    //unknown error
    MessageBox( "An unknown error has occurred. The Web.Config file could NOT be read.", SEVERE );
    return nResult;
  endswitch;
 end;


////////////////////////////////////////////////////////////////////////
// Function: AddKey
// Purpose: Add a key to the Web.Config, using FileGrep
////////////////////////////////////////////////////////////////////////
function AddKey(hmsi, svFilePath, svType, svNewEntry)
 NUMBER nResult, nvLineNumber;
 STRING WebConfigFile, svReturnLine;

 begin
  // build the path to the Web.Config    
  WebConfigFile = svFilePath ^ "web.config";

  if svType = "VERB" then
   // search the file for "</httpHandlers>" and insert ours immediately before it
   nResult = FileGrep( WebConfigFile, "</httpHandlers>", svReturnLine, nvLineNumber, RESTART );
  elseif svType = "KEY" then
   // search the file for "</appSettings>" and insert ours immediately before it
   nResult = FileGrep( WebConfigFile, "</appsettings>", svReturnLine, nvLineNumber, RESTART );
  endif;
  
  switch(nResult)
   case 0:
    // found it, now put our new key just before it
    if ( FileInsertLine( WebConfigFile, svNewEntry, nvLineNumber, BEFORE ) < 0 ) then
     // hmmm... we couldn't insert the new key
     MessageBox( "Unable to update Web.Config file.", SEVERE );
    endif;
   case -2:
    // File Not Found
    MessageBox( "Web.Config file not found.", SEVERE );
   case -4:
    // EOF reached
    MessageBox( "Relevant section not found, unable to insert new entry.", SEVERE );
   default:
    //unknown error
    MessageBox( "An unknown error has occurred. The Web.Config file has NOT been updated.", SEVERE );
  endswitch;
 end;


////////////////////////////////////////////////////////////////////////
// Function: UpdateKey
// Purpose: Update specific keys in Web.Config, using FileGrep
////////////////////////////////////////////////////////////////////////
function UpdateKey(hmsi, svFilePath, svFindEntry, svNewEntry)
 NUMBER nResult, nvLineNumber;
 STRING WebConfigFile, svReturnLine;

 begin
  // build the path to the Web.Config    
  WebConfigFile = svFilePath ^ "web.config";

  // search the file for the key we specify
  nResult = FileGrep( WebConfigFile, "<add key=\"" + svFindEntry + "\"", svReturnLine, nvLineNumber, RESTART );
  switch(nResult)
   case 0:
    // Since this line normally appears twice in our web.config file, we're
    // checking for the existence of a 2nd match and updating it instead.
    // If there is no 2nd match, go ahead and update the one we find.
    if ( svFindEntry = "ConnectionString" ) then
     nResult = FileGrep( WebConfigFile, "<add key=\"" + svFindEntry + "\"", svReturnLine, nvLineNumber, CONTINUE );
     if ( nResult < 0 ) then
      FileGrep( WebConfigFile, "<add key=\"" + svFindEntry + "\"", svReturnLine, nvLineNumber, RESTART );
     endif;
    endif;
   
    // once we find the key, update (replace) it with our new values
    if ( FileInsertLine( WebConfigFile, svNewEntry, nvLineNumber, REPLACE ) < 0 ) then
     // hmmm... we couldn't update the value of the key
     MessageBox( "Unable to update Web.Config file.", SEVERE );
    endif;
   case -2:
    // File Not Found
    MessageBox( "Web.Config file not found.", SEVERE );
   case -4:
    // EOF reached
    MessageBox( svFindEntry + " key not found.", SEVERE );
   default:
    //unknown error
    MessageBox( "An unknown error has occurred. The Web.Config file has NOT been updated.", SEVERE );
  endswitch;
 end;


////////////////////////////////////////////////////////////////////////
// Function: UpdateCustomErrors
// Purpose: Update customErrors in Web.Config, using FileGrep
////////////////////////////////////////////////////////////////////////
function UpdateCustomErrors(hmsi, svFilePath, svNewEntry)
 NUMBER nResult, nvLineNumber;
 STRING svResult, WebConfigFile, svReturnLine;

 begin

  //build the path to the Web.Config    
  WebConfigFile = svFilePath ^ "web.config";  

  // search the file for the key we specify
  nResult = FileGrep( WebConfigFile, "<customErrors mode=", svReturnLine, nvLineNumber, RESTART );
  switch(nResult)
   case 0:
    // once we find customErrors, set it to OFF
    if ( FileInsertLine( WebConfigFile, "<customErrors mode=\"" + svNewEntry + "\" />", nvLineNumber, REPLACE ) < 0 ) then
     // hmmm... we couldn't update it
     MessageBox( "Unable to update Web.Config file.", SEVERE );
    endif;
   case -2:
    // File Not Found
    MessageBox( "Web.Config file not found.", SEVERE );
   case -4:
    // EOF reached
    MessageBox( "customErrors setting not found.", SEVERE );
   default:
    //unknown error
    MessageBox( "An unknown error has occurred. The Web.Config file has NOT been updated.", SEVERE );
  endswitch;

 end;

 

////////////////////////////////////////////////////////////////////////
// Function: CheckRegistryForPath
// Purpose:  look in the HKEY_LOCAL_MACHINE\SOFTWARE\etc... for a
//           key matching the GUID passed in as a parameter. Returns
//    the location of the installation.
////////////////////////////////////////////////////////////////////////
function STRING CheckRegistryForPath(szProductGUID)
 NUMBER nSize, nResult, nType;
 STRING szKey, szProductName, szReturn, szInstallLocation;
 
 begin
  RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
  szReturn = "";
  szInstallLocation = "";
  nSize = -1;
  nType = REGDB_STRING;
  szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" + szProductGUID + "
\\InstallProperties";
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBGetKeyValueEx (szKey, "InstallLocation", nType, szInstallLocation, nSize);
   if (nResult = 0) then
    szReturn = szInstallLocation;
   endif;
  endif;
  RegDBSetDefaultRoot ( HKEY_CLASSES_ROOT );

  return szReturn;
 end;
  

////////////////////////////////////////////////////////////////////////
// Function: CheckRegistryForMSI
// Purpose:  look in the HKEY_LOCAL_MACHINE\SOFTWARE\etc... for a
//           key matching the GUID passed in as a parameter. Returns
//    the location of the msi file.
////////////////////////////////////////////////////////////////////////
function STRING CheckRegistryForMSI(szProductGUID)
 NUMBER nSize, nResult, nType;
 STRING szKey, szProductName, szLocalPackage;
 
 begin
  RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
  szLocalPackage = "";
  nSize = 256;
  nType = REGDB_STRING;
  szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" + szProductGUID + "
\\InstallProperties";
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBGetKeyValueEx (szKey, "LocalPackage", nType, szLocalPackage, nSize);
   if (nResult != 0) then
    MessageBox("Unable to retrieve MSI location for " + szProductGUID, INFORMATION);
   endif;
  endif;
  RegDBSetDefaultRoot ( HKEY_CLASSES_ROOT );

  return szLocalPackage;
 end;


////////////////////////////////////////////////////////////////////////
// Function: RemoveLegacyInstall
// Purpose:  look in the HKEY_LOCAL_MACHINE\SOFTWARE\etc... for a
//           key matching the GUID passed in as a parameter. If found
//    delete the key.  This should remove it from the
//    Add/Remove Programs applet
////////////////////////////////////////////////////////////////////////
function NUMBER RemoveLegacyInstall(szUninstallGUID, szInstallerGUID, szMSILocation)
 NUMBER nSize, nReturn1, nReturn2, nReturn3, nReturn4, nResult, nType, nLocation;
 STRING szKey, szDir;
 
 begin
  RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );

  // remove the Uninstall entry (this should clear it out of Add/Remove Programs)
  nReturn1 = FALSE;
  nSize = -1;
  nType = REGDB_STRING;
  szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\" + szUninstallGUID;
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBDeleteKey (szKey);
   if (nResult = 0) then
    nReturn1 = TRUE;
   else
    MessageBox("Unable to Remove Uninstall Key for " + szUninstallGUID + ".",INFORMATION);
   endif;
  else
   MessageBox("Unable to Find Uninstall Key for " + szUninstallGUID + ".",INFORMATION);
  endif;

  // remove the Installer entry (this should keep it from being detected again)
  nReturn2 = FALSE;
  nSize = -1;
  nType = REGDB_STRING;
  szKey = "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Installer\\UserData\\S-1-5-18\\Products\\" + szInstallerGUID;
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBDeleteKey (szKey);
   if (nResult = 0) then
    nReturn2 = TRUE;
   else
    MessageBox("Unable to Remove Installer Key for " + szInstallerGUID + ".",INFORMATION);
   endif;
  else
   MessageBox("Unable to Find Installer Key for " + szInstallerGUID + ".",INFORMATION);
  endif;

  // remove the key under HKLM\SOFTWARE\Classes\Installer\Products
  nReturn3 = FALSE;
  nSize = -1;
  nType = REGDB_STRING;
  szKey = "SOFTWARE\\Classes\\Installer\\Products\\" + szInstallerGUID;
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBDeleteKey (szKey);
   if (nResult = 0) then
    nReturn3 = TRUE;
   else
    MessageBox("Unable to Remove Classes\Installer Key for " + szInstallerGUID + ".",INFORMATION);
   endif;
  else
   MessageBox("Unable to Find Classes\Installer Key for " + szInstallerGUID + ".",INFORMATION);
  endif;

  RegDBSetDefaultRoot ( HKEY_CLASSES_ROOT );

  // remove the key (if any) under HKCR\Installer\Products
  nSize = -1;
  nType = REGDB_STRING;
  szKey = "Installer\\Products\\" + szInstallerGUID;
  nResult = RegDBKeyExist (szKey);
  if (nResult = 1) then
   nResult = RegDBDeleteKey (szKey);
  endif;

  // delete the appropriate MSI file since we don't need it anymore
  nResult = DeleteFile(szMSILocation);
  if (nResult = 0) then
   nReturn4 = TRUE;
  else
   nReturn4 = FALSE;
   MessageBox("Unable to delete MSI file for " + szMSILocation + ".",INFORMATION);
  endif;
    
  // only return TRUE if all results are TRUE
  if ((nReturn1 = TRUE) && (nReturn2 = TRUE) && (nReturn3 = TRUE) && (nReturn4 = TRUE)) then
   return TRUE;
  else
   return FALSE;
  endif;
  
 end;


////////////////////////////////////////////////////////////////////////
// Function: DeleteVirtualDir
// Purpose:  Pass in the name of a virtual directory and this function
//    will delete it and return TRUE. If it can't delete it, or
//    the virtual directory isn't there, function returns FALSE
////////////////////////////////////////////////////////////////////////
function number DeleteVirtualDir(hmsi, sVDirName)
 NUMBER nReturn;
 OBJECT objIIS_Root;

 begin
  set objIIS_Root = CoGetObject("IIS://localhost/W3SVC/1/Root", "");
  if (IsObject(objIIS_Root)) then
   try
    objIIS_Root.Delete("IISWebVirtualDir", sVDirName);
    nReturn = TRUE;
   catch
    // VDir doesn't exist.
    nReturn = FALSE;
   endcatch;
  else
   // objIIS_Root has not been assigned a reference to a valid object.
   nReturn = FALSE;
  endif;

  return nReturn;
 end;
 
////////////////////////////////////////////////////////////////////////
// Function: CheckIISExists
// Purpose:  Checks for the existence (and major version) of IIS
//    Returns -1 if not found OR major version number if found
//    Example:  Server 2003 would return 6 if IIS is installed
////////////////////////////////////////////////////////////////////////
function number CheckIISExists(hmsi)
 NUMBER  nvType, nResult, nvIISVer, nvSize;
 STRING  szKey, szIISVersion;

 begin
     RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
        
  nvIISVer = -1;
  nvType = REGDB_NUMBER;
  szKey = "
\\SOFTWARE\\Microsoft\\InetStp";
  nResult = RegDBKeyExist(szKey);
  if (nResult = 1) then
   nResult = RegDBGetKeyValueEx(szKey, "MajorVersion", nvType, szIISVersion, nvSize);
   if (nResult = 0) && (szIISVersion != "") then
    StrToNum(nvIISVer, szIISVersion);
   endif;
  endif;
 
     RegDBSetDefaultRoot (HKEY_CLASSES_ROOT);
     return nvIISVer;
 end;
 

////////////////////////////////////////////////////////////////////////
// Function: CheckVirtualDirExists
// Purpose:  Checks for the existence of a specific virtual directory
//          
// NOTE:  THIS FUNCTION DOES NOT WORK ON SERVER 2003.  XP ONLY!!
//    DeleteVirtualDir does not need this function to be called.   
////////////////////////////////////////////////////////////////////////
function number CheckVirtualDirExists(hmsi, sVDirName)
 NUMBER  nType, nvSize, nReturn, nResult;
 STRING  svReturn, VDir;

 begin
  VDir     = "/" + sVDirName;
  nType    = REGDB_STRING;
  nvSize   = MAX_PATH;

  RegDBSetDefaultRoot ( HKEY_LOCAL_MACHINE );
  nResult = RegDBGetKeyValueEx("
\\SYSTEM\\CurrentControlSet\\Services\\W3SVC\\Parameters\\Virtual Roots\\", VDir, nType, svReturn, nvSize );
  RegDBSetDefaultRoot ( HKEY_CLASSES_ROOT );
  
  if (nResult < 0) then
   // The Virtual Directory does not exist
   nReturn = FALSE;
   MessageBox("VirtualDir " + sVDirName + " not found, or does not exist.", INFORMATION);
     else
   // The Virtual Directory does exist
   nReturn = TRUE;
   MessageBox("VirtualDir " + sVDirName + " exists.", INFORMATION);
     endif;

  return nReturn;
 end;

 

Posted on Friday, March 11, 2005 4:08 PM Installshield | Back to top


Comments on this post: my Installshield "utility belt"

# re: my Installshield "utility belt"
Requesting Gravatar...
Thank you so much! You cut at least 6 hours off my release time! I cannot tell you how releaved I was to find this set of functions since I am just learning Installshield.
Left by Barry R. on Jun 16, 2005 12:29 PM

# re: my Installshield "utility belt"
Requesting Gravatar...
Hey I'm glad to hear it!!
Left by BlogusMaximus on Jun 16, 2005 12:33 PM

# re: my Installshield "utility belt"
Requesting Gravatar...
These functions look great but how do I use them. For example: How would I use the AddKey function within the function OnFirstUIAfter() ?
What is submitted for hmsi?
How would I prototype the AddKey function? Thanks.
Left by wfflcmysh on Jul 18, 2005 7:12 AM

# re: my Installshield "utility belt"
Requesting Gravatar...
These functions look great but how do I use them. For example: How would I use the AddKey function within the function OnFirstUIAfter() ?
What is submitted for hmsi?
How would I prototype the AddKey function? Thanks.
Left by wfflcmysh on Jul 18, 2005 7:13 AM

# re: my Installshield "utility belt"
Requesting Gravatar...
These functions look great but how do I use them. For example: How would I use the AddKey function within the function OnFirstUIAfter() ?
What is submitted for hmsi?
How would I prototype the AddKey function? Thanks.
Left by wfflcmysh on Jul 18, 2005 7:13 AM

# re: my Installshield "utility belt"
Requesting Gravatar...
take a look at the top of the file. The functions are already protyped. As for hmsi, use the ISMSI_HANDLE keyword.

<P>sample usage: AddKey (hmsi, szWebConfigPath, "KEY", "<add key=\"myServiceURL\" value=\"" + svURL + "/folder/Service.asmx\" />");
Left by blogusmaximus on Jul 18, 2005 7:23 AM

# re: my Installshield "utility belt"
Requesting Gravatar...
Thank You - got it working! Sorry for the prototype oversite.
Left by wfflcmysh on Jul 18, 2005 12:47 PM

# re: my Installshield "utility belt"
Requesting Gravatar...
no problem, glad you found it useful. :)
Left by blogusmaximus on Jul 18, 2005 1:06 PM

# re: my Installshield "utility belt"
Requesting Gravatar...
Thanks a lot, very useful script
Left by R.Boddu on Mar 19, 2008 12:22 AM

Your comment:
 (will show your gravatar)


Copyright © Chris G. Williams | Powered by: GeeksWithBlogs.net