Finden Sie heraus, ob die Chrome-Konsole geöffnet ist

141

Ich benutze dieses kleine Skript, um herauszufinden, ob Firebug geöffnet ist:

if (window.console && window.console.firebug) {
    //is open
};

Und es funktioniert gut. Jetzt suchte ich eine halbe Stunde lang nach einer Möglichkeit, festzustellen, ob die integrierte Webentwicklerkonsole von Google Chrome geöffnet ist, konnte jedoch keinen Hinweis finden.

Dies:

if (window.console && window.console.chrome) {
    //is open
};

funktioniert nicht

BEARBEITEN:

Es scheint also nicht möglich zu sein, festzustellen, ob die Chrome-Konsole geöffnet ist. Aber es gibt einen " Hack ", der funktioniert, mit einigen Nachteilen:

  • funktioniert nicht, wenn die Konsole nicht angedockt ist
  • funktioniert nicht, wenn die Konsole beim Laden der Seite geöffnet ist

Also werde ich vorerst die Antwort von Unsigned wählen, aber wenn jemand eine brillante Idee hat, kann er gerne noch antworten und ich ändere die ausgewählte Antwort! Vielen Dank!

r0skar
quelle
Die Lösung in der Antwort scheint jedoch nur zu funktionieren, wenn die Konsole angedockt ist. Es funktioniert auch nicht, wenn die Konsole beim Laden der Seite bereits geöffnet ist, während das Firebug-Skript diese Probleme nicht aufweist und anscheinend immer funktioniert. Aber damit kann ich jetzt leben! Vielen Dank @pimvdb !! Ich werde die Frage trotzdem offen halten, um vielleicht einen ähnlichen Weg wie das Firebug-Skript zu finden, der immer funktioniert.
r0skar
Ich habe versucht, einen Fehler auszulösen und festzustellen, ob er .messageabgerufen wird (was passiert, wenn der Debugger geöffnet ist, weil Sie die Meldung sehen), aber leider passiert dies auch, wenn der Debugger nicht geöffnet ist. Ich würde gerne einen Hack dafür wissen, wenn er existiert ...
pimvdb
4
@Spudley Es ist nicht relevant für die Frage, warum ich es brauche und ich möchte nicht anfangen zu erklären. Ich weiß, dass es keine Möglichkeit gibt, das Debuggen von some1 zu verhindern, aber das versuche ich nicht. Ich versuche nur herauszufinden, ob die Konsole geöffnet ist oder nicht. Das ist alles :)
r0skar
1
Die JFYI-Methode console.profiles wurde kürzlich aus der Konsolen-API entfernt. Src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Antworten:

97

requestAnimationFrame (Ende 2019)

Lassen Sie diese vorherigen Antworten hier für den historischen Kontext. Derzeit ist Muhammad Ulers Ansatz funktioniert in Chrome 78 mit dem zusätzlichen Vorteil, dass sowohl geschlossene als auch offene Ereignisse erkannt werden.

Funktion toString (2019)

Dank an Overcl9cks Kommentar zu dieser Antwort. Das Ersetzen des regulären Ausdrucks /./durch ein leeres Funktionsobjekt funktioniert weiterhin.

var devtools = function() {};
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

Regex toString (2017-2018)

Da der ursprüngliche Fragesteller nicht mehr in der Nähe zu sein scheint und dies immer noch die akzeptierte Antwort ist, fügen Sie diese Lösung zur besseren Sichtbarkeit hinzu. Kredit geht an Antonin Hildebrand ‚s Kommentar auf zswang ‘ s Antwort . Diese Lösung nutzt die Tatsache, dass toString()protokollierte Objekte nur aufgerufen werden, wenn die Konsole geöffnet ist.

var devtools = /./;
devtools.toString = function() {
  if (!this.opened) {
    alert("Opened");
  }
  this.opened = true;
}

console.log('%c', devtools);
// devtools.opened will become true if/when the console is opened

console.profiles (2013)

Aktualisieren: console.profiles wurde aus Chrome entfernt. Diese Lösung funktioniert nicht mehr.

Vielen Dank an Paul Irish für den Hinweis auf diese Lösung von Discover DevTools mit dem Profiler:

