示例#1
0
 internal InstallationPart(string id, string productCode, string userSid, UserContexts context)
 {
     this.id = id;
     this.productCode = productCode;
     this.userSid = userSid;
     this.context = context;
 }
示例#2
0
 /// <summary>
 /// Creates a new instance of the <see cref="SourceInfo"/> class.
 /// </summary>
 /// <param name="productCode">The ProductCode to which the source is registered.</param>
 /// <param name="userSid">The user SID of the product.</param>
 /// <param name="userContext">The user context of the product.</param>
 /// <param name="path">The registered source path.</param>
 /// <param name="order">The order in which the source path is tried.</param>
 internal SourceInfo(string productCode, string userSid, UserContexts userContext, string path, int order)
 {
     this.ProductCode = productCode;
     this.UserSid = userSid;
     this.UserContext = userContext;
     this.Path = path;
     this.Order = order;
 }
 /// <summary>
 /// Creates a new ComponentInstallation for a component installed by a
 /// specific product.
 /// </summary>
 /// <param name="componentCode">component GUID</param>
 /// <param name="productCode">ProductCode GUID</param>
 /// <param name="szUserSid">context user SID</param>
 /// <param name="dwContext">user contexts</param>
 internal ComponentInstallation(string componentCode, string productCode, string szUserSid, UserContexts dwContext)
     : base(componentCode, productCode, szUserSid, dwContext)
 {
     if (string.IsNullOrEmpty(componentCode))
     {
         throw new ArgumentNullException("componentCode");
     }
 }
示例#4
0
 /// <summary>
 /// Creates a new object for accessing information about a product installation on the current system.
 /// </summary>
 /// <param name="productCode">ProductCode (GUID) of the product.</param>
 /// <param name="userSid">The specific user, when working in a user context.  This
 /// parameter may be null to indicate the current user.  The parameter must be null
 /// when working in a machine context.</param>
 /// <param name="context">The user context. The calling process must have administrative
 /// privileges to get information for a product installed for a user other than the
 /// current user.</param>
 public ProductInstallation(string productCode, string userSid, UserContexts context)
     : base(productCode, userSid, context)
 {
     if (string.IsNullOrWhiteSpace(productCode))
     {
         throw new ArgumentNullException("productCode");
     }
 }
示例#5
0
 /// <summary>
 /// Creates a new object for accessing information about a product installation on the current system.
 /// </summary>
 /// <param name="productCode">ProductCode (GUID) of the product.</param>
 /// <param name="userSid">The specific user, when working in a user context.  This
 /// parameter may be null to indicate the current user.  The parameter must be null
 /// when working in a machine context.</param>
 /// <param name="context">The user context. The calling process must have administrative
 /// privileges to get information for a product installed for a user other than the
 /// current user.</param>
 internal ProductInstallation(string productCode, string userSid, UserContexts context)
     : base(productCode, userSid, context)
 {
     if (String.IsNullOrEmpty(productCode))
     {
         throw new ArgumentNullException("productCode");
     }
 }
示例#6
0
        /// <summary>
        /// Creates a new object for accessing information about a patch installation on the current system.
        /// </summary>
        /// <param name="patchCode">Registered patch code (GUID) of the patch.</param>
        /// <param name="productCode">ProductCode (GUID) the patch has been applied to.
        /// This parameter may be null for patches that are registered only and not yet
        /// applied to any product.</param>
        /// <param name="userSid">The specific user, when working in a user context.  This
        /// parameter may be null to indicate the current user.  The parameter must be null
        /// when working in a machine context.</param>
        /// <param name="context">The user context. The calling process must have administrative
        /// privileges to get information for a product installed for a user other than the
        /// current user.</param>
        /// <remarks><p>
        /// If the <paramref name="productCode"/> is null, the Patch object may
        /// only be used to read and update the patch's SourceList information.
        /// </p></remarks>
        public PatchInstallation(string patchCode, string productCode, string userSid, UserContexts context)
            : base(patchCode, userSid, context)
        {
            if (String.IsNullOrEmpty(patchCode))
            {
                throw new ArgumentNullException("patchCode");
            }

            this.productCode = productCode;
        }
