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

Help With Some Patch Detection Code...


1 reply to this topic

Superfreak3

Superfreak3
  • Full Members
  • 437 posts

Posted 01 March 2013 - 16:49

Hi there,

This isn't really directly related to InstallShield, but I hope someone can help me out.

Years ago I posted to see how I can detect if a patch has been applied on a particular machine. We have an update utility that will fire a Myapp.msp if it is detected in a particular folder. What is happening is that everytime the file is detected it reapplies the patch. I would like to check if the patch has been applied and only do so if absent.

I received a reply with this information... http://www.packagede...event-apply-31/

QUOTE
Have your app query the Revision Number of the summary information stream of
your MSP file to get the patch's GUID. Then use MsiEnumPatchesEx (or
minimum MsiEnumPatches) to check if patch is on the machine.

If it is not on the machine you could also check that the MSP is applicable
by using MsiDeterminePatchSequence or MsiDetermineApplicablePatches. The
idea is that with patch sequencing an MSP could be superseded by a different
MSP already on the machine. Thus applying the so called "new" patch even
though it is not installed locally (MsiEnumPatchesEx returns not found)
would result in a redundant installation.


The utility is written in some form of C and I'm a VB.Net guy, however I would still need help with MsiEnumPatches or MsiEnumPatchesEx. Here's the current code for firing the patch...

QUOTE
if (GetFileAttributes(m_ServerUpdateFolder + "MyPatch.msp") != -1)
    {
     LogMsg.Format("Running %sMyPatch.msp", m_ServerUpdateFolder);
     m_LogTrace.WriteLine(LogMsg);
     CmdLine.Format("msiexec /qn /p \"%sMyPatch.msp\"", m_ServerUpdateFolder);
     RunProcessAndWait(CmdLine, &dwThreadRtnValue);
     if (dwThreadRtnValue == 0)
     {
      m_LogTrace.WriteLine("\tClient Patch successfully or previously applied!");
      m_LogTrace.WriteLine("******************************************");
      m_LogTrace.WriteLine("Log Trace ended %s\n", COleDateTime::GetCurrentTime().Format());
     }
     else
     {
      m_LogTrace.WriteLine("\tAn error occurred while applying the Client patch: %d!", dwThreadRtnValue);
      m_LogTrace.WriteLine("\tPossible causes: Patch target not installed or patch no longer applicable.");
      m_LogTrace.WriteLine("******************************************");
      m_LogTrace.WriteLine("Log Trace ended %s\n", COleDateTime::GetCurrentTime().Format());
     }
    }
    else
    {
     m_LogTrace.WriteLine("No Client patch found in update location!");
     m_LogTrace.WriteLine("******************************************");
     m_LogTrace.WriteLine("Log Trace ended %s\n", COleDateTime::GetCurrentTime().Format());
    }


What I would like to do is, if a patch is detected, grab any needed code and determine if it is applied. If not, run it as above.

I guess I would need to grab the ProductCode from the base .msi, which will also be in the update folder, m_ServerUpdateFolder.

Any help with coding this would be greatly appreciated!

I guess I'll need to enumerate through installed products, get the patch guid and another needed info then see if the patch has been applied to any products. If so, skip else, fire the patch.

The impetus for this whole mess can be found here.

Thanks much and sorry if this is way out of bounds for this forum!!

Edited by Superfreak3, 02 March 2013 - 21:37.


Superfreak3

Superfreak3
  • Full Members
  • 437 posts

Posted 22 March 2013 - 20:00

Here's what we're going with. Hope it helps someone...

CODE
Type t = Type.GetTypeFromProgID("WindowsInstaller.Installer");
               Installer iInstaller = (Installer)Activator.CreateInstance(t);

               string strPatchPath = null;
               string strPatchCode = null;
               string strProdCode = null;
               string strPatchXML = null;
               XmlDocument xmlMsiPatch = new XmlDocument();

               

               if (MinMsiVersion > Convert.ToDouble(iInstaller.Version.Substring(0, iInstaller.Version.IndexOf('.'))))
               {
                   MessageBox.Show("Minimum Windows Installer version " + MinMsiVersion + " required.  Current version is " + iInstaller.Version, "Windows Installer version problem...");
               }

               strPatchPath = "C:\\Program Files (x86)\\Synergis\\Adept80\\Client\\Install\\AdeptPatch.msp";
               strPatchXML = iInstaller.ExtractPatchXMLData(strPatchPath);

               xmlMsiPatch.LoadXml(strPatchXML);

               strPatchCode = xmlMsiPatch.DocumentElement.Attributes["PatchGUID"].Value;
               strProdCode = xmlMsiPatch.GetElementsByTagName("TargetProductCode").Item(0).InnerText;

               //Now check if patch is applied...

               int rtn = 0;
               dynamic ePatch = iInstaller.get_Patches(strProdCode);
 
               if (ePatch.count > 0)
               {
                   for (var i = 0; i < ePatch.count; i++)
                   {
                       if (ePatch[i] == strPatchCode)
                       {
                           MessageBox.Show("here");
                           rtn = 1;
                       }

                   }
               }