function isInspectOpen() {
  console.profile();
  console.profileEnd();
  if (console.clear) {
    console.clear();
  }
  return console.profiles.length > 0;
}
function showIfInspectIsOpen() {
  alert(isInspectOpen());
}
<button onClick="showIfInspectIsOpen()">Is it open?</button>

window.innerHeight (2011)

Diese andere Option erkennt, dass der angedockte Inspektor nach dem Laden der Seite geöffnet wird, erkennt jedoch keinen nicht angedockten Inspektor oder ob der Inspektor beim Laden der Seite bereits geöffnet war. Es besteht auch die Möglichkeit von Fehlalarmen.

window.onresize = function() {
  if ((window.outerHeight - window.innerHeight) > 100) {
    alert('Docked inspector was opened');
  }
}

Ohne Vorzeichen
quelle
1
Abrufen von TypeError: Die Eigenschaft 'Länge' von undefined in isInspectOpen () kann nicht gelesen werden
Sandeep
2
Es gibt einen neuen neuen besten Weg (Credits: @zswang): stackoverflow.com/questions/7798748/…
Vicky Chijwani
3
Die Lösung von 'toString (2017)' funktioniert nicht in Chrom
Richard Chan
2
toString scheint in Chrom fixiert worden zu sein. Bearbeiten. Eigentlich funktioniert es, wenn Sie einen function() {}anstelle eines
regulären Ausdrucks verwenden
1
@ Overcl9ck Ihre Lösung funktionierte bis zum neuesten Chrome 77-Update. Können Sie uns die richtige Richtung für eine Problemumgehung weisen?
Agustin Haller
118

Chrome 65+ (2018)

r = /./
r.toString = function () {
    document.title = '1'
}
console.log('%c', r);

Demo: https://jsbin.com/cecuzeb/edit?output (Update am 16.03.2018)

Paket: https://github.com/zswang/jdetects


Beim Drucken von "Element" erhalten Chrome-Entwicklertools ihre ID

var checkStatus;

var element = document.createElement('any');
element.__defineGetter__('id', function() {
    checkStatus = 'on';
});

setInterval(function() {
    checkStatus = 'off';
    console.log(element);
    console.clear();
}, 1000);

Eine andere Version (aus Kommentaren)

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function () {
    /* TODO */
    alert('囧');
  }
});
console.log('%cHello', element);

Drucken Sie eine reguläre Variable:

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);
zswang
quelle
3
Gute Antwort. Eine Sache, die hinzugefügt werden muss ... MDN sagt, dass sie __defineGetter__veraltet ist, also habe ich zu Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});... immer noch gearbeitet.
Denikov
5
Außerdem "liest" die Konsole das Element, sobald die Konsole geöffnet wird. Sie können also nur einmal drucken und warten, bis die Funktion im Getter ausgeführt wird, anstatt einensetInterval
xpy
8
Aufgrund dieser Entdeckung konnte ich eine weniger aufdringliche Methode finden. DevTools ruft beim Drucken auf der Konsole toString () für Funktionen auf. So kann ein benutzerdefiniertes Funktionsobjekt mit der Methode toString () gedruckt werden, die eine leere Zeichenfolge überschreibt. Darüber hinaus können Sie die Konsolenformatierungszeichenfolge% c verwenden und color: transparent festlegen, um sicherzustellen, dass potenziell gedruckte Textdrucke unsichtbar sind. Ich habe diese Technik hier angewendet: github.com/binaryage/cljs-devtools/blob/…
Antonin Hildebrand
3
Jahr 2017 hier. Chrome schreibt weiterhin Dinge in die Konsole, ohne dass Sie sie öffnen. Und dein Hack funktioniert nicht mehr.
Vothaison
2
Auf Firefox getestet funktioniert nicht mit Inspection Element (Q) und Inspect Element mit Firebug
Asif Ashraf
27

Sehr zuverlässiger Hack

Legen Sie im Grunde einen Getter für die Eigenschaft fest und melden Sie ihn in der Konsole an. Anscheinend wird auf das Ding nur zugegriffen, wenn die Konsole geöffnet ist.

https://jsfiddle.net/gcdfs3oo/44/

var checkStatus;