示例#7
0
 internal Installation(string installationCode, string userSid, UserContexts context)
 {
     if (context == UserContexts.Machine)
     {
         userSid = null;
     }
     this.installationCode = installationCode;
     this.userSid = userSid;
     this.context = context;
 }
 /// <summary>
 /// Gets the set of installed components for products in the indicated context.
 /// </summary>
 /// <exception cref="InstallerException">The installer configuration data is corrupt</exception>
 /// <remarks><p>
 /// Win32 MSI API:
 /// <a href="http://msdn.microsoft.com/library/dd407947.aspx">MsiEnumComponentsEx</a>
 /// </p></remarks>
 public static IEnumerable<ComponentInstallation> Components(string szUserSid, UserContexts dwContext)
 {
     uint pcchSid = 32;
     StringBuilder szSid = new StringBuilder((int)pcchSid);
     StringBuilder buf = new StringBuilder(40);
     UserContexts installedContext;
     for (uint i = 0; true; i++)
     {
         uint  ret = NativeMethods.MsiEnumComponentsEx(szUserSid, dwContext, i, buf, out installedContext, szSid, ref pcchSid);
         if (ret == (uint) NativeMethods.Error.MORE_DATA)
         {
             szSid.EnsureCapacity((int) ++pcchSid);
             ret = NativeMethods.MsiEnumComponentsEx(szUserSid, dwContext, i, buf, out installedContext, szSid, ref pcchSid);
         }
         if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS) break;
         if (ret != 0)
         {
             throw InstallerException.ExceptionFromReturnCode(ret);
         }
         yield return new ComponentInstallation(buf.ToString(), szSid.ToString(), installedContext);
     }
 }
 /// <summary>
 /// Creates a new ComponentInstallation, automatically detecting the
 /// product that the component is a part of.
 /// </summary>
 /// <param name="componentCode">component GUID</param>
 /// <param name="szUserSid">context user SID</param>
 /// <param name="dwContext">user contexts</param>
 public ComponentInstallation(string componentCode, string szUserSid, UserContexts dwContext)
     : this(componentCode, ComponentInstallation.GetProductCode(componentCode, szUserSid, dwContext), szUserSid, dwContext)
 {
 }
示例#10
0
        /// <summary>
        /// Determines which patches apply to a specified product and in what sequence.  If
        /// the product is installed, this method accounts for patches that have already been applied to
        /// the product and accounts for obsolete and superceded patches.
        /// </summary>
        /// <param name="product">The product that is the target for the set of patches.  This may be
        /// either a ProductCode (GUID) of a product that is currently installed, or the path to a an
        /// MSI file.</param>
        /// <param name="patches">An array of strings specifying the patches to be checked.  Each item
        /// may be the path to an MSP file, the path an XML file, or just an XML blob.</param>
        /// <param name="errorHandler">Callback to be invoked for each inapplicable patch, reporting the
        /// reason the patch is not applicable.  This value may be left null if that information is not
        /// desired.</param>
        /// <param name="userSid">Specifies a security identifier (SID) of a user. This parameter restricts
        /// the context of enumeration for this user account. This parameter cannot be the special SID
        /// strings s-1-1-0 (everyone) or s-1-5-18 (local system). If <paramref name="context"/> is set to
        /// <see cref="UserContexts.None"/> or <see cref="UserContexts.Machine"/>, then
        /// <paramref name="userSid"/> must be null. For the current user context, <paramref name="userSid"/>
        /// can be null and <paramref name="context"/> can be set to <see cref="UserContexts.UserManaged"/>
        /// or <see cref="UserContexts.UserUnmanaged"/>.</param>
        /// <param name="context">Restricts the enumeration to per-user-unmanaged, per-user-managed,
        /// or per-machine context, or (if referring to an MSI) to no system context at all.  This
        /// parameter can be <see cref="UserContexts.Machine"/>, <see cref="UserContexts.UserManaged"/>,
        /// <see cref="UserContexts.UserUnmanaged"/>, or <see cref="UserContexts.None"/>.</param>
        /// <returns>An array of selected patch strings from <paramref name="patches"/>, indicating
        /// the set of applicable patches.  The items are re-ordered to be in the best sequence.</returns>
        /// <remarks><p>
        /// If an item in <paramref name="patches"/> is a file path but does not end in .MSP or .XML,
        /// it is assumed to be an MSP file.
        /// </p><p>
        /// Passing an InstallContext of None only analyzes the MSI file; it does not consider the
        /// current state of the system. You cannot use InstallContext.None with a ProductCode GUID.
        /// </p><p>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidetermineapplicablepatches.asp">MsiDetermineApplicablePatches</a>
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msideterminepatchsequence.asp">MsiDeterminePatchSequence</a>
        /// </p></remarks>
        public static IList <string> DetermineApplicablePatches(
            string product,
            string[] patches,
            InapplicablePatchHandler errorHandler,
            string userSid,
            UserContexts context)
        {
            if (String.IsNullOrEmpty(product))
            {
                throw new ArgumentNullException("product");
            }

            if (patches == null)
            {
                throw new ArgumentNullException("patches");
            }

            NativeMethods.MsiPatchSequenceData[] sequenceData = new NativeMethods.MsiPatchSequenceData[patches.Length];
            for (int i = 0; i < patches.Length; i++)
            {
                if (String.IsNullOrEmpty(patches[i]))
                {
                    throw new ArgumentNullException("patches[" + i + "]");
                }

                sequenceData[i].szPatchData    = patches[i];
                sequenceData[i].ePatchDataType = GetPatchStringDataType(patches[i]);
                sequenceData[i].dwOrder        = -1;
                sequenceData[i].dwStatus       = 0;
            }

            uint ret;

            if (context == UserContexts.None)
            {
                ret = NativeMethods.MsiDetermineApplicablePatches(product, (uint)sequenceData.Length, sequenceData);
            }
            else
            {
                ret = NativeMethods.MsiDeterminePatchSequence(product, userSid, context, (uint)sequenceData.Length, sequenceData);
            }

            if (errorHandler != null)
            {
                for (int i = 0; i < sequenceData.Length; i++)
                {
                    if (sequenceData[i].dwOrder < 0 && sequenceData[i].dwStatus != 0)
                    {
                        errorHandler(sequenceData[i].szPatchData, InstallerException.ExceptionFromReturnCode(sequenceData[i].dwStatus));
                    }
                }
            }

            if (ret != 0)
            {
                throw InstallerException.ExceptionFromReturnCode(ret);
            }

            IList <string> patchSeq = new List <string>(patches.Length);

            for (int i = 0; i < sequenceData.Length; i++)
            {
                for (int j = 0; j < sequenceData.Length; j++)
                {
                    if (sequenceData[j].dwOrder == i)
                    {
                        patchSeq.Add(sequenceData[j].szPatchData);
                    }
                }
            }
            return(patchSeq);
        }
