Scopri se la console di Chrome è aperta


143

Sto usando questo piccolo script per scoprire se Firebug è aperto:

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

E funziona bene. Ora stavo cercando mezz'ora per trovare un modo per rilevare se la console di sviluppo web integrata di Google Chrome è aperta, ma non sono riuscito a trovare alcun suggerimento.

Questo:

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

non funziona

MODIFICARE:

Quindi sembra che non sia possibile rilevare se la console di Chrome è aperta. Ma c'è un " hack " che funziona, con alcuni inconvenienti:

  • non funzionerà quando la console è sganciata
  • non funzionerà quando la console è aperta al caricamento della pagina

Quindi, sceglierò la risposta di Unsigned per ora, ma se some1 ha un'idea geniale, è il benvenuto a rispondere ancora e cambio la risposta selezionata! Grazie!



La soluzione nella risposta sembra funzionare, tuttavia solo se la console è ancorata. Inoltre, non funziona se la console è già aperta al caricamento della pagina, mentre lo script Firebug non presenta questi problemi e sembra funzionare sempre. Ma per ora posso conviverci! Grazie mille @pimvdb !! Terrò comunque aperta la domanda per trovare forse un modo simile allo script Firebug, che funziona sempre.
r0skar,

Ho provato cose come lanciare un errore e vedere se .messageviene recuperato (cosa che succede quando il debugger è aperto perché vedi il messaggio), ma sfortunatamente ciò accade anche quando il debugger non è aperto. Mi piacerebbe sapere un trucco per questo se esiste ...
pimvdb,

4
@Spudley Non è pertinente alla domanda sul perché ne ho bisogno e non voglio iniziare a spiegare. So che non c'è modo di impedire il debug di some1, ma non è quello che sto cercando di fare. Sto solo cercando di capire un modo per sapere se la console è aperta o meno. Questo è tutto :)
r0skar,

1
Il metodo JFYI console.profiles è stato rimosso dall'API della console di recente src.chromium.org/viewvc/blink?view=revision&revision=151136
loislo

Risposte:


98

requestAnimationFrame (Fine 2019)

Lasciando queste risposte precedenti qui per il contesto storico. Attualmente l'approccio di Muhammad Umer funziona su Chrome 78, con l'ulteriore vantaggio di rilevare eventi sia chiusi che aperti.

function toString (2019)

Ringraziamo il commento di Overcl9ck su questa risposta. La sostituzione di regex /./con un oggetto funzione vuoto funziona ancora.

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)

Poiché il richiedente originale non sembra più essere in giro e questa è ancora la risposta accettata, aggiungendo questa soluzione per la visibilità. Merito va a Antonin Hildebrand 's commento su zswang ' s risposta . Questa soluzione sfrutta il fatto che toString()non viene chiamato su oggetti registrati a meno che la console non sia aperta.

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)

Aggiornamento: console.profiles è stato rimosso da Chrome. Questa soluzione non funziona più.

Grazie a Paul Irish per aver segnalato questa soluzione da Discover DevTools , usando il 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)

Questa altra opzione può rilevare l' apertura dell'ispettore ancorato , dopo il caricamento della pagina, ma non sarà in grado di rilevare un ispettore sganciato o se l'ispettore era già aperto al caricamento della pagina. Esistono anche alcuni potenziali falsi positivi.

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


1
Ottenere TypeError: Impossibile leggere la proprietà 'lunghezza' di undefined in isInspectOpen ()
Sandeep

2
C'è un nuovo nuovo modo migliore (crediti: @zswang): stackoverflow.com/questions/7798748/...
Vicky Chijwani

3
la soluzione di 'toString (2017)' non funziona in Chrome
Richard Chan

2
toString sembra essere stato risolto in Chrome. Modificare. In realtà funziona se si utilizza un function() {}anziché un regex
Overcl9ck

1
@ Overcl9ck la tua soluzione funzionava fino all'ultimo aggiornamento di Chrome 77. Puoi indicarci la giusta direzione per una soluzione alternativa?
Agustin Haller,

118

Chrome 65+ (2018)

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

demo: https://jsbin.com/cecuzeb/edit?output (aggiornamento al 16-03-2018)

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