var element = new Image();
Object.defineProperty(element, 'id', {
  get: function() {
    checkStatus='on';
    throw new Error("Dev tools checker");
  }
});

requestAnimationFrame(function check() {
  checkStatus = 'off';
  console.dir(element);
  document.querySelector('#devtool-status').className  = checkStatus;
  requestAnimationFrame(check);
});
.on{
  color:limegreen;
}

.off{
  color:red;
}
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.7.1/css/all.css" integrity="sha256-DVK12s61Wqwmj3XI0zZ9MFFmnNH8puF/eRHTB4ftKwk=" crossorigin="anonymous" />

<p>
  <ul>
    <li>
      dev toolbar open: icon is <span class="on">green</span>
    </li>
    <li>
      dev toolbar closed: icon is <span class="off">red</span>
    </li>
  </ul>
</p>
<div id="devtool-status"><i class="fas fa-7x fa-power-off"></i></div>
<br/>
<p><b>Now press F12 to see if this works for your browser!</b></p>

Muhammad Umer
quelle
Chrome Version 79 ✅
Legends
4
Wofür ist das throw new Error("Dev tools checker");? Weil es ohne funktioniert.
Legenden
Dies scheint die Konsole zu spammen (wenn geöffnet)? Ich
gehe
23

Ich habe devtools-detect erstellt, das erkennt, wann DevTools geöffnet ist:

console.log('is DevTools open?', window.devtools.open);

Sie können sich auch ein Ereignis anhören:

window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
});

Es funktioniert nicht, wenn DevTools nicht angedockt ist. Funktioniert jedoch mit den Chrome / Safari / Firefox DevTools und Firebug.

Sindre Sorhus
quelle
@barbushin Ich denke, Ihr offenes Devtool hat angedockt, es kann kein separates Fenster erkennen.
Mithril
15

Ich habe einen Weg gefunden, um festzustellen, ob die Chrome-Konsole geöffnet ist oder nicht. Es ist immer noch ein Hack, aber es ist viel genauer und funktioniert, ob die Konsole nicht angedockt ist oder nicht.

Grundsätzlich dauert das Ausführen dieses Codes bei geschlossener Konsole ungefähr 100 Mikrosekunden, und während die Konsole geöffnet ist, dauert es ungefähr doppelt so viel wie 200 Mikrosekunden.

console.log(1);
console.clear();

(1 Millisekunde = 1000 Mikrosekunden)

Ich habe mehr darüber geschrieben hier .

Demo ist da .


Aktualisieren:

@zswang hat die derzeit beste Lösung gefunden - lesen Sie seine Antwort

Guya
quelle
1
Es ist eine sehr falsche Lösung. Google it -> "Race Hazard". Langsamer oder schneller Computer und ...?
18.
1
"Race Hazard" ist hier nicht verwandt. Es gibt immer eine relative Langsamkeit, wenn die Konsole geöffnet wird.
Guya
1
Relative Langsamkeit, aber nicht immer 100 oder 200 ms. Also Race Hazard. Übrigens. Wenn Sie gleichzeitig ein Spiel spielen, gibt diese "Lösung" ein falsch positives Ergebnis zurück.
18.
8

Wenn Sie die Entwicklertools blockieren möchten, versuchen Sie Folgendes (ich habe eine kompliziertere Version an einer Stelle gefunden, an der JS-Code verschleiert wurde, was sehr ärgerlich ist):

setTimeout(function() {while (true) {eval("debugger");}}, 0);
Robert Moore
quelle
Der Benutzer kann in Chrome das Abhören des Debuggers deaktivieren.
Jack Giffin
3

Es gibt eine schwierige Möglichkeit, mit der Berechtigung "Tabs" nach Erweiterungen zu suchen:

chrome.tabs.query({url:'chrome-devtools://*/*'}, function(tabs){
    if (tabs.length > 0){
        //devtools is open
    }
});

Sie können auch überprüfen, ob es für Ihre Seite geöffnet ist:

chrome.tabs.query({
    url: 'chrome-devtools://*/*',
    title: '*example.com/your/page*'
}, function(tabs){ ... })
norlin
quelle
3

Ich habe einen Blog-Beitrag darüber geschrieben: http://nepjua.org/check-if-browser-console-is-open/