示例#11
0
        private IEnumerable <PatchSequence> DetermineApplicablePatches(string product, string userSid, UserContexts context)
        {
            var patches = this.Patches.ToArray();
            InapplicablePatchHandler handler = (patch, ex) => this.OnInapplicablePatch(new InapplicablePatchEventArgs(patch, product, ex));

            // Keep track of the sequence.
            int i = 0;

            // The current implementation does not return a null list.
            var applicable = Installer.DetermineApplicablePatches(product, patches, handler, userSid, context);

            foreach (var path in applicable)
            {
                yield return(new PatchSequence()
                {
                    Patch = path,
                    Sequence = i++,
                    Product = product,
                    UserSid = userSid,
                    UserContext = context,
                });
            }
        }
示例#12
0
 /// <summary>
 /// Gets a list of patches that are applicable to the given ProductCode.
 /// </summary>
 /// <param name="product">The ProductCode for which applicability is determined.</param>
 /// <param name="userSid">The SID of the user for which the product is installed. The default is null.</param>
 /// <param name="context">The <see cref="UserContexts"/> into which the product is installed. This must be <see cref="UserContexts.None"/> for a package path. The default is <see cref="UserContexts.None"/>.</param>
 /// <returns>An ordered list of applicable patch or patch XML files.</returns>
 /// <exception cref="ArgumentException">The parameters are not correct for the given package path or installed ProductCode (ex: cannot use <see cref="UserContexts.All"/> in any case).</exception>
 internal IEnumerable <PatchSequence> GetApplicablePatches(string product, string userSid = null, UserContexts context = UserContexts.None)
 {
     // Enumerate all applicable patches immediately and return.
     return(this.DetermineApplicablePatches(product, userSid, context).ToList());
 }
示例#13
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern int MsiGetComponentPathEx(string szProduct, string szComponent, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, StringBuilder lpPathBuf, ref uint pcchBuf);
示例#14
0
        /// <summary>
        /// Gets the weight of a package given its ProductCode.
        /// </summary>
        /// <param name="productCode">The ProductCode of the product to query.</param>
        /// <param name="userSid">The optional user SID of the product to query. The default is null.</param>
        /// <param name="context">The optional context of the product ot query. The default is <see cref="UserContexts.All"/>.</param>
        /// <returns>The weight of a package given its ProductCode or 0 if the product is not installed or the package missing.</returns>
        internal static long GetWeightFromProductCode(string productCode, string userSid = null, UserContexts context = UserContexts.All)
        {
            var product = new ProductInstallation(productCode, userSid, context);
            if (null != product && product.IsInstalled)
            {
                var path = product.LocalPackage;
                if (!string.IsNullOrEmpty(path))
                {
                    return PackageInfo.GetWeightFromPath(path);
                }
            }

            return 0;
        }
示例#15
0
        /// <summary>
        /// Enumerates patch installations based on certain criteria.
        /// </summary>
        /// <param name="patchCode">PatchCode (GUID) of the patch to be enumerated. Only
        /// instances of patches within the scope of the context specified by the
        /// <paramref name="userSid"/> and <paramref name="context"/> parameters will be
        /// enumerated. This parameter may be set to null to enumerate all patches in the specified
        /// context.</param>
        /// <param name="targetProductCode">ProductCode (GUID) product whose patches are to be
        /// enumerated. If non-null, patch enumeration is restricted to instances of this product
        /// within the specified context. If null, the patches for all products under the specified
        /// context are enumerated.</param>
        /// <param name="userSid">Specifies a security identifier (SID) that restricts the context
        /// of enumeration. A SID value other than s-1-1-0 is considered a user SID and restricts
        /// enumeration to the current user or any user in the system. The special SID string
        /// s-1-1-0 (Everyone) specifies enumeration across all users in the system. This parameter
        /// can be set to null to restrict the enumeration scope to the current user. When
        /// <paramref name="userSid"/> must be null.</param>
        /// <param name="context">Specifies the user context.</param>
        /// <param name="states">The <see cref="PatchStates"/> of patches to return.</param>
        /// <remarks><p>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumpatchesex.asp">MsiEnumPatchesEx</a>
        /// </p></remarks>
        public static IEnumerable <PatchInstallation> GetPatches(
            string patchCode,
            string targetProductCode,
            string userSid,
            UserContexts context,
            PatchStates states)
        {
            StringBuilder buf = new StringBuilder(40);
            StringBuilder targetProductBuf = new StringBuilder(40);
            UserContexts  targetContext;
            StringBuilder targetSidBuf = new StringBuilder(40);

            for (uint i = 0; ; i++)
            {
                uint targetSidBufSize = (uint)targetSidBuf.Capacity;
                uint ret = NativeMethods.MsiEnumPatchesEx(
                    targetProductCode,
                    userSid,
                    context,
                    (uint)states,
                    i,
                    buf,
                    targetProductBuf,
                    out targetContext,
                    targetSidBuf,
                    ref targetSidBufSize);
                if (ret == (uint)NativeMethods.Error.MORE_DATA)
                {
                    targetSidBuf.Capacity = (int)++targetSidBufSize;
                    ret = NativeMethods.MsiEnumPatchesEx(
                        targetProductCode,
                        userSid,
                        context,
                        (uint)states,
                        i,
                        buf,
                        targetProductBuf,
                        out targetContext,
                        targetSidBuf,
                        ref targetSidBufSize);
                }

                if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }

                string thisPatchCode = buf.ToString();
                if (patchCode == null || patchCode == thisPatchCode)
                {
                    yield return(new PatchInstallation(
                                     buf.ToString(),
                                     targetProductBuf.ToString(),
                                     targetSidBuf.ToString(),
                                     targetContext));
                }
            }
        }
