Page 1 of 2

My UAC function

Posted: 05 Oct 2013 08:37
by Adrianvdh
Hi everyone.

I am having an issue with my UAC check function:

Code: Select all

:checkfileUAC
pause
set "/h="&set "/l="&set "/dl="&set "/ui="&set "/du="
for %%a in (%*) do (
        if "%%~a"=="/h" ( set "/h=true"
   ) else if "%%~a"=="/l" ( set "/l=true"
   ) else if "%%~a"=="/dl" ( set "/dl=true"
   ) else if "%%~a"=="/ui" ( set "/ui=true"
   ) else if "%%~a"=="/du" set "/du=true"
)
if defined /h set "UACcheckfile=%HostFileName%" && set "writeError=Writing hosts to file"
if defined /l set "UACcheckfile=%logdir%" && set "writeError=Writing log to file"
if defined /dl set "UACcheckfile=%logdir%" && set "writeError=Deleting log file"
if defined /ui set "UACcheckfile=%updateinfofile%" && set "writeError=Storing update information to file"
if defined /du set "UACcheckfile=%newversionupdatefile%" && set "writeError=Downloading new update file"
if exist "%UACcheckfile%" attrib -r "%UACcheckfile%"
for /F %%a in ('^(^(set "X=" ^< nul^)^>^>"%UACcheckfile%"^)2^>^&1') do (
goto Errorwritefiles )
exit /b


I call it when I write a log sting line to a file like this:

Code: Select all

call :checkfileUAC "/l" && if "%logmode%"=="Enabled" if "%logtype%"=="Detailed" echo [%time%] [Msg]>>"%logdir%"


What am I doing wrong?

I use it in my script like so as well an nothing, just jumps to the first label:

Code: Select all

choice /C 12r /N /M "Make your selection: "
if errorlevel 3 cls & goto restart
if errorlevel 2 ( set mainmenuvar=Text1
goto mainmenuloginput )
if errorlevel 1 ( set mainmenuvar=Text2
goto mainmenuloginput )

:mainmenuloginput
if "%logmode%"=="Enabled" call :checkfileUAC "/l" && if "%logtype%"=="Detailed" echo [%time%] [Msg: %mainmenuvar%]>>"%logdir%"
if errorlevel 2 goto 222
if errorlevel 1 goto 111

:333
echo No redirection label here
pause

:111
echo 111
pause

:222
echo 222
pause

exit


ANy idea?

Thanks
Adrianvdh

Re: My UAC function

Posted: 06 Oct 2013 03:35
by Adrianvdh
Any one?

Re: My UAC function

Posted: 06 Oct 2013 05:11
by aGerman
What's the purpose of that function? Do you try to figure out whether or not you are allowed to write into a certain file or directory?
"I am having an issue" is not an adequate error description btw. What figured you out if ECHO is ON?

Regards
aGerman

Re: My UAC function

Posted: 06 Oct 2013 06:19
by Adrianvdh
I am confused with what you are telling me?

That function there is because if the program need to write to a file and Access is denied, it would echo Done!. When it actually didn't write to that file and complete the task.

So? Could you help me with the function? It seems to error out when I call it.

Any advice?

Re: My UAC function

Posted: 06 Oct 2013 06:29
by foxidrive
Adrianvdh wrote:I am having an issue with my UAC check function:


aGerman obliquely asked the question "what exactly is the issue?"

Re: My UAC function

Posted: 06 Oct 2013 06:45
by aGerman
Why so complicated?

Code: Select all

@echo off &setlocal

