We're using a parser program (which I have no access to) that parses a bunch of computer generated mails but needs some help to decide on what it has to do in particular. Because of that, an employee kann use the subject line for additional commands. Since there are more than 500 mails per day that we feed to the program and the commands do all look similar to that: Ba,Vi;#TD*; x0003, it's impossible to write them manually. So I wrote a small C# script that creates an Autohotkey script which does 90% of the work. In theory. It works but only as long as I don't use any special characters, like , : & % etc.
I tried:
clipboard := Ba{,}Vi{;}{#}TD{*}{;} x0003
clipboard := "Ba,Vi;#TD*; x0003"
clipboard := Ba',Vi';'#TD'*'; x0003
clipboard := {raw} Ba,Vi;#TD*; x0003
(plus some others that I probably forgot here)
Here's the entire AHK script with annotations. You start it while having an email selected in Outlook:
;Win+z -> start script
#z::
;Currently only one iteration
loop,1
{
;CTRL+F to forward selected mail,
;which then automatically selects the "To:" line
Send, {CTRLDOWN}f{CTRUP}
Sleep, 500
Send, someemail#adress
Sleep, 500
;Initialize GUI
Gui, +AlwaysOnTop
Gui, Font, S5, Verdana, bold
Gui, Add, Text,, SCANNING-BOOSTER:
Gui, Color, F4A460
;Example for the C# generated buttons below (they all do the same thing):
;Clicking the Button "Google" will run the following script
;Start:
;clipboard := www.Google.com
;return
;This is the part where AHK fails because instead
;of www.Google.com I have codes like "Ba,Vi;#TD*; x0003" which crash AHK
Gui,add,Button,gLabel,Google
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
Gui,add,Button, ......
..... (around 60 more auto-generated buttons)
Gui,show
Return
Label:
;run the script that has the same name as the Button
;in this case it would be Google.ahk
Run, % A_GuiControl ".ahk"
GuiClose:
Gui, Hide
Sleep, 1000
;after the user has pressed a button and the according code
;has been copied to the clipboard, the GUI closes, the
;mail window becomes active again and we can continue to paste
;the code into the subject line
;Go to subject line
Send, {ALTDOWN}r{ALTUP}
Sleep, 500
;CTRL+a
Send, {CTRLDOWN}a{CTRUP}
Sleep, 500
;Write text from your clipboard to the subject line
Send, %clipboard%
Sleep, 500
return
}
Apparently it's currently not possible to copy a (more or less) random string to your clipboard in Autohotkey and then paste it somewhere else without receiving so many errors that it's worth pursuing it. I was left with no choice other than programming everything myself in C#. Here's how I did it:
First, start a new Console Application and then change it to a Windows Application How to change a console application to a windows form application?
This is the easiest way to make a program completely invisible to the user.
Next, we need a key listener. Here's the one I used: https://blogs.msdn.microsoft.com/toub/2006/05/03/low-level-keyboard-hook-in-c/
I would advise you to put it in a new class. This code needs to be slightly altered anyway because it prints every key press to the console. We don't want that, we want to call a method from it. Change HookCallback to:
private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam)
{
if (nCode >= 0 && wParam == (IntPtr)WM_KEYDOWN)
{
int vkCode = Marshal.ReadInt32(lParam);
if (KeyPressed == vkCode)
DoWork();
}
return CallNextHookEx(_HookID, nCode, wParam, lParam);
}
For the code above to work, we need to add a new delegate and a new int variable to our class:
private static int KeyPressed;
public delegate void SomethingToDo();
private static SomethingToDo DoWork;
SetHook also needs some minor alterations:
private static IntPtr SetHook(KeyboardProc _proc, int KeyCode, SomethingToDo GiveMeWork)
{
DoWork = GiveMeWork;
KeyPressed = KeyCode;
...(leave the rest as it is)...
}
The program is now completely invisible and can react to a key press. Let's do the opposite, simulating keys!
Ctrl key kept down after simulating a ctrl key down event and ctrl key up event
This is a lot simpler. I made three methods, PressKey, ReleaseKey and TapKey. Keep in mind that ALT and F10 are special system keys which might not work.
[DllImport("user32.dll", SetLastError = true)]
static extern void keybd_event(byte bVk, byte bScan, int dwFlags, int dwExtraInfo);
private const int KeyPressCode = 0x0001;
private const int KeyReleaseCode = 0x0002;
public static void PressKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | 0, 0);
Thread.Sleep(10);
}
public static void ReleaseKey(System.Windows.Forms.Keys Key)
{
keybd_event((byte)Key, 0, KeyPressCode | KeyReleaseCode, 0);
Thread.Sleep(10);
}
public static void TapKey(System.Windows.Forms.Keys Key)
{
PressKey(Key);
ReleaseKey(Key);
}
That's it, a basic Autohokey-Clone that can cope with strings. If you want to go even further and make a try icon for it:
https://translate.google.de/translate?sl=de&tl=en&js=y&prev=_t&hl=de&ie=UTF-8&u=https%3A%2F%2Fdotnet-snippets.de%2Fsnippet%2Fvorlage-fuer-tray-notifyicon-anwendung%2F541&edit-text=&act=url
Showing a GUI with buttons is also surprisingly simple:
using (Form _form = new Form())
{
_form.size = ...
//....
Button MyButton = new Button();
//....
//closing is also pretty simple, just like your everyday Windows Forms Application:
MyButton.Click += new EventHandler((sender, e) => { Application.Exit(); });
_form.ShowDialog();
}
Putting everything together in the main method:
private static NotifyIcon TrayIcon = new NotifyIcon();
[STAThread]
static void Main(string[] args)
{
bool WindowOpen = true;
try
{
//Make a new method above or below Main() and replace DoSomething with it.
//It will be executed everytime the F2 key is pressed.
KeyListener._HookID = KeyListener.SetHook(proc, System.Windows.Forms.Keys.F2, DoSomething);
System.Windows.Forms.ContextMenu SmallMenu = new System.Windows.Forms.ContextMenu();
System.Windows.Forms.MenuItem MenuElement;
int MenuIndex = 0;
MenuElement = new System.Windows.Forms.MenuItem();
MenuElement.Index = ++MenuIndex;
MenuElement.Text = "Close";
MenuElement.Click += new EventHandler((sender, e) => { WindowOpen = false; System.Windows.Forms.Application.Exit(); });
SmallMenu.MenuItems.Add(MenuElement);
TrayIcon.Icon = new System.Drawing.Icon("Ghost.ico");
TrayIcon.Text = "String Compatible AHK";
TrayIcon.Visible = true;
TrayIcon.ContextMenu = SmallMenu;
while (WindowOpen)
System.Windows.Forms.Application.Run();
}
finally
{
TrayIcon.Dispose();
KeyListener.UnhookWindowsHookEx(KeyListener._HookID);
}
}
I installed Android Studio yesterday, and I tried to use the LogCat to see the logs. But there is nothing to show in the logcat. I used the terminal to run ./adb logcat and it works.
Is there someone who can explain to me how to use logcat in Android Studio?
Restarting logcat helps me always.
I get into this state often. Logcat is blank. Debugging works, I can hit breakpoints. No filters are set. Log level is on Verbose. I fix it by repeatedly looping through the following:
Restart logcat (see Zatziky's answer above)
Change the log level to Debug (or anything else) and back to Verbose.
unplugging and plugging back in the device
running adb kill-server && adb start-server
Close Android Studio and launch ddms on the command line.
Restart Android Studio
And finally restarting the computer if all else fails.
The problem is intermittent, I think Android Studio is just buggy.
I had the same problem but I solved by the following steps, Try this once.
1) In the android studio.
2) Open android Monitor window(bottom of android studio)
3) You can see the drop down in the right corner(spinner)
4) select -- Show only Selected application.
You need to press Alt+6 twice to restart the logcat window. That way it'll show the log outputs.
The problem mainly happens in debug mode.
Best way to fix some unnecessary changes is to invalidate caches
Go to FILE -> click "INVALIDATE CACHES/RESTART" then a dialog box will pop-up,
Select "INVALIDATE CACHES/RESTART" button.
Android studio will automatically restart and rebuild the index.
These helped me :
1.Enable ADB integration
2. Go to Android Device Monitor
Check if your device is online and Create a required filter
Run this command in terminal. It will start working again.
adb kill-server && adb start-server
Restarting Android Studio helped me.
In android Studio application you need to click Debug application option (Shift+f9) to run in debug mode and to enable LogCat.
Not a technical answer but you might want to check the search box for the logcat. If there is any character inputted, your logcat will be empty as it will be searching for that certain character or word, and then if its not present, your logcat log will be totally empty.
Make sure you have Logger buffer sizes propper value in your emulator developer menu option.
For me, the issue was that I had two emulators with the same name (I created it, deleted it, and then created it again with the same name). There were two emulator entries in the logcat dropdown and it was connected to the wrong one. All I had to do was switch to the other one. I prevented the problem permanently by renaming the emulator.
**
Read this if you are still stuck with logcat being empty
**
I've just solved this after MONTHS of annoyment and trouble.
Nothing helped, the device monitor worked fine during debugging but the standard logcat view was always empty.
The reason was annoyingly simple:
The logcat view was there but it had been moved to 0 width by an update!
You are in "ALT 6" Tab, you see two tabs in there "ADB logs" and "Devices | logcat"
Devices | logcat really means that it consists of Devices AND logcat, split by a vertical border.
The vertical border can be moved and during an update it seems to have moved to 100% right.
This results in the logcat to be collected but not displayed, move your mouse pointer to the right of the tool window and just DRAG logcat back into view.
This solution won't help everyone but I found many people with working ADB connection and still no logcat output, those might be hit by the same problem.
Try to close the project and re-open it .It worked for me. Logs will be reappear.
In my case, I removed "image" from the little dropdown on the right. It showed up just fine after that. That's because it will be searching the log for the keyword in that searchbox, so if it doesn't find any matches, it returns blank
It's weird to still encounter this problem even on a recent version of Android Studio. I read through the long list of solutions but they did not work for me.
The accepted answer worked on an earlier version of Android Studio ( I guess it was v2.3)
I did the following to get Logcat working again:
Logcat > Show only selected application > No filters
Logcat > No filters > Show only selected application
I expected resetting logcat should ideally give me the same effect but it didn't. Manually toggling filter was the only thing that worked.
This is on Android Studio 3.0.1 (stable) (I can't update it before finishing the current project)
The issue occurred when I started Android studio in the morning to continue the work I left at night. I hope the devs will look into this. It was painstaking to try over 15 solutions from stackoverflow and still see no result. It's even irritating to reveal another solution for future victims of this issue.
When everything else didn't work, here's what I did. Since adb logcat worked nicely, I decided to rely on it. Running adb logcat -v color in the Android Studio's embedded terminal produced outputs similar to the normal logcat, and allowed code links to work too:
But this came with a few issues:
You can't specify a package to watch. Using the --pid=<your PID> option, you can watch the output of a single process. But since every time you restart your app the PID changes, you have re-run this command with every restart.
The colors are annoying (in my opinion).
The output fields are not aligned with previous messages, the whole thing is not well formatted which makes following the logcat much harder than it should be (the same happens with the embedded logcat, though).
So I decided to make my own tool to automatically watch my package PID(s) and prettify the logcat output:
import java.awt.AWTException;
import java.io.*;
import java.util.ArrayList;
import java.awt.Robot;
import java.awt.event.KeyEvent;
public class Logcat {
private static final String ADB_FILE_PATH = "adb";
// Customizations,
private static final Color V_COLOR = Color.RESET;
private static final Color D_COLOR = Color.RESET;
private static final Color I_COLOR = Color.RESET;
private static final Color W_COLOR = Color.BLUE;
private static final Color E_COLOR = Color.RED_BRIGHT;
private static final Color HINT_COLOR = Color.MAGENTA_BOLD_BRIGHT;
private static final Color OTHER_COLOR = Color.GREEN_BOLD_BRIGHT;
private static final int DATE_LENGTH = 5;
private static final int TIME_LENGTH = 12;
private static final int PROCESS_ID_LENGTH = 5;
private static final int THREAD_ID_LENGTH = 5;
private static final int LOG_LEVEL_LENGTH = 1;
private static final int TAG_LENGTH = 20;
private static final int MESSAGE_LENGTH = 110;
private static final String SEPARATOR = " | ";
private static final String CONTINUATION = "→";
private static final String INDENTATION = " ";
private static final int PROCESS_IDS_UPDATE_INTERVAL_MILLIS = 1224;
private static final int HISTORY_LENGTH = 1000;
// State,
private static boolean skipProcessIDCheck;
private static ArrayList<String> processIDs = new ArrayList<String>();
private static String logLevelToShow="V"; // All.
private static Process logcatProcess;
private static boolean appClosed;
private static boolean stopEverything;
private static String[] history = new String[HISTORY_LENGTH];
private static int currentLocationInHistory, historyLength;
public static void main(final String args[]) {
clearAndroidStudioConsole();
System.out.println("besm Allah");
// Get processes ids of the provided package,
if (args.length==0) {
skipProcessIDCheck = true;
} else {
skipProcessIDCheck = false;
getProcessIDs (args[0]); // Do it once before we start.
monitorProcessIDs(args[0]); // Do it periodically from now on.
}
// Start capturing and prettifying logcat,
if (!monitorLogcat()) {
stopEverything = true;
return;
}
// Handle user input,
handleUserInput();
}
private static void watch(final Process process, final ProcessListener listener) {
// Read process standard output and send it to the listener line by line,
new Thread() {
public void run() {
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
String line = "";
try {
do {
if (bufferedReader.ready()) {
line = bufferedReader.readLine();
if (line!=null && !line.isEmpty()) listener.onNewLine(line);
} else {
Thread.sleep(100);
}
} while (line!=null && !stopEverything);
} catch (Exception e) { e.printStackTrace(); }
}
}.start();
}
private static void monitorProcessIDs(String packageName) {
// Continuously monitor the process IDs of this package and update when changed,
new Thread() {
public void run() {
do {
try { Thread.sleep(PROCESS_IDS_UPDATE_INTERVAL_MILLIS); } catch (InterruptedException e) {}
getProcessIDs(packageName);
} while (!stopEverything);
}
}.start();
}
private static void getProcessIDs(String packageName) {
// Get the process IDs associated with this package once,
ArrayList<String> newProcessIDs = new ArrayList<String>();
Runtime runtime = Runtime.getRuntime();
try {
Process getPIDProcess = runtime.exec(ADB_FILE_PATH + " shell ps");
watch(getPIDProcess, (line) -> {
if (line.contains(packageName)) {
newProcessIDs.add(removeRedundantSpaces(line).split(" ")[1]);
}
});
getPIDProcess.waitFor();
Thread.sleep(500); // Make sure we've already handled all the input from the process.
} catch (Exception e) { e.printStackTrace(); }
// Return immediately if program is closed,
if (stopEverything) return ;
// Some action upon getting the pid(s),
boolean shouldRepeatHistory = false;
if (newProcessIDs.isEmpty()) {
// Just closed,
if (!appClosed) {
appClosed = true;
prettify("----- App closed -----");
}
} else if (appClosed) {
// Just opened, clear,
appClosed = false;
clearAndroidStudioConsole();
prettify("----- App opened -----");
shouldRepeatHistory = true;
} else {
// Detect changes in processes,
for (String pid : newProcessIDs) {
if (!processIDs.contains(pid)) {
clearAndroidStudioConsole();
prettify("----- Process(es) changed (or app restarted - some logs could have been missed) -----");
shouldRepeatHistory = true;
break ;
}
}
}
// Set the new PID(s),
processIDs = newProcessIDs;
if (shouldRepeatHistory) repeatHistory();
}
private static boolean monitorLogcat() {
Runtime runtime = Runtime.getRuntime();
try {
logcatProcess = runtime.exec(ADB_FILE_PATH + " logcat -v threadtime");
watch(logcatProcess, (line) -> {
// Learn history, in case we need to repeat it,
if (appClosed || processLogcatLine(line)) {
history[currentLocationInHistory] = line;
currentLocationInHistory = (currentLocationInHistory + 1) % history.length;
if (historyLength<history.length) historyLength++;
}
});
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private static boolean processLogcatLine(String line) {
try {
return prettify(line);
} catch (Exception e) {
print(line, OTHER_COLOR);
System.out.println();
// Debug,
e.printStackTrace();
return true;
}
}
// Returns true if line should be kept in history,
private static synchronized boolean prettify(String line) {
if (line.startsWith("-")) {
// It's a "beginning of <something>" line,
print(line, HINT_COLOR);
System.out.println();
return true;
}
// Get the individual fields,
String date = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String time = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String processID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
// Break early if possible,
if (!skipProcessIDCheck && !processIDs.contains(processID.trim())) return false;
// Continue parsing,
String threadID = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
String logLevel = line.substring(0, line.indexOf(' ')); line = line.substring(line.indexOf(' ')+1); line = line.trim();
// Break early if possible,
switch (logLevel) {
case "V": if (!"V" .contains(logLevelToShow)) return true; break;
case "D": if (!"VD" .contains(logLevelToShow)) return true; break;
case "I": if (!"VDI" .contains(logLevelToShow)) return true; break;
case "W": if (!"VDIW" .contains(logLevelToShow)) return true; break;
case "E": if (!"VDIWE".contains(logLevelToShow)) return true; break;
}
// Continue parsing,
String tag = line.substring(0, line.indexOf(':')); line = line.substring(line.indexOf(':')+1); line = line.trim();
// Because some tags have a trailing ":",
if (line.startsWith(":")) {
tag += ":";
line = line.substring(1);
}
// Indent lines starting by "at",
String indentation = "";
if (line.startsWith("at ")) {
indentation = " " + INDENTATION;
line = " " + INDENTATION + line;
}
// Print the prettified log,
Color color;
switch (logLevel) {
case "V": color = V_COLOR; break;
case "D": color = D_COLOR; break;
case "I": color = I_COLOR; break;
case "W": color = W_COLOR; break;
case "E": color = E_COLOR; break;
default:
color = Color.RESET;
}
String fields = adjustLength( date, DATE_LENGTH) + SEPARATOR +
adjustLength( time, TIME_LENGTH) + SEPARATOR +
adjustLength(processID, PROCESS_ID_LENGTH) + SEPARATOR +
adjustLength( threadID, THREAD_ID_LENGTH) + SEPARATOR +
adjustLength( logLevel, LOG_LEVEL_LENGTH) + SEPARATOR +
adjustLength( tag, TAG_LENGTH) + SEPARATOR;
// Split the message onto multiple lines if needed,
String message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2);
print(fields + message, color);
System.out.println();
while (line.length() > message.length()) {
// Debug,
//print(line, OTHER_COLOR);
//System.out.println("Line: " + line.length() + "length: " + message.length() + ", cont: " + CONTINUATION.length() + "dent: " + indentation.length());
//System.out.println();
// Remove the already printed part.
line = line.substring(message.length()-CONTINUATION.length());
// Add a dot to make links work,
boolean shouldAddDot=false;
if (line.matches("^[^\\.]*\\(.*:[123456789][1234567890]*\\).*")) shouldAddDot = true;
// Indent,
line = (shouldAddDot ? "." : (indentation.isEmpty() ? "" : " ")) + indentation + line;
// Take another chunk,
message = chunkPreservingParentheses(line, MESSAGE_LENGTH, 2+indentation.length());
// Front pad to align this part with the message body,
String paddedMessage = message;
for (int i=0; i<fields.length(); i++) paddedMessage = ' ' + paddedMessage;
// Print,
print(paddedMessage, color);
System.out.println();
}
return true; // Keep in local buffer.
}
private static String adjustLength(String text, int length) {
while (text.length() < length) text += ' ';
if (text.length() > length) {
text = text.substring(0, length-CONTINUATION.length());
text += CONTINUATION;
}
return text;
}
private static String chunkPreservingParentheses(String text, int length, int minChunckLength) {
if (text.length() <= length) return text;
// Take a chunk out of the text,
String chunk = text.substring(0, length-CONTINUATION.length()) + CONTINUATION;
// Check if a paranthesis was opened and not closed,
int lastOpenParanthesisIndex = chunk.lastIndexOf('(');
int lastCloseParanthesisIndex = chunk.lastIndexOf(')');
if (lastCloseParanthesisIndex <= lastOpenParanthesisIndex) { // Also works when either is not found.
if (minChunckLength<1) minChunckLength = 1;
if (lastOpenParanthesisIndex > minChunckLength+CONTINUATION.length()) { // Avoid endless loops.
int includeParenthesisSize = (CONTINUATION.length()>0) ? 1 : 0;
chunk = text.substring(0, lastOpenParanthesisIndex+includeParenthesisSize-CONTINUATION.length()) + CONTINUATION;
}
}
return chunk;
}
private static void repeatHistory() {
int index = currentLocationInHistory-historyLength;
if (index < 0) index += history.length;
for (int i=0; i<historyLength; i++) {
processLogcatLine(history[index]);
index = (index + 1) % history.length;
}
}
private static void print(String text, Color color) {
System.out.print(color);
System.out.print(text);
System.out.print(Color.RESET);
}
private static String removeRedundantSpaces(String text) {
String newText = text.replace(" ", " ");
while (!text.equals(newText)) {
text = newText;
newText = text.replace(" ", " ");
}
return text;
}
private static void clearAndroidStudioConsole() {
// Couldn't find a reliable way to clear Intellij terminal scrollback, so we just print
// a LOT of newlines,
StringBuilder bunchOfNewLines = new StringBuilder();
for (int i=0; i<124; i++) bunchOfNewLines.append(System.lineSeparator());
System.out.print(bunchOfNewLines);
// Scroll the current line to the top of the window,
try {
// If we are on Windows,
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
} catch (Exception e) {
// We are not on Windows,
bunchOfNewLines = new StringBuilder();
for (int i=0; i<124; i++) bunchOfNewLines.append("\b\r");
System.out.print(bunchOfNewLines);
}
}
private static void handleUserInput() {
// Line read. Unfortunately, java doesn't provide character by character reading out of the box.
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(System.in));
String input = "";
do {
try {
if (bufferedReader.ready()) {
input = input = bufferedReader.readLine().toUpperCase();
// Set log level,
if (input.equals("V")||input.equals("D")||input.equals("I")||input.equals("W")||input.equals("E")) {
if (!logLevelToShow.equals(input)) {
logLevelToShow = input;
clearAndroidStudioConsole();
repeatHistory();
}
prettify("----- Log level set to " + logLevelToShow + " -----");
} else if (input.equals("C")) {
// Clear screen and history,
clearAndroidStudioConsole();
historyLength = 0;
}
} else {
Thread.sleep(100);
}
} catch (Exception e) { e.printStackTrace(); }
// Check if the logcat process is still alive,
if (!logcatProcess.isAlive()) {
prettify("----- adb logcat process terminated -----");
stopEverything = true;
}
} while (!stopEverything && !input.equals("Q"));
// Allow all monitoring threads to exit,
stopEverything = true;
}
interface ProcessListener {
void onNewLine(String line);
}
enum Color {
// Thanks to this answer: https://stackoverflow.com/a/51944613/1942069
//Color end string, color reset
RESET("\033[0m"),
// Regular Colors. Normal color, no bold, background color etc.
BLACK ("\033[0;30m"),
RED ("\033[0;31m"),
GREEN ("\033[0;32m"),
YELLOW ("\033[0;33m"),
BLUE ("\033[0;34m"),
MAGENTA("\033[0;35m"),
CYAN ("\033[0;36m"),
WHITE ("\033[0;37m"),
// Bold
BLACK_BOLD ("\033[1;30m"),
RED_BOLD ("\033[1;31m"),
GREEN_BOLD ("\033[1;32m"),
YELLOW_BOLD ("\033[1;33m"),
BLUE_BOLD ("\033[1;34m"),
MAGENTA_BOLD("\033[1;35m"),
CYAN_BOLD ("\033[1;36m"),
WHITE_BOLD ("\033[1;37m"),
// Underline
BLACK_UNDERLINED ("\033[4;30m"),
RED_UNDERLINED ("\033[4;31m"),
GREEN_UNDERLINED ("\033[4;32m"),
YELLOW_UNDERLINED ("\033[4;33m"),
BLUE_UNDERLINED ("\033[4;34m"),
MAGENTA_UNDERLINED("\033[4;35m"),
CYAN_UNDERLINED ("\033[4;36m"),
WHITE_UNDERLINED ("\033[4;37m"),
// Background
BLACK_BACKGROUND ("\033[40m"),
RED_BACKGROUND ("\033[41m"),
GREEN_BACKGROUND ("\033[42m"),
YELLOW_BACKGROUND ("\033[43m"),
BLUE_BACKGROUND ("\033[44m"),
MAGENTA_BACKGROUND("\033[45m"),
CYAN_BACKGROUND ("\033[46m"),
WHITE_BACKGROUND ("\033[47m"),
// High Intensity
BLACK_BRIGHT ("\033[0;90m"),
RED_BRIGHT ("\033[0;91m"),
GREEN_BRIGHT ("\033[0;92m"),
YELLOW_BRIGHT ("\033[0;93m"),
BLUE_BRIGHT ("\033[0;94m"),
MAGENTA_BRIGHT("\033[0;95m"),
CYAN_BRIGHT ("\033[0;96m"),
WHITE_BRIGHT ("\033[0;97m"),
// Bold High Intensity
BLACK_BOLD_BRIGHT ("\033[1;90m"),
RED_BOLD_BRIGHT ("\033[1;91m"),
GREEN_BOLD_BRIGHT ("\033[1;92m"),
YELLOW_BOLD_BRIGHT ("\033[1;93m"),
BLUE_BOLD_BRIGHT ("\033[1;94m"),
MAGENTA_BOLD_BRIGHT("\033[1;95m"),
CYAN_BOLD_BRIGHT ("\033[1;96m"),
WHITE_BOLD_BRIGHT ("\033[1;97m"),
// High Intensity backgrounds
BLACK_BACKGROUND_BRIGHT ("\033[0;100m"),
RED_BACKGROUND_BRIGHT ("\033[0;101m"),
GREEN_BACKGROUND_BRIGHT ("\033[0;102m"),
YELLOW_BACKGROUND_BRIGHT ("\033[0;103m"),
BLUE_BACKGROUND_BRIGHT ("\033[0;104m"),
MAGENTA_BACKGROUND_BRIGHT("\033[0;105m"),
CYAN_BACKGROUND_BRIGHT ("\033[0;106m"),
WHITE_BACKGROUND_BRIGHT ("\033[0;107m");
private final String code;
Color(String code) { this.code = code; }
#Override public String toString() { return code; }
}
}
Just dump this code into Logcat.java and compile using:
javac Logcat.java
And run inside the Android Studio's embedded terminal:
java Logcat <your.package.name>
For example:
java Logcat com.nomone.vr_desktop
The result looks like this:
It's highly customizable, I've separated most of the options in the first section of the app, so you can tweak the colors and formatting easily. If the adb tool is not in your PATH environment variable, just set its full path in the ADB_FILE_PATH variable (in the code) before compiling.
When the application is running, you can type the following shortcuts:
c to clear the screen and local buffer.
v, i, d, w, e to change the logcat level.
q to quit gracefully. Ctrl+c works too.
Unfortunately, you have to press enter after pressing these keys. Seems like Java doesn't allow single character input from console without writing system specific code. Sorry!
Disclaimer
This doesn't work if multiple devices are connected using adb.
I haven't thoroughly tested this. I've only used it for a while on a few devices.
I haven't tested this on Windows or Mac, but I tried to avoid using anything system specific, so it should still work.
I hope this solves your problem :)
In my case, in the developer options menu there is an option called
Revoke USB debugging authorisations.
Once you revoke all the existing authorisations it will ask again to trust the computer that you are using after that it started to show the logs again.
In Android 3.6.1 I had to:
Upgrade to latest Android Studio version (4.x.x)
Restart Logcat
Restart the app
Restart Android Studio
Restart the Android testing device
This may not be your issue, but I've found that when having multiple windows of Android Studio open, logcat is only directed to one of them, and not necessarily the one that's running an active application.
For example, Window 1 is where I'm developing a Tic-Tac-Toe app, and Window 2 is where I'm developing a weather app. If I run the weather app in debug mode, it's possible only Window 1 will be able to display logcat entries.
On the right side of tab "Devices logcat" there is the button "Show only Logcat from selected Process". Its not perfect, because everytime I run another process I need to push it again, but thats the only solution that works for me. So far...
For me, the problem was that the device was connected in the Charge only mode.
Changing the mode to Media device (MTP) (or Transfer files in some devices) solved the problem.
Step 1: Connect Your Phone with Android Developer option On and USB Debug On.
Step 2: Go TO View > Tools Window > Logcat
Step 3: Before Run Project Make Sure Your Phone Connect Android Studio. Then run application
Note: If You Can not Show Logcat Just Restart Android Studio : File > Invalid Caches/ restart
In Android studio 0.8.0 you should enable ADB integration through Tools -> Android, before run your app. Then the log cat will work correctly. Notice that if you make ADB integration disabled while your app is running and again make it enable, then the log cat dosen't show anything unless you rebuild your project.
In my case I just had filtered the output so it appeared empty even after restarting Logcat etc.
My problem solved, after I add android:debuggable="true" under application in your AndroiManifest.xml (even the ide mark as a wrong syntax!????)
I checked the answer and only found my mistake accidentally while checking my logcat.
Make sure the box on the right says "Show only selected application". Mine was showing "Firebase", so it showed me messages from Firebase.
In Android Studio 0.8.9, I opened Android Device Monitor, selected my emulator from the Devices list and got the output in the LogCat tab.
After that, I went back to the main view of Android Studio and selected Restore Logcat view in the right of the Android DDMS tab and there it was!
If this doesn't work, you could see your logcat in the Android Device Monitor as I explained in the first sentence.
Make sure you have enabled the build variant to "debug" in the Build Variants context menu. (You can find this at the bottom left corner of the window). This option will be set to release mode, if you have signed the apk for the application previously. This causes the debug messages not to show in the log cat.
Had the same issue today.
Apparently I had eclipse running too and all the logcat output was redirected to eclipse. Since the logs can only be shown at once place, make sure you dont have multiple debuggers running.
Using C# 4 in a Windows console application that continually reports progress how can I make the "redraw" of the screen more fluid?
I'd like to do one of the following:
- Have it only "redraw" the part of the screen that's changing (the progress portion) and leave the rest as is.
- "Redraw" the whole screen but not have it flicker.
Currently I re-write all the text (application name, etc.). Like this:
Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0"), total.ToString("N0"), (count / (decimal)total).ToString("P2")));
Which causes a lot of flickering.
Try Console.SetCursorPosition. More details here: How can I update the current line in a C# Windows Console App?
static void Main(string[] args)
{
Console.SetCursorPosition(0, 0);
Console.Write("################################");
for (int row = 1; row < 10; row++)
{
Console.SetCursorPosition(0, row);
Console.Write("# #");
}
Console.SetCursorPosition(0, 10);
Console.Write("################################");
int data = 1;
System.Diagnostics.Stopwatch clock = new System.Diagnostics.Stopwatch();
clock.Start();
while (true)
{
data++;
Console.SetCursorPosition(1, 2);
Console.Write("Current Value: " + data.ToString());
Console.SetCursorPosition(1, 3);
Console.Write("Running Time: " + clock.Elapsed.TotalSeconds.ToString());
Thread.Sleep(1000);
}
Console.ReadKey();
}
I know this question is a bit old but I found if you set Console.CursorVisible = false then the flickering stops as well.
Here's a simple working demo that shows multi-line usage without flickering. It shows the current time and a random string every second.
private static void StatusUpdate()
{
var whiteSpace = new StringBuilder();
whiteSpace.Append(' ', 10);
var random = new Random();
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
var randomWord = new string(Enumerable.Repeat(chars, random.Next(10)).Select(s => s[random.Next(s.Length)]).ToArray());
while (true)
{
Console.SetCursorPosition(0, 0);
var sb = new StringBuilder();
sb.AppendLine($"Program Status:{whiteSpace}");
sb.AppendLine("-------------------------------");
sb.AppendLine($"Last Updated: {DateTime.Now}{whiteSpace}");
sb.AppendLine($"Random Word: {randomWord}{whiteSpace}");
sb.AppendLine("-------------------------------");
Console.Write(sb);
Thread.Sleep(1000);
}
}
The above example assumes your console window is blank to start. If not, make sure to use Console.Clear() first.
Technical Note:
SetCursorPosition(0,0) places the cursor back to the top (0,0) so the next call to Console.Write will start from line 0, char 0. Note, it doesn't delete the previous content before writing. As an example, if you write "asdf" over a previous line such as "0123456", you'll end up with something like "asdf456" on that line. For that reason, we use a whiteSpace variable to ensure any lingering characters from the previous line are overwritten with blank spaces. Adjust the length of the whiteSpace variable to meet your needs. You only need the whiteSpace variable for lines that change.
Personal Note:
For my purposes, I wanted to show the applications current status (once a second) along with a bunch of other status information and I wanted to avoid any annoying flickering that can happen when you use Console.Clear(). In my application, I run my status updates behind a separate thread so it constantly provides updates even though I have numerous other threads and long running tasks going at the same time.
Credits:
Thanks to previous posters and dtb for the random string generator used in the demo.
How can I generate random alphanumeric strings in C#?
You could try to hack something together using the core libraries.
Rather than waste your time for sub-standard results, I would check out this C# port of the ncurses library (which is a library used for formatting console output):
Curses Sharp
I think you can use \r in Windows console to return the beginning of a line.
You could also use SetCursorPosition.
I would recommend the following extension methods. They allow you to use a StringBuilder to refresh the console view without any flicker, and also tidies up any residual characters on each line
The Problem: The following demo demonstrates using a standard StringBuilder, where updating lines that are shorter than the previously written line get jumbled up. It does this by writing a short string, then a long string on a loop:
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLine("Short msg");
else
sb.AppendLine("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
The Solution: By using the extension method provided below, the issue is resolved
public static void Main(string[] args)
{
var switchTextLength = false;
while(true)
{
var sb = new StringBuilder();
if (switchTextLength)
sb.AppendLineEx("Short msg");
else
sb.AppendLineEx("Longer message");
sb.UpdateConsole();
switchTextLength = !switchTextLength;
Thread.Sleep(500);
}
}
Result:
Extension Methods:
public static class StringBuilderExtensions
{
/// <summary>
/// Allows StrinbBuilder callers to append a line and blank out the remaining characters for the length of the console buffer width
/// </summary>
public static void AppendLineEx(this StringBuilder c, string msg)
{
// Append the actual line
c.Append(msg);
// Add blanking chars for the rest of the buffer
c.Append(' ', Console.BufferWidth - msg.Length - 1);
// Finish the line
c.Append(Environment.NewLine);
}
/// <summary>
/// Combines two StringBuilders using AppendLineEx
/// </summary>
public static void AppendEx(this StringBuilder c, StringBuilder toAdd)
{
foreach (var line in toAdd.ReadLines())
{
c.AppendLineEx(line);
}
}
/// <summary>
/// Hides the console cursor, resets its position and writes out the string builder
/// </summary>
public static void UpdateConsole(this StringBuilder c)
{
// Ensure the cursor is hidden
if (Console.CursorVisible) Console.CursorVisible = false;
// Reset the cursor position to the top of the console and write out the string builder
Console.SetCursorPosition(0, 0);
Console.WriteLine(c);
}
}
I actually had this issue so I made a quick simple method to try and eliminate this.
static void Clear(string text, int x, int y)
{
char[] textChars = text.ToCharArray();
string newText = "";
//Converts the string you just wrote into a blank string
foreach(char c in textChars)
{
text = text.Replace(c, ' ');
}
newText = text;
//Sets the cursor position
Console.SetCursorPosition(x, y);
//Writes the blank string over the old string
Console.WriteLine(newText);
//Resets cursor position
Console.SetCursorPosition(0, 0);
}
It actually worked surprisingly well and I hope it may work for you!
Naive approach but for simple applications is working:
protected string clearBuffer = null; // Clear this if window size changes
protected void ClearConsole()
{
if (clearBuffer == null)
{
var line = "".PadLeft(Console.WindowWidth, ' ');
var lines = new StringBuilder();
for (var i = 0; i < Console.WindowHeight; i++)
{
lines.AppendLine(line);
}
clearBuffer = lines.ToString();
}
Console.SetCursorPosition(0, 0);
Console.Write(clearBuffer);
Console.SetCursorPosition(0, 0);
}
Console.SetCursorPosition(0, 0); //Instead of Console.Clear();
WriteTitle();
Console.WriteLine();
Console.WriteLine("Deleting:\t{0} of {1} ({2})".FormatString(count.ToString("N0")