示例#16
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiSourceListClearMediaDisk(string szProductCodeOrPatchCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwOptions, uint dwDiskID);
示例#17
0
 private static string GetProductCode(string component, string szUserSid, UserContexts dwContext)
 {
     // TODO: We really need what would be MsiGetProductCodeEx, or at least a reasonable facsimile thereof (something that restricts the search to the context defined by szUserSid & dwContext)
     return(GetProductCode(component));
 }
示例#18
0
        /// <summary>
        /// Creates a new object for accessing information about a patch installation on the current system.
        /// </summary>
        /// <param name="patchCode">Registered patch code (GUID) of the patch.</param>
        /// <param name="productCode">ProductCode (GUID) the patch has been applied to.
        /// This parameter may be null for patches that are registered only and not yet
        /// applied to any product.</param>
        /// <param name="userSid">The specific user, when working in a user context.  This
        /// parameter may be null to indicate the current user.  The parameter must be null
        /// when working in a machine context.</param>
        /// <param name="context">The user context. The calling process must have administrative
        /// privileges to get information for a product installed for a user other than the
        /// current user.</param>
        /// <remarks><p>
        /// If the <paramref name="productCode"/> is null, the Patch object may
        /// only be used to read and update the patch's SourceList information.
        /// </p></remarks>
        public PatchInstallation(string patchCode, string productCode, string userSid, UserContexts context)
            : base(patchCode, userSid, context)
        {
            if (string.IsNullOrWhiteSpace(patchCode))
            {
                throw new ArgumentNullException("patchCode");
            }

            this.productCode = productCode;
        }
示例#19
0
        /// <summary>
        /// Gets the set of installed components for products in the indicated context.
        /// </summary>
        /// <exception cref="InstallerException">The installer configuration data is corrupt</exception>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/dd407947.aspx">MsiEnumComponentsEx</a>
        /// </p></remarks>
        public static IEnumerable <ComponentInstallation> Components(string szUserSid, UserContexts dwContext)
        {
            uint          pcchSid = 32;
            StringBuilder szSid   = new StringBuilder((int)pcchSid);
            StringBuilder buf     = new StringBuilder(40);
            UserContexts  installedContext;

            for (uint i = 0; true; i++)
            {
                uint ret = NativeMethods.MsiEnumComponentsEx(szUserSid, dwContext, i, buf, out installedContext, szSid, ref pcchSid);
                if (ret == (uint)NativeMethods.Error.MORE_DATA)
                {
                    szSid.EnsureCapacity((int)++pcchSid);
                    ret = NativeMethods.MsiEnumComponentsEx(szUserSid, dwContext, i, buf, out installedContext, szSid, ref pcchSid);
                }
                if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }
                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }
                yield return(new ComponentInstallation(buf.ToString(), szSid.ToString(), installedContext));
            }
        }
示例#20
0
 /// <summary>
 /// Creates a new ComponentInstallation for a component installed by a
 /// specific product.
 /// </summary>
 /// <param name="componentCode">component GUID</param>
 /// <param name="productCode">ProductCode GUID</param>
 /// <param name="szUserSid">context user SID</param>
 /// <param name="dwContext">user contexts</param>
 public ComponentInstallation(string componentCode, string productCode, string szUserSid, UserContexts dwContext)
     : base(componentCode, productCode, szUserSid, dwContext)
 {
     if (string.IsNullOrWhiteSpace(componentCode))
     {
         throw new ArgumentNullException("componentCode");
     }
 }
示例#21
0
 /// <summary>
 /// Creates a new ComponentInstallation, automatically detecting the
 /// product that the component is a part of.
 /// </summary>
 /// <param name="componentCode">component GUID</param>
 /// <param name="szUserSid">context user SID</param>
 /// <param name="dwContext">user contexts</param>
 public ComponentInstallation(string componentCode, string szUserSid, UserContexts dwContext)
     : this(componentCode, ComponentInstallation.GetProductCode(componentCode, szUserSid, dwContext), szUserSid, dwContext)
 {
 }
