Unity: CommandRunner.cs (csharp run adb shell on adroid)

from: https://searchcode.com/codesearch/view/5667336/


using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Text.RegularExpressions;
using System.Drawing;
using ICSharpCode.SharpZipLib.Zip;
using DroidExplorer.Core.IO;
using System.Threading;
using System.Globalization;
using DroidExplorer.Core.Components;
using DroidExplorer.Core.Exceptions;
using System.ComponentModel;
using DroidExplorer.Core.Plugins;
using DroidExplorer.Core.Collections;
using DroidExplorer.Core.Configuration;
using System.Xml.Serialization;
using System.Drawing.Imaging;
using Managed.Adb.IO;
using Managed.Adb;
using System.Net;
using Managed.Adb.Exceptions;

namespace DroidExplorer.Core {
	/// <summary>
	/// 
	/// </summary>
	public class CommandRunner {
		private static CommandRunner _commandRunner;

		/// <summary>
		/// Occurs when [device state changed].
		/// </summary>
		public event EventHandler<DeviceEventArgs> DeviceStateChanged;
		/// <summary>
		/// Occurs when [connected].
		/// </summary>
		public event EventHandler<DeviceEventArgs> Connected;
		/// <summary>
		/// Occurs when [disconnected].
		/// </summary>
		public event EventHandler<DeviceEventArgs> Disconnected;
		/// <summary>
		/// Occurs when [top process updated].
		/// </summary>
		public event EventHandler<ProcessInfoEventArgs> TopProcessUpdated;
		/// <summary>
		/// Occurs when [top process update complete].
		/// </summary>
		public event EventHandler TopProcessUpdateComplete;
		/// <summary>
		/// Occurs when [top process update started].
		/// </summary>
		public event EventHandler TopProcessUpdateStarted;
		/// <summary>
		/// 
		/// </summary>
		public enum AaptCommand {
			/// <summary>
			/// 
			/// </summary>
			Dump_Badging,
			/// <summary>
			/// 
			/// </summary>
			Dump_Permissions,
			/// <summary>
			/// 
			/// </summary>
			Dump_Resources,
			/// <summary>
			/// 
			/// </summary>
			Dump_Configuration,
			/// <summary>
			/// 
			/// </summary>
			Dump_XmlTree,
			/// <summary>
			/// 
			/// </summary>
			Dump_XmlStrings,
			/// <summary>
			/// 
			/// </summary>
			List,
			/// <summary>
			/// 
			/// </summary>
			Package,
			/// <summary>
			/// 
			/// </summary>
			Remove,
			/// <summary>
			/// 
			/// </summary>
			Add,
			/// <summary>
			/// 
			/// </summary>
			Version,
		}

		/// <summary>
		/// 
		/// </summary>
		public enum AdbCommand {
			/// <summary>
			/// 
			/// </summary>
			Devices,
			/// <summary>
			/// 
			/// </summary>
			Help,
			/// <summary>
			/// 
			/// </summary>
			Root,
			/// <summary>
			/// 
			/// </summary>
			Remount,
			/// <summary>
			/// 
			/// </summary>
			Status_Window,
			/// <summary>
			/// 
			/// </summary>
			Get_SerialNo,
			/// <summary>
			/// 
			/// </summary>
			Get_State,
			/// <summary>
			/// 
			/// </summary>
			Kill_Server,
			/// <summary>
			/// 
			/// </summary>
			Start_Server,
			/// <summary>
			/// 
			/// </summary>
			Wait_For_Device,
			/// <summary>
			/// 
			/// </summary>
			Version,
			/// <summary>
			/// 
			/// </summary>
			Bugreport,
			/// <summary>
			/// 
			/// </summary>
			Uninstall,
			/// <summary>
			/// 
			/// </summary>
			Install,
			/// <summary>
			/// 
			/// </summary>
			Jdwp,
			/// <summary>
			/// 
			/// </summary>
			Forward,
			/// <summary>
			/// 
			/// </summary>
			Logcat,
			/// <summary>
			/// 
			/// </summary>
			Emu,
			/// <summary>
			/// 
			/// </summary>
			Shell,
			/// <summary>
			/// 
			/// </summary>
			Sync,
			/// <summary>
			/// 
			/// </summary>
			Push,
			/// <summary>
			/// 
			/// </summary>
			Pull,
			/// <summary>
			/// 
			/// </summary>
			PPP,
			/// <summary>
			/// 
			/// </summary>
			ShellLS,
			/// <summary>
			/// 
			/// </summary>
			ShellPackageManager,
		}

		/// <summary>
		/// 
		/// </summary>
		public const string SYSTEM_APP_PATH = "/system/app/";
		/// <summary>
		/// 
		/// </summary>
		public const string APP_PUBLIC_PATH = "/data/app/";

		/// <summary>
		/// 
		/// </summary>
		public const string APP_SD_PUBLIC_PATH = "/sd-ext/app/";

		/// <summary>
		/// 
		/// </summary>
		public const string APP_PRIVATE_PATH = "/data/app-private/";

		/// <summary>
		/// 
		/// </summary>
		public const string APP_SD_PRIVATE_PATH = "/sd-ext/app-private/";
		/// <summary>
		/// 
		/// </summary>
		public const string TEMP_DIRECTORY = "DroidExplorer";


		private DeviceState _deviceState = DeviceState.Unknown;


		/// <summary>
		/// Initializes a new instance of the <see cref="CommandRunner"/> class.
		/// </summary>
		public CommandRunner ( ) {
			if ( Settings == null ) {
				throw new ArgumentNullException ( "Settings not set. Must initialize settings before getting CommandRunner instance." );
			}
			String tsdk = Settings.SystemSettings.SdkPath;
			if ( String.IsNullOrEmpty ( tsdk ) || !System.IO.Directory.Exists(tsdk) ) {
				SdkPath = System.IO.Path.Combine ( AssemblyDirectory, "sdk" );
			} else {
				SdkPath = tsdk;
			}
		}

