using System;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Collections;
using System.CodeDom.Compiler;
using System.IO;
namespace NaGet.Packages.Install
{
///
/// Description of Uninstallation.
///
public class Uninstallation
{
///
/// アンインストールするパッケージ
///
public InstalledPackage UninstalledPackage;
///
/// 外部アプリのエラー出力の受信ハンドラ
///
public event EventHandler> ErrorDataReceived;
///
/// 外部アプリの標準出力の受信ハンドラ
///
public event EventHandler> OutputDataReceived;
///
/// サイレントアンインストールするか否か
///
public bool Silent = false;
///
/// コンストラクタ
///
/// アンインストールするパッケージ
public Uninstallation(InstalledPackage package)
{
UninstalledPackage = package;
}
///
/// インストールされた状態か否か
///
public bool Installed
{
get {
if ((UninstalledPackage.Type == InstallerType.ARCHIVE)
|| UninstalledPackage.Type == InstallerType.ITSELF) {
return Directory.Exists(UninstalledPackage.UninstallInfo.InstallLocation);
} else {
foreach (UninstallInformation info in RegistriedUninstallers.Uninstallers) {
if (! string.IsNullOrEmpty(UninstalledPackage.UninstallerKey)) {
Match match = Regex.Match(info.DisplayName, UninstalledPackage.UninstallerKey);
if (match.Success) {
return true;
}
}
}
}
return false;
}
}
///
/// アンインストーラー等を起動してアンインストール作業を行う
///
/// アンインストーラーの終了コード
public int Uninstall()
{
if (! Installed) {
throw new ApplicationException("Program not found, may be already uninstalled");
}
int exitValue = 0;
string uninstallString = Silent? UninstalledPackage.UninstallInfo.QuietUninstallString : UninstalledPackage.UninstallInfo.UninstallString;
if (string.IsNullOrEmpty(uninstallString)) {
throw new ApplicationException(string.Format("Could not found {0}install script", Silent? "silent " : ""));
}
if (UninstalledPackage.Type == InstallerType.ARCHIVE
|| UninstalledPackage.Type == InstallerType.ITSELF) {
string argument = string.Format("-x \"{0}\"", UninstalledPackage.Name);
using (Process hProcess = createExtractArchiveProcess(argument,
this.OutputDataReceived,
this.ErrorDataReceived)) {
if (NaGet.Env.InstallProcessOnBackground) {
try {
hProcess.PriorityClass = ProcessPriorityClass.Idle;
} catch (Exception) {}
}
hProcess.WaitForExit();
exitValue = hProcess.ExitCode;
}
} else if (UninstalledPackage.UninstallInfo.WindowsInstaller &&
Regex.Match(uninstallString.Substring("MsiExec.exe /I".Length),
@"^\{[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}\}$").Success) {
string guid = uninstallString.Substring("MsiExec.exe /I".Length);
using (Process hProcess = NaGet.Utils.ProcessStartWithOutputCapture(
new ProcessStartInfo("msiexec", string.Format("/X{0}", guid)),
this.OutputDataReceived,
this.ErrorDataReceived) ) {
if (NaGet.Env.InstallProcessOnBackground) {
try {
hProcess.PriorityClass = ProcessPriorityClass.Idle;
} catch (Exception) {}
}
hProcess.WaitForExit();
exitValue = hProcess.ExitCode;
}
} else if (File.Exists(uninstallString)) {
// 単独のファイルの場合
using (Process hProcess = NaGet.Utils.ProcessStartWithOutputCapture(
new ProcessStartInfo(uninstallString),
this.OutputDataReceived,
this.ErrorDataReceived) ) {
if (NaGet.Env.InstallProcessOnBackground) {
try {
hProcess.PriorityClass = ProcessPriorityClass.Idle;
} catch (Exception) {}
}
hProcess.WaitForExit();
exitValue = hProcess.ExitCode;
}
} else {
ProcessStartInfo procInfo = new ProcessStartInfo(null, uninstallString);
procInfo.UseShellExecute = false;
procInfo.CreateNoWindow = true;
using (NaGet.InteropServices.CreateProcessCaller p = new NaGet.InteropServices.CreateProcessCaller(procInfo)) {
if (NaGet.Env.InstallProcessOnBackground) {
try {
p.PriorityClass = ProcessPriorityClass.Idle;
} catch (Exception) {}
}
p.WaitForExit();
exitValue = p.ExitCode;
}
}
return exitValue;
}
///
/// アーカイブファイルのアンインストールを行う
///
/// "archive-inst.exe"への引数
/// 標準出力用リスナ(null可)
/// エラー出力用リスナ(null可)
/// 実行プロセス
private static Process createExtractArchiveProcess(string archiveInstArgs,
EventHandler> outputReceived,
EventHandler> errorReceived)
{
string archiveInstExe = Path.GetFullPath("archive-inst.exe");
if (! File.Exists(archiveInstExe)) {
string errMsg = string.Format("\"{0}\" does not found!");
throw new ApplicationException(errMsg,
new FileNotFoundException(errMsg, archiveInstExe));
}
ProcessStartInfo procInfo = new ProcessStartInfo(archiveInstExe, archiveInstArgs);
procInfo.UseShellExecute = false;
procInfo.CreateNoWindow = true;
procInfo.WorkingDirectory = Environment.CurrentDirectory;
return NaGet.Utils.ProcessStartWithOutputCapture(procInfo, outputReceived, errorReceived);
}
public override string ToString()
{
return string.Format("{0}({1})", UninstalledPackage.Name, UninstalledPackage.Version);
}
}
}