示例#22
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiSourceListSetInfo(string szProductCodeOrPatchCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwOptions, string szProperty, string szValue);
示例#23
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiDeterminePatchSequence(string szProductCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint cPatchInfo, [MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3), In, Out] MsiPatchSequenceData[] pPatchInfo);
示例#24
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiSourceListEnumMediaDisks(string szProductCodeOrPatchCode, string szUserSID, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwOptions, uint dwIndex, out uint pdwDiskId, StringBuilder szVolumeLabel, ref uint pcchVolumeLabel, StringBuilder szDiskPrompt, ref uint pcchDiskPrompt);
示例#25
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiEnumPatchesEx(string szProductCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwFilter, uint dwIndex, StringBuilder szPatchCode, StringBuilder szTargetProductCode, [MarshalAs(UnmanagedType.I4)] out UserContexts pdwTargetProductContext, StringBuilder szTargetUserSid, ref uint pcchTargetUserSid);
示例#26
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiEnumClientsEx(string szComponent, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint iProductIndex, StringBuilder lpProductBuf, [MarshalAs(UnmanagedType.I4)] out UserContexts pdwInstalledContext, StringBuilder szSid, ref uint pcchSid);
示例#27
0
 private static string GetProductCode(string component, string szUserSid, UserContexts dwContext)
 {
     // TODO: We really need what would be MsiGetProductCodeEx, or at least a reasonable facimile thereof (something that restricts the search to the context defined by szUserSid & dwContext)
     return GetProductCode(component);
 }
示例#28
0
 /// <summary>
 /// Initializes a new instance of the <see cref="PatchSourceInfo"/> class.
 /// </summary>
 /// <param name="productCode">The ProductCode to which the source is registered.</param>
 /// <param name="patchCode">The patch code to which the source is regisered.</param>
 /// <param name="userSid">The user SID of the product.</param>
 /// <param name="userContext">The user context of the product.</param>
 /// <param name="path">The registered source path.</param>
 /// <param name="order">The order in which the source path is tried.</param>
 internal PatchSourceInfo(string productCode, string patchCode, string userSid, UserContexts userContext, string path, int order)
     : base(productCode, userSid, userContext, path, order)
 {
     this.PatchCode = patchCode;
 }
示例#29
0
 /// <summary>
 /// Gets a list of patches that are applicable to the given ProductCode.
 /// </summary>
 /// <param name="product">The ProductCode for which applicability is determined.</param>
 /// <param name="userSid">The SID of the user for which the product is installed. The default is null.</param>
 /// <param name="context">The <see cref="UserContexts"/> into which the product is installed. This must be <see cref="UserContexts.None"/> for a package path. The default is <see cref="UserContexts.None"/>.</param>
 /// <returns>An ordered list of applicable patch or patch XML files.</returns>
 /// <exception cref="ArgumentException">The parameters are not correct for the given package path or installed ProductCode (ex: cannot use <see cref="UserContexts.All"/> in any case).</exception>
 internal IEnumerable<PatchSequence> GetApplicablePatches(string product, string userSid = null, UserContexts context = UserContexts.None)
 {
     // Enumerate all applicable patches immediately and return.
     return this.DetermineApplicablePatches(product, userSid, context).ToList();
 }
示例#30
0
 /// <summary>
 /// Creates a new instance of the <see cref="SourceInfo"/> class.
 /// </summary>
 /// <param name="productCode">The ProductCode to which the source is registered.</param>
 /// <param name="patchCode">The patch code to which the source is regisered.</param>
 /// <param name="userSid">The user SID of the product.</param>
 /// <param name="userContext">The user context of the product.</param>
 /// <param name="path">The registered source path.</param>
 /// <param name="order">The order in which the source path is tried.</param>
 internal PatchSourceInfo(string productCode, string patchCode, string userSid, UserContexts userContext, string path, int order)
     : base(productCode, userSid, userContext, path, order)
 {
     this.PatchCode = patchCode;
 }
示例#31
0
 /// <summary>
 /// Enumerates patches for the given patch codes and ProductCodes and writes them to the pipeline.
 /// </summary>
 /// <param name="patchCode">The patch code to enumerate.</param>
 /// <param name="productCode">The ProductCode having patches to enumerate.</param>
 /// <param name="userSid">The user's SID for patches to enumerate.</param>
 /// <param name="context">The installation context for patches to enumerate.</param>
 /// <param name="filter">The patch installation state for patches to enumerate.</param>
 private void WritePatches(string patchCode, string productCode, string userSid, UserContexts context, PatchStates filter)
 {
     foreach (PatchInstallation patch in PatchInstallation.GetPatches(patchCode, productCode, userSid, context, filter))
     {
         this.WritePatch(patch);
     }
 }
 ///<inheritdoc/>
 public IEnumerable<IProductInstallation> GetProducts(string productCode, string userSid, UserContexts context)
 {
     return ProductInstallation.GetProducts(productCode, userSid, context).Select(x => new ProductInstallationWrap(x) as IProductInstallation);
 }
