649 lines
18 KiB
C#
649 lines
18 KiB
C#
/**
|
|
* Copyright Epic Games, Inc. All Rights Reserved.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using Ionic.Zip;
|
|
using System.IO;
|
|
using System.Security.Cryptography.X509Certificates;
|
|
|
|
namespace iPhonePackager
|
|
{
|
|
public partial class GraphicalResignTool : Form
|
|
{
|
|
|
|
public static GraphicalResignTool ActiveInstance = null;
|
|
|
|
private string ExportImportPListFilename = "";
|
|
private byte[] ImportedPListData = null;
|
|
|
|
public static GraphicalResignTool GetActiveInstance()
|
|
{
|
|
if (ActiveInstance == null)
|
|
{
|
|
ActiveInstance = new GraphicalResignTool();
|
|
}
|
|
return ActiveInstance;
|
|
}
|
|
|
|
public GraphicalResignTool()
|
|
{
|
|
InitializeComponent();
|
|
|
|
SwitchingInfoEditMode(null, null);
|
|
SwitchingSigningMode(null, null);
|
|
SwitchingMobileProvisionMode(null, null);
|
|
|
|
InitializeGameSelectionBox();
|
|
|
|
ActiveInstance = this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Reads through directories that are peer to Binaries for any that match the *Game pattern
|
|
/// and adds the games to a drop-down list that can be picked.
|
|
/// </summary>
|
|
void InitializeGameSelectionBox()
|
|
{
|
|
}
|
|
|
|
private void GraphicalResignTool_Load(object sender, EventArgs e)
|
|
{
|
|
Text = Config.AppDisplayName + ": Signing tool";
|
|
}
|
|
|
|
|
|
private void InputIPABrowseButton_Click(object sender, EventArgs e)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.IpaFilter, "Picking an application", "ipa", IPAFilenameEdit.Text, ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
IPAFilenameEdit.Text = PickedFilename;
|
|
ImportedPListData = null;
|
|
}
|
|
}
|
|
|
|
private void MobileProvisionBrowseButton_Click(object sender, EventArgs e)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.MobileProvisionFilter, "Picking a mobile provision to embed", "mobileprovision", MobileProvisionEdit.Text, ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
MobileProvisionEdit.Text = PickedFilename;
|
|
}
|
|
}
|
|
|
|
private void CertificateBrowseButton_Click(object sender, EventArgs e)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.CertificatesFilter, "Picking a signing certificate to codesign with", "p12", CertificateEdit.Text, ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
CertificateEdit.Text = PickedFilename;
|
|
}
|
|
}
|
|
|
|
void ShowError(string Context, Exception ex)
|
|
{
|
|
MessageBox.Show(String.Format("Error '{0}' encountered while {1}", ex.Message, Context), Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
|
|
void ShowErrorMessage(string Msg, params object [] Args)
|
|
{
|
|
MessageBox.Show(String.Format(Msg, Args), Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
|
|
private void ExportInfoButton_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
FileOperations.FileSystemAdapter IPA = new FileOperations.ReadOnlyZipFileSystem(IPAFilenameEdit.Text);
|
|
|
|
if (IPA != null)
|
|
{
|
|
saveFileDialog1.DefaultExt = "plist";
|
|
saveFileDialog1.Title = "Exporting Info.plist";
|
|
saveFileDialog1.Filter = ToolsHub.PListFilter;
|
|
saveFileDialog1.FileName = ExportImportPListFilename;
|
|
|
|
string CWD = Directory.GetCurrentDirectory();
|
|
bool bDialogSucceeded = (saveFileDialog1.ShowDialog() == DialogResult.OK);
|
|
Directory.SetCurrentDirectory(CWD);
|
|
|
|
if (bDialogSucceeded)
|
|
{
|
|
ExportImportPListFilename = saveFileDialog1.FileName;
|
|
byte[] DataToSave = IPA.ReadAllBytes("Info.plist");
|
|
File.WriteAllBytes(ExportImportPListFilename, DataToSave);
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError("exporting Info.plist", ex);
|
|
}
|
|
}
|
|
|
|
private void ImportInfoButton_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.PListFilter, "Importing Info.plist", "plist", ExportImportPListFilename, ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
ExportImportPListFilename = PickedFilename;
|
|
ImportedPListData = File.ReadAllBytes(ExportImportPListFilename);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError("importing Info.plist", ex);
|
|
}
|
|
}
|
|
|
|
private void SwitchingInfoEditMode(object sender, EventArgs e)
|
|
{
|
|
ImportInfoButton.Enabled = RBReplaceInfoPList.Checked;
|
|
ExportInfoButton.Enabled = RBReplaceInfoPList.Checked;
|
|
DisplayNameEdit.Enabled = RBModifyInfoPList.Checked;
|
|
BundleIDEdit.Enabled = RBModifyInfoPList.Checked;
|
|
|
|
if (!RBReplaceInfoPList.Checked)
|
|
{
|
|
ImportedPListData = null;
|
|
}
|
|
}
|
|
|
|
private void SwitchingSigningMode(object sender, EventArgs e)
|
|
{
|
|
CertificateEdit.Enabled = RBUseExplicitCert.Checked;
|
|
CertificateBrowseButton.Enabled = RBUseExplicitCert.Checked;
|
|
}
|
|
|
|
private void SwitchingMobileProvisionMode(object sender, EventArgs e)
|
|
{
|
|
MobileProvisionEdit.Enabled = RBSpecifyMobileProvision.Checked;
|
|
MobileProvisionBrowseButton.Enabled = RBSpecifyMobileProvision.Checked;
|
|
}
|
|
|
|
private void ResignButton_Click(object sender, EventArgs e)
|
|
{
|
|
saveFileDialog1.DefaultExt = "ipa";
|
|
saveFileDialog1.FileName = "";
|
|
saveFileDialog1.Filter = ToolsHub.IpaFilter;
|
|
saveFileDialog1.Title = "Choose a filename for the re-signed IPA";
|
|
|
|
string CWD = Directory.GetCurrentDirectory();
|
|
bool bDialogSucceeded = (saveFileDialog1.ShowDialog() == DialogResult.OK);
|
|
Directory.SetCurrentDirectory(CWD);
|
|
|
|
if (bDialogSucceeded)
|
|
{
|
|
bool bSavedVerbose = Config.bVerbose;
|
|
Config.bVerbose = true;
|
|
Program.ProgressDialog.OnBeginBackgroundWork = delegate
|
|
{
|
|
string SrcFilename = IPAFilenameEdit.Text;
|
|
string DestFilename = saveFileDialog1.FileName;
|
|
|
|
// Delete the target location and copy the source there
|
|
FileOperations.DeleteFile(DestFilename);
|
|
FileOperations.CopyRequiredFile(SrcFilename, DestFilename);
|
|
|
|
// Open the file
|
|
FileOperations.ZipFileSystem FileSystem = new FileOperations.ZipFileSystem(DestFilename);
|
|
FileSystem.SetCompression(CBCompressModifiedFiles.Checked ? Ionic.Zlib.CompressionLevel.BestCompression : Ionic.Zlib.CompressionLevel.None);
|
|
|
|
// Resign and save the file
|
|
ResignIPA(FileSystem);
|
|
FileSystem.Close();
|
|
};
|
|
Config.bVerbose = bSavedVerbose;
|
|
|
|
Program.ProgressDialog.ShowDialog();
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This class is used to override specific parts of the default resigning behavior
|
|
/// </summary>
|
|
class CustomCodeSigner : CodeSignatureBuilder
|
|
{
|
|
/// <summary>
|
|
/// If non-null, this will be used instead of the existing embedded mobile provision
|
|
/// </summary>
|
|
public byte[] CustomMobileProvision = null;
|
|
|
|
/// <summary>
|
|
/// If non-null, this certificate will be used instead of doing a cert scan
|
|
/// </summary>
|
|
public X509Certificate2 CustomSigningCert = null;
|
|
|
|
/// <summary>
|
|
/// If non-null, this data will completely replace the original Info.plist
|
|
/// </summary>
|
|
public byte[] CustomInfoPList = null;
|
|
|
|
protected override byte[] GetMobileProvision(string CFBundleIdentifier)
|
|
{
|
|
return (CustomMobileProvision != null) ? CustomMobileProvision : FileSystem.ReadAllBytes("embedded.mobileprovision");
|
|
}
|
|
|
|
protected override X509Certificate2 LoadSigningCertificate()
|
|
{
|
|
return (CustomSigningCert != null) ? CustomSigningCert : base.LoadSigningCertificate();
|
|
}
|
|
|
|
protected override Utilities.PListHelper LoadInfoPList()
|
|
{
|
|
if (CustomInfoPList != null)
|
|
{
|
|
return new Utilities.PListHelper(Encoding.UTF8.GetString(CustomInfoPList));
|
|
}
|
|
else
|
|
{
|
|
return base.LoadInfoPList();
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Using the stub IPA previously compiled on the Mac, create a new IPA with assets
|
|
*/
|
|
void ResignIPA(FileOperations.FileSystemAdapter FileSystem)
|
|
{
|
|
try
|
|
{
|
|
DateTime StartTime = DateTime.Now;
|
|
|
|
// Configure the custom code signer
|
|
CustomCodeSigner SigningContext = new CustomCodeSigner();
|
|
SigningContext.FileSystem = FileSystem;
|
|
|
|
// Custom mobile provision?
|
|
if (RBSpecifyMobileProvision.Checked)
|
|
{
|
|
SigningContext.CustomMobileProvision = File.ReadAllBytes(MobileProvisionEdit.Text);
|
|
}
|
|
|
|
// Custom cert?
|
|
if (RBUseExplicitCert.Checked)
|
|
{
|
|
string CertificatePassword = "";
|
|
try
|
|
{
|
|
SigningContext.CustomSigningCert = new X509Certificate2(CertificateEdit.Text, CertificatePassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
|
//Cert = new X509Certificate2(CertificateFilename, CertificatePassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
|
}
|
|
catch (System.Security.Cryptography.CryptographicException)
|
|
{
|
|
// Try once with a password
|
|
if (PasswordDialog.RequestPassword(out CertificatePassword))
|
|
{
|
|
SigningContext.CustomSigningCert = new X509Certificate2(CertificateEdit.Text, CertificatePassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
|
//Cert = new X509Certificate2(CertificateFilename, CertificatePassword, X509KeyStorageFlags.PersistKeySet | X509KeyStorageFlags.Exportable | X509KeyStorageFlags.MachineKeySet);
|
|
}
|
|
else
|
|
{
|
|
// User cancelled dialog, rethrow
|
|
throw;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Totally replace Info.plist? (just editing it is handled later)
|
|
if (RBReplaceInfoPList.Checked)
|
|
{
|
|
SigningContext.CustomInfoPList = ImportedPListData;
|
|
}
|
|
|
|
// Start the resign process
|
|
SigningContext.PrepareForSigning();
|
|
|
|
// Partially modify Info.plist?
|
|
if (RBModifyInfoPList.Checked)
|
|
{
|
|
SigningContext.Info.SetString("CFBundleDisplayName", DisplayNameEdit.Text);
|
|
SigningContext.Info.SetString("CFBundleIdentifier", BundleIDEdit.Text);
|
|
}
|
|
|
|
// Re-sign the executable
|
|
SigningContext.PerformSigning();
|
|
|
|
// Save the IPA
|
|
Program.Log("Saving IPA ...");
|
|
FileSystem.Close();
|
|
|
|
TimeSpan ElapsedTime = DateTime.Now - StartTime;
|
|
Program.Log(String.Format("Finished re-signing IPA in took {0:0.00} s", ElapsedTime.TotalSeconds));
|
|
|
|
MessageBox.Show("Re-signing succeeded!", Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
ShowError("re-signing IPA", ex);
|
|
}
|
|
}
|
|
|
|
private void CloseThisWindowButton_Click(object sender, EventArgs e)
|
|
{
|
|
Close();
|
|
}
|
|
|
|
private void InstallIPAButton_Click(object sender, EventArgs e)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.IpaFilter, "Choose an IPA to install", "ipa", "", ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
Program.ProgressDialog.OnBeginBackgroundWork = delegate
|
|
{
|
|
DeploymentHelper.InstallIPAOnConnectedDevices(PickedFilename);
|
|
};
|
|
Program.ProgressDialog.ShowDialog();
|
|
}
|
|
}
|
|
|
|
private void UninstallIPAButton_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
void ScanConnectedDevices()
|
|
{
|
|
ConnectedDeviceInformation [] DeviceMap = null;
|
|
|
|
Program.ProgressDialog.OnBeginBackgroundWork = delegate
|
|
{
|
|
DeviceMap = DeploymentHelper.GetAllConnectedDevices();
|
|
};
|
|
|
|
if ((Program.ProgressDialog.ShowDialog() == DialogResult.OK) && (DeviceMap != null))
|
|
{
|
|
ConnectedDevicesList.BeginUpdate();
|
|
ConnectedDevicesList.Items.Clear();
|
|
|
|
foreach (var DeviceInfo in DeviceMap)
|
|
{
|
|
string DisplayName = DeviceInfo.DeviceName;
|
|
string UDID = DeviceInfo.UDID;
|
|
string DeviceType = DeviceInfo.DeviceType;
|
|
|
|
ListViewItem NewItem = ConnectedDevicesList.Items.Add(DisplayName);
|
|
NewItem.SubItems.Add(UDID);
|
|
NewItem.SubItems.Add(DeviceType);
|
|
}
|
|
|
|
ConnectedDevicesList.EndUpdate();
|
|
}
|
|
else
|
|
{
|
|
Program.Error("Enumerating devices failed");
|
|
}
|
|
}
|
|
|
|
private void FetchUDIDButton_Click(object sender, EventArgs e)
|
|
{
|
|
ScanConnectedDevices();
|
|
}
|
|
|
|
private void UDIDContextMenu_Opening(object sender, CancelEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void textBox1_TextChanged(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void ImportCertificateButton3_Click(object sender, EventArgs e)
|
|
{
|
|
ToolsHub.TryInstallingCertificate_PromptForKey(null);
|
|
RefreshProvisionsList();
|
|
}
|
|
|
|
private void ImportProvisionButton3_Click(object sender, EventArgs e)
|
|
{
|
|
ToolsHub.TryInstallingMobileProvision(null);
|
|
RefreshProvisionsList();
|
|
}
|
|
|
|
void RefreshProvisionsList()
|
|
{
|
|
}
|
|
|
|
private void RefreshProvisionListButton_Click(object sender, EventArgs e)
|
|
{
|
|
RefreshProvisionsList();
|
|
}
|
|
|
|
private void GraphicalResignTool_FormClosed(object sender, FormClosedEventArgs e)
|
|
{
|
|
if (ActiveInstance == this)
|
|
{
|
|
ActiveInstance = null;
|
|
}
|
|
}
|
|
|
|
private void TabBook_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
if (TabBook.SelectedTab == DeploymentPage)
|
|
{
|
|
ScanConnectedDevices();
|
|
}
|
|
}
|
|
|
|
private void GameSelectionBox_SelectedIndexChanged(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
// THIS IS NO LONGER VALID, WE NEED A PATH TO THE GAME, AND RE-RUN CONFIG
|
|
System.Windows.Forms.MessageBox.Show("This function is no longer supported - it will need work!");
|
|
// Program.GameName = GameSelectionBox.Items[GameSelectionBox.SelectedIndex] as string;
|
|
// Config.Initialize();
|
|
// RefreshProvisionsList();
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
private void copyToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void copyFullPathToProvisionToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void GraphicalResignTool_Shown(object sender, EventArgs e)
|
|
{
|
|
TabBook_SelectedIndexChanged(sender, e);
|
|
}
|
|
|
|
private void copyUDIDToClipboardToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
string ClipboardText = "";
|
|
foreach (ListViewItem i in ConnectedDevicesList.SelectedItems)
|
|
{
|
|
string Line = i.Text + " " + i.SubItems[1].Text;
|
|
if (ClipboardText == "")
|
|
{
|
|
ClipboardText = Line;
|
|
}
|
|
else
|
|
{
|
|
ClipboardText = ClipboardText + "\n" + Line;
|
|
}
|
|
}
|
|
|
|
Clipboard.SetText(ClipboardText);
|
|
}
|
|
|
|
static void CheckProvisionForUDID(MobileProvision Provision, string UDID, string Context)
|
|
{
|
|
if (Provision == null)
|
|
{
|
|
MessageBox.Show(String.Format("Failed to load or parse {0}", Context), Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Error);
|
|
}
|
|
else
|
|
{
|
|
if (Provision.ContainsUDID(UDID))
|
|
{
|
|
MessageBox.Show(String.Format("Found the UDID {0} in {1}", UDID, Context), Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Information);
|
|
}
|
|
else
|
|
{
|
|
MessageBox.Show(String.Format("Warning: Failed to find UDID {0} in {1}!", UDID, Context), Config.AppDisplayName, MessageBoxButtons.OK, MessageBoxIcon.Warning);
|
|
}
|
|
}
|
|
}
|
|
|
|
void PickProvisionAndCheckForUDID(string UDID)
|
|
{
|
|
if (UDID != null)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.MobileProvisionFilter, "Picking a mobile provision to check", "mobileprovision", "", ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
MobileProvision Provision = MobileProvisionParser.ParseFile(PickedFilename);
|
|
|
|
CheckProvisionForUDID(
|
|
Provision,
|
|
UDID,
|
|
String.Format("mobile provision {0}", Path.GetFileNameWithoutExtension(PickedFilename)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckThisUDIDAgainstAMobileprovMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
string UDID = null;
|
|
foreach (ListViewItem i in ConnectedDevicesList.SelectedItems)
|
|
{
|
|
UDID = i.SubItems[1].Text;
|
|
break;
|
|
}
|
|
|
|
PickProvisionAndCheckForUDID(UDID);
|
|
}
|
|
|
|
void PickIpaAndCheckForUDID(string UDID)
|
|
{
|
|
if (UDID != null)
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.IpaFilter, "Picking an application to check", "ipa", "", ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
MobileProvision Provision = MobileProvisionParser.ParseIPA(PickedFilename);
|
|
|
|
CheckProvisionForUDID(
|
|
Provision,
|
|
UDID,
|
|
String.Format("embedded mobile provision in {0}", Path.GetFileName(PickedFilename)));
|
|
}
|
|
}
|
|
}
|
|
|
|
private void CheckUDIDInIPAMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
string UDID = null;
|
|
foreach (ListViewItem i in ConnectedDevicesList.SelectedItems)
|
|
{
|
|
UDID = i.SubItems[1].Text;
|
|
break;
|
|
}
|
|
|
|
PickIpaAndCheckForUDID(UDID);
|
|
}
|
|
|
|
private void CheckIPAForUDIDButton_Click(object sender, EventArgs e)
|
|
{
|
|
string UDID = ScanningUDIDEdit.Text.Trim();
|
|
|
|
if (UDID.Length <= 0)
|
|
{
|
|
ShowErrorMessage("The UDID value is not properly set");
|
|
}
|
|
else
|
|
{
|
|
PickIpaAndCheckForUDID(UDID);
|
|
}
|
|
}
|
|
|
|
private void CheckProvisionForUDIDButton_Click(object sender, EventArgs e)
|
|
{
|
|
string UDID = ScanningUDIDEdit.Text.Trim();
|
|
|
|
if (UDID.Length <= 0)
|
|
{
|
|
ShowErrorMessage("The UDID value is not properly set");
|
|
}
|
|
else
|
|
{
|
|
PickProvisionAndCheckForUDID(UDID);
|
|
}
|
|
}
|
|
|
|
string PickIPAAndFetchBundleIdentifier()
|
|
{
|
|
string PickedFilename;
|
|
if (ToolsHub.ShowOpenFileDialog(ToolsHub.IpaFilter, "Choose an IPA to provide the bundle identifier", "ipa", "", ref ToolsHub.ChoosingIpaDirectory, out PickedFilename))
|
|
{
|
|
FileOperations.FileSystemAdapter IPA = new FileOperations.ReadOnlyZipFileSystem(PickedFilename);
|
|
|
|
if (IPA != null)
|
|
{
|
|
byte[] InfoData = IPA.ReadAllBytes("Info.plist");
|
|
Utilities.PListHelper Info = new Utilities.PListHelper(Encoding.UTF8.GetString(InfoData));
|
|
|
|
string BundleID;
|
|
if (Info.GetString("CFBundleIdentifier", out BundleID))
|
|
{
|
|
return BundleID;
|
|
}
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
private void BackupDocumentsButton_Click(object sender, EventArgs e)
|
|
{
|
|
string BundleID = PickIPAAndFetchBundleIdentifier();
|
|
|
|
if (BundleID != null)
|
|
{
|
|
Program.ProgressDialog.OnBeginBackgroundWork = delegate
|
|
{
|
|
DeploymentHelper.BackupDocumentsDirectory(BundleID, Config.GetRootBackedUpDocumentsDirectory());
|
|
};
|
|
Program.ProgressDialog.ShowDialog();
|
|
}
|
|
}
|
|
|
|
private void UninstallIPAButton_Click_1(object sender, EventArgs e)
|
|
{
|
|
string BundleID = PickIPAAndFetchBundleIdentifier();
|
|
|
|
if (BundleID != null)
|
|
{
|
|
Program.ProgressDialog.OnBeginBackgroundWork = delegate
|
|
{
|
|
DeploymentHelper.UninstallIPAOnDevices(BundleID);
|
|
};
|
|
Program.ProgressDialog.ShowDialog();
|
|
}
|
|
}
|
|
|
|
private void exportCertificateToolStripMenuItem_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
}
|
|
}
|