echo(
echo "%~f0"
call :checkAccess "%~f0"
if errorlevel 1 (echo Access denied) else echo OK

echo(
echo "%SystemDrive%\pagefile.sys"
call :checkAccess "%SystemDrive%\pagefile.sys"
if errorlevel 1 (echo Access denied) else echo OK

echo(
pause
goto :eof

:checkAccess
>nul 2>&1 (>>"%~1" type nul) && (exit /b 0) || exit /b 1

Regards
aGerman

Re: My UAC function

Posted: 06 Oct 2013 12:27
by Adrianvdh
Sorry, I meant I wanted you the obviously test the code and see where my problem is, but I didn't say that. Sorry :)

But, your code does work nicely. Only it does not suite the way I need to function like mine. How can i change this.

I need it kinda like mine. So it uses switches and if the error level is 0 it will goto ErrorWritefile and if not exit /b

Any idea?

Thanks

Re: My UAC function

Posted: 06 Oct 2013 13:39
by aGerman
if the error level is 0 it will goto ErrorWritefile and if not exit /b


GOTO <AnyLabel> in a called function? What's next? How do you return to the point where the function was called?
Sorry but I don't get it.

Regards
aGerman

Re: My UAC function

Posted: 07 Oct 2013 07:51
by Adrianvdh
I need the technique to be like mine, the if errorlevel statement must be in the function.

And I need the use switches.

The main reason is my batch file writes to a log and there of over 500 entries. So I can't have an errorlevel statement under every line.
Basic how it works:

Code: Select all

if %log%==Yes call :Function /l && echo Log msg > log.txt


Do you understand now? :) (not being sarcastic :))

Re: My UAC function

Posted: 07 Oct 2013 15:11
by aGerman
Adrianvdh wrote:Do you understand now?

No sorry.
Is your problem the handling of the switches?

Code: Select all

@echo off &setlocal
call :checkfileUAC /l
echo(
call :checkfileUAC /ui /du
echo(
call :checkfileUAC /h /dl
echo(
pause
goto :eof

:checkfileUAC
for %%i in (/h /l /dl /ui /du) do (
  set "%%i="
  for %%j in (%*) do (
    if /i "%%i"=="%%~j" set "%%i=1"
  )
)
if defined /h echo /h defined
if defined /l echo /l defined
if defined /dl echo /dl defined
if defined /ui echo /ui defined
if defined /du echo /du defined
goto :eof


Try to write a simplified example (whole batch code) that shows the problem.

Regards
aGerman

Re: My UAC function

Posted: 08 Oct 2013 10:35
by Adrianvdh
Maybe it is the switches, I don't know. That switch work code is penpen's

But I will give it a shot and report back

Re: My UAC function

Posted: 08 Oct 2013 10:40
by Adrianvdh
Ok, just realised it is the choice.exe errorlevel handling.

I have a baisc setup here:

Code: Select all

:checkfileUAC
if "%~1"=="/h" set "UACcheckfile=%MainFileName%" & set "writeError=msg"
if "%~1"=="/l" set "UACcheckfile=%logdir%" & set "writeError=msg"
if "%~1"=="/dl" set "UACcheckfile=%logdir%" & set "writeError=msg"
if "%~1"=="/ui" set "UACcheckfile=%updateinfofile%" & set "writeError=msg"
if "%~1"=="/du" set "UACcheckfile=%newversionupdatefile%" & set "writeError=msg"
call :UACselectedfile
exit /b

:UACselectedfile
for /F %%a in ('^(^(set "X=" ^< nul^)^>^>"!UACcheckfile!"^)2^>^&1') do (
goto Errorwrite


Code: Select all

choice /C 12 /N /M "Make your selection: "
if errorlevel 2 ( set mainmenuvar=msg
goto mainmenuloginput )
if errorlevel 1 ( set mainmenuvar=msg
goto mainmenuloginput )
:mainmenuloginput
if "%logmode%"=="Enabled" call :checkfileUAC "/l" if "%logtype%"=="Detailed" echo [%time%] [Main menu user input status: %mainmenuvar%]>>"%logdir%"
if errorlevel 2 goto test2
if errorlevel 1 goto test1


The:

Code: Select all

if errorlevel 1 goto test1

is what is causing the problem I think. So if take the echo statement to logfile it would work, unless no.

Any idea?

Re: My UAC function

Posted: 08 Oct 2013 17:39
by penpen
I understand the problems aGernman has, as i assume, that i have the same problems:
Your problem is (still) unclear.
Basing on the code and the description you've given it is nearly impossible to guess the problem (all we can do is to check the syntax and guess what might happen, if we assume this or that).
Our problem in understanding your problem is we don't know the algorithm you have implemented.

If you have a problem, then you should always post:
1) a detailed description of the error; not to meet your semantical target may be insufficient, even if you give the semantical target: This is such a case.
So you should give the full algorithm (idea behind your (problematic) code (part)).
2) the (full) problematic code: That means all code lines from a verified error free state to an error state. So :Errorwrite part is missing as it is between your assumed error and the call of the problematic function.

If you assume that the problem is caused by errorlevel handling, then you should also post:
- what type of batch script you are using *.bat, *.cmd (->1), and
- the (idea behind the) algorithm: For example (i know it is not the full description):
Create a writing file handle to a file A and write nothing to it, supressing all errormessage by using "((set /p "=" <nul) >> A) 2>1" by to check if A is accessible.
To avoid exceptional exits this code is placed within a for loop.
(I'm sure you would have described it in another way, but without saying anything about that line(s), we only can assume it is code that works as expected if the syntax is correct.)
To make it clear you should not describe all lines in detail, it suffices if you say this block of lines should do this (the same for the complete for loop):
If it is not possible to write to file A then jump to label :Errorwrite, else do nothing.

If you assume the error handling part is the problem, then the optimal error description should contain this:
- which script type you are using (*.cmd, *.bat) (-> 1), and
- how and when you initialize/set the errorlevel (-> 1), and
- on important lines (this means, lines where the errorlevel may be changed by design): what case you are watching, and what errorlevel do you expect to be set in such a case,
- what happens in the :Errorwrite part (we cannot see it) (-> 2). I assume that's why aGerman has wrote this:
aGerman wrote:GOTO <AnyLabel> in a called function? What's next? How do you return to the point where the function was called?
(And the other comments for other parts that may be problematic, as we do not know what they do:
In which cases you are using the parameters; are they independent, or do they similar things: Maybe the order of those operations may be important, or if they interact in a special way.
But noone can say this, if noone knows for what they are good for.)

Maybe it is good if i give an example, to move you to our point of view:
What is the problem in this code:

Code: Select all

:computeSum
:: %%~1 result
:: %%~2 maximum (has to be >0)
set /A "%~1=(%~2*(%~2-(%~2/%~2)))/((%~2+%~2)/%~2)"
exit /B
This is (nearly) a very famous (alienated) function, so you might guess the problem, but if you don't see or know it, it is very hard to find the problem.

penpen

Re: My UAC function

Posted: 09 Oct 2013 09:09
by Adrianvdh
Ok I am sorry, I thought I said the problem in the first post but I forgot to :) but :( I wasted your time as well.

So...

How it work is I have a few variable file directories set...
Example a log dir ok

The log directory is set:

Code: Select all

set "logdir=%~d0%~p0Log.txt"


Ok so the UAC function would use switches. Ok
So... Quick I would echo to a log file:

Code: Select all

if "%logmode%"=="Enabled" call :checkfileUAC "/l" && if "%logtype%"=="Detailed" echo [%time%] [Msg]>>"%logdir%"


The "/L" in the calling of the function is to let the function know it is working with the logdir variable or the log file
Hence /L for log

So I have changed to function to make it more simple:

Code: Select all

if "%~1"=="/l" set "UACcheckfile=%logdir%" & set "writeError=Writing log to file"


The UACcheckfile variable is the functions only variable to set the file it is working with. OK
And the writeError variable is the Msg the user would see if the selected file is access denied. OK

So if the file is access denied it would goto Errorwritefiles
which would tell the user to problem


Now I found that the switch feature in the UAC function is the problem, but I will get to that in a second:

Code: Select all

:checklogUAC
for /F %%a in ('^(^(set "X=" ^< nul^)^>^>"%logdir%"^)2^>^&1') do (
set "writeError=Writing log to file"
goto Errorwritefiles )
exit /b

:checkupdateinfoUAC
if exist "%updateinfofile%" attrib -r "%updateinfofile%"
for /F %%a in ('^(^(set "X=" ^< nul^)^>^>"%updateinfofile%"^)2^>^&1') do (
set "writeError=Storing update information to file"
goto Errorwritefiles )
exit /b

etc


This was the old way of me using the function

That, (above) I had to have a set function's for every file I needed to check the UAC, but that was taking space in my batch file. So I wanted to shorten it and make
it more smarter. So I just had one function thing and for every file it need to work with it would use switches to do that. Ok


Now the switch problem:

So when the main batch file is starting the UAC function using the switch "/L" (for log file) has no problem, but when it is done loading it has to goto the main menu
for user input. That uses the choice.exe

Code: Select all

if "%logmode%"=="Enabled" call :checkfileUAC "/l" && if "%logtype%"=="Detailed" echo [%time%] [Main menu status: Loaded menu]>>"%logdir%"                  (WORKS FINE)
choice /C 12 /N /M "Make your selection: "
if errorlevel 2 ( set mainmenuvar=Msg
goto mainmenuloginput )
if errorlevel 1 ( set mainmenuvar=Msg
goto mainmenuloginput )
:mainmenuloginput
if "%logmode%"=="Enabled" call :checkfileUAC "/l" if "%logtype%"=="Detailed" echo [%time%] [Main menu user input status: %mainmenuvar%]>>"%logdir%"
if errorlevel 2 goto Test2
if errorlevel 1 goto Test1


Now the choice.exe's errorlevel interferes with the UAC function and the switch.

That is the problem. When it calls the UAC function the errorlevel statements are completely ignored and the goes to the first lable following

Code: Select all

:Test1
echo First
echo The label it come to because errorlevel does not work now


So that raps it up I guess :)

Sorry again penpen and aGerman for wasting your time with my stupidity and not posting the problem.
Now do you understand?

P.S. penpen: I think that is a calculator, the first switch is the first number and the second is the second?
but that is just me guessing

EDITED: I forgot to say, it is a .bat file, my program with the problem

Re: My UAC function

Posted: 09 Oct 2013 11:32
by penpen
Adrianvdh wrote:Now the choice.exe's errorlevel interferes with the UAC function and the switch.

That is the problem. When it calls the UAC function the errorlevel statements are completely ignored and the goes to the first lable following
If that is the problem, just store the result into a variable, right after the choice and use this variable with the if's.

Code: Select all

choice /C 12 /N /M "Make your selection: "
set "errno=%errorlevel%"
:: ...

::replace: if errorlevel 2 goto Test2
if %errno% GEQ 2 goto Test2
::replace: if errorlevel 1 goto Test1
if %errno% GEQ 1 goto Test1
This should fix this Problem.

Beside: The Problem in the small codeblock i've given above can better be seen, if you replace %~2 by n and shorten the expression:
(%~2*(%~2-(%~2/%~2)))/((%~2+%~2)/%~2)=(n*(n-(n/n)))/((n+n)/n)=(n*(n-1))/2
This formula computes the sum of all positive numbers up to (n-1).
As i defined %~2 to be the maximum value, the correct sum should have been computed by:(n*(n+1))/2.
So the '-' was wrong and has to be a '+' instead.

penpen