Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions Appium Wizard/Appium Wizard.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,9 @@
<None Update="Resources\iOS\cygwin1.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\iOS\ddi-downloader.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="Resources\iOS\openssl.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
Expand Down
3 changes: 3 additions & 0 deletions Appium Wizard/Appium Wizard.csproj.user
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
<Compile Update="DeviceInformation.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="DownloadWDA.cs">
<SubType>Form</SubType>
</Compile>
<Compile Update="EnterPassword.cs">
<SubType>Form</SubType>
</Compile>
Expand Down
4 changes: 2 additions & 2 deletions Appium Wizard/ExcludeInInstaller/Installer Script.iss
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!

#define MyAppName "Appium Wizard"
#define MyAppVersion "8.6.0"
#define MyAppVersion "8.6.1"
#define MyAppPublisher "Meganathan C"
#define MyAppExeName "Appium Wizard.exe"

[Setup]
AlwaysRestart = no
AlwaysRestart = no
AppId={{408E2B01-BCF1-40E3-8F27-F11B32572D03}
AppName={#MyAppName}
UninstallDisplayName = Appium Wizard
Expand Down
2 changes: 2 additions & 0 deletions Appium Wizard/FilesPath.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,5 +24,7 @@ public static class FilesPath
public static string FFMpegFilePath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\Executables\\FFMpeg\\";
public static string logsFilesPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\Logs\\";
public static string scrcpy = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\Executables\\scrcpy\\scrcpy.exe";
public static string ddiDownloaderFilePath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\iOS\\ddi-downloader.exe";
public static string devImagesPath = Path.GetDirectoryName(AppDomain.CurrentDomain.BaseDirectory) + "\\Resources\\iOS\\devimages\\";
}
}
1 change: 1 addition & 0 deletions Appium Wizard/MainScreen.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public partial class MainScreen : Form
public static bool useScrcpy;
//public static List<string> UDIDPreInstalledWDA = new List<string>();
public static Dictionary<string, string> UDIDPreInstalledWDA = new Dictionary<string, string>();
public static HashSet<string> UDIDsUsingRunWDA = new HashSet<string>(); // Devices that should use runwda command instead of launch
private static readonly Logger Logger = LogManager.GetCurrentClassLogger();
private Timer uncheckTimer; private Timer highlightTimer;
public static Dictionary<int, WebView2> serverNumberWebView = new Dictionary<int, WebView2>();
Expand Down
14 changes: 14 additions & 0 deletions Appium Wizard/Object Spy.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

31 changes: 31 additions & 0 deletions Appium Wizard/Object Spy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1211,6 +1211,37 @@ private void helpButton_Click(object sender, EventArgs e)
MessageBox.Show(message, "Object Spy - BETA", MessageBoxButtons.OK, MessageBoxIcon.Information);
}