Es kann erkennen, ob es angedockt oder nicht angedockt ist

function isConsoleOpen() {  
  var startTime = new Date();
  debugger;
  var endTime = new Date();

  return endTime - startTime > 100;
}

$(function() {
  $(window).resize(function() {
    if(isConsoleOpen()) {
        alert("You're one sneaky dude, aren't you ?")
    }
  });
});
Nepjua
quelle
3
Das ist schön, aber es veraltet die Seite und es wird keine Nachricht angezeigt, bis der Benutzer auf die Schaltfläche "Fortsetzen" klickt. Es wird für den Benutzer sehr aufdringlich sein.
Guya
2
Nächste "Race Hazard" -Lösung. Sehr falsch. Übrigens. Der Befehl "debugger" kann deaktiviert werden.
18.
3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)
Chen
quelle
Es hat nicht funktioniert. Und der Link zu test onlinehat nicht funktioniert.
Samuel
2

Die Chrome-Entwicklertools sind eigentlich nur ein Teil der WebCore-Bibliothek von WebKit. Diese Frage gilt also für Safari, Chrome und alle anderen WebCore-Kunden.

Wenn eine Lösung vorhanden ist, basiert sie auf einem Unterschied im DOM, wenn der WebKit-Webinspektor geöffnet und geschlossen ist. Leider ist dies eine Art Henne-Ei-Problem, da wir den Inspektor nicht verwenden können, um das DOM zu beobachten, wenn der Inspektor geschlossen ist.

Möglicherweise können Sie ein wenig JavaScript schreiben, um den gesamten DOM-Baum zu sichern. Führen Sie es dann einmal aus, wenn der Inspektor geöffnet ist, und einmal, wenn der Inspektor geschlossen ist. Jeder Unterschied im DOM ist wahrscheinlich eine Nebenwirkung des Webinspektors, und wir können ihn möglicherweise verwenden, um zu testen, ob der Benutzer prüft oder nicht.

Dieser Link ist ein guter Anfang für ein DOM-Dumping-Skript, aber Sie möchten DOMWindownicht nur das gesamte Objekt sichern document.

Aktualisieren:

Sieht so aus, als gäbe es jetzt eine Möglichkeit, dies zu tun. Schauen Sie sich den Chrome Inspector Detector an

Pepsi
quelle
Chrome Inspector Detector funktioniert nicht mehr für Google Chrome, wie vom Entwickler erwähnt
Angelo
1

Sie können dies auch versuchen: https://github.com/sindresorhus/devtools-detect

// check if it's open
console.log('is DevTools open?', window.devtools.open);
// check it's orientation, null if not open
console.log('and DevTools orientation?', window.devtools.orientation);

// get notified when it's opened/closed or orientation changes
window.addEventListener('devtoolschange', function (e) {
    console.log('is DevTools open?', e.detail.open);
    console.log('and DevTools orientation?', e.detail.orientation);
});
Vladimir Ishenko
quelle
1
Funktioniert nicht gut. Wenn sich ein Benutzer auf einem mobilen Gerät befindet, dreht er sein Gerät um 90 Grad, und die Größe des Bildschirms wird geändert.
Jack Giffin
Arbeiten auf Chrom und ff nicht heißt oder Kante ab 2019.04.05
Solid Snake
0

Wenn Sie Entwickler sind, die während der Entwicklung Dinge tun. Schauen Sie sich diese Chrome-Erweiterung an. Es hilft Ihnen zu erkennen, wann Chrome Devtoos geöffnet oder geschlossen wird.

https://chrome.google.com/webstore/detail/devtools-status-detector/pmbbjdhohceladenbdjjoejcanjijoaa?authuser=1

Mit dieser Erweiterung können Javascript-Entwickler erkennen, wann Chrome Devtools auf der aktuellen Seite geöffnet oder geschlossen ist. Wenn Chrome Devtools geschlossen / geöffnet wird, löst die Erweiterung ein Ereignis mit dem Namen 'devtoolsStatusChanged' im Element window.document aus.

Dies ist ein Beispielcode:

 function addEventListener(el, eventName, handler) {
    if (el.addEventListener) {
        el.addEventListener(eventName, handler);
    } else {
        el.attachEvent('on' + eventName,
            function() {
                handler.call(el);
            });
    }
}


