1.

Solve : I need hope (sorry!)?

Answer»

I have a script that calls dsrm to delete computer accounts. Some accounts have special "features" and dsrm will not remove them. I understand why, but my problem is that when dsrm fails, it sets the ERRORLEVEL to -2147016643 and I cannot test for it in my batch script.

more...
when i run the command from the commandline
Code: [Select]> dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt you get this error:
dsrm failed:cn=bob1,ou=workstations,dc=ourcompany,dc=com:The directory service can perform the requested operation only on a leaf object.

and if I then run Code: [Select]> echo %errorlevel% it returns -2147016643

However, if I ADD that same command on the line immediately after the dsrm command in my script, the script echos "0". Code: [Select] dsrm %CN% -noprompt >>%actlog%
echo %errorlevel%
Similarly, if I test using Code: [Select]IF ERRORLEVEL 1 or Code: [Select]IF /i %errorlevel% NEQ 0 the test always fails.

It APPEARS cmd shell has a problem with this errorlevel.

What don't I know?

\\uSlackr
i bet that dsrm sets errorlevel higher than cmd can handle, i mean 32 bit integer is highest number in cmd

you can try echo dsrm to file and check for errors:



Code: [Select]@echo off
dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt >dsrm_log.txt

for /f "tokens=1-3* delims=:" %%a in ('type dsrm_log.txt ^| findstr "failed"') do (
if not "%%a" equ "" (
echo.%%a
echo.%%c
)
)
pauseI have a follow up question. Can I get the output of stderr to be read by a for loop without first sending it to a file? That way I could run the dsrm in a for command and maybe find the results there.

Maybe something like:

Code: [Select]for /f "tokens=*" %a in ('dsrm .... &2>1') do ...
\\uSlackrQuote from: devcom on May 01, 2009, 02:26:35 AM


Code: [Select]@echo off
dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt >dsrm_log.txt

for /f "tokens=1-3* delims=:" %%a in ('type dsrm_log.txt ^| findstr "failed"') do (
if not "%%a" equ "" (
echo.%%a
echo.%%c
)
)
[/QUOTE]

devcom, what does the carat do in the type line? (type dsrm_log.txt ^| findstr "failed"). Is it an escape character?

\\uSlackr
Code: [Select]@echo off

for /f "tokens=1-3* delims=:" %%a in ('dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt 1>nul ^|findstr "failed"') do (
if not "%%a" equ "" (
echo.%%a
echo.%%c
)
)
try thisQuote from: devcom on May 04, 2009, 10:25:53 AM
Code: [Select]@echo off

for /f "tokens=1-3* delims=:" %%a in ('dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt 1>nul ^|findstr "failed"') do (
if not "%%a" equ "" (
echo.%%a
echo.%%c
)
)

'for' doesn't like the redirection characters in the command. I've tried a couple things to get around this to no avail.

Also it appears that dsrm sends the error message to stderr and therefore is not being captured by the for command. I'm currently working with this code:

Code: [Select] del %tempout%
dsrm %CN% -noprompt 2>>%tempout%
for /f "tokens=1,2 delims=: " %%a in (%tempout%) do (
echo b:%%b
if /i %%b EQU failed echo "failed"
)
to send stderr to a file and read it from there.

\\uSlackr





devcom, I need a little more help, if you please. I couldn't make your code work as the for command barfed on the >1. Here is the code I wound up with. It sends the stderr output of dsrm to a temp file and looks at that for results (I call is as a subroutine with the CN as a parameter)

Code: [Select]:DeleteAcct2
set CN=%1
if %MODE%==Prod (
del %tempout%
dsrm %CN% -noprompt 2>>%tempout% 1>nul
for /f "tokens=1,2 delims=: " %%a in (%tempout%) do (
if /i %%b EQU failed (
echo "Error deleting %CN%"
set /a ErrCount+=1
) else (
echo Computer account deleted: %CN%
set /a ActCount+=1
)
)
) else (
echo "Mode is %MODE% - not deleting, %CN% >>%inactlog%
)
goto :EOFThis seems to work, except the output of the command is two lines and this code attempts to process both lines:
Code: [Select]dsrm failed:CN=cn=bob1,ou=workstations,dc=ourcompany,dc=com:The directory service can perform the requested operation only on a leaf object.
type dsrm /? for help.
How can I stop the for loop from processing the second line?

about that last error you get
Code: [Select]@echo off

for /f "tokens=1-3* delims=:" %%a in ('dsrm cn=bob1,ou=workstations,dc=ourcompany,dc=com -noprompt 1>nul ^|findstr "failed"') do (
if not "%%a" equ "" (
echo.%%a
echo.%%c
)
)
in for loop you need to escape characters so it must look like 1^>nul


back to last question,
the easiest way would be using some kind of counter like this:

Code: [Select]setlocal enabledelayedexpansion

set num=0
for /f "tokens=1,2 delims=: " %%a in (%tempout%) do (
if /i %%b EQU failed (
if !num! equ 0 echo "Error deleting %CN%"
set /a num+=1
set /a ErrCount+=1
) else (
echo Computer account deleted: %CN%
set /a ActCount+=1
)

if you want ask question about why i use !! insted of %% google delayed expansionOK, this makes sense and I made it all work (well, almost). I now understand how to escape certain characters - and that's a good thing. Here's my current code:

Code: [Select]:DeleteAcct
::Disable and flag the account if not already disabled
set CN=%1
if %MODE%==Prod (
for /f "tokens=2 delims=: " %%c in ('dsrm %CN% -noprompt 2^>^&1 ^|findstr "failed" ') do (
if /i %%c EQU failed (
echo "Error deleting %CN%"
echo "Error deleting %CN%" >>%errlog%
set /a ErrCount+=1
) else (
echo "Computer account deleted: %CN%" >> %actlog%
echo "Computer account deleted: %CN%"
set /a ActCount+=1
)
)
) else (
echo "Mode is %MODE% - not deleting, %CN% >>%inactlog%
)
goto :EOF
The problem now is that if the delete suceeds, the output in the for command is nothing and the code below it doesn't execute. Thus I get to confirmation of the delete. I can work around it by "assuming" success, but we all know where that gets us. Any thoughts on that?


In fact, this solution depends on failure string always containing the word 'failed' .I'm starting to think batch scripting may not be the best solution for this...

\\uSlackrdevcom, thanks for the assist. Here's where I landed.

  • I modified the script to assume a successful delete and clean up if it fails. So I increment the delete counter and decrement it if there is a problem.
  • I then saw a post about having dsrm delete the problem objects the correct way. So, I added the -subtree switch - which makes me nervous. So here's the final code (well the delete routine)


Code: [Select]if %MODE%==Prod (
echo "Trying to delete computer account: %CN%" >> %actlog%
echo "Trying to delete computer account: %CN%"
set /a ActCount+=1
for /f "tokens=2 delims=: " %%c in ('dsrm %CN% -subtree -noprompt 2^>^&1 ^|findstr "failed" ') do (
if /i %%c EQU failed (
echo "Error deleting %CN%"
echo "Error deleting %CN%" >>%errlog%
set /a ErrCount+=1
set /a ActCount-=1
) else (
echo "Computer account deleted: %CN%" >> %actlog%
echo "Computer account deleted: %CN%"
set /a ActCount+=1
)
)
) else (
echo "Mode is %MODE% - not deleting, %CN% >>%inactlog%
)
goto :EOF



All in all, a good batch file exercise!


Discussion

No Comment Found