		/// <summary>
		/// Gets the assembly directory.
		/// </summary>
		/// <value>The assembly directory.</value>
		public string AssemblyDirectory {
			get {
				return System.IO.Path.GetDirectoryName ( this.GetType ( ).Assembly.Location );
			}
		}

		/// <summary>
		/// Gets the SDK tool.
		/// </summary>
		/// <param name="relativePath">The relative path.</param>
		/// <returns></returns>
		public string GetSdkTool ( string relativePath ) {
			//return System.IO.Path.Combine ( SdkPath, relativePath );
			String sdkTool = System.IO.Path.Combine ( Settings.SystemSettings.SdkToolsPath, relativePath );
			String platformTool = System.IO.Path.Combine ( Settings.SystemSettings.PlatformToolsPath, relativePath );
			if ( System.IO.File.Exists ( sdkTool ) ) {
				return sdkTool;
			} else if ( System.IO.File.Exists ( platformTool ) ) {
				return platformTool;
			} else {
				throw new System.IO.FileNotFoundException ( String.Format ( "Unable to located {0} in the SDK path", relativePath ) );
			}
		}

		/// <summary>
		/// Verifies the android SDK tools.
		/// </summary>
		/// <returns></returns>
		public bool VerifyAndroidSdkTools ( ) {
			try {
				return System.IO.File.Exists ( GetSdkTool ( AndroidDebugBridge.ADB ) ) && System.IO.File.Exists ( GetSdkTool ( AndroidDebugBridge.AAPT ) );
			} catch ( Exception ex ) {
				return false;
			}
		}

		/// <summary>
		/// Launches the activity.
		/// </summary>
		/// <param name="package">The package.</param>
		/// <param name="classFullName">Full name of the class.</param>
		public void LaunchActivity ( string package, string classFullName ) {
			LaunchActivity ( this.DefaultDevice, package, classFullName );
		}

		/// <summary>
		/// Launches the activity.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="package">The package.</param>
		/// <param name="classFullName">Full name of the class.</param>
		public void LaunchActivity( Device device, string package, string classFullName ) {
			//ShellRun ( device, string.Format ( CultureInfo.InvariantCulture, "am start -a android.intent.action.MAIN -n {0}/{1}", package, classFullName ) );
			device.ExecuteShellCommand ( "am start -a android.intent.action.MAIN -n {0}/{1}", ConsoleOutputReceiver.Instance, package, classFullName );
		}

		/// <summary>
		/// Makes the mount point read write.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="mountPoint">The mount point.</param>
		public void MakeReadWrite( Device device, string mountPoint ) {
			if ( !mountPoint.StartsWith ( "/" ) ) {
				throw new DroidExplorer.Core.Exceptions.AdbException ( "Invalid mount point" );
			}
			//ShellRun ( device, string.Format ( CultureInfo.InvariantCulture, "busybox mount -o rw,remount {0}", mountPoint ) );
			device.RemountMountPoint ( mountPoint, true );
		}

		/// <summary>
		/// Makes the mount point read write.
		/// </summary>
		/// <param name="mountPoint">The mount point.</param>
		public void MakeReadWrite ( string mountPoint ) {
			MakeReadWrite ( this.DefaultDevice, mountPoint );
		}

		/// <summary>
		/// Makes the mount point read only.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="mountPoint">The mount point.</param>
		public void MakeReadOnly( Device device, string mountPoint ) {
			if ( !mountPoint.StartsWith ( "/" ) ) {
				throw new DroidExplorer.Core.Exceptions.AdbException ( "Invalid mount point" );
			}
			device.RemountMountPoint ( mountPoint, true );
			//ShellRun ( device, string.Format ( CultureInfo.InvariantCulture, "busybox mount -o ro,remount {0}", mountPoint ) );
		}

		/// <summary>
		/// Makes the mount point read only.
		/// </summary>
		/// <param name="mountPoint">The mount point.</param>
		public void MakeReadOnly ( string mountPoint ) {
			MakeReadOnly ( this.DefaultDevice, mountPoint );
		}

		/// <summary>
		/// Gets or sets the default device.
		/// </summary>
		/// <value>The default device.</value>
		public Device DefaultDevice { get; set; }

		/// <summary>
		/// Gets the path of the SDK Tools
		/// </summary>
		public string SdkPath { get; set; }

		/// <summary>
		/// Gets or sets the top process.
		/// </summary>
		/// <value>The top process.</value>
		private Process TopProcess { get; set; }

		/// <summary>
		/// Gets or sets the status process.
		/// </summary>
		/// <value>The status process.</value>
		private Process StatusProcess { get; set; }

