% date% produce risultati diversi nel file batch quando viene eseguito da Operazioni pianificate in Server 2016

Il file batch esegue robocopy e crea un file di registro di robocopyServer_% date% .txt

Quando il file batch viene eseguito manualmente, il risultato è robocopyServer_yyyy-mm-dd.txt

Quando il file batch viene eseguito da Operazioni pianificate, il risultato è robocopyServer_Tue (o qualunque sia il giorno della settimana) e nessuna estensione di file.

Questo file batch ha funzionato perfettamente con Server 2012R2 (attività manuali o pianificate).

% data% o date /t non è sempre affidabile in quanto dipende dalla regione e dalle impostazioni utente. Ecco come è ansible ottenere una data universalmente valida:

 for /f %%# in ('wmic os get localdatetime^|findstr .') do if "%%#" neq "" set date=%%# set date=%date:~,4%-%date:~4,2%-%date:~6,2% echo %date% 

Questo farà eco alla data corrente nel formato aaaa-mm-gg.

È necessario creare un profilo Windows per l’utente utilizzato per eseguire l’attività e configurare le impostazioni internazionali e il formato data sotto tale profilo.

Il formato delle stringhe delle variabili di ambiente DATA e ORA dipendono dalle impostazioni della regione Windows definite per l’account utilizzato.

Una stringa di data / ora indipendente dalla regione può essere ottenuta utilizzando lo strumento WMIC della riga di comando di Strumentazione gestione Windows .

Usando la riga di comando

 wmic OS GET LocalDateTime /VALUE 

uscite UTF-16 Little Endian codificato per esempio:

 LocalDateTime=20170621095402.953000+120 

Vi sono due righe vuote, quindi la riga con la data / ora locale corrente nel formato AAAAMMGGHHmmmm.microsecondo ± UTC in minuti e altre due righe vuote.

Questi dati possono essere utilizzati con un codice batch come questo:

 @echo off for /F "tokens=2 delims==." %%I in ('%SystemRoot%\System32\wbem\wmic.exe OS GET LocalDateTime /VALUE') do set "FileNameDate=%%I" set "FileNameDate=%FileNameDate:~0,4%-%FileNameDate:~4,2%-%FileNameDate:~6,2%" echo %FileNameDate% 

Di interesse per i nomi di file e cartelle è solo la stringa data / ora tra il segno di uguale e il punto decimale che è la ragione per l’utilizzo for /F tokens=2 delims==. opzioni for /F tokens=2 delims==. per ottenere solo 20170621095402 assegnato alla variabile di ciclo I cui valore viene assegnato accanto alla variabile di ambiente FileNameDate .

La variabile di ambiente FileNameDate viene riformattata utilizzando le sostituzioni di stringhe per ottenere una stringa di data nel formato YYYY-MM-DD che viene emessa per la verifica risultante in 2017-06-21 .

Il vantaggio dell’utilizzo di WMIC per ottenere data / ora locali è indipendente dalle impostazioni della regione di Windows. Lo svantaggio è che l’esecuzione del comando richiede un tempo piuttosto lungo (da 1 a 2 secondi) rispetto all’uso delle variabili di ambiente DATE e TIME a cui si accede in pochi microsecondi.

Il comando FOR ha problemi di parsing dell’output Unicode corretto. Interpreta la sequenza di byte 0D 00 0A 00 0D 00 0A 00 alla fine dell’uscita WMIC a causa delle due righe vuote come 0D 0D 0A, ovvero come due ritorni a capo e un avanzamento riga. Ciò risulta nell’interpretazione delle ultime due righe vuote alla fine dell’output WMIC come una singola riga con un singolo ritorno a capo come stringa.

Questo è molto spesso un problema poiché il risultato del set "EnvironmentVariable=%%I" è con %%I espande al solo ritorno a capo nell’eliminazione della variabile di ambiente già definita prima con il valore corretto.

