Qual è la ragione per cui ‘…’ non viene riconosciuto come comando interno o esterno, programma eseguibile o file batch?

Ho uno snippet a una riga che funziona perfettamente nella riga di comando, ma fallisce e genera errori quando lo eseguo come parte di uno script batch.

I comandi sottostanti si comportano come previsto, eliminando tutte le sottocartelle vuote nella cartella.

for /f "delims=" %d in ('dir /s /b /ad ^| sort /r') do rd "%d"

Tuttavia, quando inserisci un file batch come questo …

FOR /f "delims=" %%d in ('dir /s /b /ad ^| sort /r') do rd "%%d"

… genera l’errore standard: Sort is not recognised as an internal or external command...

Ho sperimentato per l’ultima ora o giù di lì con e senza sfuggire alla pipa, cambiando l’ordine delle opzioni, cercando la documentazione sia di dir che di sort , ecc., Ma non sono ancora riuscito a capire cosa sia sta succedendo qui. Il resto del file batch, che è solo poche righe, funziona bene, e questa è l’unica riga in essa che non riesce.

Qualcuno può aiutare? Grazie in anticipo, lo apprezzerei davvero.

A) In che modo l’interprete dei comandi di Windows cerca i comandi?

L’interprete dei comandi di Windows cerca un comando da eseguire

  1. non è un comando interno di cmd.exe e
  2. è appena specificato con il nome del file senza estensione di file e senza percorso

per un file che corrisponde al command.* pattern command.* e con un’estensione di file elencata nella variabile di ambiente locale PATHEXT

  1. prima nella directory corrente e
  2. successivamente in tutte le directory della variabile di ambiente locale PATH .

SORT and FIND e FINDSTR e ROBOCOPY e XCOPY e molti altri comandi non sono comandi interni di cmd.exe . Si tratta di applicazioni console installate con Windows nella directory %SystemRoot%\System32 con nome file sort.exe , find.exe , findstr.exe , xcopy.exe , xcopy.exe , …

Tali applicazioni console disponibili per impostazione predefinita su Windows sono chiamate comandi esterni per distinguerle meglio dalle applicazioni console non installate con il sistema operativo Windows.


B) Come viene definita la variabile d’ambiente PATH?

Esistono 3 tipi di variabili PATH :

  1. Sistema PATH che viene utilizzato per tutti gli account e memorizzato nel registro di Windows sotto chiave:

     HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment 
  2. PATH utente che viene utilizzato solo per l’account corrente e memorizzato nel registro di Windows sotto chiave:

     HKEY_CURRENT_USER\Environment 
  3. PATH locale che è sempre una copia del PATH locale del processo principale che ha avviato il processo corrente.

Windows concatena il PATH dell’utente e del sistema al PATH locale per l’istanza di Windows Explorer utilizzata come desktop di Windows con i collegamenti sullo schermo del desktop e il menu Start di Windows come interfaccia visibile per l’utente.

All’avvio di un nuovo processo, l’intera tabella delle variabili di ambiente attualmente attive del processo in esecuzione viene copiata per il nuovo processo da Windows.

Il processo padre non può modificare le variabili di ambiente di alcun processo figlio né un processo figlio può modificare le variabili di ambiente del suo processo genitore.

Ciò significa che una volta avviato un processo come cmd.exe per l’esecuzione di un file batch, il processo ha il proprio insieme di variabili d’ambiente che solo il processo stesso può modificare. Nessun altro processo può modificare le variabili di ambiente di un processo già in esecuzione.


C) Che cosa significa il messaggio di errore?

Il messaggio di errore

‘…’ non è riconosciuto come comando interno o esterno,
programma operativo o file batch.

significa sempre

  1. il nome del file di a

    • applicazione console
    • Applicazione GUI
    • script (file batch, script PowerShell, script Perl, VBScript, JScript, …)

    è stato specificato per l’esecuzione molto probabilmente senza estensione del file e senza (completo) percorso per il file eseguibile / script e

  2. Windows non è riuscito a trovare un file corrispondente al modello FileName.* Con un’estensione di file elencata nella variabile di ambiente PATHEXT attualmente triggers nella directory corrente o in qualsiasi altra directory nella variabile di ambiente attualmente triggers PATH .