		/// <summary>
		/// Connects the specified device.
		/// </summary>
		/// <param name="device">The device.</param>
		/*public void Connect ( string device ) {
			try {
				if ( StatusProcess == null || StatusProcess.HasExited ) {
					StatusProcess = new Process ( );
					ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( ADB_COMMAND ), AdbCommandArguments ( device, AdbCommand.Status_Window ) );
					psi.CreateNoWindow = true;
					psi.ErrorDialog = false;
					psi.WindowStyle = ProcessWindowStyle.Hidden;
					psi.UseShellExecute = false;
					psi.RedirectStandardOutput = true;
					psi.RedirectStandardError = true;

					StatusProcess.StartInfo = psi;
					StatusProcess.OutputDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
						if ( !string.IsNullOrEmpty ( e.Data ) ) {
							Regex regex = new Regex ( @"state\:\s+((device)|(unknown)|(offline)|(bootloader)|(recovery))", RegexOptions.Compiled | RegexOptions.Singleline | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace );
							Match m = regex.Match ( e.Data );
							if ( m.Success ) {
								DeviceState pstate = State;
								State = StringToDeviceState ( m.Result ( "$1" ) );

								if ( State == DeviceState.Unknown ) {
									State = this.GetDeviceState ( device );
								}

								if ( State == DeviceState.Device || State == DeviceState.Recovery ) {
									if ( this.Connected != null ) {
										this.Connected ( this, new DeviceEventArgs ( device, State ) );
									}
								} else {
									if ( this.Disconnected != null ) {
										this.Disconnected ( this, new DeviceEventArgs ( device, State ) );
									}
								}
								if ( pstate != State ) {
									if ( this.DeviceStateChanged != null ) {
										this.DeviceStateChanged ( this, new DeviceEventArgs ( device, State ) );
									}
								}
							}
						}
					};

					StatusProcess.ErrorDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
					};

					StatusProcess.Exited += delegate ( object sender, EventArgs e ) {
						if ( State == DeviceState.Device ) {
							Disconnect ( );
						}
					};
					StatusProcess.Start ( );
					StatusProcess.BeginOutputReadLine ( );
					StatusProcess.BeginErrorReadLine ( );
				}
			} catch ( Exception ex ) {
				this.LogError ( ex.Message, ex );
				State = DeviceState.Unknown;
			}
		}*/

		
		/// <summary>
		/// Tops the process kill.
		/// </summary>
		/*public void TopProcessKill ( ) {
			if ( TopProcess != null && !TopProcess.HasExited ) {
				try {
					TopProcess.Kill ( );
				} catch {
				}
			}
		}*/

		/// <summary>
		/// Tops the process run.
		/// </summary>
		/*public void TopProcessRun ( ) {
			try {
				if ( TopProcess == null || TopProcess.HasExited ) {
					TopProcess = new Process ( );
					ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( ADB_COMMAND ), string.Format ( CultureInfo.InvariantCulture, "{0} top -d 1 -s cpu", AdbCommandArguments ( DefaultDevice, AdbCommand.Shell ) ) );
					psi.CreateNoWindow = true;
					psi.ErrorDialog = false;
					psi.WindowStyle = ProcessWindowStyle.Hidden;
					psi.UseShellExecute = false;
					psi.RedirectStandardOutput = true;
					psi.RedirectStandardError = true;

					TopProcess.StartInfo = psi;
					TopProcess.OutputDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
						if ( TopProcessUpdateStarted != null ) {
							TopProcessUpdateStarted ( this, EventArgs.Empty );
						}
						Regex regex = new Regex ( Properties.Resources.TopProcessRegexPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace |
							RegexOptions.Multiline );
						if ( string.IsNullOrEmpty ( e.Data ) ) {
							return;
						}

						Match m = regex.Match ( e.Data );
						while ( m.Success ) {
							int pid = 0;
							int.TryParse ( m.Groups[ 1 ].Value, out pid );
							int cpu = 0;
							int.TryParse ( m.Groups[ 2 ].Value, out cpu );
							int thread = 0;
							int.TryParse ( m.Groups[ 4 ].Value, out thread );
							long vss = 0;
							long.TryParse ( m.Groups[ 5 ].Value, out vss );
							long rss = 0;
							long.TryParse ( m.Groups[ 6 ].Value, out rss );
							string uid = m.Groups[ 7 ].Value.Trim ( );
							string name = m.Groups[ 8 ].Value.Trim ( );

							ProcessInfo pi = new ProcessInfo ( pid, name, thread, vss, rss, uid, cpu );
							if ( TopProcessUpdated != null ) {
								TopProcessUpdated ( this, new ProcessInfoEventArgs ( pi ) );
							}
							m = m.NextMatch ( );
						}

						if ( TopProcessUpdateComplete != null ) {
							TopProcessUpdateComplete ( this, EventArgs.Empty );
						}
					};

					TopProcess.ErrorDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {

					};

					TopProcess.Exited += delegate ( object sender, EventArgs e ) {

					};
					TopProcess.Start ( );
					TopProcess.BeginOutputReadLine ( );
					TopProcess.BeginErrorReadLine ( );
				}
			} catch ( Exception ex ) {
				this.LogError ( ex.Message, ex );
			}
		}*/

		public void AdbProcessCleanUp ( ) {
			Process[] procs = Process.GetProcessesByName ( "adb" );
			foreach ( var item in procs ) {
				try {
					item.Kill ( );
				} catch { }
			}
		}

		/// <summary>
		/// Determines whether [is app directory] [the specified path].
		/// </summary>
		/// <param name="path">The path.</param>
		/// <returns>
		/// 	<c>true</c> if [is app directory] [the specified path]; otherwise, <c>false</c>.
		/// </returns>
		public static bool IsAppDirectory ( string path ) {
			return string.Compare ( path, SYSTEM_APP_PATH, false ) == 0 ||
				string.Compare ( path, APP_PRIVATE_PATH, false ) == 0 || 
				string.Compare ( path, APP_PUBLIC_PATH, false ) == 0 || 
				string.Compare(path, APP_SD_PUBLIC_PATH, false) == 0 ||
				string .Compare (path, APP_SD_PRIVATE_PATH, false ) == 0;
		}

		public string TempDataPath {
			get { return System.IO.Path.Combine ( System.IO.Path.GetTempPath ( ), TEMP_DIRECTORY ); }
		}

		/// <summary>
		/// Temps the path cleanup.
		/// </summary>
		public void TempPathCleanup ( ) {
			string tempPath = System.IO.Path.Combine ( System.IO.Path.GetTempPath ( ), TEMP_DIRECTORY );
			try {
				if ( System.IO.Directory.Exists ( tempPath ) ) {
					System.IO.Directory.Delete ( tempPath, true );
					System.IO.Directory.CreateDirectory ( tempPath );
				}
			} catch ( Exception ex ) {
				throw;
			}
		}