Durante la stampa degli strumenti di sviluppo di "Element" Chrome otterrà il suo ID

var checkStatus;

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

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

Un'altra versione (dai commenti)

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

Stampa una variabile regolare :

var r = /./;
r.toString = function() {
  document.title = 'on';
};
console.log(r);

3
Bella risposta. Una cosa da aggiungere ... MDN dice che __defineGetter__è deprecato, quindi ho cambiato in Object.defineProperty(element, 'id', {get:function() {checkStatus='on';}});... ancora funzionante.
Denikov

5
Inoltre, la console "leggerà" l'elemento non appena si aprirà, in modo da poter stampare solo una volta e attendere che setInterval
venga

8
Sulla base di questa scoperta sono stato in grado di trovare un metodo meno invadente. DevTools chiama toString () sulle funzioni quando le stampa sulla console. Quindi si può stampare un oggetto funzione personalizzato con il metodo toString () sovrascrivere restituendo una stringa vuota. Inoltre, è possibile utilizzare la stringa di formattazione della console% c e impostare il colore: trasparente per assicurarsi che il testo potenzialmente stampato venga stampato come invisibile. Ho usato questa tecnica qui: github.com/binaryage/cljs-devtools/blob/…
Antonin Hildebrand

3
Anno 2017 qui. Chrome scrive ancora cose su console senza che tu le apra. E il tuo hack non funziona più.
vothaison,

2
Testato su firefox non funziona con Inspection Element (Q) e Inspect Element con firebug
Asif Ashraf,

28

Hack molto affidabile

Fondamentalmente imposta un getter sulla proprietà e accedi alla console. Apparentemente alla cosa si accede solo quando la console è aperta.

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>


Chrome versione 79 ✅
Legends,

4
A cosa serve throw new Error("Dev tools checker");? Perché funziona senza di essa.
Legends,

questo sembra spammare la console (quando aperta)? che presumo inizierà a consumare quantità significative di memoria dopo alcuni giorni :)
pythonator il

L'unico modo che funziona a partire da 2020.7
laike9m

24

Ho creato devtools-detect che rileva quando DevTools è aperto:

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

Puoi anche ascoltare un evento:

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

Non funziona quando DevTools è sganciato. Tuttavia, funziona con DevTools e Firebug per Chrome / Safari / Firefox.


@barbushin Penso che il tuo devtool aperto sia ancorato, non è in grado di rilevare una finestra separata.
Mithril,

Purtroppo ha smesso di funzionare per Chrome github.com/sindresorhus/devtools-detect/issues/40
laike9m

15

Ho trovato un modo per sapere se la console di Chrome è aperta o meno. È ancora un trucco, ma è molto più preciso e funzionerà quando la console viene sganciata o meno.

Fondamentalmente l'esecuzione di questo codice con la console chiusa richiede circa ~ 100 microsecondi e mentre la console è aperta richiede circa il doppio di ~ 200 microsecondi.

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

(1 millisecondo = 1000 microsecondi)

Ne ho scritto di più qui .

La demo è qui .


Aggiornare:

@zswang ha trovato la migliore soluzione attuale: controlla la sua risposta


1
È una soluzione molto sbagliata. Google it -> "Race Hazard". Computer più lento o più veloce e ...?
18C

1
"Race Hazard" non è correlato qui. C'è sempre una relativa lentezza all'apertura della console.
Guya,

1
Lentezza relativa ma non sempre 100 o 200ms. Quindi Race Hazard. Btw. Se giocherai allo stesso tempo, questa "soluzione" restituirà risultati falsi positivi.
18C,

8

Se il tuo obiettivo è bloccare gli strumenti di sviluppo, prova questo (ho trovato una versione più complicata di esso in un luogo in cui il codice JS era offuscato, è molto fastidioso):

setTimeout(function() {while (true) {eval("debugger");}}, 0);

L'utente può, in Chrome, disabilitare l'ascolto del debugger.
Jack Giffin,

3

C'è un modo complicato per controllarlo per le estensioni con l'autorizzazione 'tabs':

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

Inoltre puoi verificare se è aperto per la tua pagina:

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

3

Ho scritto un post sul blog su questo: http://nepjua.org/check-if-browser-console-is-open/

