Why is change directory not working when SETLOCAL ENABLEDELAYEDEXPANSION is used

This question was already answered on stackoverflow here. The relevant part of the answer is the following:

The only thing that is not obvious is that "localization of environment changes" doesn't just include environment variables, but also includes the current directory, and the delayed expansion and extensions states.

So you need to 'endlocal' before changing directory, making your script

@echo off

SETLOCAL ENABLEDELAYEDEXPANSION

set nop=4

for  /l %%z in (1, 1, %nop%) do (
set x=%%z
echo !x!
)

endlocal

chdir /d D:\app\

ENABLEDELAYEDEXPANSION is a parameter passed to the SETLOCAL command. It's not this parameter that causes the problem, but the command itself. (Try setlocal without any parameters and see that the same thing happens.)

The setlocal command is described as:

Starts localization of environment variables in a batch file. Localization continues until a matching endlocal command is encountered or the end of the batch file is reached.

In particular, this means that if you use setlocal in a script, all environment variable changes are lost at the end unless you take measures.

One of the variables that is returned is the CD environment variable which holds the current directory. This means that the current directory is returned and is no longer D:\APP. It seems like the CD command failed, but in fact it did work, but was undone when the .bat script terminated.