Files
UnrealEngine/Engine/Source/Programs/UnrealAndroidFileTool/Program.cs
2025-05-18 13:04:45 +08:00

1404 lines
35 KiB
C#

// 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<string> 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<string> EntriesToDeploy = new HashSet<string>();
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<string> devices = new List<string>();
AndroidFileClient.GetConnectedDevices(out devices);
foreach (string DeviceName in devices)
{
Logger.LogInformation("{0}", DeviceName);
}
return;
}
if (Device == "")
{
// look for connected devices
List<string> devices = new List<string>();
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<string> 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);
}
}
}