D) Quali sono le possibili ragioni per questo messaggio di errore?

I motivi tipici sono:

1. Il nome del file da eseguire è stato specificato errato a causa di un errore di digitazione.

Controlla carattere per carattere il nome del comando / eseguibile.

2. La directory corrente è diversa dalla directory che contiene il file da eseguire.

Esegui echo Current directory is: %CD% sulla riga di comando o aggiungi questa riga al file batch sopra la riga di comando che non riesce a vedere qual è la directory corrente.

3. L’eseguibile o lo script da eseguire non è installato affatto.

Verificare l’esistenza dell’eseguibile da eseguire. Alcuni pacchetti di installazione funzionano solo se prima sono stati installati altri pacchetti come Java, NPM, PHP, ecc.

4. La directory del file da eseguire non è affatto in PATH .

Aprire nel pannello di controllo di Windows la finestra delle impostazioni di sistema , fare clic su Impostazioni di sistema avanzate sul lato sinistro, fare clic sul pulsante Variabili d’ambiente e cercare in entrambi gli elenchi per Path e i relativi valori. Per impostazione predefinita, Path esiste solo nell’elenco delle variabili di sistema .

5. Un processo / applicazione in esecuzione non è stato riavviato dopo la modifica del sistema o dell’utente PATH .

Una modifica del PATH di sistema o PATH utente con comando setx o tramite Pannello di controllo – Sistema – Impostazioni di sistema avanzate è stata effettuata dall’utente o da un programma di installazione, ma un processo / applicazione già in esecuzione come un prompt dei comandi aperto o la finestra PowerShell non è stato chiuso / chiuso e aperto / riavviato dopo la modifica del PATH . Ciò è necessario come descritto in dettaglio nel capitolo F) di seguito.

6. La variabile LOCAL PATH stata modificata prima sulla riga di comando o nel file batch.

Esegui il set path sulla riga di comando o aggiungi questo comando al file batch sopra la riga di comando che non riesce a vedere i valori correnti delle variabili d’ambiente PATH e PATHEXT .

L’ultimo motivo è responsabile del fatto che il comando esterno SORT non venga trovato all’esecuzione del file batch che contiene qualcosa sopra il set path=...


E) Come evitare questo messaggio di errore?

La cosa migliore è la codifica di un file batch per essere indipendente su PATH e PATHEXT e l’ordine delle directory in PATH che significa qui usando la riga di comando:

 FOR /f "delims=" %%d in ('dir /s /b /ad ^| %SystemRoot%\System32\sort.exe /r') do rd "%%d" 

Qualsiasi comando esterno il cui eseguibile è memorizzato in %SystemRoot%\System32 deve essere specificato in un file batch con questo percorso e con estensione .exe . Quindi l’interprete dei comandi di Windows non ha bisogno di cercare un file utilizzando PATH e PATHEXT locali e il file batch funziona sempre (purché la variabile di ambiente SystemRoot non venga modificata anche nel file batch che non ho mai visto).


F) Quando una modifica del PATH utente o di sistema viene applicata ai processi?

Quando un utente apre una finestra del prompt dei comandi tramite il menu Start di Windows o all’interno di una finestra di Windows Explorer, l’utente avvia cmd.exe con l’opzione implicita usando /K per mantenere la finestra della console aperta dopo aver terminato un comando che è buono per il debug di un file batch .

Quando viene duplicato un file batch in Esplora risorse, l’utente avvia cmd.exe per l’elaborazione del file batch con l’opzione implicita utilizzando /C per chiudere la finestra della console dopo aver terminato l’elaborazione batch che non è buona per eseguire il debug di un file batch come i messaggi di errore non possono essere visto in questo caso.

In entrambi i casi, Windows crea una copia delle variabili di ambiente dell’applicazione che inizia con cmd.exe che di solito è Windows Explorer. Di conseguenza, il processo di comando avviato ha un PATH locale il cui valore è uguale al processo padre all’avvio di cmd.exe .

