Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

SignUp Now!

Issue with CD_ENTER Alias

Jun
538
3
Now I've encountered a problem with the CD_ENTER alias. The help file says:

CD_Enter - TCC will execute this alias immediately after changing the current directory.

Note that it says that the alias will be executed AFTER the directory change has been made. However, look at this.

TCC(27.01.23): C:\>alias cd_enter
set newcwd=%1 & echo `%1=`%1 & echo oldcwd=%oldcwd & echo newcwd=%newcwd & dir a*

TCC(27.01.23): C:\>cd temp
%1=C:\temp
oldcwd=C:\
newcwd=C:\temp

Volume in drive C is Windows Serial number is a879:820d
TCC: (Sys) The system cannot find the file specified.
"C:\a*"
0 bytes in 0 files and 0 dirs
734,644,273,152 bytes free

TCC(27.01.23): C:\temp>

The alias displays some debugging information and then runs the command "dir a*" to generate a short (or empty) display with a header to show which directory is being examined. Note that the command was run not in the new directory "c:\temp" but in the old directory "c\". It seems to have run before the directory change had been completed.
 
Update. Things do seem to work if one changes the drive.

TCC(27.01.23): C:\>d:\
%1=D:\
oldcwd=C:\
newcwd=D:\

Volume in drive D is HardDisk Serial number is 8649:440d
Directory of D:\a*

[apps] [archive]
0 bytes in 0 files and 2 dirs
1,564,825,952,256 bytes free

TCC(27.01.23): D:\>

Nope. Things are more complicated still. If I now change to another directory on drive C, the DIR command runs in the old area on THAT drive (c:\) rather than the directory to which I'm changing.

TCC(27.01.23): D:\>tmp:
%1=C:\temp
oldcwd=D:\
newcwd=C:\temp

Volume in drive C is Windows Serial number is a879:820d
TCC: (Sys) The system cannot find the file specified.
"C:\a*"
0 bytes in 0 files and 0 dirs
734,644,137,984 bytes free

TCC(27.01.23): C:\temp>
 
Still more weirdness. I just used EREN (from a toolbar) to rename a subdirectory of the directory I'm logged into, and that triggered the CD_ENTER alias!!!

Here's a slightly edited version of the screen output. The last three lines are the output of the CD_ENTER alias.

TCC(27.01.23): C:\Users\Jay>eren %@quote[Mt_Auburn_files]

NewFileName=Mt_Auburn_Images
C:\Users\Jay\Mt_Auburn_files -> C:\Users\Jay\Mt_Auburn_Images
1 dir renamed
%1=C:\Users\Jay\Dropbox\genealogy\JGSGB\Mass-Pocha\2021-06
oldcwd=C:\Users\Jay\Dropbox\genealogy\JGSGB\Mass-Pocha\2021-06
newcwd=C:\Users\Jay\Dropbox\genealogy\JGSGB\Mass-Pocha\2021-06
 
I don't know what "EREN" is.

The CD_ENTER alias is definitely being executed immediately after the directory change is executed (with the Windows SetCurrentDirectory API). What's happening is that your alias is run before the environment is updated with the "=c:" variable that specifies the current directory for the drive. So when your "a*" filename is expanded in the DIR command, it's still using the old current directory variable.
 
Sorry, I use eren (like eset) so often that I forgot that it is my own btm file and not a built-in command. That's the least of the issues.

As I wrote, perhaps somewhere else, I even added a "delay 1" command before the "dir" command thinking that that would allow enough time for everything to settle down in the new directory. It did not help.

It's not just a matter of variable expansion either. In the real case, the alias was defined to run the autoex.btm file, and it would run in the old directory. I just tried the following:

cd_enter=echo Running CD_ENTER & delay 1 & if exist autoex.btm autoex.btm

When I change directories, autoex.btm runs, but in the directory I just left!
 
The "=:c" environment variable isn't being updated until after the CD_ENTER alias is executed.
Besides DIR, what commands are affected by that? That is, what commands will behave like the current directory is the old one?
 
We cross-posted. It happens for me with an external BTM file. It runs in the old directory.
 
Hmm. I've just been testing the very same alias definition, and now the autoex.btm file is never running, neither in the old nor the new directory.
 
Maybe this will help. Note that the two %@full[autoex.btm] expressions get expanded differently!

Code:
TCC(27.01.23): C:\>al cd_enter
echo Running CD_ENTER & delay 1 & echo Delayed 1 sec & echo if exist %@full[autoex.btm] %@full[autoex.btm]

TCC(27.01.23): C:\>dhm:
Running CD_ENTER
Delayed 1 sec
if exist C:\autoex.btm C:\autoex.btm C:\Users\Jay\Documents\DigitalHeritageMapping

I also tried using "%1\autoex.btm". In that case, both the IF argument and the command came out the same (but did not run).
 
Looks like it's not running because you have an ECHO in front of the IF.
 
