【问题标题】:Cancel installation from my custom action从我的自定义操作中取消安装
【发布时间】:2011-01-28 02:35:33
【问题描述】:

我正在使用 Windows Installer(不是 wix)为我的程序编写安装程序。 在某些情况下,我想从我的自定义操作中取消安装过程。此外,我想在我的文本中显示一条错误消息。 这是怎么做到的?

C#,.net 3.5

【问题讨论】:

    标签: windows-installer custom-action


    【解决方案1】:

    在您认为需要中止的任何时候:

    throw new InstallException("This user name doesn't exist in this system!.");
    

    安装程序将弹出 User Aborted 对话框,其中包含您的异常消息。

    【讨论】:

      【解决方案2】:

      只需从您的自定义操作中返回 ERROR_INSTALL_USEREXIT。

      http://msdn.microsoft.com/en-us/library/windows/desktop/aa368072(v=vs.85).aspx

      有关如何显示错误消息,请参阅以下链接:

      http://msdn.microsoft.com/en-us/library/windows/desktop/aa371247(v=vs.85).aspx

      【讨论】:

      • “只是”? :) 你能举个例子吗?
      【解决方案3】:

      为我工作:

      上下文:出于某种原因,我需要检查用户是否安装了 3.5SP1,如果没有,请取消安装并重定向到正确的下载页面。

      第一步: 像这样修改你的安装程序

          [System.Security.Permissions.SecurityPermission(System.Security.Permissions.SecurityAction.Demand)]
          public override void Install(IDictionary stateSaver)
          {
              //Check if the FrameWork 3.5SP1 is installed
              if (mycondition)
              {
                  //3.5SP1 is installed, ask for framework install
                  if (TopMostMessageBox.Show("body", "title", MessageBoxButtons.YesNo) == DialogResult.Yes)
                      System.Diagnostics.Process.Start("http://Microsoft FRW Link");
      
                  WindowHandler.Terminate();
              }
              else
                  base.Install(stateSaver);
          }
      

      第二步: 使用该代码来托管您的 MessageBox(我把它带到别处,没有时间自己找到它)

      static public class TopMostMessageBox
      {
          static public DialogResult Show(string message)
          {
              return Show(message, string.Empty, MessageBoxButtons.OK);
          }
      
          static public DialogResult Show(string message, string title)
          {
              return Show(message, title, MessageBoxButtons.OK);
          }
      
          static public DialogResult Show(string message, string title,
              MessageBoxButtons buttons)
          {
              // Create a host form that is a TopMost window which will be the 
      
              // parent of the MessageBox.
      
              Form topmostForm = new Form();
              // We do not want anyone to see this window so position it off the 
      
              // visible screen and make it as small as possible
      
              topmostForm.Size = new System.Drawing.Size(1, 1);
              topmostForm.StartPosition = FormStartPosition.Manual;
              System.Drawing.Rectangle rect = SystemInformation.VirtualScreen;
              topmostForm.Location = new System.Drawing.Point(rect.Bottom + 10,
                  rect.Right + 10);
              topmostForm.Show();
              // Make this form the active form and make it TopMost
      
              topmostForm.Focus();
              topmostForm.BringToFront();
              topmostForm.TopMost = true;
              // Finally show the MessageBox with the form just created as its owner
      
              DialogResult result = MessageBox.Show(topmostForm, message, title,
                  buttons);
              topmostForm.Dispose(); // clean it up all the way
      
      
              return result;
          }
      }
      

      第三步: 杀死 msiexec

      internal static class WindowHandler
      {
          internal static void Terminate()
          {
              var processes = Process.GetProcessesByName("msiexec").OrderBy(x => x.StartTime); \\DO NOT FORGET THE ORDERBY!!! It makes the msi processes killed in the right order
              foreach (var process in processes)
              {
                  var hWnd = process.MainWindowHandle.ToInt32(); 
                  ShowWindow(hWnd, 0); //This is to hide the msi window and only show the popup
                  try
                  {
                      process.Kill();
                  }
                  catch
                  {
                  }
              }
          }
      
          [DllImport("User32")]
          private static extern int ShowWindow(int hwnd, int nCmdShow);
      }
      

      用勺子而不是用振动器混合,然后上桌;)

      【讨论】:

      • -1。杀死 msiexec 是邪恶的——它类似于砍树收获果实......
      • 这可能会在您通过调用 Terminate 终止 msiexec 进程时留下一些文件。最好在 base.Install(savedState); 之后抛出 new InstallException("User cancelled");(不要抓住它);这样后续的回滚清理工作会更好。
      【解决方案4】:

      您可以通过创建错误自定义操作来做到这一点。将错误自定义操作的条件设置为失败条件(如果条件评估为 true,则安装将失败)并将消息设置为您的自定义文本。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-11-28
        相关资源
        最近更新 更多