Esempio:

  1. Aprire una finestra del prompt dei comandi, eseguire il title Process1 ed eseguire il set path .
    L’output è PATH e PATHEXT come attualmente definito per l’account utente corrente nella finestra della console avente ora il titolo Process1 della finestra.

  2. Esegui il set PATH=%SystemRoot%\System32 e successivamente set path nuovamente il set path .
    L’output è di nuovo PATH e PATHEXT , ma con PATH contenente solo una directory ora.

  3. Avvia start "Process2" ed esegui nella nuova finestra della console il titolo della finestra Process2 il set path comandi.
    L’output è PATH e PATHEXT con gli stessi valori di prima in Process1 .
    Ciò dimostra che all’avvio di un nuovo processo vengono copiate le variabili di ambiente correnti del processo in esecuzione e non quelle che Windows ha attualmente memorizzato nel registro di Windows.

  4. Esegui in Process2 il comando set PATH= e il prossimo set path .
    L’output è solo PATHEXT perché PATH locale non esiste più per Process2 .
    Ciò dimostra che ogni processo può modificare le sue variabili d’ambiente inclusa la cancellazione completa.

  5. Passare alla finestra Process1 , eseguire il comando set PATH=%PATH%;%SystemRoot% e il successivo set path .
    L’output è PATH con due directory e PATHEXT .

  6. Avvia il comando start "Process3" e nella finestra aperta con il titolo Process3 il comando set path .
    L’output è PATH con due directory definite anche per Process1 e PATHEXT .

  7. Esegui in Process3 il comando set PATH=%SystemRoot%\System32 .

Esistono 3 processi di comando in esecuzione con i seguenti valori per il PATH locale quando %SystemRoot% espande in C:\Windows :

Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH non esiste affatto.
Process3 : PATH=C:\Windows\System32

Quindi, cosa succede ora aprendo Pannello di controllo – Sistema – Impostazioni di sistema avanzate – Variabili d’ambiente e aggiungendo alla lista delle variabili utente la nuova variabile d’ambiente PATH con valore C:\Temp , o nel caso ci sia già una variabile d’ambiente PATH dell’utente , modifica PATH e append ;C:\Temp al valore?

Bene, finché la finestra di dialogo con il titolo Variabili d’ambiente che mostra i due elenchi è aperta, non accade nulla sulla modifica delle variabili, finché non viene cliccato il pulsante OK per prendere tutte le modifiche nel registro di Windows e chiudere la finestra.

Torniamo ai 3 processi di comando in esecuzione ed eseguiamo in Process1 , Process2 e Process3 il set path comandi. Può essere visto:

Process1 : PATH=C:\Windows\System32;C:\Windows
Process2 : PATH non esiste affatto.
Process3 : PATH=C:\Windows\System32

Nulla è cambiato nei processi già in esecuzione.

Nessun processo può modificare le variabili di ambiente di un processo in esecuzione.

Apri dal menu di avvio di Windows un’altra finestra del prompt dei comandi ed esegui nel quarto comando l’elaborazione del set path comandi. Si può vedere che il PATH locale del quarto processo di comando ha aggiunto la directory C:\Temp ora.

Quindi chiudere tutti i 4 processi di comando ed eliminare rispettivamente il PATH utente aggiunto rimuovere ;C:\Temp dal PATH utente se prima era stato aggiunto questo percorso di directory.

Com’è ansible se nessun processo può modificare le variabili di ambiente di un processo già in esecuzione?

In che modo l’elenco delle variabili di ambiente dell’istanza di Windows Explorer in esecuzione come desktop di Windows è stato modificato alla chiusura della finestra Variabili d’ambiente con il pulsante OK ?

La risposta a queste due domande è stata data da eryksun nel suo commento.

Dopo aver scritto le modifiche sul sistema e le variabili utente nel registro facendo clic sul pulsante OK della finestra Variabili d’ ambiente , Windows invia il messaggio WM_SETTINGCHANGE a tutte le windows di primo livello per informare le applicazioni in esecuzione sui parametri di sistema modificati.