		/// <summary>
		/// Gets the adb version.
		/// </summary>
		/// <returns></returns>
		/*public string GetAdbVersion ( ) {
			try {
				string data = RunAdbCommand ( string.Empty, AdbCommand.Version, string.Empty, true );
				
				Regex regex = new Regex ( @"(\d{1,}\.\d{1,}\.\d{1,})", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline );
				Match m = regex.Match ( data.Trim ( ) );
				if ( m.Success ) {
					return m.Groups[ 1 ].Value;
				} else {
					return string.Empty;
				}
			} catch ( DroidExplorer.Core.Exceptions.AdbException aex ) {
				this.LogError ( aex.Message, aex );
				return string.Empty;
			} catch ( Exception ex ) {
				this.LogError ( ex.Message, ex );
				throw;
			}
		}*/

		/// <summary>
		/// Gets the aapt version.
		/// </summary>
		/// <returns></returns>
		public string GetAaptVersion ( ) {
			try {
				string data = RunAaptCommand ( AaptCommand.Version, string.Empty );
				Regex regex = new Regex ( @"(\d{1,}\.\d{1,}(\.\d{1,}\.\d{1,})?)", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.Multiline );
				Match m = regex.Match ( data );
				if ( m.Success ) {
					return m.Groups[ 1 ].Value;
				} else {
					return string.Empty;
				}
			} catch ( DroidExplorer.Core.Exceptions.AdbException aex ) {
				this.LogError ( aex.Message, aex );
				return string.Empty;
			} catch ( Exception ex ) {
				this.LogError ( ex.Message, ex );
				throw;
			}
		}

	
		
		/// <summary>
		/// Flashes the image.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="image">The image.</param>
		public void FlashImage ( Device device, string image ) {
			//ShellRun ( device, string.Format ( "flash_image recovery \"{0}\"", image ) );
			device.ExecuteShellCommand ( String.Format ( "flash_image recovery \"{0}\"", image ),new ConsoleOutputReceiver() );
		}

		/// <summary>
		/// Flashes the image.
		/// </summary>
		/// <param name="image">The image.</param>
		public void FlashImage ( string image ) {
			FlashImage ( this.DefaultDevice, image );
		}

		public void FastbootEraseRecovery ( Device device ) {
			device.ExecuteShellCommand ( "fastboot erase recovery", new ConsoleOutputReceiver ( ) );

			//ShellRun ( device, "fastboot erase recovery" );
		}

		/// <summary>
		/// Uses Fastboots to erase recovery image.
		/// </summary>
		public void FastbootEraseRecovery ( ) {
			FastbootEraseRecovery ( this.DefaultDevice );
		}

		public void FastbootFlashImage ( Device device, string image ) {
			//ShellRun ( device, string.Format ( "fastboot flash recovery \"{0}\"", image ) );
			device.ExecuteShellCommand ( string.Format ( "fastboot flash recovery \"{0}\"", image ), new ConsoleOutputReceiver ( ) );
		}

		public void FastbootFlashImage ( string image ) {
			FastbootFlashImage ( this.DefaultDevice, image );
		}

		/// <summary>
		/// Reboots the default device.
		/// </summary>
		public void Reboot ( ) {
			//Reboot ( this.DefaultDevice );
			this.DefaultDevice.Reboot ( );
		}

		/// <summary>
		/// Reboots the specified device.
		/// </summary>
		/// <param name="device">The device.</param>
		public void Reboot ( Device device ) {
			//ShellRun ( device, "reboot" );
			device.Reboot ( );
		}

		/// <summary>
		/// Reboots in to recovery.
		/// </summary>
		/// <param name="device">The device.</param>
		public void RebootRecovery ( Device device ) {
			//ShellRun ( device, "reboot recovery" );
			device.Reboot ( "recovery" );
		}

		/// <summary>
		/// Reboots in to recovery.
		/// </summary>
		public void RebootRecovery ( ) {
			RebootRecovery ( this.DefaultDevice );
		}

		/// <summary>
		/// Applies the update.
		/// </summary>
		/// <param name="device">The device.</param>
		public void ApplyUpdate ( Device device ) {
			/*
				mkdir -p /cache/recovery/
				echo 'boot-recovery' >/cache/recovery/command
				echo '--nandroid' >> /cache/recovery/command
				echo '--update_package=SDCARD:update.zip' >> /cache/recovery/command
			*/
			device.ExecuteShellCommand ( "mkdir -p /cache/recovery/", new ConsoleOutputReceiver() );
			device.ExecuteShellCommand ( "echo 'boot-recovery ' > /cache/recovery/command", new ConsoleOutputReceiver ( ) );
			device.ExecuteShellCommand ( "echo '--update_package=SDCARD:update.zip' >> /cache/recovery/command", new ConsoleOutputReceiver ( ) );
			RebootRecovery ( device );
		}

		/// <summary>
		/// Applies the update.
		/// </summary>
		public void ApplyUpdate ( ) {
			ApplyUpdate ( this.DefaultDevice );
		}