Esistono più soluzioni per risolvere questo errore di analisi del comando Unicode FOR . È ansible aggiungere & goto Label per uscire dal ciclo con un salto su :Label sotto il ciclo FOR una volta che il valore è assegnato alla variabile di ambiente per evitare di incorrere in questo problema.

Un’altra soluzione è quella usata in questo codice. A causa dell’utilizzo dell’opzione WMIC /VALUE il nome della proprietà e il suo valore vengono emessi sulla stessa riga. Il comando FOR esegue il comando SET a causa di tokens=2 solo quando può suddividere la linea corrente in almeno 2 sottostringhe (token) usando segno uguale e punto come delimitatori a causa di delims==. . Ma la fine parsed errata dell’output WMIC è per FOR una riga che contiene solo un ritorno a capo e quindi non ha un secondo token. Per questo motivo anche le righe vuote analizzate in modo errato vengono qui ignorate da FOR .

Vedi Come correggere il comportamento scorretto della sovrascrittura delle variabili durante l’analisi dell’output? e cmd sta in qualche modo scrivendo il testo cinese come output per i dettagli sul problema di parsing di FOR sull’uscita codificata UTF-16 LE.

Per capire i comandi usati e come funzionano, apri una finestra del prompt dei comandi, esegui i seguenti comandi e leggi attentamente tutte le pagine di aiuto visualizzate per ciascun comando.

  • echo /?
  • for /?
  • set /?
  • wmic /?
  • wmic os /?
  • wmic os get /?
  • wmic os get localdatetime /?

Ho avuto un problema simile all’OP e adoro il metodo che usa wmic @Regejok. Ecco la mia soluzione per gestire stringhe univoche restituite da DOS DATE (soluzione USA – scusate nessun altro sistema operativo regionale per testare, ma questo può essere rifattorizzato abbastanza velocemente per altre regioni).

Avevo server che restituivano stringhe diverse per% DATE% (data / t).

ex. 1 – mer 07/04/2018 (stringa perfettamente fine)

ex. 2 – 07/04/2018 (un’altra stringa perfettamente soddisfacente, ma non è riuscito il mio script batch a causa della sottostringa di riferimento)

Stavo usando questo script selezionando sottostringhe da DATE & TIME per creare data / timestamp vars per la registrazione e l’archiviazione dei file:

SCRIPT ORIGINALE

 @echo off set HH=%TIME:~0,1% if "%HH%"==" " goto addzero goto hourOK :addzero set HH=0%TIME:~1,1% goto end :hourOK set HH=%TIME:~0,2% :end set mn=%TIME:~3,2% set SS=%TIME:~6,2% set ms=%TIME:~9,2% set MM=%DATE:~4,2% set DD=%DATE:~7,2% set YY=%DATE:~-2% set CCYY=%DATE:~-4% set dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms% set dateonly=%CCYY%%MM%%DD% set monthlog=%CCYY%%MM% @echo on 

Per favore non giudicare il codice. 🙂 Migliora.

RISULTATI PER “Mer 07/04/2018”:

 C:\>set HH= C:\>if " " == " " goto addzero C:\>set HH=09 C:\>goto end C:\>set mn=30 C:\>set SS=49 C:\>set ms=69 C:\>set MM=07 C:\>set DD=04 C:\>set YY=18 C:\>set CCYY=2018 C:\>set dts=2018070409304969 C:\>set dateonly=20180704 C:\>set monthlog=201807 

Questo ha funzionato alla grande con l’ex. 1 corda. Ho saltato il giorno abbreviato (mercoledì) e tutto andava bene. Fino a quando non ho colpito un server che ha restituito ex. 2.

RISULTATI NON RIUSCITI PER IL ’07 / 04/2018 ‘:

 C:\>set HH= C:\>if " " == " " goto addzero C:\>set HH=09 C:\>goto end C:\>set mn=31 C:\>set SS=48 C:\>set ms=59 C:\>set MM=4/ C:\>set DD=01 C:\>set YY=18 C:\>set CCYY=2018 C:\>set dts=20184/0109314859 C:\>set dateonly=20184/01 C:\>set monthlog=20184/ 