Può rilevare se è agganciato o sganciato

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 ?")
    }
  });
});

3
È bello, ma, raffermerà la pagina e nessun messaggio verrà mostrato fino a quando l'utente non farà clic sul pulsante Riprendi. Sarà altamente invadente per l'utente.
Guya,

2
Prossima soluzione "Race Hazard". Molto sbagliato. BTW. Il comando "debugger" può essere disabilitato.
18C

3
var div = document.createElement('div');
Object.defineProperty(div,'id',{get:function(){
    document.title = 'xxxxxx'
}});

setTimeout(()=>console.log(div),3000)

Non ha funzionato E il collegamento a test onlinenon ha funzionato.
Samuel,

2

Gli strumenti di sviluppo di Chrome sono in realtà solo una parte della libreria WebCore di WebKit. Quindi questa domanda si applica a Safari, Chrome e qualsiasi altro consumatore WebCore.

Se esiste una soluzione, sarà basata su una differenza nel DOM quando la finestra di ispezione Web WebKit è aperta e quando è chiusa. Sfortunatamente, questo è un tipo di problema con pollo e uova perché non possiamo usare l'ispettore per osservare il DOM quando l'ispettore è chiuso.

Quello che potresti essere in grado di fare è scrivere un po 'di JavaScript per scaricare l'intero albero DOM. Quindi eseguilo una volta quando l'ispettore è aperto e una volta quando l'ispettore è chiuso. Qualsiasi differenza nel DOM è probabilmente un effetto collaterale dell'ispettore web e potremmo essere in grado di utilizzarlo per verificare se l'utente sta ispezionando o meno.

Questo link è un buon inizio per uno script di dumping DOM, ma ti consigliamo di scaricare l'intero DOMWindowoggetto, non solo document.

Aggiornare:

Sembra che ci sia un modo per farlo ora. Dai un'occhiata a Chrome Inspector Detector


Chrome Inspector Detector non funziona più per Google Chrome, come menzionato dallo sviluppatore
Angelo,

1

Inoltre puoi provare questo: 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);
});

1
Non funziona bene Se un utente si trova su un dispositivo mobile, quindi ruota il dispositivo di 90 gradi, quindi lo schermo verrà ridimensionato.
Jack Giffin,

funziona su chrome e ff not ie or edge dal 4/5/2019
SolidSnake

1

L'approccio di Muhammad Umer ha funzionato per me e sto usando React, quindi ho deciso di fare una soluzione di hook:

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
}

NOTA: quando ci sbagliavo, non funzionava da molto tempo e non riuscivo a capire perché. Ho eliminato il console.dir(element);che è fondamentale per il suo funzionamento. Elimina la maggior parte delle azioni della console non descrittive poiché occupano solo spazio e di solito non sono necessarie alla funzione, quindi è per questo che non ha funzionato per me.

Per usarlo:

import React from 'react'

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

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

Spero che questo aiuti chiunque usi React. Se qualcuno vuole espandersi su questo, vorrei poter fermare il ciclo infinito ad un certo punto (poiché non lo uso in tutti i componenti) e trovare un modo per mantenere pulita la console.


0

Se siete sviluppatori che stanno facendo cose durante lo sviluppo. Dai un'occhiata a questa estensione di Chrome. Ti aiuta a rilevare quando Chrome Devtoos è aperto o chiuso.

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

Questa estensione aiuta gli sviluppatori Javascript a rilevare quando Chrome Devtools è aperto o chiuso nella pagina corrente. Quando Chrome Devtools si chiude / apre, l'estensione genererà un evento chiamato "devtoolsStatusChanged" sull'elemento window.document.

Questo è un codice di esempio:

 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
    }
});

0

Alcune risposte qui smetteranno di funzionare in Chrome 65. Ecco un'alternativa all'attacco di temporizzazione che funziona in modo abbastanza affidabile in Chrome ed è molto più difficile da mitigare rispetto al toString()metodo. Sfortunatamente non è così affidabile in Firefox.

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);

});

0

Per quanto riguarda Chrome / 77.0.3865.75, una versione del 2019 non funziona. toString invoca immediatamente senza l'apertura di Inspector.

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

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

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

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.