116 lines
4.4 KiB
C#
116 lines
4.4 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Win32;
|
|
using Kaitai;
|
|
|
|
namespace TSUnpack {
|
|
class Program {
|
|
private const string USAGE = @"Usage: {0} [-f|--force|/f|/force] [-d|--destination|/d|/destination destination] path [path...]
|
|
Unpacks one or more Microsoft Train Simulator Packaged Activity files.
|
|
If any of the files do not exist or if any error occurs while parsing one of the files, an error is printed and the file is skipped.
|
|
|
|
-d, --destination
|
|
When unset, the destination directory will be retrieved from the {1} value of the Windows registry key at {2}.
|
|
If the destination path does not exist or the registry key is not found, the program will throw an error.
|
|
|
|
-f, --force
|
|
Overwrite existing files when unpacking.
|
|
By default, the program stops if a file already exists.";
|
|
|
|
private const string REGISTRY_KEY = @"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft Games\Train Simulator\1.0";
|
|
|
|
private const string REGISTRY_VALUE = "Path";
|
|
|
|
private static void PrintUsage() {
|
|
Console.WriteLine(
|
|
USAGE,
|
|
Environment.GetCommandLineArgs()[0],
|
|
REGISTRY_VALUE,
|
|
REGISTRY_KEY);
|
|
}
|
|
|
|
static int Main(string[] args) {
|
|
if (args.Length == 0) {
|
|
PrintUsage();
|
|
return 2;
|
|
}
|
|
|
|
// Poor man's argument parsing because I just can't find something simple for .NET 2.0.
|
|
|
|
bool overwrite = false;
|
|
// Null by default so that we can detect duplicate arguments and handle the default value
|
|
string destination = null;
|
|
|
|
List<string> sourcePaths = new List<string>();
|
|
|
|
for (int i = 0; i < args.Length; i++) {
|
|
string arg = args[i];
|
|
if (arg.ToLower() == "-f" || arg.ToLower() == "--force" || arg.ToLower() == "/f" || arg.ToLower() == "/force")
|
|
overwrite = true;
|
|
else if (arg.ToLower() == "-d" || arg.ToLower() == "--destination" || arg.ToLower() == "/d" || arg.ToLower() == "/destination") {
|
|
// Yes, this ++i is blursed. I like it.
|
|
if (destination != null || args.Length < ++i) {
|
|
PrintUsage();
|
|
return 2;
|
|
}
|
|
destination = args[i];
|
|
} else if (arg.ToLower().StartsWith("-d=") || arg.ToLower().StartsWith("--destination=") || arg.ToLower().StartsWith("/d=") || arg.ToLower().StartsWith("/destination=")) {
|
|
if (destination != null) {
|
|
PrintUsage();
|
|
return 2;
|
|
}
|
|
destination = arg.Split(new char[] { '=' }, 2)[1];
|
|
} else
|
|
sourcePaths.Add(arg);
|
|
}
|
|
|
|
if (sourcePaths.Count == 0) {
|
|
PrintUsage();
|
|
return 2;
|
|
}
|
|
|
|
if (destination == null) {
|
|
// Try to retrieve the registry key.
|
|
destination = (string)Registry.GetValue(REGISTRY_KEY, REGISTRY_VALUE, null);
|
|
}
|
|
|
|
if (destination == null) {
|
|
Console.WriteLine(
|
|
"No destination path specified and no default Microsoft Train Simulator installation path found in the Windows Registry at {0}.",
|
|
REGISTRY_KEY);
|
|
return 1;
|
|
}
|
|
|
|
// Resolve as an absolute path
|
|
destination = Path.GetFullPath(destination);
|
|
|
|
if (!Directory.Exists(destination)) {
|
|
Console.WriteLine("The destination path {0} does not exist.", destination);
|
|
return 1;
|
|
}
|
|
|
|
bool success = false;
|
|
foreach (string path in sourcePaths) {
|
|
try {
|
|
IO.Unpack(path, destination, overwrite);
|
|
success = true;
|
|
} catch (KaitaiStructError e) {
|
|
Console.WriteLine(
|
|
"Failed parsing APK file at {0}: {1}",
|
|
path,
|
|
e.Message);
|
|
} catch (IOException e) {
|
|
Console.WriteLine(
|
|
"Failed unpacking APK file at {0} to {1}: {2}",
|
|
path,
|
|
destination,
|
|
e.Message);
|
|
}
|
|
}
|
|
|
|
return success ? 0 : 1;
|
|
}
|
|
}
|
|
}
|