示例#33
0
 /// <summary>
 /// Start to get a list of patches that are applicable to the given ProductCode in a separate thread.
 /// </summary>
 /// <param name="product">The ProductCode for which applicability is determined.</param>
 /// <param name="userSid">The SID of the user for which the product is installed. The default is null.</param>
 /// <param name="context">The <see cref="UserContexts"/> into which the product is installed. This must be <see cref="UserContexts.None"/> for a package path. The default is <see cref="UserContexts.None"/>.</param>
 /// <returns>An <see cref="IAsyncResult"/> you can use to query the current state of the task and return results when complete.</returns>
 /// <exception cref="ArgumentException">The parameters are not correct for the given package path or installed ProductCode (ex: cannot use <see cref="UserContexts.All"/> in any case).</exception>
 internal IAsyncResult BeginGetApplicablePatches(string product, string userSid = null, UserContexts context = UserContexts.None)
 {
     return this.action.BeginInvoke(product, userSid, context, null, null);
 }
示例#34
0
 /// <summary>
 /// Start to get a list of patches that are applicable to the given ProductCode in a separate thread.
 /// </summary>
 /// <param name="product">The ProductCode for which applicability is determined.</param>
 /// <param name="userSid">The SID of the user for which the product is installed. The default is null.</param>
 /// <param name="context">The <see cref="UserContexts"/> into which the product is installed. This must be <see cref="UserContexts.None"/> for a package path. The default is <see cref="UserContexts.None"/>.</param>
 /// <returns>An <see cref="IAsyncResult"/> you can use to query the current state of the task and return results when complete.</returns>
 /// <exception cref="ArgumentException">The parameters are not correct for the given package path or installed ProductCode (ex: cannot use <see cref="UserContexts.All"/> in any case).</exception>
 internal IAsyncResult BeginGetApplicablePatches(string product, string userSid = null, UserContexts context = UserContexts.None)
 {
     return(this.action.BeginInvoke(product, userSid, context, null, null));
 }
示例#35
0
 /// <summary>
 /// Enumerates products for the given ProductCode and writes them to the pipeline.
 /// </summary>
 /// <param name="productCode">The ProductCode of products to enumerate.</param>
 /// <param name="userSid">The user's SID for products to enumerate.</param>
 /// <param name="context">The installation context for products to enumerate.</param>
 /// <param name="patterns">Optional list of <see cref="WildcardPattern"/> to match product names.</param>
 private void WriteProducts(string productCode, string userSid, UserContexts context, IList<WildcardPattern> patterns = null)
 {
     foreach (ProductInstallation product in ProductInstallation.GetProducts(productCode, userSid, context))
     {
         if (0 == patterns.Count() || product.ProductName.Match(patterns))
         {
             this.WriteProduct(product);
         }
     }
 }
示例#36
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiEnumProductsEx(string szProductCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwIndex, StringBuilder szInstalledProductCode, [MarshalAs(UnmanagedType.I4)] out UserContexts pdwInstalledContext, StringBuilder szSid, ref uint pcchSid);
示例#37
0
        private IEnumerable<PatchSequence> DetermineApplicablePatches(string product, string userSid, UserContexts context)
        {
            var patches = this.Patches.ToArray();
            InapplicablePatchHandler handler = (patch, ex) => this.OnInapplicablePatch(new InapplicablePatchEventArgs(patch, product, ex));

            // Keep track of the sequence.
            int i = 0;

            // The current implementation does not return a null list.
            var applicable = Installer.DetermineApplicablePatches(product, patches, handler, userSid, context);
            foreach (var path in applicable)
            {
                yield return new PatchSequence()
                {
                    Patch = path,
                    Sequence = i++,
                    Product = product,
                    UserSid = userSid,
                    UserContext = context,
                };
            }
        }
示例#38
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiGetProductInfoEx(string szProductCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, string szProperty, StringBuilder lpValue, ref uint pcchValue);
示例#39
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiQueryComponentState(string szProductCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, string szComponent, out int pdwState);
示例#40
0
        /// <summary>
        /// Enumerates product installations based on certain criteria.
        /// </summary>
        /// <param name="productCode">ProductCode (GUID) of the product instances to be enumerated. Only
        /// instances of products within the scope of the context specified by the
        /// <paramref name="userSid"/> and <paramref name="context"/> parameters will be
        /// enumerated. This parameter may be set to null to enumerate all products in the specified
        /// context.</param>
        /// <param name="userSid">Specifies a security identifier (SID) that restricts the context
        /// of enumeration. A SID value other than s-1-1-0 is considered a user SID and restricts
        /// enumeration to the current user or any user in the system. The special SID string
        /// s-1-1-0 (Everyone) specifies enumeration across all users in the system. This parameter
        /// can be set to null to restrict the enumeration scope to the current user. When
        /// <paramref name="context"/> is set to the machine context only,
        /// <paramref name="userSid"/> must be null.</param>
        /// <param name="context">Specifies the user context.</param>
        /// <returns>An enumeration of product objects for enumerated product instances.</returns>
        /// <remarks><p>
        /// Win32 MSI API:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumproductsex.asp">MsiEnumProductsEx</a>
        /// </p></remarks>
        public static IEnumerable<ProductInstallation> GetProducts(
            string productCode, string userSid, UserContexts context)
        {
            StringBuilder buf = new StringBuilder(40);
            UserContexts targetContext;
            StringBuilder targetSidBuf = new StringBuilder(40);
            for (uint i = 0; ; i++)
            {
                uint targetSidBufSize = (uint) targetSidBuf.Capacity;
                uint ret = NativeMethods.MsiEnumProductsEx(
                    productCode,
                    userSid,
                    context,
                    i,
                    buf,
                    out targetContext,
                    targetSidBuf,
                    ref targetSidBufSize);
                if (ret == (uint) NativeMethods.Error.MORE_DATA)
                {
                    targetSidBuf.Capacity = (int) ++targetSidBufSize;
                    ret = NativeMethods.MsiEnumProductsEx(
                        productCode,
                        userSid,
                        context,
                        i,
                        buf,
                        out targetContext,
                        targetSidBuf,
                        ref targetSidBufSize);
                }

                if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }

                yield return new ProductInstallation(
                    buf.ToString(),
                    targetSidBuf.ToString(),
                    targetContext);
            }
        }
