Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c29691361 | ||
|
|
c392631339 | ||
|
|
c5de32f6dd | ||
|
|
2df8f900d6 | ||
|
|
73abfb8fa8 | ||
|
|
a62f1e998f | ||
|
|
7821de4bb4 | ||
|
|
97a89f4382 | ||
|
|
7aab701aa1 | ||
|
|
b8686d4a04 | ||
|
|
2be4c47213 | ||
|
|
d5582d17e3 | ||
|
|
ba1ba3937d | ||
|
|
fef18f8b68 | ||
|
|
d137448a7b | ||
|
|
4ce50aa635 | ||
|
|
ed5f4d7813 | ||
|
|
433330f743 | ||
|
|
e7f00bdff7 | ||
|
|
550e52cf1e | ||
|
|
0077844000 | ||
|
|
c086ad5552 | ||
|
|
0c298432f2 | ||
|
|
981fea7af8 | ||
|
|
edd7717a08 | ||
|
|
5fc505d789 | ||
|
|
fa59eed572 | ||
|
|
d9e3ca1f50 | ||
|
|
51c1c71475 | ||
|
|
0e8df6cf77 | ||
|
|
b23ded7286 | ||
|
|
f238391707 | ||
|
|
64e8e294c4 | ||
|
|
dd4ba9f34a | ||
|
|
5513cabf3e | ||
|
|
cc541e78de | ||
|
|
2d31e5199f | ||
|
|
c5fa538b42 | ||
|
|
32d0f1cde8 | ||
|
|
83fc93c670 | ||
|
|
0925798199 | ||
|
|
2c2501f89b | ||
|
|
b18245b13d | ||
|
|
317727961e |
@@ -0,0 +1,3 @@
|
||||
bin
|
||||
res
|
||||
.dub
|
||||
@@ -1,14 +1,12 @@
|
||||
# ADB-Installer
|
||||
# Android Debug Bridge Installer
|
||||
Download from [Releases](https://github.com/josephsmendoza/ADB-Installer/releases)
|
||||
|
||||
This is a re-implementation of the [15 seconds ADB Installer](https://forum.xda-developers.com/showthread.php?t=2588979)
|
||||
|
||||
This installer requires an internet connection.
|
||||
|
||||
The main component is [the PowerShell script](https://github.com/josephsmendoza/ADB-Installer/blob/master/install.ps1) which downloads [the latest android platform tools for windows](https://dl.google.com/android/repository/platform-tools-latest-windows.zip) and installs them to either `C:\adb`, an auto-detected previous install location, or a path you can specify via `-installPath`.
|
||||
|
||||
For conveinence, this is wrapped in an `.exe` file which runs the script with `ExecutionPolicy` set to `Bypass`. This file is fully automated.
|
||||
|
||||
Icon is from [Google via icon-icons.com](https://icon-icons.com/icon/adb/90476)
|
||||
|
||||
Built with [7z SFX Builder](https://sourceforge.net/projects/s-zipsfxbuilder)
|
||||
Windows version packaged with [Ptiso](https://pismotec.com/ptiso/)
|
||||
|
||||
Linux & Mac version packaged with [UPX](https://upx.github.io/)
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
Param( [Parameter()] [String[]] $installPath )
|
||||
$adb=$false
|
||||
$fastboot=$false
|
||||
|
||||
if (Get-Command "adb" -ErrorAction SilentlyContinue){
|
||||
$adb=$true
|
||||
}
|
||||
if (Get-Command "fastboot" -ErrorAction SilentlyContinue){
|
||||
$fastboot=$true
|
||||
}
|
||||
|
||||
if($installPath.Length.Equals(0)){
|
||||
if(!$adb -and $fastboot){
|
||||
Write-Output "fastboot installed without adb"
|
||||
Write-Output "Checking fastboot location via --version ..."
|
||||
$installPath=fastboot --version | Select-String -Pattern "(?<=installed as )(.+)(?=\\.*\.exe)" | % { $_.Matches } | % { $_.Value }
|
||||
}
|
||||
if($adb){
|
||||
Write-Output "adb installed, checking location via --version ..."
|
||||
$installPath=adb --version | Select-String -Pattern "(?<=installed as )(.+)(?=\\.*\.exe)" | % { $_.Matches } | % { $_.Value }
|
||||
}
|
||||
if($installPath.Length.Equals(0)){
|
||||
Write-Output "platform-tools location not found"
|
||||
$installPath="$HOME\AppData\Roaming\SideQuest\platform-tools\"
|
||||
}
|
||||
}
|
||||
Write-Output "installPath=$installPath"
|
||||
|
||||
if(!$adb -and !$fastboot){
|
||||
Write-Output "Adding $installPath to `$PATH ..."
|
||||
$oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path
|
||||
$newpath = "$oldpath;$installPath"
|
||||
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
|
||||
}
|
||||
|
||||
Write-Output "Checking Windows Defender Status..."
|
||||
$defender=cmd /c sc query Windefend
|
||||
if ( "$defender" -like "*RUNNING*" ){
|
||||
Write-Output "Defender is running, adding exclusions for adb..."
|
||||
Add-MpPreference -ExclusionPath $installPath
|
||||
Add-MpPreference -ExclusionProcess "adb.exe"
|
||||
} else {
|
||||
Write-Output "Defender is not running, skipping exclusions"
|
||||
}
|
||||
|
||||
Write-Output "Downloading platform-tools-latest-windows.zip to $env:temp ..."
|
||||
Import-Module BitsTransfer
|
||||
Start-BitsTransfer -Source "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -Destination "$env:temp\platform-tools-latest-windows.zip"
|
||||
Write-Output "Extracting $env:temp\platform-tools-latest-windows.zip to $installPath ..."
|
||||
Expand-Archive -Path "$env:temp\platform-tools-latest-windows.zip" -DestinationPath "$installPath" -Force
|
||||
Write-Output "Installing Quest ADB Driver"
|
||||
$PSScriptRootLegacy=split-path -parent $MyInvocation.MyCommand.Definition
|
||||
Start-Process $PSScriptRootLegacy/android_winusb.inf -Verb Install
|
||||
Write-Output "Done!"
|
||||
Read-Host -Prompt "Press Enter to continue"
|
||||
@@ -0,0 +1,23 @@
|
||||
name "adbi"
|
||||
description "Android Debug Bridge Installer"
|
||||
authors "josephsmendoza"
|
||||
copyright "Copyright © 2019, josephsmendoza"
|
||||
license "GPL-3.0"
|
||||
targetType "executable"
|
||||
targetPath "bin/$PLATFORM/$ARCH"
|
||||
dflags "-Llib/curl.lib" platform="windows"
|
||||
configuration "application" {
|
||||
excludedSourceFiles "source/cli.d"
|
||||
dependency "tkd" version="1.1.13"
|
||||
copyFiles \
|
||||
"$TCLTK_PACKAGE_DIR/dist/$ARCH/tcl86t.dll" \
|
||||
"$TCLTK_PACKAGE_DIR/dist/$ARCH/tk86t.dll" \
|
||||
"$TCLTK_PACKAGE_DIR/dist/library" \
|
||||
"C:/windows/system32/msvcr110.dll" \
|
||||
"C:/windows/system32/vcruntime140.dll" \
|
||||
"lib/libcurl.dll" \
|
||||
platform="windows"
|
||||
}
|
||||
configuration "cli" {
|
||||
excludedSourceFiles "source/gui.d"
|
||||
}
|
||||
-42
@@ -1,42 +0,0 @@
|
||||
Param( [Parameter()] [String[]] $installPath )
|
||||
$adb=$false
|
||||
$fastboot=$false
|
||||
|
||||
if (Get-Command "adb" -ErrorAction SilentlyContinue){
|
||||
$adb=$true
|
||||
}
|
||||
if (Get-Command "fastboot" -ErrorAction SilentlyContinue){
|
||||
$fastboot=$true
|
||||
}
|
||||
|
||||
if($installPath.Length.Equals(0)){
|
||||
if(!$adb -and $fastboot){
|
||||
Write-Output "fastboot installed without adb"
|
||||
Write-Output "Checking fastboot location via --version ..."
|
||||
$installPath=fastboot --version | Select-String -Pattern "(?<=installed as )(.+)(?=\\.*\.exe)" | % { $_.Matches } | % { $_.Value }
|
||||
}
|
||||
if($adb){
|
||||
Write-Output "adb installed, checking location via --version ..."
|
||||
$installPath=adb --version | Select-String -Pattern "(?<=installed as )(.+)(?=\\.*\.exe)" | % { $_.Matches } | % { $_.Value }
|
||||
}
|
||||
if($installPath.Length.Equals(0)){
|
||||
Write-Output "Location not found"
|
||||
$installPath="C:\android-platform-tools"
|
||||
}
|
||||
}
|
||||
Write-Output "installPath=$installPath"
|
||||
|
||||
if(!$adb -and !$fastboot){
|
||||
Write-Output "Adding $installPath to `$PATH ..."
|
||||
$oldpath = (Get-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH).path
|
||||
$newpath = "$oldpath;$installPath"
|
||||
Set-ItemProperty -Path 'Registry::HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\Environment' -Name PATH -Value $newPath
|
||||
}
|
||||
|
||||
Write-Output "Downloading platform-tools-latest-windows.zip to $env:temp ..."
|
||||
Import-Module BitsTransfer
|
||||
Start-BitsTransfer -Source "https://dl.google.com/android/repository/platform-tools-latest-windows.zip" -Destination "$env:temp\platform-tools-latest-windows.zip"
|
||||
Write-Output "Extracting $env:temp\platform-tools-latest-windows.zip to $installPath ..."
|
||||
Expand-Archive -Path "$env:temp\platform-tools-latest-windows.zip" -DestinationPath "$installPath" -Force
|
||||
Write-Output "Done!"
|
||||
Read-Host -Prompt "Press Enter to continue"
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,8 +0,0 @@
|
||||
;!@Install@!UTF-8!
|
||||
RunProgram="powershell -executionpolicy bypass -file %%T\install.ps1"
|
||||
;Config file generated by 7z SFX Builder v2.1. (http://sourceforge.net/projects/s-zipsfxbuilder/)
|
||||
;!@InstallEnd@!
|
||||
7zSFXBuilder_7zArchive=C:\Users\Josef\Documents\ADB-Installer\install.7z
|
||||
7zSFXBuilder_SFXIcon=C:\Users\Josef\Documents\ADB-Installer\adb.ico
|
||||
7zSFXBuilder_UseDefMod=7zsd_All_x64
|
||||
7zSFXBuilder_UPXCommands=--best --all-methods
|
||||
+141
@@ -0,0 +1,141 @@
|
||||
import std.path, std.process, std.algorithm.searching, std.stdio;
|
||||
|
||||
private string APPEND;
|
||||
bool userMode;
|
||||
version (Windows) string HOME = "HOMEPATH";
|
||||
version (Posix) string HOME = "HOME";
|
||||
enum LogLevel {
|
||||
SILENT,
|
||||
silent = SILENT,
|
||||
s = SILENT,
|
||||
ERROR,
|
||||
error = ERROR,
|
||||
e = ERROR,
|
||||
INFO,
|
||||
info = INFO,
|
||||
i = INFO,
|
||||
VERBOSE,
|
||||
verbose = VERBOSE,
|
||||
v = VERBOSE
|
||||
}
|
||||
|
||||
alias SILENT = LogLevel.SILENT;
|
||||
alias ERROR = LogLevel.ERROR;
|
||||
alias INFO = LogLevel.INFO;
|
||||
alias VERBOSE = LogLevel.VERBOSE;
|
||||
LogLevel logLevel = INFO;
|
||||
|
||||
void function(string message, int messageMode = INFO) log;
|
||||
|
||||
private string append() {
|
||||
if (!APPEND)
|
||||
APPEND = buildNormalizedPath("Android", "SDK", "platform-tools");
|
||||
return APPEND;
|
||||
}
|
||||
|
||||
string defaultUserDir() {
|
||||
version (Windows) string dir = "C:/" ~ environment.get(HOME) ~ "/AppData/Local";
|
||||
version (linux) string dir = "~";
|
||||
version (OSX) string dir = "~/Library";
|
||||
return buildNormalizedPath(dir.expandTilde, append);
|
||||
}
|
||||
|
||||
string defaultAllUsersDir() {
|
||||
version (Windows) string dir = "C:/Program Files";
|
||||
version (linux) string dir = "/opt";
|
||||
version (OSX) string dir = "/Library";
|
||||
return buildNormalizedPath(dir, append);
|
||||
}
|
||||
|
||||
bool isUserDir(string installDir) {
|
||||
return installDir.canFind(environment.get(HOME));
|
||||
}
|
||||
|
||||
void installTools(string installDir) {
|
||||
import std.zip, std.file, std.net.curl, std.conv;
|
||||
|
||||
version (Windows) string url = "https://dl.google.com/android/repository/platform-tools-latest-windows.zip";
|
||||
version (OSX) string url = "https://dl.google.com/android/repository/platform-tools-latest-darwin.zip";
|
||||
version (linux) string url = "https://dl.google.com/android/repository/platform-tools-latest-linux.zip";
|
||||
|
||||
log("Downloading");
|
||||
log(url, VERBOSE);
|
||||
|
||||
ubyte[] data;
|
||||
auto http = HTTP(url);
|
||||
http.onReceive = (ubyte[] response) {
|
||||
data ~= response;
|
||||
return response.length;
|
||||
};
|
||||
http.perform();
|
||||
|
||||
log("Extracting");
|
||||
log(installDir, VERBOSE);
|
||||
|
||||
auto zip = new ZipArchive(data);
|
||||
foreach (zipEntry; zip.directory) {
|
||||
auto extractPath = buildNormalizedPath(installDir, zipEntry.name[15 .. $]);
|
||||
if (zipEntry.compressedSize != 0) {
|
||||
log(zipEntry.name, VERBOSE);
|
||||
if (extractPath.exists && extractPath.isDir) {
|
||||
rmdirRecurse(extractPath);
|
||||
} else if (!extractPath.dirName.exists)
|
||||
mkdirRecurse(extractPath.dirName);
|
||||
zip.expand(zipEntry);
|
||||
extractPath.write(zipEntry.expandedData);
|
||||
version (Posix)
|
||||
setAttributes(extractPath, octal!775);
|
||||
} else {
|
||||
if (extractPath.exists) {
|
||||
if (extractPath.isFile) {
|
||||
extractPath.remove();
|
||||
extractPath.mkdir();
|
||||
}
|
||||
} else
|
||||
extractPath.mkdirRecurse();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void installPath(string installDir) {
|
||||
import std.process : environment;
|
||||
|
||||
log("Adding to PATH");
|
||||
string path = environment.get("PATH");
|
||||
if (path.canFind(installDir)) {
|
||||
log("Install folder is already in PATH");
|
||||
return;
|
||||
}
|
||||
|
||||
version (Windows) {
|
||||
import std.windows.registry : Registry, Key, REGSAM;
|
||||
|
||||
Key env;
|
||||
if (userMode) {
|
||||
env = Registry.currentUser.getKey("Environment", REGSAM.KEY_ALL_ACCESS);
|
||||
} else {
|
||||
env = Registry.localMachine.getKey("SYSTEM").getKey("CurrentControlSet").getKey("Control")
|
||||
.getKey("Session Manager").getKey("Environment", REGSAM.KEY_ALL_ACCESS);
|
||||
}
|
||||
path = env.getValue("Path").value_SZ;
|
||||
path ~= pathSeparator ~ installDir;
|
||||
env.setValue("Path", path);
|
||||
//import core.sys.windows.winuser; SendNotifyMessageW(HWND_BROADCAST,WM_SETTINGCHANGE,cast(ulong)null,cast(long)"Environment");
|
||||
} else {
|
||||
import std.file : exists,append,write;
|
||||
|
||||
string profile;
|
||||
string installProfile = "\nexport PATH=$PATH" ~ pathSeparator ~ installDir;
|
||||
if (userMode)
|
||||
profile = "~/.profile".expandTilde;
|
||||
else
|
||||
profile = "/etc/profile";
|
||||
if (profile.exists)
|
||||
append(profile, installProfile);
|
||||
else {
|
||||
write(profile, installProfile);
|
||||
}
|
||||
}
|
||||
|
||||
log("logout or reboot to finish install");
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
import adbi, std.getopt;
|
||||
|
||||
private void log(string message, int messageMode = INFO) {
|
||||
if (logLevel < messageMode)
|
||||
return;
|
||||
if (messageMode == ERROR) {
|
||||
import std.stdio : stderr;
|
||||
|
||||
stderr.writeln(message);
|
||||
} else {
|
||||
import std.stdio : writeln;
|
||||
|
||||
writeln(message);
|
||||
}
|
||||
}
|
||||
|
||||
void main(string[] args) {
|
||||
adbi.log = &cli.log;
|
||||
string installDir;
|
||||
try {
|
||||
auto xargs = getopt(args,
|
||||
"user-mode|u", "Install for current user only instead of all users.", &userMode,
|
||||
"install-dir|i", "Path to install folder.", &installDir,
|
||||
"log-level|l", "silent, error, info, or verbose", &logLevel);
|
||||
if (xargs.helpWanted) {
|
||||
defaultGetoptPrinter("Install Android Platform Tools", xargs.options);
|
||||
return;
|
||||
}
|
||||
if (!installDir) {
|
||||
if (userMode)
|
||||
installDir = defaultUserDir;
|
||||
else
|
||||
installDir = defaultAllUsersDir;
|
||||
} else if (installDir.isUserDir)
|
||||
userMode = true;
|
||||
installTools(installDir);
|
||||
installPath(installDir);
|
||||
} catch (Exception e) {
|
||||
log(cast(string) e.message, ERROR);
|
||||
}
|
||||
}
|
||||
+182
@@ -0,0 +1,182 @@
|
||||
import tkd.tkdapplication, tkd.widget.widget;
|
||||
import adbi;
|
||||
import std.concurrency, std.parallelism, std.process, std.file, std.regex,
|
||||
std.path, std.string, std.algorithm.searching, std.stdio, std.uni;
|
||||
import core.time;
|
||||
|
||||
string[] skip = ["temp"];
|
||||
|
||||
Widget packPreset(Widget w) {
|
||||
return w.pack(0, 0, GeometrySide.top, GeometryFill.both, AnchorPosition.center, true);
|
||||
}
|
||||
|
||||
bool isWriteable(DirEntry d) {
|
||||
try
|
||||
File(d.name, "a").close();
|
||||
catch (Exception e)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool isInstallable(DirEntry d) {
|
||||
if (!d.isWriteable)
|
||||
return false;
|
||||
foreach (s; skip) {
|
||||
if (d.name.toLower.canFind(s)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
class Application : TkdApplication {
|
||||
|
||||
private Label instructionLabel;
|
||||
private Label statusLabel;
|
||||
private Tid searchThread;
|
||||
|
||||
enum {
|
||||
STATUS = LogLevel.max + 1,
|
||||
INSTRUCT,
|
||||
OPTION,
|
||||
KILL
|
||||
}
|
||||
|
||||
static void search() {
|
||||
version (Windows) {
|
||||
skip ~= "recycle.bin";
|
||||
string regex = "(.*)(\\\\)(adb.exe|fastboot.exe)($)";
|
||||
string[] dirs = [
|
||||
"C:\\Program Files", "C:\\Program Files (x86)",
|
||||
"C:" ~ environment.get("HOMEPATH"), "C:\\"
|
||||
];
|
||||
} else
|
||||
string regex = "(.*)(\\/)(adb|fastboot)($)";
|
||||
version (linux) string[] dirs = ["/usr", "/opt"];
|
||||
version (OSX) string[] dirs = ["/Library", "/Applications"];
|
||||
version (Posix) {
|
||||
dirs ~= ["~".expandTilde, "/"];
|
||||
}
|
||||
adbi.log = &Application.log;
|
||||
string[] results;
|
||||
void search(DirEntry dir) {
|
||||
try {
|
||||
foreach (DirEntry d; dirEntries(dir.name, SpanMode.shallow)) {
|
||||
receiveTimeout(seconds(-1), delegate(int i) {
|
||||
if (i != KILL) {
|
||||
log("Unsupported signal received by search thread", ERROR);
|
||||
return;
|
||||
} else
|
||||
return;
|
||||
});
|
||||
if (d.isDir)
|
||||
search(d);
|
||||
else if (d.name.matchFirst(regex)) {
|
||||
string s = d.name.dirName.strip;
|
||||
if (!results.canFind(s) && d.isInstallable) {
|
||||
results ~= s;
|
||||
log(s, OPTION);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log(cast(string) e.message, ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
log("Searching for install locations");
|
||||
log(defaultAllUsersDir, OPTION);
|
||||
log(defaultUserDir, OPTION);
|
||||
log("Select install location", INSTRUCT);
|
||||
results ~= [defaultAllUsersDir, defaultUserDir, ""];
|
||||
foreach (string dir; dirs) {
|
||||
search(DirEntry(dir));
|
||||
}
|
||||
log("Search done");
|
||||
}
|
||||
|
||||
static void log(string message, int messageMode = INFO) {
|
||||
ownerTid.send(messageMode);
|
||||
ownerTid.send(message);
|
||||
}
|
||||
|
||||
int mode;
|
||||
|
||||
private void receiveInt(int i) {
|
||||
mode = i;
|
||||
}
|
||||
|
||||
static void install(string dir) {
|
||||
adbi.log = &Application.log;
|
||||
if (dir.isUserDir)
|
||||
adbi.userMode = true;
|
||||
try {
|
||||
log("Please Wait", INSTRUCT);
|
||||
adbi.installTools(dir);
|
||||
adbi.installPath(dir);
|
||||
log("You can close this window", INSTRUCT);
|
||||
} catch (immutable Exception e) {
|
||||
ownerTid.send(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void receiveString(string message) {
|
||||
switch (mode) {
|
||||
case INFO:
|
||||
case STATUS:
|
||||
statusLabel.setText(message);
|
||||
break;
|
||||
case INSTRUCT:
|
||||
instructionLabel.setText(message);
|
||||
break;
|
||||
case OPTION:
|
||||
new Button(message).setCommand(delegate(CommandArgs args) {
|
||||
spawn(&install, message);
|
||||
}).packPreset();
|
||||
break;
|
||||
case ERROR:
|
||||
import std.stdio;
|
||||
|
||||
stderr.writeln(message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
mode = INFO;
|
||||
}
|
||||
|
||||
private void receiveException(immutable Exception e) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
private void idleCommand(CommandArgs args) {
|
||||
this.mainWindow.setIdleCommand(&idleCommand);
|
||||
receiveTimeout(seconds(-1), &receiveString, &receiveInt, &receiveException);
|
||||
}
|
||||
|
||||
private void exitCommand(CommandArgs args) {
|
||||
this.exit();
|
||||
}
|
||||
|
||||
private void directoryDialog(CommandArgs args) {
|
||||
string dir = new DirectoryDialog().show().getResult();
|
||||
if (dir.isDir)
|
||||
spawn(&install, dir);
|
||||
}
|
||||
|
||||
override protected void initInterface() {
|
||||
this.mainWindow.setMinSize(300, 0);
|
||||
instructionLabel = new Label("Please wait").pack();
|
||||
statusLabel = new Label("Loading").pack();
|
||||
new Button("Manually select folder").setCommand(&directoryDialog).packPreset();
|
||||
this.mainWindow.setIdleCommand(&idleCommand);
|
||||
this.mainWindow.setProtocolCommand(WindowProtocol.deleteWindow, &exitCommand);
|
||||
searchThread = spawn(&search);
|
||||
}
|
||||
}
|
||||
|
||||
void main() {
|
||||
adbi.log = &Application.log;
|
||||
auto app = new Application();
|
||||
app.run();
|
||||
}
|
||||
Reference in New Issue
Block a user