// Add an event listener.
addEventListener(document, 'devtoolsStatusChanged', function(e) {
    if (e.detail === 'OPENED') {
        // Your code when Devtools opens
    } else {
        // Your code when Devtools Closed
    }
});
vothaison
quelle
0

Einige Antworten hier funktionieren in Chrome 65 nicht mehr. Hier ist eine Timing-Angriffsalternative , die in Chrome ziemlich zuverlässig funktioniert und viel schwerer zu entschärfen ist als die toString()Methode. Leider ist es in Firefox nicht so zuverlässig.

addEventListener("load", () => {

var baseline_measurements = [];
var measurements = 20;
var warmup_runs = 3;

const status = document.documentElement.appendChild(document.createTextNode("DevTools are closed"));
const junk = document.documentElement.insertBefore(document.createElement("div"), document.body);
junk.style.display = "none";
const junk_filler = new Array(1000).join("junk");
const fill_junk = () => {
  var i = 10000;
  while (i--) {
    junk.appendChild(document.createTextNode(junk_filler));
  }
};
const measure = () => {
    if (measurements) {
    const baseline_start = performance.now();
    fill_junk();
    baseline_measurements.push(performance.now() - baseline_start);
    junk.textContent = "";
    measurements--;
    setTimeout(measure, 0);
  } else {
    baseline_measurements = baseline_measurements.slice(warmup_runs); // exclude unoptimized runs
    const baseline = baseline_measurements.reduce((sum, el) => sum + el, 0) / baseline_measurements.length;

    setInterval(() => {
      const start = performance.now();
      fill_junk();
      const time = performance.now() - start;
      // in actual usage you would also check document.hasFocus()
      // as background tabs are throttled and get false positives
      status.data = "DevTools are " + (time > 1.77 * baseline ? "open" : "closed");
      junk.textContent = "";
    }, 1000);
  }
};

setTimeout(measure, 300);

});
Eli Gray
quelle
0

Wie für Chrome / 77.0.3865.75 funktioniert eine Version von 2019 nicht. toString wird sofort aufgerufen, ohne dass der Inspektor geöffnet wird.

const resultEl = document.getElementById('result')
const detector = function () {}

detector.toString = function () {
	resultEl.innerText = 'Triggered'
}

console.log('%c', detector)
<div id="result">Not detected</div>

korzhyk
quelle
0

Der Ansatz von Muhammad Umer hat bei mir funktioniert und ich verwende React. Deshalb habe ich beschlossen, eine Hooks-Lösung zu finden:

const useConsoleOpen = () => {
  const [consoleOpen, setConsoleOpen] = useState(true)

  useEffect(() => {
    var checkStatus;

    var element = new Image();
    Object.defineProperty(element, "id", {
      get: function () {
        checkStatus = true;
        throw new Error("Dev tools checker");
      },
    });

    requestAnimationFrame(function check() {
      checkStatus = false;
      console.dir(element); //Don't delete this line!
      setConsoleOpen(checkStatus)
      requestAnimationFrame(check);
    });
  }, []);

  return consoleOpen
}

HINWEIS: Als ich damit herumgespielt habe, hat es die längste Zeit nicht funktioniert und ich konnte nicht herausfinden, warum. Ich hatte gelöscht, console.dir(element);was für die Funktionsweise entscheidend ist. Ich lösche die meisten nicht beschreibenden Konsolenaktionen, da sie nur Speicherplatz beanspruchen und normalerweise für die Funktion nicht erforderlich sind. Deshalb hat es bei mir nicht funktioniert.

Um es zu benutzen:

import React from 'react'

const App = () => {
  const consoleOpen = useConsoleOpen()

  return (
    <div className="App">
      <h1>{"Console is " + (consoleOpen ? "Open" : "Closed")}</h1>
    </div>
  );
}

Ich hoffe, dies hilft jedem, der React verwendet. Wenn jemand dies erweitern möchte, möchte ich in der Lage sein, die Endlosschleife irgendwann zu stoppen (da ich dies nicht in jeder Komponente verwende) und einen Weg zu finden, die Konsole sauber zu halten.

Luke Redmore
quelle