示例#41
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiSourceListEnumSources(string szProductCodeOrPatchCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwOptions, uint dwIndex, StringBuilder szSource, ref uint pcchSource);
示例#42
0
        /// <summary>
        /// Enumerates patch installations based on certain criteria.
        /// </summary>
        /// <param name="patchCode">PatchCode (GUID) of the patch to be enumerated. Only
        /// instances of patches within the scope of the context specified by the
        /// <paramref name="userSid"/> and <paramref name="context"/> parameters will be
        /// enumerated. This parameter may be set to null to enumerate all patches in the specified
        /// context.</param>
        /// <param name="targetProductCode">ProductCode (GUID) product whose patches are to be
        /// enumerated. If non-null, patch enumeration is restricted to instances of this product
        /// within the specified context. If null, the patches for all products under the specified
        /// context are enumerated.</param>
        /// <param name="userSid">Specifies a security identifier (SID) that restricts the context
        /// of enumeration. A SID value other than s-1-1-0 is considered a user SID and restricts
        /// enumeration to the current user or any user in the system. The special SID string
        /// s-1-1-0 (Everyone) specifies enumeration across all users in the system. This parameter
        /// can be set to null to restrict the enumeration scope to the current user. When
        /// <paramref name="userSid"/> must be null.</param>
        /// <param name="context">Specifies the user context.</param>
        /// <param name="states">The <see cref="PatchStates"/> of patches to return.</param>
        /// <remarks><p>
        /// Win32 MSI APIs:
        /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumpatchesex.asp">MsiEnumPatchesEx</a>
        /// </p></remarks>
        public static IEnumerable<PatchInstallation> GetPatches(
            string patchCode,
            string targetProductCode,
            string userSid,
            UserContexts context,
            PatchStates states)
        {
            StringBuilder buf = new StringBuilder(40);
            StringBuilder targetProductBuf = new StringBuilder(40);
            UserContexts targetContext;
            StringBuilder targetSidBuf = new StringBuilder(40);
            for (uint i = 0; ; i++)
            {
                uint targetSidBufSize = (uint) targetSidBuf.Capacity;
                uint ret = NativeMethods.MsiEnumPatchesEx(
                    targetProductCode,
                    userSid,
                    context,
                    (uint) states,
                    i,
                    buf,
                    targetProductBuf,
                    out targetContext,
                    targetSidBuf,
                    ref targetSidBufSize);
                if (ret == (uint) NativeMethods.Error.MORE_DATA)
                {
                    targetSidBuf.Capacity = (int) ++targetSidBufSize;
                    ret = NativeMethods.MsiEnumPatchesEx(
                        targetProductCode,
                        userSid,
                        context,
                        (uint) states,
                        i,
                        buf,
                        targetProductBuf,
                        out targetContext,
                        targetSidBuf,
                        ref targetSidBufSize);
                }

                if (ret == (uint) NativeMethods.Error.NO_MORE_ITEMS)
                {
                    break;
                }

                if (ret != 0)
                {
                    throw InstallerException.ExceptionFromReturnCode(ret);
                }

                string thisPatchCode = buf.ToString();
                if (patchCode == null || patchCode == thisPatchCode)
                {
                    yield return new PatchInstallation(
                        buf.ToString(),
                        targetProductBuf.ToString(),
                        targetSidBuf.ToString(),
                        targetContext);
                }
            }
        }
示例#43
0
 [DllImport("msi.dll", CharSet = CharSet.Unicode)] internal static extern uint MsiSourceListForceResolutionEx(string szProductCodeOrPatchCode, string szUserSid, [MarshalAs(UnmanagedType.I4)] UserContexts dwContext, uint dwOptions);
