// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Threading; using System.Threading.Tasks; using System.Diagnostics; using System.Reflection; using System.IO; using System.Collections.Generic; using System.Text; using System.Linq; using AutomationTool; using EpicGames.Core; using Microsoft.Extensions.Logging; using Microsoft.CodeAnalysis.CSharp.Syntax; namespace UnrealAndroidFileTool { class Program { private static string AppVersion = "1.0.7"; private static ILogger Logger = Log.Logger; static void ShowHelp(string command) { if (command == "") { Logger.LogInformation("UnrealAndroidFileTool version {0}\n" + "Copyright Epic Games, Inc. All Rights Reserved.\n\n" + "UnrealAndroidFileTool [-s Device] [-ip ipAddress] [-t port] [-p PackageName] [-k token] command\n\n" + "Commands:\n\n" + "devices Show connected devices (@ prefix for authorized).\n" + "packages Show list of packages with receiver enabled.\n" + "stop-all [-w] Send stop request to all packages with receivers.\n" + "help [command] Get help about a command.\n" + "shell Start interactive mode.\n" + "quit Exit interactive mode.\n" + "exit Exit interactive mode.\n" + "terminate Stop remote server.\n" + "query [key] Show all variables or a specific key.\n" + "getprop [key] Get property for key.\n" + "cd path Set base directory (value of ^^).\n" + "pwd Show current base directory.\n" + "direxists path Returns true if directory path exists.\n" + // "dirlist [RSA:]path Show contents of directory path.\n" + "ls [-lsRf] path Show contents of directory path.\n" + // "dirlistflat path Show recursive contents of directories grouped.\n" + // "dircreate path Create directory path (recursive).\n" + "mkdir path Create directory path (recursive).\n" + // "dirdelete path Delete directory path (recursive).\n" + "rmdir path Delete directory path (recursive).\n" + "fileexists file Returns true if file exists.\n" + // "filedelete file Delete file.\n" + "rm file Delete file.\n" + // "filecopy src dst Copies file from src to dst on device.\n" + "cp src dst Copies file from src to dst on device.\n" + // "filemove src dst Moves file from src to dst on device.\n" + "mv src dst Moves file from src to dst on device.\n" + // "fileread src dst Pulls src file from device to local dst.\n" + "pull src dst Pulls src file from device to local dst.\n" + "pulldir src dst Pulls src directory from device to local dst.\n" + // "filewrite src dst Pushes local src file to device dst.\n" + "push [-c] src dst Pushes local src file or directories to device dst.\n" + "command [-f file] [data] Writes [file] or [data] to commandline file, or shows contents.\n" + "addcommand [data] Adds data to commandline file.\n" + "delcommand [data] Removes data from commandline file.\n" + "cat file Writes file contents from device to output.\n" + "deploy [-c] file Reads a text file with deployment source/dest pairs.\n" + "\n" + "Note: keys may be used at start of a path as shortcut.\n" + " Ex: fileread ^logfile game.log - pulls logfile.\n" + " rm ^project/Manifest.txt - deletes Manifest.txt from project dir.\n\n" , AppVersion); return; } if (command == "command") { Logger.LogInformation("No Args\t\tShow contents of commandline file"); Logger.LogInformation("-f [file]\tWrites contents of [file] to commandline file"); Logger.LogInformation("[data]\t\tOverwrites commandline file with [data]"); return; } if (command == "ls") { Logger.LogInformation("-l\tlist permissions"); Logger.LogInformation("-s\tlist size"); Logger.LogInformation("-R\tlist recursive directory tree"); Logger.LogInformation("-f\tlist flat\n"); return; } if (command == "stop-all") { Logger.LogInformation("-w\twait for all listen binds to terminate"); return; } if (command == "push") { Logger.LogInformation("-c\tcompress files\n"); return; } if (command == "deploy") { Logger.LogInformation("-c\tcompress files\n"); return; } } static string FixPath(AndroidFileClient client, string path) { if (path.StartsWith("^^")) { string cmd = client.Query("^^"); path = client.Query("^^") + path.Substring(2); } else if (!(path.StartsWith("^") || path.StartsWith("/"))) { string cwd = client.Query("^^"); if (cwd != "") { path = cwd + "/" + path; } } // remove .. sets by trimming out prior directory int dotdotIndex = path.IndexOf(".."); while (dotdotIndex > 0) { int slashIndex = path.Substring(0, dotdotIndex - 1).LastIndexOf("/"); if (slashIndex < 0) { break; } path = path.Substring(0, slashIndex) + path.Substring(dotdotIndex + 2); dotdotIndex = path.IndexOf(".."); } return path; } static int ProcessCommand(AndroidFileClient client, bool bInShell, string[] args, int ArgIndex) { if (ArgIndex < args.Length && (args[ArgIndex] == "help" || args[ArgIndex] == "?")) { ArgIndex++; if (ArgIndex < args.Length) { ShowHelp(args[ArgIndex++]); } else { ShowHelp(""); } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "shell") { ArgIndex++; while (true) { Console.Write("shell> "); string? input = Console.ReadLine(); if (input == null || input == "exit" || input == "quit") { return ArgIndex; } if (input != "") { string[] split = input.Split(new char[] { ' ', '\t' }); if (split.Length > 0) { if (ProcessCommand(client, true, split, 0) == -1) { return -1; } } } } } if (ArgIndex < args.Length && args[ArgIndex] == "packages") { ArgIndex++; List Receivers = AndroidFileClient.GetInstalledReceivers(client.GetDevice()); AndroidFileClient.GetInstalledActivities(client.GetDevice()).ForEach(item => { if (!Receivers.Contains(item)) Receivers.Add(item); }); if (Receivers.Count > 0) { foreach (string Line in Receivers) { Logger.LogInformation("{0}", Line); } return ArgIndex; } Logger.LogInformation("No packages found with receiver."); return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "stop-all") { ArgIndex++; bool bWait = false; if (ArgIndex < args.Length && args[ArgIndex].StartsWith("-w")) { bWait = true; } client.CloseConnection(); AndroidFileClient.StopAnyServers(client.GetDevice(), client.GetServerPort(), bWait); System.Environment.Exit(0); } if (ArgIndex < args.Length && args[ArgIndex] == "stats") { ArgIndex++; client.Stats_Report(); return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "terminate") { ArgIndex++; client.TerminateServer(); Logger.LogInformation("Terminated server"); return -1; } if (ArgIndex < args.Length && args[ArgIndex] == "pwd") { ArgIndex++; string result = client.Query("^^"); Logger.LogInformation("{0}", result); return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "query") { ArgIndex++; if (ArgIndex < args.Length) { string result = client.Query(args[ArgIndex++]); Logger.LogInformation("{0}", result); } else { string result = client.Query(""); string[] lines = result.Split('\n'); foreach (string line in lines) { string[] parts = line.Split("\t"); if (parts.Length > 1) { Logger.LogInformation("{0,-20}{1}", parts[0], parts[1]); } } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "getprop") { ArgIndex++; if (ArgIndex < args.Length) { string result = client.GetProp(args[ArgIndex++]); Logger.LogInformation("{0}", result); } else { string result = client.GetProp(""); Logger.LogInformation("{0}", result); } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "cd") { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.SetBaseDir(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", client.Query("^^")); return ArgIndex++; } else { string result = client.Query("^^"); Logger.LogInformation("{0}", result); } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "direxists") { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.DirExists(args[ArgIndex]); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "ls") { ArgIndex++; string path = "^^"; // process flags bool bOptions = false; bool bAttributes = false; bool bRecursive = false; bool bSize = false; bool bFlat = false; while (ArgIndex < args.Length && args[ArgIndex].StartsWith("-")) { if (args[ArgIndex].Contains("l")) { bAttributes = true; bOptions = true; } if (args[ArgIndex].Contains("R")) { bRecursive = true; bOptions = true; } if (args[ArgIndex].Contains("s")) { bSize = true; bOptions = true; } if (args[ArgIndex].Contains("f")) { bFlat = true; } ArgIndex++; } if (ArgIndex < args.Length) { path = args[ArgIndex]; ArgIndex++; } path = FixPath(client, path); if (path == "^^") { path = client.Query("^^"); } string result; if (bRecursive && bFlat) { result = client.DirListFlat(path); } else { result = client.DirList((bRecursive ? "R" : "") + (bSize ? "S" : "") + (bAttributes ? "A" : "") + (bOptions ? ":" : "") + path); } Logger.LogInformation("{0}", result); return ArgIndex++; } if (ArgIndex < args.Length && args[ArgIndex] == "dirlist") { ArgIndex++; if (ArgIndex < args.Length) { string result = client.DirList(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", result); return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "dirlistflat")) { ArgIndex++; if (ArgIndex < args.Length) { string result = client.DirListFlat(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", result); return ArgIndex++; } else { Logger.LogError("missing path"); } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "dircreate" || args[ArgIndex] == "mkdir")) { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.DirCreate(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "dirdelete" || args[ArgIndex] == "rmdir")) { ArgIndex++; if (ArgIndex < args.Length && args[ArgIndex] == "-r") { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.DirDeleteRecurse(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else if (ArgIndex < args.Length) { bool result = client.DirDelete(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "dirdeleterecurse") { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.DirDeleteRecurse(args[ArgIndex]); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "fileexists") { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.FileExists(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "filedelete" || args[ArgIndex] == "rm")) { ArgIndex++; if (ArgIndex < args.Length) { bool result = client.FileDelete(FixPath(client, args[ArgIndex])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "filecopy" || args[ArgIndex] == "cp")) { ArgIndex++; if (ArgIndex + 1 < args.Length) { bool result = client.FileCopy(FixPath(client, args[ArgIndex]), FixPath(client, args[ArgIndex+1])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex +=2; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "filemove" || args[ArgIndex] == "mv")) { ArgIndex++; if (ArgIndex + 1 < args.Length) { bool result = client.FileMove(FixPath(client, args[ArgIndex]), FixPath(client, args[ArgIndex + 1])); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && (args[ArgIndex] == "fileread" || args[ArgIndex] == "pull")) { ArgIndex++; if (ArgIndex + 1 < args.Length) { bool result = client.FileRead(args[ArgIndex], args[ArgIndex + 1]); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "pulldir") { ArgIndex++; if (ArgIndex + 1 < args.Length) { string result = client.DirListFlat(FixPath(client, args[ArgIndex])); if (result == "(null)") { Logger.LogError("false"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } // first line is the src path base string[] Lines = result.Split('\n'); string BaseSrcPath = Lines[0].Substring(0, Lines[0].Length - 1); int BaseSrcPathLength = BaseSrcPath.Length; string DestBasePath = ""; foreach (string Line in Lines) { if (Line == "") { continue; } if (Line.EndsWith(":")) { DestBasePath = Line.Substring(BaseSrcPathLength, Line.Length - BaseSrcPathLength - 1); if (DestBasePath.StartsWith("/")) { DestBasePath = DestBasePath.Substring(1); } // make directories if don't exist string TargetDir = args[ArgIndex + 1] + (DestBasePath.Length > 0 ? "/" + DestBasePath : ""); try { System.IO.Directory.CreateDirectory(TargetDir); } catch (Exception) { Logger.LogError("Failed to create {0}\nfalse", TargetDir); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } continue; } string Src = BaseSrcPath + "/" + (DestBasePath.Length > 0 ? DestBasePath + "/" : "") + Line; string Dest = args[ArgIndex + 1] + "/" + (DestBasePath.Length > 0 ? DestBasePath + "/" : "") + Line; bool copyresult = client.FileRead(Src, Dest); if (!bInShell && !copyresult) { Logger.LogError("false"); client.CloseConnection(); System.Environment.Exit(1); } } Logger.LogInformation("true"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "filewrite") { ArgIndex++; if (ArgIndex + 1 < args.Length) { //Logger.LogInformation("Src: '{0}', Dest: '{1}'", args[ArgIndex], args[ArgIndex + 1]); bool result = client.FileWrite(args[ArgIndex], args[ArgIndex + 1]); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex += 2; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "push") { ArgIndex++; if (ArgIndex + 1 < args.Length) { bool result = false; bool bCompress = false; if (args[ArgIndex] == "-c") { bCompress = true; ArgIndex++; } if (ArgIndex + 1 < args.Length) { string source = args[ArgIndex]; string dest = args[ArgIndex + 1]; ArgIndex += 2; try { FileAttributes attributes = File.GetAttributes(source); if ((attributes & FileAttributes.Directory) == FileAttributes.Directory) { result = client.PushDirectories(source, dest, bCompress, 1); } else { result = client.PushFile(source, dest, bCompress, 1); } } catch (Exception) { Logger.LogInformation("false"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex; } Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex; } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { Logger.LogError("missing paths"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } if (ArgIndex < args.Length && args[ArgIndex] == "command") { ArgIndex++; if (ArgIndex < args.Length) { string command = args[ArgIndex++]; if (command == "-f") { if (ArgIndex < args.Length && File.Exists(args[ArgIndex])) { string[] CommandLines = File.ReadAllLines(args[ArgIndex++]); command = ""; if (CommandLines.Length > 0) { command = CommandLines[0]; } } else { Logger.LogError("missing filename"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { while (ArgIndex < args.Length) { command = command + " " + args[ArgIndex++]; } } bool result = client.FileWriteString(command, "^commandfile"); Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell && !result) { client.CloseConnection(); System.Environment.Exit(1); } return ArgIndex; } else { string TempFilename = Path.GetTempFileName(); bool result = client.FileRead("^commandfile", TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); Console.WriteLine(myReader.ReadToEnd()); myReader.Close(); File.Delete(TempFilename); } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", TempFilename, e.ToString()); } } else { Logger.LogInformation("No commandline file found."); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "addcommand") { ArgIndex++; if (ArgIndex < args.Length) { string command = ""; string TempFilename = Path.GetTempFileName(); bool result = client.FileRead("^commandfile", TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); string? line = myReader.ReadLine(); command = (line != null) ? line : ""; myReader.Close(); File.Delete(TempFilename); } catch (Exception) { } } while (ArgIndex < args.Length) { command = command + " " + args[ArgIndex++]; } result = client.FileWriteString(command, "^commandfile"); if (!bInShell && !result) { Logger.LogError("false"); client.CloseConnection(); System.Environment.Exit(1); } Logger.LogInformation("New commandline: {0}", command); return ArgIndex; } else { string TempFilename = Path.GetTempFileName(); bool result = client.FileRead("^commandfile", TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); Console.WriteLine(myReader.ReadToEnd()); myReader.Close(); File.Delete(TempFilename); } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", TempFilename, e.ToString()); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { Logger.LogInformation("No commandline file found."); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "delcommand") { ArgIndex++; if (ArgIndex < args.Length) { string command = ""; string TempFilename = Path.GetTempFileName(); bool result = client.FileRead("^commandfile", TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); string? line = myReader.ReadLine(); command = (line != null) ? line : ""; myReader.Close(); File.Delete(TempFilename); } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", TempFilename, e.ToString()); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } while (ArgIndex < args.Length) { command = command.Replace(args[ArgIndex++], ""); } result = client.FileWriteString(command, "^commandfile"); if (!bInShell && !result) { Logger.LogError("false"); client.CloseConnection(); System.Environment.Exit(1); } Logger.LogInformation("New commandline: {0}", command); return ArgIndex; } else { string TempFilename = Path.GetTempFileName(); bool result = client.FileRead("^commandfile", TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); Console.WriteLine(myReader.ReadToEnd()); myReader.Close(); File.Delete(TempFilename); } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", TempFilename, e.ToString()); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { Logger.LogInformation("No commandline file found."); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "cat") { ArgIndex++; if (ArgIndex < args.Length) { string TempFilename = Path.GetTempFileName(); bool result = client.FileRead(FixPath(client, args[ArgIndex]), TempFilename); if (result) { try { StreamReader myReader = File.OpenText(TempFilename); Console.WriteLine(myReader.ReadToEnd()); myReader.Close(); File.Delete(TempFilename); } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", TempFilename, e.ToString()); } } else { Logger.LogInformation("{0}", (result ? "true" : "false")); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex++; } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } if (ArgIndex < args.Length && args[ArgIndex] == "deploy") { ArgIndex++; if (ArgIndex < args.Length) { bool bCompress = false; if (args[ArgIndex] == "-c") { bCompress = true; ArgIndex++; } if (ArgIndex < args.Length) { try { StreamReader myReader = File.OpenText(args[ArgIndex]); ArgIndex++; string? SourceDir = myReader.ReadLine(); string? DestDir = myReader.ReadLine(); HashSet EntriesToDeploy = new HashSet(); string? Entry; while ((Entry = myReader.ReadLine()) != null) { if (Entry != null) { EntriesToDeploy.Add(Entry); } } myReader.Close(); if (SourceDir != null && DestDir != null) { client.Deploy(EntriesToDeploy, SourceDir, DestDir, bCompress, false, true, null); } } catch (Exception e) { Logger.LogError("Error reading temp file {0}, Exception: {1}", args[ArgIndex], e.ToString()); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } } else { Logger.LogError("missing path"); if (!bInShell) { client.CloseConnection(); System.Environment.Exit(1); } } return ArgIndex; } Logger.LogWarning("Unknown command"); return ArgIndex; } static AndroidFileClient? CreateAndConnectClient(string Device, string PackageName, string Token, string IPAddress, int Port) { AndroidFileClient? client = new AndroidFileClient(Device, Port); if (client != null) { if (!client.OpenConnection(IPAddress)) { if (PackageName == "") { Logger.LogError("Need package name to start server on {0}!", Device); return null; } else { Logger.LogInformation("Trying to start file server {0}", PackageName); if (!client.StartServer(PackageName, Token, IPAddress)) { Logger.LogError("Unable to connect to " + Device); return null; } } } // verify connection to the correct server string DevicePackageName = client.Query("^packagename"); if (DevicePackageName != PackageName) { if (PackageName == "") { Logger.LogError("Need package name to start server on {0}!", Device); client.CloseConnection(); return null; } Logger.LogInformation("Connected to wrong server {0}, trying again", DevicePackageName); client.TerminateServer(); Logger.LogInformation("Trying to start file server {0}", PackageName); if (!client.StartServer(PackageName)) { Logger.LogError("Failed to start server"); return null; } } return client; } return null; } static void Main(string[] args) { string IPAddress = ""; string Device = ""; int Port = AndroidFileClient.GetDefaultPort(); string PackageName = ""; string Token = ""; // Ensure we can resolve any external assemblies as necessary. Assembly? assembly = Assembly.GetEntryAssembly(); if (assembly != null) { string? PathToBinariesDotNET = Path.GetDirectoryName(AppContext.BaseDirectory);//assembly.GetOriginalLocation()); if (PathToBinariesDotNET != null) { AssemblyUtils.InstallAssemblyResolver(PathToBinariesDotNET); AssemblyUtils.InstallRecursiveAssemblyResolver(PathToBinariesDotNET); } } if (args.Length == 0 || (args.Length == 1 && args[0] == "help")) { ShowHelp(""); System.Environment.Exit(0); } if (args.Length > 1 && args[0] == "help") { ShowHelp(args[1]); System.Environment.Exit(0); } int ArgIndex = 0; if (ArgIndex < args.Length && args[ArgIndex] == "-s") { ArgIndex++; if (ArgIndex < args.Length) { Device = "@" + args[ArgIndex]; ArgIndex++; } else { Logger.LogError("Missing device id"); System.Environment.Exit(1); } } if (ArgIndex < args.Length && args[ArgIndex] == "-p") { ArgIndex++; if (ArgIndex < args.Length) { PackageName = args[ArgIndex]; ArgIndex++; } else { Logger.LogError("Missing package name"); System.Environment.Exit(1); } } if (ArgIndex < args.Length && args[ArgIndex] == "-k") { ArgIndex++; if (ArgIndex < args.Length) { Token = args[ArgIndex]; ArgIndex++; } else { Logger.LogError("Missing security token key"); System.Environment.Exit(1); } } if (ArgIndex < args.Length && args[ArgIndex] == "-t") { ArgIndex++; if (ArgIndex < args.Length) { try { Port = int.Parse(args[ArgIndex]); ArgIndex++; } catch (Exception) { Logger.LogError("Invalid port"); System.Environment.Exit(1); } } else { Logger.LogError("Missing port"); System.Environment.Exit(1); } } if (ArgIndex < args.Length && args[ArgIndex] == "-ip") { ArgIndex++; if (ArgIndex < args.Length) { IPAddress = args[ArgIndex]; ArgIndex++; } else { Logger.LogError("Missing IP address"); System.Environment.Exit(1); } } if (ArgIndex < args.Length && args[ArgIndex] == "devices") { List devices = new List(); AndroidFileClient.GetConnectedDevices(out devices); foreach (string DeviceName in devices) { Logger.LogInformation("{0}", DeviceName); } return; } if (Device == "") { // look for connected devices List devices = new List(); AndroidFileClient.GetConnectedDevices(out devices); if (devices.Count == 0) { Logger.LogError("No connected devices"); } else if (devices.Count == 1) { Device = devices[0]; } else { Logger.LogError("Multiple devices connected, select one -s!"); foreach (string DeviceName in devices) { Logger.LogInformation("{0}", DeviceName); } } } if (Device == "") { Logger.LogError("No devices attached!"); System.Environment.Exit(0); } // check these here since may not have a running server to connect if (ArgIndex < args.Length && args[ArgIndex] == "packages") { ArgIndex++; List Receivers = AndroidFileClient.GetInstalledReceivers(Device.Substring(1)); AndroidFileClient.GetInstalledActivities(Device.Substring(1)).ForEach(item => { if (!Receivers.Contains(item)) Receivers.Add(item); }); if (Receivers.Count > 0) { foreach (string Line in Receivers) { Logger.LogInformation("{0}", Line); } System.Environment.Exit(0); } Logger.LogInformation("No packages found with receiver."); System.Environment.Exit(0); } if (ArgIndex < args.Length && args[ArgIndex] == "stop-all") { ArgIndex++; bool bWait = false; if (ArgIndex < args.Length && args[ArgIndex].StartsWith("-w")) { bWait = true; } AndroidFileClient.StopAnyServers(Device.Substring(1), Port, bWait); System.Environment.Exit(0); } AndroidFileClient? client = CreateAndConnectClient(Device.Substring(1), PackageName, Token, IPAddress, Port); if (client == null) { System.Environment.Exit(1); } Logger.LogInformation("Connected!"); if (ArgIndex < args.Length) { ArgIndex = ProcessCommand(client, false, args, ArgIndex); if (client != null) { client.CloseConnection(); } System.Environment.Exit(0); } ShowHelp(""); if (client != null) { client.CloseConnection(); } System.Environment.Exit(0); } } }