Tutte le date / timestamp contenevano un ‘/’ (errore nella denominazione dei file). Tutto ciò è dovuto alla differenza di stringa DATE e ai riferimenti sub-string. Il TEMPO andava bene. Anche con le stringhe dei guasti del mese (MM) e del giorno (DD) ho notato che le vars dell’anno a 2 e 4 cifre andavano bene (YY e CCYY). Come? Referenziamento negativo. Questa è diventata la più grande correzione per il mio script finale. Insieme alla sostituzione delle corde.

IL MIO NUOVO SCRIPT (Adoro il metodo usando wmic, questo è solo un modo alternativo che consente i 2 diversi tipi di ritorno per DATE usando solo DOS)

 01 @echo off 02 set str=%DATE% 03 set str=%str:/=% 04 05 set MM=%str:~-8,2% 06 set DD=%str:~-6,2% 07 set YY=%str:~-2% 08 set CCYY=%str:~-4% 09 10 set HH=%TIME:~0,2% 11 set HH=%HH: =0% 12 set mn=%TIME:~3,2% 13 set SS=%TIME:~6,2% 14 set ms=%TIME:~9,2% 15 16 set _dts=%CCYY%%MM%%DD%%HH%%mn%%SS%%ms% 17 set _dateonly=%CCYY%%MM%%DD% 18 set _monthlog=%CCYY%%MM% 19 @echo on 

GLI APPUNTI:

linea 2:

 'str' var holds the value returned from DATE. Could be formatted like ex. 1 or ex. 2, does not matter 

linea 3:

 this is string replacement, all '/' replaced with '' (null). ex. 1 - 'Wed 07/04/2018' >> 'Wed 07042018', ex. 2 - '07/04/2018' >> '07042018' 

linea 5:

 this is where negative referencing made both date strings equal (in a sense), month (MM) starts at '-8' characters from the end of the string in both examples, length of '2' 

linea 6:

 Same with day (DD), '-6' characters from end of string, length of '2' 

linea 7:

 2-digit year (YY) works as it did before (already used negative referencing) 

linea 8:

 4-digit year (CCYY) works as it did before as well 

linea 10:

 TIME always returns 2-digits in its hour (HH) position, it just doesn't have a leading '0' if less than 10, what it does return is a leading space ie %TIME:~0,2% will return ' 9' for 9:00 AM (not desired for date/timestamps) 

linea 11:

 string replacement to the rescue again, replace all spaces with '0', turns the ' 9' to '09' (exactly what we want) 

riga 12:

 minutes, seconds, milliseconds all work as they did previously, using sub-strings to avoid the colons (':') & the period ('.') in the time stamp ie 10:01:26.29 

RISULTATI DEL NUOVO SCRIPT:

 C:\>set str=07/04/2018 C:\>set str=07042018 C:\>set MM=07 C:\>set DD=04 C:\>set YY=18 C:\>set CCYY=2018 C:\>set HH= 9 C:\>set HH=09 C:\>set mn=42 C:\>set SS=26 C:\>set ms=48 C:\>set _dts=2018070409422648 C:\>set _dateonly=20180704 C:\>set _monthlog=201807 C:\>set str=Wed 07/04/2018 C:\>set str=Wed 07042018 C:\>set MM=07 C:\>set DD=04 C:\>set YY=18 C:\>set CCYY=2018 C:\>set HH=10 C:\>set HH=10 C:\>set mn=50 C:\>set SS=55 C:\>set ms=48 C:\>set dts=2018070410505548 C:\>set dateonly=20180704 C:\>set monthlog=201807 

Spero che questo ti aiuti. Non è unico o sconvolgente, solo un altro modo.