private void downloadXmlButton_Click(object sender, EventArgs e)
{
if (string.IsNullOrEmpty(xmlContent))
{
MessageBox.Show("No XML content available to save. Please refresh the screen first.", "No Content", MessageBoxButtons.OK, MessageBoxIcon.Warning);
return;
}

using (SaveFileDialog saveFileDialog = new SaveFileDialog())
{
saveFileDialog.Filter = "XML files (*.xml)|*.xml|All files (*.*)|*.*";
saveFileDialog.DefaultExt = "xml";
saveFileDialog.FileName = $"page_source_{DateTime.Now:yyyyMMdd_HHmmss}.xml";
saveFileDialog.Title = "Save XML Hierarchy";

if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
try
{
File.WriteAllText(saveFileDialog.FileName, xmlContent);
MessageBox.Show($"XML saved successfully to:\n{saveFileDialog.FileName}", "Success", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
Logger.Error(ex, "Error saving XML file");
MessageBox.Show($"Error saving XML file:\n{ex.Message}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
}

private void Object_Spy_FormClosing(object sender, FormClosingEventArgs e)
{
if (isAndroid)
Expand Down
46 changes: 42 additions & 4 deletions Appium Wizard/OpenDevice.cs
Original file line number Diff line number Diff line change
Expand Up @@ -339,16 +339,50 @@ await Task.Run(() =>
}
commonProgress.UpdateStepLabel(title, "Mounting developer disk image. Please wait, this may take some time...", 60);
var output = iOSMethods.GetInstance().MountImage(udid);

// Handle personalized DDI download for iOS 17+/26+
if (output.Contains("Downloading personalized DDI"))
{
commonProgress.UpdateStepLabel(title, "Downloading personalized developer disk image for iOS 17+/26+. This may take a few minutes...", 65);
}

if (output.Contains("MountImage: failed to get signature from Apple"))
{
commonProgress.Close();
isScreenServerStarted = false;
MessageBox.Show("Mounting image failed. Please check your internet connection and try again.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

// Check for identity mismatch error (fallback if personalized DDI also failed)
if ((output.Contains("could not find identity") || output.Contains("findIdentity: failed")) && output.Contains("Failed to download personalized DDI"))
{
commonProgress.Close();
isScreenServerStarted = false;
MessageBox.Show("Failed to mount developer disk image. The personalized DDI download failed.\nPlease check your internet connection and try again.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}

if (!iOSMethods.GetInstance().isImageMounted(udid))
{
iOSMethods.GetInstance().MountImage(udid);
Logger.Info("Image not mounted after first attempt, trying again...");
commonProgress.UpdateStepLabel(title, "Developer disk image not mounted. Retrying mount...", 62);
var retryOutput = iOSMethods.GetInstance().MountImage(udid);
Logger.Info("Retry mount output: " + retryOutput);

// Wait a bit for mount to complete
Thread.Sleep(2000);

// Check again if mounted
if (!iOSMethods.GetInstance().isImageMounted(udid))
{
commonProgress.Close();
isScreenServerStarted = false;
Logger.Error("Failed to mount developer disk image after retry. Output: " + retryOutput);
MessageBox.Show("Failed to mount developer disk image.\n\nPossible causes:\n1. Device was restarted (DDI gets unmounted on restart)\n2. Internet connection issue (for iOS 17+/26+ personalized DDI)\n3. DDI files corrupted\n\nSolution:\n- Ensure device is unlocked\n- Check internet connection\n- Try again\n\nIf issue persists, delete the folder:\n" + FilesPath.devImagesPath + "iOS_DDI\nand try again to re-download the DDI.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
Logger.Info("Image mounted successfully after retry");
}
if (deviceVersion >= version17Plus)
{
Expand All @@ -374,8 +408,12 @@ await Task.Run(() =>
MessageBox.Show("Please enable Developer Mode in your " + deviceName + " and try again.\nGo to Settings->Privacy & Security->Developer Mode->Turn ON.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
commonProgress.UpdateStepLabel(title, "Starting WebDriverAgent... Please enter passcode in your iPhone, if it asks...\nOnce you see Automation Running, Go to home screen to reduce the retry.", 70);
WDAsessionId = iOSAsyncMethods.GetInstance().RunWebDriverAgent(commonProgress, udid, proxyPort);
commonProgress.UpdateStepLabel(title, "Starting WebDriverAgent, Please enter passcode if it asks...", 70);

// Use runwda command directly (more stable than launch command)
Logger.Info("Using runwda command to start WebDriverAgent");
WDAsessionId = iOSAsyncMethods.GetInstance().RunWebDriverAgentWithRunWDA(commonProgress, udid, proxyPort);

Logger.Info("WDAsessionId:" + WDAsessionId);
if (WDAsessionId.Equals("Enable Developer Mode"))
{
Expand All @@ -402,7 +440,7 @@ await Task.Run(() =>
{
commonProgress.Close();
isScreenServerStarted = false;
MessageBox.Show("Unable to launch WebDriverAgent on your iPhone. Please enter passcode on your " + deviceName + " when it asks.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show("Unable to launch WebDriverAgent using runwda command.\n\nPlease:\n1. Enter passcode on your " + deviceName + " when it asks\n2. Ensure Developer Mode is enabled\n3. Unlock your device before opening\n\nNote: If you see WDA running on your device, try going to the home screen and reopening the device.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
return;
}
else if (string.IsNullOrEmpty(WDAsessionId) | WDAsessionId.Equals("unhandled"))
Expand Down
Binary file added Appium Wizard/Resources/iOS/ddi-downloader.exe
Binary file not shown.
14 changes: 14 additions & 0 deletions Appium Wizard/ScreenControl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,20 @@ private void ScreenControl_FormClosing(object sender, FormClosingEventArgs e)
}
udidScreenControl.Remove(udid);
webview2.Remove(udid);

// Stop runwda process if running for this device
if (OSType.Equals("iOS"))
{
try
{
iOSAsyncMethods.GetInstance().StopRunWDAProcess(udid);
}
catch (Exception ex)
{
Logger.Error(ex, "Failed to stop RunWDA process during form closing");
}
}

//Hide();
//try
//{
Expand Down
13 changes: 7 additions & 6 deletions Appium Wizard/USBWatcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
private ManagementEventWatcher connectWatcher;
private ManagementEventWatcher disconnectWatcher;
ListView listView1;
public USBWatcher(ListView listview)

Check warning on line 11 in Appium Wizard/USBWatcher.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable field 'disconnectWatcher' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.

Check warning on line 11 in Appium Wizard/USBWatcher.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Non-nullable field 'connectWatcher' must contain a non-null value when exiting constructor. Consider adding the 'required' modifier or declaring the field as nullable.
{
this.listView1 = listview;
}
Expand Down Expand Up @@ -52,7 +52,7 @@
var dependent = (string)targetInstance.GetPropertyValue("Dependent");
var deviceId = dependent.Split(new[] { '\\', '"' }, StringSplitOptions.RemoveEmptyEntries).LastOrDefault();
Console.WriteLine("USB device connected: " + deviceId);
if (!deviceId.Contains('&'))

Check warning on line 55 in Appium Wizard/USBWatcher.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Dereference of a possibly null reference.
{
listView1.Invoke((MethodInvoker)async delegate
{
Expand Down Expand Up @@ -80,7 +80,7 @@
await isiOSScreenLoaded(udid);
int screenPort = ScreenControl.devicePorts[udid].Item1;
var control = ScreenControl.udidScreenControl[udid];
control.LoadScreen(udid, screenPort);

Check warning on line 83 in Appium Wizard/USBWatcher.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
}
else
{
Expand Down Expand Up @@ -143,7 +143,7 @@
AndroidMethods.GetInstance().StartAndroidProxyServer(screenPort, 7810, udid);
Thread.Sleep(5000);
var control = ScreenControl.udidScreenControl[udid];
control.LoadScreen(udid, screenPort);

Check warning on line 146 in Appium Wizard/USBWatcher.cs

View workflow job for this annotation

GitHub Actions / build (Release)

Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.
}
}
GoogleAnalytics.SendEvent("UsbDeviceConnected", OSVersion);
Expand Down Expand Up @@ -258,12 +258,13 @@
Database.UpdateDataInDevicesTable(udid, "Connection", "");
}
}
if (ScreenControl.webview2.ContainsKey(udid))
{
var control = ScreenControl.udidScreenControl[udid];
control.LoadDeviceDisconnected(udid);
}
else if (ScreenControl.udidScreenControl.ContainsKey(udid))
//if (ScreenControl.webview2.ContainsKey(udid))
//{
// var control = ScreenControl.udidScreenControl[udid];
// control.LoadDeviceDisconnected(udid);
//}
//else if (ScreenControl.udidScreenControl.ContainsKey(udid))
if (ScreenControl.udidScreenControl.ContainsKey(udid))
{
var control = ScreenControl.udidScreenControl[udid];
control.Close();
Expand Down
4 changes: 2 additions & 2 deletions Appium Wizard/VersionInfo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
{
public static class VersionInfo
{
public const string VersionNumber = "8.6.0";
public const string ReleaseNotes = "Server settings, screen control, download wda, main screen close update";
public const string VersionNumber = "8.6.1";
public const string ReleaseNotes = "Some iPhones not working fix";
}
}
Loading
Loading