private static void CheckInstallResult(uint ret) { switch (ret) { case (uint)NativeMethods.Error.SUCCESS: break; case (uint)NativeMethods.Error.SUCCESS_REBOOT_REQUIRED: Installer.rebootRequired = true; break; case (uint)NativeMethods.Error.SUCCESS_REBOOT_INITIATED: Installer.rebootInitiated = true; break; default: throw InstallerException.ExceptionFromReturnCode(ret); } }
private void ClearSourceType(NativeMethods.SourceType type) { uint ret = NativeMethods.MsiSourceListClearAllEx( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint)type | (uint)this.installation.InstallationType); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Forces the installer to search the source list for a valid /// source the next time a source is required. For example, when the /// installer performs an installation or reinstallation, or when it /// requires the path for a component that is set to run from source. /// </summary> /// <remarks><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistforceresolution.asp">MsiSourceListForceResolution</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistforceresolutionex.asp">MsiSourceListForceResolutionEx</a> /// </p></remarks> internal void ForceResolution() { uint ret = NativeMethods.MsiSourceListForceResolutionEx( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint)this.installation.InstallationType); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Apply a transform to the database, specifying error conditions to suppress. /// </summary> /// <param name="transformFile">Path to the transform file</param> /// <param name="errorConditionsToSuppress">Error conditions that are to be suppressed</param> /// <exception cref="InstallerException">the transform could not be applied</exception> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseapplytransform.asp">MsiDatabaseApplyTransform</a> /// </p></remarks> internal void ApplyTransform(string transformFile, TransformErrors errorConditionsToSuppress) { if (String.IsNullOrEmpty(transformFile)) { throw new ArgumentNullException("transformFile"); } uint ret = NativeMethods.MsiDatabaseApplyTransform((int)this.Handle, transformFile, (int)errorConditionsToSuppress); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Sets the value of a field to a nullable integer. /// </summary> /// <param name="field">Specifies the field to set.</param> /// <param name="value">new value of the field</param> /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the /// number of fields in the Record.</exception> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordsetinteger.asp">MsiRecordSetInteger</a> /// </p></remarks> /// <seealso cref="SetInteger(int,int)"/> internal void SetNullableInteger(int field, int?value) { this.CheckRange(field); uint ret = RemotableNativeMethods.MsiRecordSetInteger( (int)this.Handle, (uint)field, value.HasValue ? (int)value : Int32.MinValue); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <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> internal 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)); } }
internal void Execute(Record executeParams) { uint ret = RemotableNativeMethods.MsiViewExecute( (int)this.Handle, (executeParams != null ? (int)executeParams.Handle : 0)); if (ret == (uint)NativeMethods.Error.BAD_QUERY_SYNTAX) { throw new BadQuerySyntaxException(this.sql); } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Finalizes the persistent form of the database. All persistent data is written /// to the writeable database, and no temporary columns or rows are written. /// </summary> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// For a database open in <see cref="DatabaseOpenMode.ReadOnly"/> mode, this method has no effect. /// </p><p> /// For a database open in <see cref="DatabaseOpenMode.CreateDirect" /> or <see cref="DatabaseOpenMode.Direct" /> /// mode, it is not necessary to call this method because the database will be automatically committed /// when it is closed. However this method may be called at any time to persist the current state of tables /// loaded into memory. /// </p><p> /// For a database open in <see cref="DatabaseOpenMode.Create" /> or <see cref="DatabaseOpenMode.Transact" /> /// mode, no changes will be persisted until this method is called. If the database object is closed without /// calling this method, the database file remains unmodified. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabasecommit.asp">MsiDatabaseCommit</a> /// </p></remarks> internal void Commit() { if (this.summaryInfo != null && !this.summaryInfo.IsClosed) { this.summaryInfo.Persist(); this.summaryInfo.Close(); this.summaryInfo = null; } uint ret = NativeMethods.MsiDatabaseCommit((int)this.Handle); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Executes an action sequence described in the specified table. /// </summary> /// <param name="sequenceTable">Name of the table containing the action sequence.</param> /// <exception cref="InvalidHandleException">the Session handle is invalid</exception> /// <exception cref="InstallCanceledException">the user exited the installation</exception> /// <remarks><p> /// This method queries the specified table, ordering the actions by the numbers in the Sequence column. /// For each row retrieved, an action is executed, provided that any supplied condition expression does /// not evaluate to FALSE. /// </p><p> /// An action sequence containing any actions that update the system, such as the InstallFiles and /// WriteRegistryValues actions, cannot be run by calling DoActionSequence. The exception to this rule is if /// DoActionSequence is called from a custom action that is scheduled in the InstallExecuteSequence table /// between the InstallInitialize and InstallFinalize actions. Actions that do not update the system, such /// as AppSearch or CostInitialize, can be called. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisequence.asp">MsiSequence</a> /// </p></remarks> internal void DoActionSequence(string sequenceTable) { if (String.IsNullOrEmpty(sequenceTable)) { throw new ArgumentNullException("sequenceTable"); } this.ValidateSessionAccess(); uint ret = RemotableNativeMethods.MsiSequence((int)this.Handle, sequenceTable, 0); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Checks to see if sufficient disk space is present for the current installation. /// </summary> /// <returns>True if there is sufficient disk space; false otherwise.</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiverifydiskspace.asp">MsiVerifyDiskSpace</a> /// </p></remarks> internal bool VerifyDiskSpace() { this.ValidateSessionAccess(); uint ret = RemotableNativeMethods.MsiVerifyDiskSpace((int)this.Handle); if (ret == (uint)NativeMethods.Error.DISK_FULL) { return(false); } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(true); }
/// <summary> /// Sets a record stream field from a file. Stream data cannot be inserted into temporary fields. /// </summary> /// <param name="field">Specifies the field of the Record to set.</param> /// <param name="filePath">Specifies the path to the file containing the stream.</param> /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the /// number of fields in the Record.</exception> /// <remarks><p> /// The contents of the specified file are read into a stream object. The stream persists if /// the Record is inserted into the Database and the Database is committed. /// </p><p> /// To reset the stream to its beginning you must pass in null for filePath. /// Do not pass an empty string, "", to reset the stream. /// </p><p> /// Setting a stream with this method is more efficient than setting a field to a /// FileStream object. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordsetstream.asp">MsiRecordsetStream</a> /// </p></remarks> internal void SetStream(int field, string filePath) { this.CheckRange(field); if (String.IsNullOrEmpty(filePath)) { throw new ArgumentNullException("filePath"); } uint ret = RemotableNativeMethods.MsiRecordSetStream((int)this.Handle, (uint)field, filePath); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Makes the current process the owner of the multi-package installation transaction. /// </summary> /// <param name="attributes">Select optional behavior when joining the transaction.</param> /// <exception cref="InvalidHandleException">The transaction handle is not valid.</exception> /// <exception cref="InstallerException">The transaction could not be joined.</exception> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msijointransaction.asp">MsiJoinTransaction</a> /// </p></remarks> internal void Join(TransactionAttributes attributes) { IntPtr hChangeOfOwnerEvent; uint ret = NativeMethods.MsiJoinTransaction((int)this.Handle, (int)attributes, out hChangeOfOwnerEvent); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } this.ownerChangeEvent = hChangeOfOwnerEvent; if (this.ownerChangeEvent != IntPtr.Zero && this.ownerChangeListeners.Count >= 1) { new Thread(this.WaitForOwnerChange).Start(); } }
/// <summary> /// Adds or updates a disk of the media source for the product or patch. /// </summary> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistaddmediadisk.asp">MsiSourceListAddMediaDisk</a> /// </p></remarks> public void Add(MediaDisk item) { uint ret = NativeMethods.MsiSourceListAddMediaDisk( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint)this.installation.InstallationType, (uint)item.DiskId, item.VolumeLabel, item.DiskPrompt); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Removes a specified disk from the set of registered disks. /// </summary> /// <param name="diskId">ID of the disk to remove</param> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisourcelistclearmediadisk.asp">MsiSourceListClearMediaDisk</a> /// </p></remarks> internal bool Remove(int diskId) { uint ret = NativeMethods.MsiSourceListClearMediaDisk( this.installation.InstallationCode, this.installation.UserSid, this.installation.Context, (uint)this.installation.InstallationType, (uint)diskId); if (ret != 0) { // TODO: Figure out when to return false. throw InstallerException.ExceptionFromReturnCode(ret); } return(true); }
/// <summary> /// Generates an advertise script. The method enables the installer to write to a /// script the registry and shortcut information used to assign or publish a product. /// </summary> /// <param name="packagePath">Path to the package of the product being advertised</param> /// <param name="scriptFilePath">path to script file to be created with the advertise information</param> /// <param name="transforms">Semi-colon delimited list of transforms to be applied. This parameter may be null.</param> /// <param name="locale">The language to use if the source supports multiple languages</param> /// <param name="processor">Targeted processor architecture.</param> /// <param name="instance">True to install multiple instances through product code changing transform. /// Advertises a new instance of the product. Requires that the <paramref name="transforms"/> parameter /// includes the instance transform that changes the product code.</param> /// <seealso cref="AdvertiseProduct"/> /// <remarks><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiadvertiseproduct.asp">MsiAdvertiseProduct</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiadvertiseproductex.asp">MsiAdvertiseProductEx</a> /// </p></remarks> internal static void GenerateAdvertiseScript( string packagePath, string scriptFilePath, string transforms, int locale, ProcessorArchitecture processor, bool instance) { if (String.IsNullOrEmpty(packagePath)) { throw new ArgumentNullException("packagePath"); } if (String.IsNullOrEmpty(scriptFilePath)) { throw new ArgumentNullException("scriptFilePath"); } if (!File.Exists(packagePath)) { throw new FileNotFoundException(null, packagePath); } uint platform = 0; switch (processor) { case ProcessorArchitecture.X86: platform = (uint)1; break; case ProcessorArchitecture.IA64: platform = (uint)2; break; case ProcessorArchitecture.Amd64: platform = (uint)4; break; } uint ret = NativeMethods.MsiAdvertiseProductEx( packagePath, scriptFilePath, transforms, (ushort)locale, platform, instance ? (uint)1 : 0); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
internal IList <InstallCost> GetTotalCost() { this.ValidateSessionAccess(); IList <InstallCost> costs = new List <InstallCost>(); StringBuilder driveBuf = new StringBuilder(20); for (uint i = 0; true; i++) { int cost, tempCost; uint driveBufSize = (uint)driveBuf.Capacity; uint ret = RemotableNativeMethods.MsiEnumComponentCosts( (int)this.Handle, null, i, (int)InstallState.Default, driveBuf, ref driveBufSize, out cost, out tempCost); if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS) { break; } if (ret == (uint)NativeMethods.Error.MORE_DATA) { driveBuf.Capacity = (int)++driveBufSize; ret = RemotableNativeMethods.MsiEnumComponentCosts( (int)this.Handle, null, i, (int)InstallState.Default, driveBuf, ref driveBufSize, out cost, out tempCost); } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } costs.Add(new InstallCost(driveBuf.ToString(), cost * 512L, tempCost * 512L)); } return(costs); }
/// <summary> /// Examines a shortcut and returns its product, feature name, and component if available. /// </summary> /// <param name="shortcut">Full path to a shortcut</param> /// <returns>ShortcutTarget structure containing target product code, feature, and component code</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetshortcuttarget.asp">MsiGetShortcutTarget</a> /// </p></remarks> internal static ShortcutTarget GetShortcutTarget(string shortcut) { StringBuilder productBuf = new StringBuilder(40); StringBuilder featureBuf = new StringBuilder(40); StringBuilder componentBuf = new StringBuilder(40); uint ret = NativeMethods.MsiGetShortcutTarget(shortcut, productBuf, featureBuf, componentBuf); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(new ShortcutTarget( productBuf.Length > 0 ? productBuf.ToString() : null, featureBuf.Length > 0 ? featureBuf.ToString() : null, componentBuf.Length > 0 ? componentBuf.ToString() : null)); }
internal void Modify(ViewModifyMode mode, Record record) { if (record == null) { throw new ArgumentNullException("record"); } uint ret = RemotableNativeMethods.MsiViewModify((int)this.Handle, (int)mode, (int)record.Handle); if (mode == ViewModifyMode.Insert || mode == ViewModifyMode.InsertTemporary) { record.IsFormatStringInvalid = true; } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Gets the full path to a Windows Installer component containing an assembly. This method prompts for a source and /// increments the usage count for the feature. /// </summary> /// <param name="assemblyName">Assembly name</param> /// <param name="appContext">Set to null for global assemblies. For private assemblies, set to the full path of the /// application configuration file (.cfg file) or executable file (.exe) of the application to which the assembly /// has been made private.</param> /// <param name="installMode">Installation mode; this can also include bits from <see cref="ReinstallModes"/></param> /// <param name="isWin32Assembly">True if this is a Win32 assembly, false if it is a .NET assembly</param> /// <returns>Path to the assembly</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiprovideassembly.asp">MsiProvideAssembly</a> /// </p></remarks> internal static string ProvideAssembly(string assemblyName, string appContext, InstallMode installMode, bool isWin32Assembly) { StringBuilder pathBuf = new StringBuilder(512); uint pathBufSize = (uint)pathBuf.Capacity; uint ret = NativeMethods.MsiProvideAssembly(assemblyName, appContext, unchecked ((uint)installMode), (isWin32Assembly ? (uint)1 : 0), pathBuf, ref pathBufSize); if (ret == (uint)NativeMethods.Error.MORE_DATA) { pathBuf.Capacity = (int)++pathBufSize; ret = NativeMethods.MsiProvideAssembly(assemblyName, appContext, unchecked ((uint)installMode), (isWin32Assembly ? (uint)1 : 0), pathBuf, ref pathBufSize); } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(pathBuf.ToString()); }
/// <summary> /// Gets the set of all products with a specified upgrade code. This method lists the /// currently installed and advertised products that have the specified UpgradeCode /// property in their Property table. /// </summary> /// <param name="upgradeCode">Upgrade code of related products</param> /// <returns>Enumeration of product codes</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienumrelatedproducts.asp">MsiEnumRelatedProducts</a> /// </p></remarks> internal static IEnumerable <ProductInstallation> GetRelatedProducts(string upgradeCode) { StringBuilder buf = new StringBuilder(40); for (uint i = 0; true; i++) { uint ret = NativeMethods.MsiEnumRelatedProducts(upgradeCode, 0, i, buf); if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS) { break; } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } yield return(new ProductInstallation(buf.ToString())); } }
/// <summary> /// Opens an installer package for an installed product using the product code. /// </summary> /// <param name="productCode">Product code of the installed product</param> /// <returns>A Session object allowing access to the product database and install engine, /// or null if the specified product is not installed.</returns> /// <exception cref="ArgumentException">An unknown product was requested</exception> /// <exception cref="InstallerException">The product could not be opened</exception> /// <exception cref="InstallerException">The installer configuration data is corrupt</exception> /// <remarks><p> /// Note that only one Session object can be opened by a single process. OpenProduct cannot be /// used in a custom action because the active installation is the only session allowed. /// </p><p> /// The Session object should be <see cref="InstallerHandle.Close"/>d after use. /// It is best that the handle be closed manually as soon as it is no longer /// needed, as leaving lots of unused handles open can degrade performance. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiopenproduct.asp">MsiOpenProduct</a> /// </p></remarks> internal static Session OpenProduct(string productCode) { int sessionHandle; uint ret = NativeMethods.MsiOpenProduct(productCode, out sessionHandle); if (ret != 0) { if (ret == (uint)NativeMethods.Error.UNKNOWN_PRODUCT) { return(null); } else { throw InstallerException.ExceptionFromReturnCode(ret); } } return(new Session((IntPtr)sessionHandle, true)); }
/// <summary> /// Extracts information from a patch that can be used to determine whether the patch /// applies on a target system. The method returns an XML string that can be provided to /// <see cref="DetermineApplicablePatches(string,string[],InapplicablePatchHandler,string,UserContexts)"/> /// instead of the full patch file. /// </summary> /// <param name="patchPath">Full path to the patch being queried.</param> /// <returns>XML string containing patch data.</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiextractpatchxmldata.asp">MsiExtractPatchXMLData</a> /// </p></remarks> internal static string ExtractPatchXmlData(string patchPath) { StringBuilder buf = new StringBuilder(""); uint bufSize = 0; uint ret = NativeMethods.MsiExtractPatchXMLData(patchPath, 0, buf, ref bufSize); if (ret == (uint)NativeMethods.Error.MORE_DATA) { buf.Capacity = (int)++bufSize; ret = NativeMethods.MsiExtractPatchXMLData(patchPath, 0, buf, ref bufSize); } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(buf.ToString()); }
/// <summary> /// Gets the full component path for a qualified component that is published by a product and /// performs any necessary installation. This method prompts for source if necessary and increments /// the usage count for the feature. /// </summary> /// <param name="component">Specifies the component ID for the requested component. This may not be the /// GUID for the component itself but rather a server that provides the correct functionality, as in the /// ComponentId column of the PublishComponent table.</param> /// <param name="qualifier">Specifies a qualifier into a list of advertising components (from PublishComponent Table).</param> /// <param name="installMode">Installation mode; this can also include bits from <see cref="ReinstallModes"/></param> /// <param name="product">Optional; specifies the product to match that has published the qualified component.</param> /// <returns>Path to the component</returns> /// <remarks><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiprovidequalifiedcomponent.asp">MsiProvideQualifiedComponent</a> /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiprovidequalifiedcomponentex.asp">MsiProvideQualifiedComponentEx</a> /// </p></remarks> internal static string ProvideQualifiedComponent(string component, string qualifier, InstallMode installMode, string product) { StringBuilder pathBuf = new StringBuilder(512); uint pathBufSize = (uint)pathBuf.Capacity; uint ret = NativeMethods.MsiProvideQualifiedComponentEx(component, qualifier, unchecked ((uint)installMode), product, 0, 0, pathBuf, ref pathBufSize); if (ret == (uint)NativeMethods.Error.MORE_DATA) { pathBuf.Capacity = (int)++pathBufSize; ret = NativeMethods.MsiProvideQualifiedComponentEx(component, qualifier, unchecked ((uint)installMode), product, 0, 0, pathBuf, ref pathBufSize); } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(pathBuf.ToString()); }
/// <summary> /// Sets the designated mode flag for the current install session. /// </summary> /// <param name="mode">The type of mode to be set.</param> /// <param name="value">The desired value of the mode.</param> /// <exception cref="InvalidHandleException">the Session handle is invalid</exception> /// <exception cref="ArgumentOutOfRangeException">an invalid mode flag was specified</exception> /// <exception cref="InvalidOperationException">the mode cannot not be set</exception> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetmode.asp">MsiSetMode</a> /// </p></remarks> internal void SetMode(InstallRunMode mode, bool value) { this.ValidateSessionAccess(); uint ret = RemotableNativeMethods.MsiSetMode((int)this.Handle, (uint)mode, value); if (ret != 0) { if (ret == (uint)NativeMethods.Error.ACCESS_DENIED) { throw new InvalidOperationException(); } else { throw InstallerException.ExceptionFromReturnCode(ret); } } }
/// <summary> /// Fetches the next sequential record from the view, or null if there are no more records. /// </summary> /// <exception cref="InstallerException">the View is not in an active state</exception> /// <exception cref="InvalidHandleException">the View handle is invalid</exception> /// <remarks><p> /// The Record object should be <see cref="InstallerHandle.Close"/>d after use. /// It is best that the handle be closed manually as soon as it is no longer /// needed, as leaving lots of unused handles open can degrade performance. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiviewfetch.asp">MsiViewFetch</a> /// </p></remarks> internal Record Fetch() { int recordHandle; uint ret = RemotableNativeMethods.MsiViewFetch((int)this.Handle, out recordHandle); if (ret == (uint)NativeMethods.Error.NO_MORE_ITEMS) { return(null); } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } Record r = new Record((IntPtr)recordHandle, true, this); r.IsFormatStringInvalid = true; return(r); }
/// <summary> /// Gets a field value as a string. /// </summary> /// <param name="field">Specifies the field to retrieve.</param> /// <returns>String value of the field, or an empty string if the field is null.</returns> /// <exception cref="ArgumentOutOfRangeException">The field is less than 0 or greater than the /// number of fields in the Record.</exception> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msirecordgetstring.asp">MsiRecordGetString</a> /// </p></remarks> internal string GetString(int field) { this.CheckRange(field); StringBuilder buf = new StringBuilder(String.Empty); uint bufSize = 0; uint ret = RemotableNativeMethods.MsiRecordGetString((int)this.Handle, (uint)field, buf, ref bufSize); if (ret == (uint)NativeMethods.Error.MORE_DATA) { buf.Capacity = (int)++bufSize; ret = RemotableNativeMethods.MsiRecordGetString((int)this.Handle, (uint)field, buf, ref bufSize); } if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(buf.ToString()); }
/// <summary> /// Generates an advertise script. The method enables the installer to write to a /// script the registry and shortcut information used to assign or publish a product. /// </summary> /// <param name="packagePath">Path to the package of the product being advertised</param> /// <param name="scriptFilePath">path to script file to be created with the advertise information</param> /// <param name="transforms">Semi-colon delimited list of transforms to be applied. This parameter may be null.</param> /// <param name="locale">The language to use if the source supports multiple languages</param> /// <exception cref="FileNotFoundException">the specified package file does not exist</exception> /// <seealso cref="AdvertiseProduct"/> /// <remarks><p> /// Win32 MSI APIs: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiadvertiseproduct.asp">MsiAdvertiseProduct</a>, /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msiadvertiseproductex.asp">MsiAdvertiseProductEx</a> /// </p></remarks> internal static void GenerateAdvertiseScript(string packagePath, string scriptFilePath, string transforms, int locale) { if (String.IsNullOrEmpty(packagePath)) { throw new ArgumentNullException("packagePath"); } if (!File.Exists(packagePath)) { throw new FileNotFoundException(null, packagePath); } uint ret = NativeMethods.MsiAdvertiseProduct(packagePath, scriptFilePath, transforms, (ushort)locale); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Calculates the disk space required by the feature and its selected children and parent features. /// </summary> /// <param name="includeParents">If true, the parent features are included in the cost.</param> /// <param name="includeChildren">If true, the child features are included in the cost.</param> /// <param name="installState">Specifies the installation state.</param> /// <returns>The disk space requirement in bytes.</returns> /// <remarks><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msigetfeaturecost.asp">MsiGetFeatureCost</a> /// </p></remarks> internal long GetCost(bool includeParents, bool includeChildren, InstallState installState) { const int MSICOSTTREE_CHILDREN = 1; const int MSICOSTTREE_PARENTS = 2; int cost; uint ret = RemotableNativeMethods.MsiGetFeatureCost( (int)this.session.Handle, this.name, (includeParents ? MSICOSTTREE_PARENTS : 0) | (includeChildren ? MSICOSTTREE_CHILDREN : 0), (int)installState, out cost); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(cost * 512L); }
/// <summary> /// Gets a View object representing the query specified by a SQL string. /// </summary> /// <param name="sqlFormat">SQL query string, which may contain format items</param> /// <param name="args">Zero or more objects to format</param> /// <returns>A View object representing the query specified by a SQL string</returns> /// <exception cref="BadQuerySyntaxException">the SQL syntax is invalid</exception> /// <exception cref="InvalidHandleException">the Database handle is invalid</exception> /// <remarks><p> /// The <paramref name="sqlFormat"/> parameter is formatted using <see cref="String.Format(string,object[])"/>. /// </p><p> /// The View object should be <see cref="InstallerHandle.Close"/>d after use. /// It is best that the handle be closed manually as soon as it is no longer /// needed, as leaving lots of unused handles open can degrade performance. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msidatabaseopenview.asp">MsiDatabaseOpenView</a> /// </p></remarks> internal View OpenView(string sqlFormat, params object[] args) { if (String.IsNullOrEmpty(sqlFormat)) { throw new ArgumentNullException("sqlFormat"); } string sql = (args == null || args.Length == 0 ? sqlFormat : String.Format(CultureInfo.InvariantCulture, sqlFormat, args)); int viewHandle; uint ret = RemotableNativeMethods.MsiDatabaseOpenView((int)this.Handle, sql, out viewHandle); if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(new View((IntPtr)viewHandle, sql, this)); }
internal bool Merge(Record record) { if (record == null) { throw new ArgumentNullException("record"); } uint ret = RemotableNativeMethods.MsiViewModify((int)this.Handle, (int)ViewModifyMode.Merge, (int)record.Handle); if (ret == (uint)NativeMethods.Error.FUNCTION_FAILED) { return(false); } else if (ret != 0) { throw InstallerException.ExceptionFromReturnCode(ret); } return(true); }