I added the echo later to see what the command actually looked like. It wasn't running when the echo was not there. I just took it out again, and autoex.btm is never running.

Next I will try it in another tab or close TCMD and restart it. This is really bizarre.
 
I see some "Code:" in post #11. Did you get the buttons working?
 
Aha. As you noticed, Vince, the problem occurs when a batch file is run from the alias. Not only does it not work as expected, but eventually the TCC tab stops functioning properly. When I switched to another tab or opened a new tab, the original problematic behavior resumed.

I made the following change, and this seems to work.

Code:
TCC(27.01.23): C:\Users\Jay\Documents\Finance\FinNow>alias cd_enter
echo Running CD_ENTER & delay 1 & *dir /a:d
 
I don't understand. Given Rex's remarks, I'd expect the "*dir /a:d" to give results from the old directory.

Was that a "yes" (got the buttons working)? How?
 
Any internal command that is trying to expand a filename that doesn't include a full path.
That kinda takes the bite out of CD_ENTER.

And you can't even get around it by starting a transient instance (in the new directory) because it inherits the CD_ENTER alias even when it doesn't inherit aliases! Here's one started with START /LA.

Code:
v:\empty> alias
TCC: No aliases defined

v:\empty> alias cd_enter
TCC: Not an alias "cd_enter"

v:\empty> cd ..
This is CDENTER.BTM called by the CD_ENTER alias.

v:\>
 
You can workaround this whole mess by setting the "=drive:" variable yourself.

Below, check out the first line of CDENTER.BTM and notice how the DIR command executes in the NEW directory.

Code:
v:\> alias cd_enter
call v:\cdenter.btm

v:\> type cdenter.btm
set =%@drive[%_cwd]=%_cwd
dir /k /m zzzz*


v:\> cd empty\
TCC: (Sys) V:\cdenter.btm [2]  The system cannot find the file specified.
 "V:\empty\zzzz*"

v:\empty> cd ..
TCC: (Sys) V:\cdenter.btm [2]  The system cannot find the file specified.
 "V:\zzzz*"

v:\>
 
You can even do it in the alias itself.

Code:
v:\> alias cd_enter `set =%%@drive[%%_cwd]=%%_cwd ^^& call v:\cdenter.btm`

v:\> alias cd_enter
set =%@drive[%_cwd]=%_cwd & call v:\cdenter.btm

v:\> type cdenter.btm
dir /k /m zzzz*

v:\> cd empty\
TCC: (Sys) V:\cdenter.btm [1]  The system cannot find the file specified.
 "V:\empty\zzzz*"

v:\empty> cd -
TCC: (Sys) V:\cdenter.btm [1]  The system cannot find the file specified.
 "V:\zzzz*"

v:\>
 
There's no problem with UNC paths; they work with no fudging. So you might do something like this. The first line below will (might?) protect from a failed change of directory.

Code:
v:\> type cdenter.btm
if %_? != 0 quit
iff "%@instr[1,1,%_cwd]" == ":" then
    set =%@drive[%_cwd]=%_cwd
endiff
dir /k /m zzzz*

Code:
v:\> cdd d:\gnu\
TCC: (Sys) V:\cdenter.btm [4]  The system cannot find the file specified.
 "D:\gnu\zzzz*"

d:\gnu> cdd \\jj\d$\tc28
TCC: (Sys) V:\cdenter.btm [4]  The system cannot find the file specified.
 "\\jj\d$\tc28\zzzz*"

\\jj\d$\tc28> cdd no_exist
TCC: (Sys) The system cannot find the file specified.
 "no_exist"

\\jj\d$\tc28>
 
Vince,

I don't understand "set =%@drive[%_cwd]=%_cwd". When I run that, it produces an error message. Can an environment variable start with an equal sign?
 
There are hidden environment variables named "=c:", "=d:", and so on. They're relics from the MSDOS days. They keep track of a process's current directories on each of the various drives; issuing just "drive:" takes you to that drive's current directory. Here's an example from C_M_D (which lets you see them but not set them).

Code:
Microsoft Windows [Version 10.0.19042.985]
(c) Microsoft Corporation. All rights reserved.

v:\> cd /d d:\gnu

d:\gnu> cd /d v:\

v:\> echo %=d:%
d:\gnu

v:\> d:

d:\gnu>

I don't know why TCC won't let you set them. I'm not doing anything special. Here are a couple examples from TCC.

Code:
v:\> set =c:=c:\windows

v:\> c:

c:\windows>

This one isn't exactly kosher (because v:\empty isn't really the CWD on drive v:) but it makes a point.

Code:
v:\> set =%@drive[%_cwd]=%_cwd\empty

v:\> v:

v:\empty>

What error message do you get when you try set =%@drive[%_cwd]=%_cwd
 
I now have the follow definitions for the aliases:

Code:
TCC(27.01.23): C:\>alias cd_leave
set oldcwd=%1 & set newcwd=%2

TCC(27.01.23): C:\>alias cd_enter
set =%@drive[%_cwd]:=%_cwd & if %oldcwd NE %newcwd (if exist autoex.btm call autoex.btm)

This seems to be working. Hooray!
 
Are you sure about that? @DRIVE[%_CWD] already has a colon (:) in it and you have added another.

Also, with that, changing directory to a UNC path will cause TCC to hang (at least it did for me). That's why I wrote a more elaborate one and put it in the BTM.
 
Not here:

TCC(27.01.23): D:\Records\House\Landscaping>echo %@drive[%_cwd]
D

That's why I had to add the colon to prevent the error message and make the command work. Aha, I just checked the documentation, and it should return with a colon. Sure enough, I have a user function! I wonder why? I'll have to look at where I use it and consider removing it.

Since setting that variable is only needed when actually changing to a new directory, I updated it to

TCC(27.01.23): D:\Records\House\Landscaping>alias cd_enter
if %oldcwd NE %newcwd (set =%@drive[%_cwd]:=%_cwd & if exist autoex.btm call autoex.btm)

I probably could even move it into the IF EXIST test part, since the problem arises only when the alias actually tries to do something.
 
This morning I played around with a different strategy. Put all the sanity tests in one BTM and only call autoex.btm if the tests go OK. It works pretty well.

Code:
v:\> alias cd*
cd_enter=call v:\cdtests.btm && call autoex.btm
cd_leave=set oldcwd=%1 & set newcwd=%2

v:\> type v:\cdtests.btm
if %_? NE 0 .or. "%@instr[1,1,%_cwd]" NE ":" .or. %oldcwd EQ %newcwd quit 1

set =%@drive[%_cwd]=%_cwd

if not exist autoex.btm quit 1

quit 0
 
What is the purpose of the %_? NE 0 test?

Am I right that the second test,
"%@instr[1,1,%_cwd]" NE ":", is to cover references to UNC paths.

Is there a reason why you execute the set =%@drive[%_cwd]=%_cwd command even if autoex.btm does not exist? Doesn't the drive variable eventually get set right, just not in time for the code run from the alias?
 
What is the purpose of the %_? NE 0 test?
I think that would indicate that the attempted change of directory failed. I tested only a little. Even with automatic changes (no CD or CDD) _? is set to non-zero if the change fails. If I do cdd d:\I_dont_exist %newcwd is set to d:\I_dont_exist so your newcwd/oldcwd test won't catch it, but _? will be 2.
Am I right that the second test, "%@instr[1,1,%_cwd]" NE ":", is to cover references to UNC paths.
Yup. It's to make sure the second character is a colon.
Is there a reason why you execute the set =%@drive[%_cwd]=%_cwd command even if autoex.btm does not exist? Doesn't the drive variable eventually get set right, just not in time for the code run from the alias?
If you test for autoex.btm existence before fixing the "=drive:" variable, the test will be done in the wrong directory (as at the beginning of this thread). As to the second question, I think YES ... that's how I interpret Rex's remarks.

Now that I think of it, you could probably also throw in a test for %newcwd existing.
 
You know, UNC paths aren't a problem except that you don't want to do set =%@drive[%_cwd]=%_cwd (they don't need it and it screws things up). So here's a little modification to cdtests.btm that makes things work even if the CWD is a UNC path. My autoex.btm is pretty lame (see below).

Code:
v:\> alias cd*
cd_enter=call v:\cdtests.btm && call autoex.btm
cd_leave=set oldcwd=%1 & set newcwd=%2

v:\> type cdtests.btm
if %_? NE 0 .or. %oldcwd EQ %newcwd quit 1
if "%@instr[1,1,%_cwd]" EQ ":" set =%@drive[%_cwd]=%_cwd
if not exist autoex.btm quit 1
quit 0

v:\> type autoex.btm
echo %@files[*]

v:\> REM v: and \\jj\v$ are actually the same drive.

v:\> cdd d:\gnu

d:\gnu> \\jj\v$
106

\\jj\v$> v:\
106

v:\>
 
Vince,

Thanks so much for all your help with this. Here's what I have now for cdtests.btm.

Code:
@echo off

:: This script performs some tests and does some work for the cd_enter alias,
:: which can be defined as: cd_enter=batrun cdtests.btm && call autoex.btm

if %_? NE 0 quit 1
if not exist %newcwd quit 1
if %newcwd EQ %oldcwd quit 1
if "%@instr[1,1,%_cwd]" NE ":" quit 1

set =%@drive[%_cwd]=%_cwd

if not exist autoex.btm quit 1

quit 0

I have many commands defined by BTM files and use the alias BATRUN to make it easy to invoke them. It is defined as

call c:\commands\bat\%@name[%1].btm %2$.
 

Similar threads

Back
Top