Spetta all’applicazione se questo messaggio di evento viene gestito e come. Esplora risorse in esecuzione come desktop di Windows legge le variabili di ambiente dal registro e aggiorna di conseguenza l’elenco di variabili d’ambiente. Altre applicazioni come Total Commander gestiscono anche questo messaggio e aggiornano anche i loro elenchi di variabili di ambiente. Ma cmd.exe non lo fa per fortuna dato che sarebbe davvero problematico.

Esiste la possibilità di modificare un sistema o una variabile utente con notifica tramite WM_SETTINGCHANGE da una finestra del prompt dei comandi o da un file batch?

È ansible modificare il valore di registro di una variabile d’ambiente utilizzando il comando reg add . Ma questo non risulta nell’invio del messaggio WM_SETTINGCHANGE a tutte le windows di primo livello. Tali modifiche apportate con reg add o con regedit richiedono il riavvio di Windows (o almeno una disconnessione e l’accesso dell’utente corrente) da prendere in considerazione.

Ma c’è anche il comando setx che è progettato per modificare un sistema o una variabile utente e che invia anche il messaggio WM_SETTINGCHANGE a tutte le windows di primo livello dopo che il registro è stato aggiornato secondo gli argomenti specificati. Esegui setx /? in una finestra del prompt dei comandi per i dettagli. Ma si prega di tener conto del fatto che setx non modifica la variabile di ambiente locale del processo di comando in esecuzione. Questo deve essere fatto usando il set comandi usato in aggiunta a setx .


G) Come viene gestita la variabile di ambiente PATHEXT da Windows?

La variabile d’ambiente PATHEXT con l’elenco delle estensioni di file è gestita da Windows diversa rispetto alla variabile d’ambiente PATH .

Il sistema PATHEXT e l’ utente PATHEXT NON sono concatenati al PATHEXT locale .

Un utente PATHEXT sostituisce il PATHEXT sistema per tutti i processi in esecuzione nell’ambiente dell’account definito dall’utente PATHEXT .

Per impostazione predefinita, è definita solo una variabile di ambiente PATHEXT sistema .


H) È ansible disabilitare la ricerca di file nella directory corrente?

Il processore dei comandi di Windows cerca per impostazione predefinita nella directory corrente se il nome file di un file script o eseguibile è specificato sulla riga di comando o in un file batch senza alcun percorso che significa senza barra rovesciata \ (o una barra diretta / grazie alla correzione automatica) in stringa argomento.

Ma su Windows Vista e versioni successive di client Windows e su Windows Server 2003 e versioni successive di server Windows è infatti ansible disabilitare la ricerca di uno script / eseguibile nella directory corrente specificata senza almeno un percorso relativo .\ Definendo la variabile d’ambiente NoDefaultCurrentDirectoryInExePath con qualsiasi valore come scritto da eryksun nel suo commento qui sotto e spiegato da Microsoft nell’articolo di MSDN sulla funzione NeedCurrentDirectoryForExePath .

Consultare Rimozione della directory di lavoro corrente dal percorso per ulteriori dettagli sull’utilizzo di questa variabile di ambiente.

Molto probabilmente, hai incasinato la variabile PATH . Forse lo stai sovrascrivendo da qualche altra parte nel tuo script. Poiché sort è un comando esterno, opposto a tutti gli altri nella riga di comando come for , dir , rd , che sono i comandi cmd -internal, la variabile PATH è necessaria per trovare il comando. Se PATH non è definito, i comandi esterni vengono cercati solo nella directory di lavoro corrente. C’è anche una variabile PATHEXT che è necessaria per definire estensioni di file standard per gli eseguibili, come .com , .exe . Quindi, quando l’ sort appare nel prompt dei comandi o in un file batch, il sistema ricerca la directory di lavoro corrente e tutte le directory specificate dalla variabile PATH per un file con l’ sort nome di base e una delle estensioni specificate da PATHEXT . L’ sort comandi è in realtà chiamato sort.exe e in genere si trova in C:\Windows\System32 .