/// <summary> /// Enables logging of the selected message type for all subsequent install sessions in /// the current process space. /// </summary> /// <param name="logModes">One or more mode flags specifying the type of messages to log</param> /// <param name="logFile">Full path to the log file. A null path disables logging, /// in which case the logModes paraneter is ignored.</param> /// <param name="append">If true, the log lines will be appended to any existing file content. /// If false, the log file will be truncated if it exists. The default is false.</param> /// <param name="flushEveryLine">If true, the log will be flushed after every line. /// If false, the log will be flushed every 20 lines. The default is true.</param> /// <exception cref="ArgumentException">an invalid log mode was specified</exception> /// <remarks><p> /// This method takes effect on any new installation processes. Calling this /// method from within a custom action will not start logging for that installation. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienablelog.asp">MsiEnableLog</a> /// </p></remarks> public static void EnableLog(InstallLogModes logModes, string logFile, bool append, bool flushEveryLine) { uint ret = NativeMethods.MsiEnableLog((uint)logModes, logFile, (append ? (uint)1 : 0) + (flushEveryLine ? (uint)2 : 0)); if (ret != 0 && ret != (uint)NativeMethods.Error.FILE_INVALID) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Enables an external user-interface handler. This external UI handler is called before the /// normal internal user-interface handler. The external UI handler has the option to suppress /// the internal UI by returning a non-zero value to indicate that it has handled the messages. /// </summary> /// <param name="uiHandler">A callback delegate that handles the UI messages</param> /// <param name="messageFilter">Specifies which messages to handle using the external message handler. /// If the external handler returns a non-zero result, then that message will not be sent to the UI, /// instead the message will be logged if logging has been enabled.</param> /// <returns>The previously set external handler, or null if there was no previously set handler</returns> /// <remarks><p> /// To restore the previous UI handler, a second call is made to SetExternalUI using the /// ExternalUIHandler returned by the first call to SetExternalUI and specifying /// <see cref="InstallLogModes.None"/> as the message filter. /// </p><p> /// The external user interface handler does not have full control over the external user /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not /// handled by the external user interface handler is handled by Windows Installer. The initial /// "Preparing to install..." dialog always appears even if the external user interface /// handler handles all messages. /// </p><p> /// SetExternalUI should only be called from a bootstrapping application. You cannot call /// it from a custom action /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternalui.asp">MsiSetExternalUI</a> /// </p></remarks> public static ExternalUIHandler SetExternalUI(ExternalUIHandler uiHandler, InstallLogModes messageFilter) { NativeExternalUIHandler nativeHandler = null; if (uiHandler != null) { nativeHandler = new ExternalUIProxy(uiHandler).ProxyHandler; Installer.externalUIHandlers.Add(nativeHandler); } NativeExternalUIHandler oldNativeHandler = NativeMethods.MsiSetExternalUI(nativeHandler, (uint) messageFilter, IntPtr.Zero); if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIProxy) { Installer.externalUIHandlers.Remove(oldNativeHandler); return ((ExternalUIProxy) oldNativeHandler.Target).Handler; } else { return null; } }
/// <summary> /// Enables an external user-interface handler. This external UI handler is called before the /// normal internal user-interface handler. The external UI handler has the option to suppress /// the internal UI by returning a non-zero value to indicate that it has handled the messages. /// </summary> /// <param name="uiHandler">A callback delegate that handles the UI messages</param> /// <param name="messageFilter">Specifies which messages to handle using the external message handler. /// If the external handler returns a non-zero result, then that message will not be sent to the UI, /// instead the message will be logged if logging has been enabled.</param> /// <returns>The previously set external handler, or null if there was no previously set handler</returns> /// <remarks><p> /// To restore the previous UI handler, a second call is made to SetExternalUI using the /// ExternalUIHandler returned by the first call to SetExternalUI and specifying /// <see cref="InstallLogModes.None"/> as the message filter. /// </p><p> /// The external user interface handler does not have full control over the external user /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not /// handled by the external user interface handler is handled by Windows Installer. The initial /// "Preparing to install..." dialog always appears even if the external user interface /// handler handles all messages. /// </p><p> /// SetExternalUI should only be called from a bootstrapping application. You cannot call /// it from a custom action /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternalui.asp">MsiSetExternalUI</a> /// </p></remarks> public static ExternalUIHandler SetExternalUI(ExternalUIHandler uiHandler, InstallLogModes messageFilter) { NativeExternalUIHandler nativeHandler = null; if (uiHandler != null) { nativeHandler = new ExternalUIProxy(uiHandler).ProxyHandler; Installer.externalUIHandlers.Add(nativeHandler); } NativeExternalUIHandler oldNativeHandler = NativeMethods.MsiSetExternalUI(nativeHandler, (uint)messageFilter, IntPtr.Zero); if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIProxy) { Installer.externalUIHandlers.Remove(oldNativeHandler); return(((ExternalUIProxy)oldNativeHandler.Target).Handler); } else { return(null); } }
private void Initialize() { if (this.initialized) { return; } if (string.IsNullOrEmpty(this.path)) { string temp = Path.GetTempPath(); string name = DefaultPrefix + DefaultExtension; this.path = Path.Combine(temp, name); } if (string.IsNullOrEmpty(this.filename)) { string path = Path.GetDirectoryName(this.path); string name = Path.GetFileNameWithoutExtension(this.path); this.filename = Path.Combine(path, name); } if (string.IsNullOrEmpty(this.extension)) { this.extension = Path.GetExtension(this.path); } // If the log mode is not already set up for debugging, check the system policy. if (InstallLogModes.ExtraDebug != (InstallLogModes.ExtraDebug & this.Mode)) { string policy = GetLoggingPolicy(); if (!string.IsNullOrEmpty(policy) && 0 <= policy.IndexOf("X", StringComparison.OrdinalIgnoreCase)) { this.Mode |= InstallLogModes.ExtraDebug; } } this.initialized = true; }
/// <summary> /// [MSI 3.1] Enables a record-based external user-interface handler. This external UI handler is called /// before the normal internal user-interface handler. The external UI handler has the option to suppress /// the internal UI by returning a non-zero value to indicate that it has handled the messages. /// </summary> /// <param name="uiHandler">A callback delegate that handles the UI messages</param> /// <param name="messageFilter">Specifies which messages to handle using the external message handler. /// If the external handler returns a non-zero result, then that message will not be sent to the UI, /// instead the message will be logged if logging has been enabled.</param> /// <returns>The previously set external handler, or null if there was no previously set handler</returns> /// <remarks><p> /// To restore the previous UI handler, a second call is made to SetExternalUI using the /// ExternalUIHandler returned by the first call to SetExternalUI and specifying /// <see cref="InstallLogModes.None"/> as the message filter. /// </p><p> /// The external user interface handler does not have full control over the external user /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not /// handled by the external user interface handler is handled by Windows Installer. The initial /// "Preparing to install..." dialog always appears even if the external user interface /// handler handles all messages. /// </p><p> /// SetExternalUI should only be called from a bootstrapping application. You cannot call /// it from a custom action /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternaluirecord.asp">MsiSetExternalUIRecord</a> /// </p></remarks> public static ExternalUIRecordHandler SetExternalUI(ExternalUIRecordHandler uiHandler, InstallLogModes messageFilter) { NativeExternalUIRecordHandler nativeHandler = null; if (uiHandler != null) { nativeHandler = new ExternalUIRecordProxy(uiHandler).ProxyHandler; Installer.externalUIHandlers.Add(nativeHandler); } NativeExternalUIRecordHandler oldNativeHandler; uint ret = NativeMethods.MsiSetExternalUIRecord(nativeHandler, (uint)messageFilter, IntPtr.Zero, out oldNativeHandler); if (ret != 0) { Installer.externalUIHandlers.Remove(nativeHandler); throw InstallerException.ExceptionFromReturnCode(ret); } if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIRecordProxy) { Installer.externalUIHandlers.Remove(oldNativeHandler); return(((ExternalUIRecordProxy)oldNativeHandler.Target).Handler); } else { return(null); } }
/// <summary> /// [MSI 3.1] Enables a record-based external user-interface handler. This external UI handler is called /// before the normal internal user-interface handler. The external UI handler has the option to suppress /// the internal UI by returning a non-zero value to indicate that it has handled the messages. /// </summary> /// <param name="uiHandler">A callback delegate that handles the UI messages</param> /// <param name="messageFilter">Specifies which messages to handle using the external message handler. /// If the external handler returns a non-zero result, then that message will not be sent to the UI, /// instead the message will be logged if logging has been enabled.</param> /// <returns>The previously set external handler, or null if there was no previously set handler</returns> /// <remarks><p> /// To restore the previous UI handler, a second call is made to SetExternalUI using the /// ExternalUIHandler returned by the first call to SetExternalUI and specifying /// <see cref="InstallLogModes.None"/> as the message filter. /// </p><p> /// The external user interface handler does not have full control over the external user /// interface unless <see cref="SetInternalUI(InstallUIOptions)"/> is called with the uiLevel parameter set to /// <see cref="InstallUIOptions.Silent"/>. If SetInternalUI is not called, the internal user /// interface level defaults to <see cref="InstallUIOptions.Basic"/>. As a result, any message not /// handled by the external user interface handler is handled by Windows Installer. The initial /// "Preparing to install..." dialog always appears even if the external user interface /// handler handles all messages. /// </p><p> /// SetExternalUI should only be called from a bootstrapping application. You cannot call /// it from a custom action /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msisetexternaluirecord.asp">MsiSetExternalUIRecord</a> /// </p></remarks> public static ExternalUIRecordHandler SetExternalUI(ExternalUIRecordHandler uiHandler, InstallLogModes messageFilter) { NativeExternalUIRecordHandler nativeHandler = null; if (uiHandler != null) { nativeHandler = new ExternalUIRecordProxy(uiHandler).ProxyHandler; Installer.externalUIHandlers.Add(nativeHandler); } NativeExternalUIRecordHandler oldNativeHandler; uint ret = NativeMethods.MsiSetExternalUIRecord(nativeHandler, (uint) messageFilter, IntPtr.Zero, out oldNativeHandler); if (ret != 0) { Installer.externalUIHandlers.Remove(nativeHandler); throw InstallerException.ExceptionFromReturnCode(ret); } if (oldNativeHandler != null && oldNativeHandler.Target is ExternalUIRecordProxy) { Installer.externalUIHandlers.Remove(oldNativeHandler); return ((ExternalUIRecordProxy) oldNativeHandler.Target).Handler; } else { return null; } }
/// <summary> /// Enables logging of the selected message type for all subsequent install sessions in /// the current process space. /// </summary> /// <param name="logModes">One or more mode flags specifying the type of messages to log</param> /// <param name="logFile">Full path to the log file. A null path disables logging, /// in which case the logModes paraneter is ignored.</param> /// <param name="append">If true, the log lines will be appended to any existing file content. /// If false, the log file will be truncated if it exists. The default is false.</param> /// <param name="flushEveryLine">If true, the log will be flushed after every line. /// If false, the log will be flushed every 20 lines. The default is true.</param> /// <exception cref="ArgumentException">an invalid log mode was specified</exception> /// <remarks><p> /// This method takes effect on any new installation processes. Calling this /// method from within a custom action will not start logging for that installation. /// </p><p> /// Win32 MSI API: /// <a href="http://msdn.microsoft.com/library/en-us/msi/setup/msienablelog.asp">MsiEnableLog</a> /// </p></remarks> public static void EnableLog(InstallLogModes logModes, string logFile, bool append, bool flushEveryLine) { uint ret = NativeMethods.MsiEnableLog((uint) logModes, logFile, (append ? (uint) 1 : 0) + (flushEveryLine ? (uint) 2 : 0)); if (ret != 0 && ret != (uint) NativeMethods.Error.FILE_INVALID) { throw InstallerException.ExceptionFromReturnCode(ret); } }
/// <summary> /// Enables logging of the selected message type for all subsequent install sessions in /// the current process space. /// </summary> /// <param name="logModes">One or more mode flags specifying the type of messages to log</param> /// <param name="logFile">Full path to the log file. A null path disables logging, /// in which case the logModes paraneter is ignored.</param> /// <exception cref="ArgumentException">an invalid log mode was specified</exception> /// <remarks>This method takes effect on any new installation processes. Calling this /// method from within a custom action will not start logging for that installation.</remarks> public static void EnableLog(InstallLogModes logModes, string logFile) { Installer.EnableLog(logModes, logFile, false, true); }
public void CustomActionTest1() { InstallLogModes logEverything = InstallLogModes.FatalExit | InstallLogModes.Error | InstallLogModes.Warning | InstallLogModes.User | InstallLogModes.Info | InstallLogModes.ResolveSource | InstallLogModes.OutOfDiskSpace | InstallLogModes.ActionStart | InstallLogModes.ActionData | InstallLogModes.CommonData | InstallLogModes.Progress | InstallLogModes.Initialize | InstallLogModes.Terminate | InstallLogModes.ShowDialog; Installer.SetInternalUI(InstallUIOptions.Silent); ExternalUIHandler prevHandler = Installer.SetExternalUI( WindowsInstallerTest.ExternalUILogger, logEverything); try { string[] customActions = new string[] { "SampleCA1", "SampleCA2" }; #if DEBUG string caDir = @"..\..\..\..\..\build\debug\x86\"; #else string caDir = @"..\..\..\..\..\build\ship\x86\"; #endif caDir = Path.GetFullPath(caDir); string caFile = "WixToolset.Dtf.Samples.ManagedCA.dll"; string caProduct = "CustomActionTest.msi"; this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, false); Exception caughtEx = null; try { Installer.InstallProduct(caProduct, String.Empty); } catch (Exception ex) { caughtEx = ex; } Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException), "Exception thrown while installing product: " + caughtEx); string arch = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITECTURE"); string arch2 = Environment.GetEnvironmentVariable("PROCESSOR_ARCHITEW6432"); if (arch == "AMD64" || arch2 == "AMD64") { caDir = caDir.Replace("x86", "x64"); this.CreateCustomActionProduct(caProduct, caDir + caFile, customActions, true); caughtEx = null; try { Installer.InstallProduct(caProduct, String.Empty); } catch (Exception ex) { caughtEx = ex; } Assert.IsInstanceOfType(caughtEx, typeof(InstallCanceledException), "Exception thrown while installing 64bit product: " + caughtEx); } } finally { Installer.SetExternalUI(prevHandler, InstallLogModes.None); } }