Superfreak3 0 Newbie Poster

Hi there,

Years ago I posted in an InstallShield forum to see how I can detect if a patch has been applied on a particular machine programmatically. 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...

"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 (I think ++) 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...

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. Or I could enumerate all installed products I guess, but I don't know how long it would take to check the patch against each app.

The impetus for the desired changes can be found here...http://www.itninja.com/question/weird-occurrence-with-different-patch-application-command-line-parameters . We are using patches more frequently and just firing them if present isn't the best way to go anylonger.

Any help with coding this would be greatly appreciated!

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