% date% produce resultados diferentes en el archivo por lotes cuando se ejecuta desde tareas progtwigdas en Server 2016

El archivo de proceso por lotes ejecuta robocopy y crea un archivo de registro de robocopyServer_% date% .txt

Cuando el archivo por lotes se ejecuta manualmente, el resultado es robocopyServer_aaaa-mm-dd.txt

Cuando el archivo por lotes se ejecuta desde Tareas progtwigdas, el resultado es robocopyServer_Tue (o lo que sea el día de la semana), y no hay extensión de archivo.

Este archivo de proceso por lotes se ejecutó impecablemente en el servidor 2012R2 (tareas manuales o progtwigdas).

% date% o date /t no siempre es confiable ya que depende de la región y la configuración del usuario. A continuación, le mostramos cómo puede obtener una fecha universalmente válida:

 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% 

Esto reproducirá la fecha actual en el formato aaaa-mm-dd.

Debe crear un perfil de Windows para el usuario que se está utilizando para ejecutar la Tarea y configurar las configuraciones regionales y el formato de fecha bajo ese perfil.

El formato de las cadenas de variables de entorno DATE y TIME depende de la configuración regional de Windows, tal como se define para la cuenta utilizada.

Se puede obtener una cadena de fecha / hora independiente de la región utilizando la herramienta de línea de comandos de administración de Windows WMIC .

Usando la línea de comando

 wmic OS GET LocalDateTime /VALUE 

salidas UTF-16 Little Endian codificadas por ejemplo:

 LocalDateTime=20170621095402.953000+120 

Hay dos líneas vacías, luego la línea con la fecha / hora local actual en formato YYYYMMDDHHmmSS.microsegundo ± desplazamiento UTC en minutos y dos líneas más vacías.

Estos datos se pueden usar con un código de lote como este:

 @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% 

De interés para los nombres de archivos y carpetas es solo la cadena de fecha / hora entre el signo igual y el punto decimal, que es la razón por la que se utilizan tokens=2 delims==. opciones for /F tokens=2 delims==. para obtener solo 20170621095402 asignado a la variable de ciclo I cuyo valor se asigna junto a la variable de entorno FileNameDate .

La variable de entorno FileNameDate se reformatea utilizando sustituciones de cadena para obtener solo la cadena de fecha en el formato YYYY-MM-DD que se imprime para la verificación resultante en 2017-06-21 .

La ventaja de usar WMIC para obtener la fecha / hora local es independiente en la configuración de región de Windows. La desventaja es que la ejecución del comando lleva bastante tiempo (1 a 2 segundos) en comparación con el uso de las variables de entorno DATE y TIME a las que se accede en unos pocos microsegundos.

El comando FOR tiene problemas para analizar correctamente la salida Unicode. Interpreta la secuencia de bytes 0D 00 0A 00 0D 00 0A 00 al final de la salida WMIC debido a las dos líneas vacías como 0D 0D 0A, es decir, como dos retornos de carro y un avance de línea. Esto resulta en la interpretación de las dos últimas líneas vacías al final de la salida de WMIC como una sola línea con un solo retorno de carro como cadena.

Eso es muy a menudo un problema ya que el resultado del set "EnvironmentVariable=%%I" está con %%I expandiéndose al retorno de carro al eliminar la variable de entorno ya definida anteriormente con el valor correcto.

Hay varias soluciones para solucionar este error de análisis Unicode del comando FOR . Es posible adjuntar & goto Label para salir del bucle con un salto a :Label debajo del bucle FOR una vez que el valor se asigna a la variable de entorno para evitar encontrarse con este problema.

Otra solución es la que se usa en este código. Debido al uso de la opción WMIC /VALUE el nombre de la propiedad y su valor se envían a la misma línea. El comando FOR ejecuta el comando SET debido a tokens=2 solo cuando podría dividir la línea actual en al menos 2 subcadenas (tokens) usando igual signo y punto como delimitadores debido a delims==. . Pero el final analizado incorrecto de la salida de WMIC es para FOR una línea que contiene solo un retorno de carro y, por lo tanto, no tiene un segundo token. Por esa razón, FOR también hace caso omiso de las líneas vacías mal analizadas.

Consulte ¿Cómo corregir el error de sobreescritura de variables al analizar el resultado? y cmd de alguna manera está escribiendo texto chino como salida para obtener detalles sobre el problema de análisis de FOR en la salida codificada UTF-16 LE.

Para comprender los comandos utilizados y cómo funcionan, abra una ventana de símbolo del sistema, ejecute allí los siguientes comandos y lea con atención todas las páginas de ayuda que se muestran para cada comando.

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

Tuve un problema similar al OP y me encanta el método usando wmic @Regejok. Aquí está mi solución para manejar cadenas exclusivas devueltas por DOS DATE (solución de EE. UU .: lo sentimos, no hay otro SO de la región para probar, pero esto se puede refactorizar bastante rápido para otras regiones).

Tenía servidores que devolvían cadenas diferentes para% DATE% (date / t).

ex. 1 – mié 07/04/2018 (cuerda perfectamente fina)

ex. 2 – 07/04/2018 (otra cadena perfectamente fina pero falló mi secuencia de comandos por lotes debido a la referencia de subcadena)

Estaba usando esta secuencia de comandos seleccionando subcadenas de FECHA Y HORA para crear fechas / marcas de fecha y hora para registrar y archivar archivos:

GUIÓN ORIGINAL

 @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 

Por favor, no juzgues el código. 🙂 Se pone mejor.

RESULTADOS PARA ‘Mié 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 

Esto funcionó muy bien con el ex. 1 cuerda Me salté el día abreviado (miércoles) y todo estaba bien. Hasta que golpeé un servidor que devolvió ex. 2.

RESULTADOS FRACASADOS PARA ’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/ 

Todas las indicaciones de fecha / hora contenían un ‘/’ (error al nombrar los archivos). Todo esto se debe a la diferencia de cadena DATE y las referencias de subcadena. El TIEMPO estaba bien. Incluso con el fallo en las cadenas del mes (MM) y del día (DD) noté que los vars del año de 2 y 4 dígitos estaban bien (AA y CCYY). ¿Cómo? Referencia negativa. Esta se convirtió en la mejor solución para mi script final. Junto con el reemplazo de cuerdas.

MY NEW SCRIPT (Todavía me encanta el método que usa wmic, esta es solo una forma alternativa que permite los 2 tipos de devolución diferentes para DATE solo con 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 

NOTAS:

línea 2:

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

línea 3:

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

línea 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' 

línea 6:

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

línea 7:

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

línea 8:

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

línea 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) 

línea 11:

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

línea 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 

RESULTADOS DE NUEVA ESCRITURA:

 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 

Espero que esto ayude. No es único o devastador, solo otra forma.