示例#44
0
    /// <summary>
    /// Determines which patches apply to a specified product and in what sequence.  If
    /// the product is installed, this method accounts for patches that have already been applied to
    /// the product and accounts for obsolete and superceded patches.
    /// </summary>
    /// <param name="product">The product that is the target for the set of patches.  This may be
    /// either a ProductCode (GUID) of a product that is currently installed, or the path to a an
    /// MSI file.</param>
    /// <param name="patches">An array of strings specifying the patches to be checked.  Each item
    /// may be the path to an MSP file, the path an XML file, or just an XML blob.</param>
    /// <param name="errorHandler">Callback to be invoked for each inapplicable patch, reporting the
    /// reason the patch is not applicable.  This value may be left null if that information is not
    /// desired.</param>
    /// <param name="userSid">Specifies a security identifier (SID) of a user. This parameter restricts
    /// the context of enumeration for this user account. This parameter cannot be the special SID
    /// strings s-1-1-0 (everyone) or s-1-5-18 (local system). If <paramref name="context"/> is set to
    /// <see cref="UserContexts.None"/> or <see cref="UserContexts.Machine"/>, then
    /// <paramref name="userSid"/> must be null. For the current user context, <paramref name="userSid"/>
    /// can be null and <paramref name="context"/> can be set to <see cref="UserContexts.UserManaged"/>
    /// or <see cref="UserContexts.UserUnmanaged"/>.</param>
    /// <param name="context">Restricts the enumeration to per-user-unmanaged, per-user-managed,
    /// or per-machine context, or (if referring to an MSI) to no system context at all.  This
    /// parameter can be <see cref="UserContexts.Machine"/>, <see cref="UserContexts.UserManaged"/>,
    /// <see cref="UserContexts.UserUnmanaged"/>, or <see cref="UserContexts.None"/>.</param>
    /// <returns>An array of selected patch strings from <paramref name="patches"/>, indicating
    /// the set of applicable patches.  The items are re-ordered to be in the best sequence.</returns>
    /// <remarks><p>
    /// If an item in <paramref name="patches"/> is a file path but does not end in .MSP or .XML,
    /// it is assumed to be an MSP file.
    /// </p><p>
    /// Passing an InstallContext of None only analyzes the MSI file; it does not consider the
    /// current state of the system. You cannot use InstallContext.None with a ProductCode GUID.
    /// </p><p>
    /// Win32 MSI APIs:
    /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidetermineapplicablepatches.asp">MsiDetermineApplicablePatches</a>
    /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msideterminepatchsequence.asp">MsiDeterminePatchSequence</a>
    /// </p></remarks>
    public static IList<string> DetermineApplicablePatches(
        string product,
        string[] patches,
        InapplicablePatchHandler errorHandler,
        string userSid,
        UserContexts context)
    {
        if (String.IsNullOrEmpty(product))
        {
            throw new ArgumentNullException("product");
        }

        if (patches == null)
        {
            throw new ArgumentNullException("patches");
        }

        NativeMethods.MsiPatchSequenceData[] sequenceData = new NativeMethods.MsiPatchSequenceData[patches.Length];
        for (int i = 0; i < patches.Length; i++)
        {
            if (String.IsNullOrEmpty(patches[i]))
            {
                throw new ArgumentNullException("patches[" + i + "]");
            }

            sequenceData[i].szPatchData = patches[i];
            sequenceData[i].ePatchDataType = GetPatchStringDataType(patches[i]);
            sequenceData[i].dwOrder = -1;
            sequenceData[i].dwStatus = 0;
        }
        
        uint ret;
        if (context == UserContexts.None)
        {
            ret = NativeMethods.MsiDetermineApplicablePatches(product, (uint) sequenceData.Length, sequenceData);
        }
        else
        {
            ret = NativeMethods.MsiDeterminePatchSequence(product, userSid, context, (uint) sequenceData.Length, sequenceData);
        }

        if (errorHandler != null)
        {
            for (int i = 0; i < sequenceData.Length; i++)
            {
                if (sequenceData[i].dwOrder < 0 && sequenceData[i].dwStatus != 0)
                {
                    errorHandler(sequenceData[i].szPatchData, InstallerException.ExceptionFromReturnCode(sequenceData[i].dwStatus));
                }
            }
        }

        if (ret != 0)
        {
            throw InstallerException.ExceptionFromReturnCode(ret);
        }

        IList<string> patchSeq = new List<string>(patches.Length);
        for (int i = 0; i < sequenceData.Length; i++)
        {
            for (int j = 0; j < sequenceData.Length; j++)
            {
                if (sequenceData[j].dwOrder == i)
                {
                    patchSeq.Add(sequenceData[j].szPatchData);
                }
            }
        }
        return patchSeq;
    }
示例#45
0
        /// <summary>
        /// Gets the weight of a package given its ProductCode.
        /// </summary>
        /// <param name="productCode">The ProductCode of the product to query.</param>
        /// <param name="userSid">The optional user SID of the product to query. The default is null.</param>
        /// <param name="context">The optional context of the product ot query. The default is <see cref="UserContexts.All"/>.</param>
        /// <returns>The weight of a package given its ProductCode or 0 if the product is not installed or the package missing.</returns>
        internal static long GetWeightFromProductCode(string productCode, string userSid = null, UserContexts context = UserContexts.All)
        {
            var product = new ProductInstallation(productCode, userSid, context);

            if (null != product && product.IsInstalled)
            {
                var path = product.LocalPackage;
                if (!string.IsNullOrEmpty(path))
                {
                    return(PackageInfo.GetWeightFromPath(path));
                }
            }

            return(0);
        }