private bool DoUninstall() { var flags = GetAuthorizationFlags(); bool isSuccess = true; using (var auth = Authorization.Create(flags)) { // disable firewall var ret = IVPN.Shell.ShellCommand.RunCommand("/Applications/IVPN.app/Contents/MacOS/cli/ivpn", "firewall -off"); if (ret.IsAborted || ret.ExitCode != 0) { Logging.Info("Failed to disable firewall." + ((string.IsNullOrEmpty(ret.ErrorOutput)) ? "" : ret.ErrorOutput)); } // disconnect (if connected) ret = IVPN.Shell.ShellCommand.RunCommand("/Applications/IVPN.app/Contents/MacOS/cli/ivpn", "disconnect"); if (ret.IsAborted || ret.ExitCode != 0) { Logging.Info("Failed to disconnect." + ((string.IsNullOrEmpty(ret.ErrorOutput)) ? "" : ret.ErrorOutput)); } // logout ret = IVPN.Shell.ShellCommand.RunCommand("/Applications/IVPN.app/Contents/MacOS/cli/ivpn", "logout"); if (ret.IsAborted || ret.ExitCode != 0) { Logging.Info("Failed to logout." + ((string.IsNullOrEmpty(ret.ErrorOutput)) ? "" : ret.ErrorOutput)); } if (PrivilegeHelper.IsHelperInstalled()) { // Hack to force "authentication required" window to pop-up; auth.ExecuteWithPrivileges("/bin/echo", flags, new string[] { }); if (!PrivilegeHelper.Uninstall(auth)) { return(false); } } const string IVPNAppBundleID = "net.ivpn.client.IVPN"; // Erasing app NSUserDefaults data ret = IVPN.Shell.ShellCommand.RunCommand("defaults", $"delete {IVPNAppBundleID}"); if (ret.IsAborted || ret.ExitCode != 0) { Logging.Info("Failed to delete application user defaults." + ((string.IsNullOrEmpty(ret.ErrorOutput)) ? "" : ret.ErrorOutput)); isSuccess = false; } // Erasing KeyChain int i = 0; while (IVPN.Shell.ShellCommand.RunCommand("security", $"delete-generic-password -s {IVPNAppBundleID}").ExitCode == 0) { if (i++ > 1000) // ensure that we will not have infinite loop { break; } } string[] filesToRemove = new string[] { "/Library/Logs/IVPN Agent.log", "/Library/Logs/IVPN Agent.log.0", "/Library/Logs/IVPN Agent CrashInfo.log", "/Library/Logs/IVPN Agent CrashInfo.log.0", "/Library/Application Support/net.ivpn.client.Agent/last-btime", // seems, the file created by OS System.IO.Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.Personal), "Library/Preferences/net.ivpn.client.IVPN.plist") }; string[] foldersToRemove = new string[] { "/Applications/IVPN.app", "/Library/Application Support/IVPN/OpenVPN", System.IO.Path.Combine(System.Environment.GetFolderPath(System.Environment.SpecialFolder.UserProfile), "Library/Application Support/IVPN"), "/Library/Application Support/IVPN", "~/Library/Application Support/IVPN", "/Library/Application Support/net.ivpn.client.Agent/LocalMachine", // seems, the folder created by OS "/Library/Application Support/net.ivpn.client.Agent" // seems, the folder created by OS }; foreach (var file in filesToRemove) { if (!MacHelpers.RemoveFile(auth, file)) { Logging.Info(String.Format("Cannot remove: {0}", file)); isSuccess = false; } } foreach (var folder in foldersToRemove) { if (!MacHelpers.RemoveDirectory(auth, folder)) { Logging.Info(String.Format("Cannot remove: {0}", folder)); isSuccess = false; } } } return(isSuccess); }