		/// <summary>
		/// Gets the installed packages.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <returns></returns>
		/*public PackageManagerListPackagesCommandResult GetInstalledPackages ( string device ) {
			PackageManagerListPackagesCommandResult result = CommandRun ( device, AdbCommand.ShellPackageManager, "list packages -f" ) as PackageManagerListPackagesCommandResult;
			return result;
		}

		/// <summary>
		/// Gets the installed packages.
		/// </summary>
		/// <returns></returns>
		public PackageManagerListPackagesCommandResult GetInstalledPackages ( ) {
			return GetInstalledPackages ( this.DefaultDevice );
		}

		/// <summary>
		/// Gets the installed packages apk information.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <returns></returns>
		public List<AaptBrandingCommandResult> GetInstalledPackagesApkInformation ( string device ) {
			PackageManagerListPackagesCommandResult result = GetInstalledPackages ( device );
			List<AaptBrandingCommandResult> apkInfo = new List<AaptBrandingCommandResult> ( );
			foreach ( var item in result.Packages.Keys ) {
				AaptBrandingCommandResult ainfo = GetApkInformation ( result.Packages[ item ] );
				ainfo.DevicePath = result.Packages[ item ];
				if ( string.IsNullOrEmpty ( ainfo.Package ) ) {
					ainfo.Package = item;
				}
				apkInfo.Add ( ainfo );
			}
			apkInfo.Sort ( new DroidExplorer.Core.Components.AaptBrandingCommandResultComparer ( ) );
			return apkInfo;
		}


		/// <summary>
		/// Gets the installed packages apk information.
		/// </summary>
		/// <returns></returns>
		public List<AaptBrandingCommandResult> GetInstalledPackagesApkInformation ( ) {
			return GetInstalledPackagesApkInformation ( this.DefaultDevice );
		}

		/// <summary>
		/// Determines whether the specified package is installed on the device.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="package">The package.</param>
		/// <returns>
		/// 	<c>true</c> if the specified package is installed on the device; otherwise, <c>false</c>.
		/// </returns>
		public bool IsPackageInstalled ( string device, string package ) {
			GenericCommandResult gr = new GenericCommandResult ( RunAdbCommand ( device, AdbCommand.Shell, string.Format ( CultureInfo.InvariantCulture, "pm path {0}", package ) ) );

			if ( gr.Output.Length > 0 ) {
				return gr.Output.ToString ( ).StartsWith ( "package:" );
			} else {
				return false;
			}

		}

		/// <summary>
		/// Determines whether the specified package is installed on the default device.
		/// </summary>
		/// <param name="package">The package.</param>
		/// <returns>
		/// 	<c>true</c> if the specified package is installed on the default device; otherwise, <c>false</c>.
		/// </returns>
		public bool IsPackageInstalled ( string package ) {
			return IsPackageInstalled ( this.DefaultDevice, package );
		}

		public AaptBrandingCommandResult GetApkInformation ( string apkFile ) {
			System.IO.FileInfo lApk = PullFile ( apkFile );
			if ( lApk == null || !lApk.Exists ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", System.IO.Path.GetFileName ( apkFile ) );
			}

			return GetLocalApkInformation ( lApk.FullName );
		}

		public AaptBrandingCommandResult GetApkInformationFromLocalCache ( String apkFile, String cacheDirectory ) {
			string keyName = apkFile;
			if ( keyName.StartsWith ( "/" ) ) {
				keyName = keyName.Substring ( 1 );
			}
			keyName = keyName.Replace ( "/", "." );

			// find if there is a local cache
			System.IO.FileInfo lcache = new System.IO.FileInfo ( System.IO.Path.Combine ( cacheDirectory, String.Format ( "{0}.cache", keyName ) ) );
			if ( lcache.Exists ) {
				AaptBrandingCommandResult result = null;
				XmlSerializer ser = new XmlSerializer ( typeof ( AaptBrandingCommandResult ) );
				using ( System.IO.FileStream fs = new System.IO.FileStream ( lcache.FullName, System.IO.FileMode.Open, System.IO.FileAccess.Read ) ) {
					result = ser.Deserialize ( fs ) as AaptBrandingCommandResult;
				}

				return result;
			} else {
				System.IO.FileInfo lApk = PullFile ( apkFile );
				if ( lApk == null || !lApk.Exists ) {
					throw new System.IO.FileNotFoundException ( "File was not found on device.", System.IO.Path.GetFileName ( apkFile ) );
				}

				AaptBrandingCommandResult result = GetApkInformation ( lApk.FullName );
				XmlSerializer ser = new XmlSerializer ( typeof ( AaptBrandingCommandResult ) );
				using ( System.IO.FileStream fs = new System.IO.FileStream ( lcache.FullName, System.IO.FileMode.Create, System.IO.FileAccess.Write ) ) {
					ser.Serialize ( fs, result );
				}
				return result;
			}
		}

		public AaptBrandingCommandResult GetLocalApkInformation ( string apkFile ) {
			if ( string.IsNullOrEmpty ( apkFile ) || !System.IO.File.Exists ( apkFile ) ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", System.IO.Path.GetFileName ( apkFile ) );
			}

			AaptBrandingCommandResult result = AaptCommandRun ( AaptCommand.Dump_Badging, string.Format ( "\"{0}\"", apkFile ) ) as AaptBrandingCommandResult;
			result.LocalApk = apkFile;
			return result;
		}

		public List<string> GetApkPermissions ( string apkFile ) {
			System.IO.FileInfo lApk = PullFile ( apkFile );
			if ( lApk == null || !lApk.Exists ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", apkFile );
			}

			return GetLocalApkPermissions ( lApk.FullName );
		}

		public List<string> GetLocalApkPermissions ( string apkFile ) {
			System.IO.FileInfo lApk = new System.IO.FileInfo ( apkFile );
			if ( lApk == null || !lApk.Exists ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", apkFile );
			}

			AaptPermissionsCommandResult result = AaptCommandRun ( AaptCommand.Dump_Permissions, string.Format ( "\"{0}\"", apkFile ) ) as AaptPermissionsCommandResult;

			if ( result != null ) {
				return result.Permissions;
			} else {
				return null;
			}
		}

		/// <summary>
		/// Gets the apk icon image.
		/// </summary>
		/// <param name="apkFile">The apk file.</param>
		/// <returns></returns>
		public Image GetApkIconImage ( string apkFile ) {
			System.IO.FileInfo lApk = PullFile ( apkFile );
			if ( lApk == null || !lApk.Exists ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", System.IO.Path.GetFileName ( apkFile ) );
			}

			AaptBrandingCommandResult result = GetLocalApkInformation ( lApk.FullName );
			result.LocalApk = lApk.FullName;

			if ( !string.IsNullOrEmpty ( result.Icon ) ) {
				string outPath = System.IO.Path.Combine ( lApk.Directory.FullName, System.IO.Path.GetFileNameWithoutExtension ( lApk.Name ) );
				try {
					ZipHelper.Unzip ( lApk.FullName, outPath, result.Icon, true, true );
				} catch ( Exception ex ) {
					this.LogError ( ex.Message, ex );
					return null;
				}
				System.IO.FileInfo imageFile = new System.IO.FileInfo ( System.IO.Path.Combine ( outPath, System.IO.Path.GetFileName ( result.Icon ) ) );
				if ( imageFile.Exists ) {
					return Image.FromFile ( imageFile.FullName );
				} else {
					return null;
				}
			} else {
				return null;
			}
		}

		public Image GetLocalApkIconImage ( string apkFile ) {
			System.IO.FileInfo lApk = new System.IO.FileInfo ( apkFile );
			if ( lApk == null || !lApk.Exists ) {
				throw new System.IO.FileNotFoundException ( "File was not found on device.", System.IO.Path.GetFileName ( apkFile ) );
			}

			AaptBrandingCommandResult result = GetLocalApkInformation ( lApk.FullName );
			result.LocalApk = lApk.FullName;

			if ( !string.IsNullOrEmpty ( result.Icon ) ) {
				string outPath = System.IO.Path.Combine ( TempDataPath, System.IO.Path.GetFileNameWithoutExtension ( lApk.Name ) );
				try {
					ZipHelper.Unzip ( lApk.FullName, outPath, result.Icon, true, true );
				} catch ( Exception ex ) {
					this.LogError ( ex.Message, ex );
					return null;
				}
				System.IO.FileInfo imageFile = new System.IO.FileInfo ( System.IO.Path.Combine ( outPath, System.IO.Path.GetFileName ( result.Icon ) ) );
				if ( imageFile.Exists ) {
					return Image.FromFile ( imageFile.FullName );
				} else {
					return null;
				}
			} else {
				return null;
			}
		}

		public Image GetApkIconImageFromCache ( string apkFile, String cacheDirectory ) {
			string keyName = apkFile;
			if ( keyName.StartsWith ( "/" ) ) {
				keyName = keyName.Substring ( 1 );
			}
			keyName = keyName.Replace ( "/", "." );

			// find if there is a local cache
			System.IO.FileInfo lcache = new System.IO.FileInfo ( System.IO.Path.Combine ( cacheDirectory, String.Format ( "{0}.png", keyName ) ) );
			if ( lcache.Exists ) {
				return Image.FromFile ( lcache.FullName );
			} else {
				Image image = GetApkIconImage ( apkFile );
				if ( image != null ) {
					image.Save ( lcache.FullName, ImageFormat.Png );
				}
				return image;
			}
		}*/

		
		/// <summary>
		/// Launches the shell window.
		/// </summary>
		/// <param name="device">The device.</param>
		public void LaunchShellWindow ( Device device ) {
			LaunchShellWindow ( device, string.Empty );
		}

		/// <summary>
		/// Launches the shell window.
		/// </summary>
		public void LaunchShellWindow ( ) {
			LaunchShellWindow ( this.DefaultDevice );
		}

		/// <summary>
		/// Launches the shell window.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="initialCommand">The initial command.</param>
		public void LaunchShellWindow( Device device, string initialCommand ) {
			Process shell = new Process ( );
			StringBuilder commandArg = new StringBuilder ( AdbCommandArguments ( device.SerialNumber, AdbCommand.Shell ) );
			if ( !string.IsNullOrEmpty ( initialCommand ) ) {
				commandArg.AppendFormat ( " {0}", initialCommand );
			}
			ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( AndroidDebugBridge.ADB ), commandArg.ToString ( ) );
			psi.CreateNoWindow = false;
			psi.ErrorDialog = true;
			psi.WindowStyle = ProcessWindowStyle.Normal;
			shell.StartInfo = psi;
			shell.Start ( );
		}

		/// <summary>
		/// Launches the redirected shell window.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="initialCommand">The initial command.</param>
		/// <param name="shellHandler">The shell handler.</param>
		public void LaunchRedirectedShellWindow( Device device, string initialCommand, IShellProcess shellHandler ) {
			new Thread ( new ThreadStart ( delegate ( ) {
				Process shell = new Process ( );
				StringBuilder commandArg = new StringBuilder ( AdbCommandArguments ( device.SerialNumber, AdbCommand.Shell ) );

				shellHandler.SetBaseProcess ( shell );
				ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( AndroidDebugBridge.ADB ), commandArg.ToString ( ) );
				psi.CreateNoWindow = true;
				psi.ErrorDialog = false;
				psi.WindowStyle = ProcessWindowStyle.Hidden;

				psi.UseShellExecute = false;
				psi.RedirectStandardOutput =
				psi.RedirectStandardInput =
				psi.RedirectStandardError = true;

				psi.StandardOutputEncoding = Encoding.UTF8;

				shell.StartInfo = psi;
				shell.Start ( );

				if ( !string.IsNullOrEmpty ( initialCommand ) ) {
					shell.StandardInput.WriteLine ( initialCommand );
				}

				shellHandler.SetInputStream ( shell.StandardInput );
				shellHandler.SetOutputStream ( shell.StandardOutput );
				shellHandler.SetErrorStream ( shell.StandardError );

				shell.WaitForExit ( );

				shellHandler.SetBaseProcess ( null );
			} ) ).Start ( );
		}

		/// <summary>
		/// Handles the OutputDataReceived event of the shell control.
		/// </summary>
		/// <param name="sender">The source of the event.</param>
		/// <param name="e">The <see cref="System.Diagnostics.DataReceivedEventArgs"/> instance containing the event data.</param>
		void shell_OutputDataReceived ( object sender, DataReceivedEventArgs e ) {
			throw new NotImplementedException ( );
		}



		/// <summary>
		/// Launches the hierarchy viewer.
		/// </summary>
		public void LaunchHierarchyViewer ( ) {
			LaunchProcessWindow ( GetSdkTool ( AndroidDebugBridge.HIERARCHYVIEWER ), string.Empty, false );
		}

		/// <summary>
		/// Launches the dalvik debug monitor.
		/// </summary>
		public void LaunchDalvikDebugMonitor ( ) {
			LaunchProcessWindow ( GetSdkTool ( AndroidDebugBridge.DDMS ), string.Empty, false );
		}

		/// <summary>
		/// Launches the process window.
		/// </summary>
		/// <param name="process">The process.</param>
		/// <param name="args">The args.</param>
		/// <param name="visible">if set to <c>true</c> [visible].</param>
		public void LaunchProcessWindow( string process, string args, bool visible ) {
			Process shell = new Process ( );
			ProcessStartInfo psi = new ProcessStartInfo ( process, args );
			psi.CreateNoWindow = !visible;
			psi.ErrorDialog = visible;
			psi.WindowStyle = visible ? ProcessWindowStyle.Normal : ProcessWindowStyle.Hidden;
			shell.StartInfo = psi;
			shell.Start ( );
		}
	

		/// <summary>
		/// Gets the process ids.
		/// </summary>
		/// <returns></returns>
		/*public List<int> GetProcessIds ( ) {
			return GetProcessIds ( this.DefaultDevice );
		}

		/// <summary>
		/// Gets the process info list.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <returns></returns>
		public List<DroidExplorer.Core.IO.ProcessInfo> GetProcessInfoList ( string device ) {
			List<DroidExplorer.Core.IO.ProcessInfo> procs = new List<DroidExplorer.Core.IO.ProcessInfo> ( );
			foreach ( int pid in this.GetProcessIds ( device ) ) {
				string data = ShellRun ( string.Format ( "ps {0}", pid ) ).Output.ToString ( );
				procs.AddRange ( new ProcessInfoListCommandResult ( data ).Processes );
			}
			return procs;
		}

		/// <summary>
		/// Gets the process info list.
		/// </summary>
		/// <returns></returns>
		public List<DroidExplorer.Core.IO.ProcessInfo> GetProcessInfoList ( ) {
			return GetProcessInfoList ( this.DefaultDevice );
		}*/


		/// <summary>
		/// runs the command
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="command">The command.</param>
		/// <param name="args">The args.</param>
		/// <returns></returns>
		/*private CommandResult CommandRun( Device device, AdbCommand command, string args ) {
			switch ( command ) {
				case AdbCommand.Devices:
					return new DeviceListCommandResult ( RunAdbCommand ( device, command, args ) );
				case AdbCommand.Help:
					this.LogWarn ( "Help command not supported" );
					return new GenericCommandResult ( "* help command not supported *" );
				case AdbCommand.Root:
					return new GenericCommandResult ( RunAdbCommand ( device, command, args ) );
				case AdbCommand.Status_Window:
					this.LogWarn ( "Status-Window command not supported" );
					return new GenericCommandResult ( "* status window command not supported *" );
				case AdbCommand.Wait_For_Device:
					this.LogWarn ( "Wait-For-Device command not supported" );
					return new GenericCommandResult ( "* wait for device command not supported *" );
				case AdbCommand.ShellLS:
					string path = args.Remove ( 0, Properties.Resources.ListDirectoryCommand.Trim ( ).Length - 4 ).Trim ( );
					return new DirectoryListCommandResult ( RunAdbCommand ( device, AdbCommand.Shell, args ), path );
				case AdbCommand.ShellPackageManager:
					return new PackageManagerListPackagesCommandResult ( RunAdbCommand ( device, AdbCommand.Shell, string.Format ( "pm {0}", args ) ) );
				case AdbCommand.Jdwp:
					return new IntegerListCommandResult ( RunAdbCommand ( device, command, args ) );
				case AdbCommand.Remount:
					return new GenericCommandResult ( RunAdbCommand ( device, command, args, false ) );
				case AdbCommand.Push:
				case AdbCommand.Pull:
					return new TransferCommandResult ( RunAdbCommand ( device, command, args ) );
				case AdbCommand.Shell:
				case AdbCommand.Get_SerialNo:
				case AdbCommand.Version:
				case AdbCommand.Get_State:
				case AdbCommand.Uninstall:
				case AdbCommand.Install:
					return new GenericCommandResult ( RunAdbCommand ( device, command, args, true ) );
				case AdbCommand.Start_Server:
				case AdbCommand.Kill_Server:
					return new GenericCommandResult ( RunAdbCommand ( device, command, args, false ) );
				case AdbCommand.Bugreport:
				case AdbCommand.Logcat:
				case AdbCommand.Forward:
				case AdbCommand.Emu:
				case AdbCommand.Sync:
				case AdbCommand.PPP:
					this.LogWarn ( string.Format ( CultureInfo.InvariantCulture, "* {0} command not supported *", AdbCommandToString ( command ) ) );
					return new GenericCommandResult ( string.Format ( CultureInfo.InvariantCulture, "* {0} command not supported *", AdbCommandToString ( command ) ) );
				default:
					this.LogWarn ( string.Format ( CultureInfo.InvariantCulture, "* unknown command ({0}) not supported *", AdbCommandToString ( command ) ) );
					return new GenericCommandResult ( string.Format ( "* unknown command ({0}) not supported *", AdbCommandToString ( command ) ) );
			}
		}*/

		/// <summary>
		/// Runs the aapt command.
		/// </summary>
		/// <param name="command">The command.</param>
		/// <param name="args">The args.</param>
		/// <returns></returns>
		private string RunAaptCommand ( AaptCommand command, string args ) {
			//string localPath = System.IO.Path.GetDirectoryName ( typeof ( CommandRunner ).Assembly.Location );

			StringBuilder result = new StringBuilder ( );
			Process proc = new Process ( );
			StringBuilder commandArg = new StringBuilder ( AaptCommandToString ( command ) );
			if ( !string.IsNullOrEmpty ( args ) ) {
				commandArg.AppendFormat ( " {0}", args );
			}
			ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( AndroidDebugBridge.AAPT ), commandArg.ToString ( ) );
			this.LogDebug ( "{0} {1}", System.IO.Path.GetFileName ( psi.FileName ), psi.Arguments );

			psi.CreateNoWindow = true;
			psi.ErrorDialog = true;
			psi.UseShellExecute = false;
			psi.RedirectStandardOutput = true;
			psi.RedirectStandardError = true;
			psi.WindowStyle = ProcessWindowStyle.Hidden;
			proc.StartInfo = psi;
			proc.OutputDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
				if ( !string.IsNullOrEmpty ( e.Data ) ) {
					result.AppendLine ( e.Data.Trim ( ) );
				}
			};

			proc.ErrorDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
				if ( !string.IsNullOrEmpty ( e.Data ) ) {
					result.AppendLine ( e.Data.Trim ( ) );
				}
			};

			proc.Exited += delegate ( object sender, EventArgs e ) {

			};
			proc.Start ( );
			proc.BeginOutputReadLine ( );
			proc.BeginErrorReadLine ( );
			proc.WaitForExit ( );
			return result.ToString ( );
		}

		private string RunAdbCommand( Device device, AdbCommand command, string args ) {
			return RunAdbCommand ( device, command, args, true );
		}

		/// <summary>
		/// Runs the adb command.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="command">The command.</param>
		/// <param name="args">The args.</param>
		/// <returns></returns>
		private string RunAdbCommand( Device device, AdbCommand command, string args, bool wait ) {
			try {
				StringBuilder result = new StringBuilder ( );
				Process proc = new Process ( );
				StringBuilder commandArg = new StringBuilder ( AdbCommandArguments ( device.SerialNumber, command ) );
				if ( !string.IsNullOrEmpty ( args ) ) {
					commandArg.AppendFormat ( " {0}", args );
				}
				ProcessStartInfo psi = new ProcessStartInfo ( GetSdkTool ( AndroidDebugBridge.ADB ), commandArg.ToString ( ) );
				this.LogDebug ( "{0} {1}", System.IO.Path.GetFileName ( psi.FileName ), psi.Arguments );

				psi.CreateNoWindow = true;
				psi.ErrorDialog = false;
				psi.UseShellExecute = false;
				psi.RedirectStandardOutput = true;
				psi.RedirectStandardError = true;
				psi.WindowStyle = ProcessWindowStyle.Hidden;
				proc.StartInfo = psi;
				proc.OutputDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
					if ( !string.IsNullOrEmpty ( e.Data ) ) {
						result.AppendLine ( e.Data.Trim ( ) );
					}
				};

				proc.ErrorDataReceived += delegate ( object sender, DataReceivedEventArgs e ) {
					if ( !string.IsNullOrEmpty ( e.Data ) ) {
						result.AppendLine ( e.Data.Trim ( ) );
					}
				};

				proc.Exited += delegate ( object sender, EventArgs e ) {

				};
				proc.Start ( );
				proc.BeginOutputReadLine ( );
				proc.BeginErrorReadLine ( );

				if ( wait ) {
					proc.WaitForExit ( );
				} else {
					Thread.Sleep ( 250 );
				}

				return result.ToString ( );
			} catch ( Win32Exception wex ) {
				this.LogError ( wex.Message, wex );
			} catch ( Exception ex ) {
				this.LogError ( ex.Message, ex );
			}
			return string.Empty;
		}

		/// <summary>
		/// gets Adbs command arguments.
		/// </summary>
		/// <param name="device">The device.</param>
		/// <param name="command">The command.</param>
		/// <returns></returns>
		private string AdbCommandArguments ( string device, AdbCommand command ) {
			if ( string.IsNullOrEmpty ( device ) ) {
				return AdbCommandToString ( command );
			} else {
				return string.Format ( "-s {0} {1}", device, AdbCommandToString ( command ) );
			}
		}

		/// <summary>
		/// Convert the Adb Command to the string value
		/// </summary>
		/// <param name="command">The command.</param>
		/// <returns></returns>
		private string AdbCommandToString ( AdbCommand command ) {
			return command.ToString ( ).Replace ( "_", "-" ).ToLower ( );
		}

		/// <summary>
		/// Convert the aapt Command to the string value
		/// </summary>
		/// <param name="command">The command.</param>
		/// <returns></returns>
		private string AaptCommandToString ( AaptCommand command ) {
			return command.ToString ( ).Replace ( "_", " " ).ToLower ( );
		}

		/// <summary>
		/// Gets the device state from the string value
		/// </summary>
		/// <param name="val">The val.</param>
		/// <returns></returns>
		private DeviceState StringToDeviceState ( string val ) {
			try {
				object o = Enum.Parse ( typeof ( DeviceState ), val, true );
				if ( o == null ) {
					return DeviceState.Unknown;
				} else {
					return (DeviceState)o;
				}
			} catch ( Exception ex ) {
				return DeviceState.Unknown;
			}

		}


		public static ISettings Settings { get; set; }


		public static CommandRunner Instance {
			get {
				if ( _commandRunner == null ) {
					_commandRunner = new CommandRunner ( );
				}
				return _commandRunner;
			}
		}
	}
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值