How to detect if folder exist (and ignore file with same name ;))

Today I experienced really annoying bug with one of my scripts. It is checking if one folder (in quite complex structure) exists(If Exist Folder…), if it does, it perfoms some actions and send few mails. However after some time it started to behave strange – it was sending sometimes mail when folder was definitely not there etc.


 It didnt take me long time to discover what was the problem – another team was using file without extension with same name as my folder :) So I rewrote today this script to detect ONLY folder and ignore files with same name.


 How to do it? Its quite simle


 If Exist Folder\nul.ext Send-Mail


For example If Exit C:\Temp\test\nul.ext will be True if folder test exists, however not if file test exists.


You just need to be very careful – Windows doesnt allow you to have folder and file with same name in same folder:


C:\Temp>mkdir Test


C:\Temp>Echo.>test
Access is denied.


C:\Temp>rmdir Test


C:\Temp>Echo.>test


C:\Temp>mkdir Test
A subdirectory or file Test already exists.


C:\Temp>

How to dial using default RAS connection

TuxExplorer send me question how to dial connection using default RAS connection – I wrote small script (two liner) to do that:


 


For /f “usebackq tokens=1-3″ %%i IN (`reg query “HKCU\Software\Microsoft\RAS AutoDial\Default” /v DefaultInternet ^| find /i “REG_SZ”`) Do If /i #%%j# EQU #REG_SZ# Set Int.DefaultRASConnection=%%k

If Defined Int.DefaultRASConnection Start RasPhone -d %Int.DefaultRASConnection%


It should work, I just connected using this script :)


 Martin

How to specify timeout for script?

Maybe you run into this issue before – you want to run some script/utility (for example query user), but you know that it hangs sometimes and you would like to have some kind of timeout utility. There is way how to handle this in batch scripts using two concurent scripts:


Create three scripts, for example Scripts.cmd, Pause.cmd and Detection.cmd


Content of Script.cmd is


Set Int.Command=%~1
Set Int.Pause=%~2


Set Int.PauseTitle=%Random%PauseScript
Set Int.DetectionTitle=%Random%DetectionScript


Start /Min Cmd /c Detection.cmd
Start cmd /c exit /b 1
Start /Min /Wait cmd /c Pause.cmd
If %ErrorLevel% EQU 0 (
 Echo Failure
) Else (
 Echo Success
)
 


Content of Pause.cmd is


Title %Int.PauseTitle%
Sleep %Int.Pause%
Taskkill /f /t /fi “WINDOWTITLE eq %Int.DetectionTitle%”


Content of Detection.cmd is


Title %Int.DetectionTitle%
%Int.Command%
Taskkill /f /t /fi “WINDOWTITLE eq %Int.PauseTitle%”
Exit /b 0


Then call Script.cmd with two arguments, command to perform and timeout. For example Script.cmd “pause” “10″.


It will try to execute command “Pause”, and if it took more then 10 seconds, it will kill this process and report it using errorlevel.


Quite simple, however functional. This way it is also fast, because if your scripts finished faster, it will automatically remove Sleep subroutine that will hold main script execution.


I am using this procedure right now to detect hanging sessions on servers – and it turns out to be really simple and functional, so I wanted to share :)

Security issue with PowerShell

Hi guys,


 after (too) long time I can finally return to Powershell (I spend few months creating batch framework to manage citrix servers, right now it is about 980 scripts).


I was playing with Get-Credential:


$Operator = get-credential


I provided my username/password. If I have a look at object, I can see Password property and GetPassword() method. I tried this, Output is in System.Security.SecureString.


I was just thinking how PowerShell is handling explicit authentication, so I had a look at available properties and methods – GetNetworkCredential grab my eye, so I tried it. And I was really surprised by output:


mzugec>$operator.GetNetworkCredential()


UserName                   Password                   Domain
——–                           ——–                         ——
mzugec                       YouPwdInPlainText     MyDomain


 


Replace YouPwdInPlainText with your actual password! So be aware, if you are using get-credentials, it is very easy to retrieve your actual password!

How to use global alias for application.

Maybe you already noticed, but I am very lazy person – that is also why I started to work with scripts ;)


I am so lazy that I really dont like to use mouse – I prefer just keyboard. And I like to use simple combinations to make my life easier.


Now I will introduce you “technology” that will save you hours (per year ;)) – global aliases for applications. For example if I wanted to run Internet Explorer, I usually pressed WinKey+R (run dialog), typed iexplore and hit enter.


But you can create global aliases (I know it is not correct name for this,however it describes the behavior perfectly) by modifying HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths.


Lets make test:


  • Create key and name it ie.exe
  • Modify (Default) and change its value to C:\Program Files\Internet Explorer\iexplore.exe
  • Open Run dialog
  • input IE
  • Hit enter

New internet explorer window should appear. I like to use this for almost everything I working with periodically (ie, icq etc.) and I am VERY surprised when I must used another computer and it is not working ;)


If you will be interested, I can write similar article how to replace some integrated utilities (for example Notepad or Calculator) same way as Process Explorer is replacing Task Manager.


Martin


 

Minimize to tray for all applications?

I run into problem when my new laptop have too small screen for all my windows and I wanted to somehow improve the way how to work with these windows.


 I started using TaskSwitchXP - utility that is working similar way as standart Alt + Tab, however with expanded functionality. What I liked about this tool is that it is fully customizable, so you can do with it whatever you want.


After some testing I found the most interesting functionality (and it is really working) – you can change behavior of minimizing applications.


If you select “_” on top-right of normal application window, application is minimized to task bar. I always prefered applications that had option to minimize to tray to save some space. But with TaskSwitchXP you can change this behavior – if you RIGHT-CLICK on “_”, application is automatically minimized to systray (of course application doesnt need to support this behavior).


This completely changed my situation with multiple applications opened – now I feel happy again :)

How to handle If operations?

Just a quick note how to write correct If structures in batch files…


Lets have a look at this line:


 If %1 EQU Success Echo Looks fine


Looks fine, right? But you could run into multiple issues:


  • If you run it and Variable doesnt exist, you will receive error message “Success was not expected at this time”. Reason is that cmd will try to execute command If EQU Success Echo Looks fine, however it is missing one argument.
  • If variable is success and not Success, it wont work.

Regarding first issue, common workaroung is to use If “%1″ EQU “Success” Echo Looks fine, however this is also not best was how to handle this issue. Problem is if your variable contains ” signs. Therefore best way (IMHO) is to use “#”. So it should looks like If #%1# EQU #Success# Echo Looks fine.


Regarding second issue, always use “/i” parameter – this means that comparison is not case sensitive.


 I personally also recommend to use %~1 at beginning. This means that quotes (“) are removed from parameter specified. If you apply quotes AGAIN to this (“%~1″), it means that this parameter is always parsed with quotes (regardless of if they were provided in original parameter). That means that Script.cmd “testing” is the same as Script.cmd testing.


So my line would looks like


If /i #”%~1″# EQU #”Success”# Echo Looks fine


Martin

Escape character in batches

I spend some time working batch frameworks and I started to think more about presentation finally… How the scripts looks like etc.


This is going to be (extremely) short topic, about two or three posts, however I hope so I could save you some time.


 First I decided to separate regular output with sections. Section should looks like <Section name>, after this there should be some tab and finally text of the script:


<Important warning>
     Earth is going to explode soon
     Starting with evacuation.


If you would like to have output like this, first problem you will run into will be “The syntax of the command is incorrect.”. This is because “<” and “>” are acting as redirection characters. If you want to ignore their function and use them “as-is”, you must specify escape character. This is “^” for batches. So instead of Echo <Important warning> you should use Echo ^<Important warning^>.


This is maybe useless with above example, however sometimes this is extremely important to understand when writing more complex scripts.


Consider following example: You want to retrieve some variable from file. File name is test.ini, variable name is TestParameter and you want to store value in variable TestValue.


You will probably create script which is similar to following:


For /f “usebackq delims== tokens=1,*” %%i IN (`Type test.ini`) Do If /i #%%i# EQU #TestParameter# Set TestValue=%%j


This syntax is correct – however if you are using biiiiiiiiiiiiiiig ini files (as I usually do ;)), your script will be quite slow. Wouldnt it be better to use something like


For /f “usebackq delims== tokens=1,*” %%i IN (`Type test.ini | Find /i TestParameter=`) Do If /i #%%i# EQU #TestParameter# Set TestValue=%%j


?


So you will do If/Set procedure only for matching lines (there will be most of the time only one)?


Problem is that if you run this line, interpreter will separate it to two parts:


For /f “usebackq delims== tokens=1,*” %%i IN (`Type test.ini | Find /i TestParameter=`) Do If /i #%%i# EQU #TestParameter# Set TestValue=%%j


So it will try to send first part through pipe to Find.com. Of course this wont work at all. However if you use escape character for pipe sign (“|”), it will work!


For /f “usebackq delims== tokens=1,*” %%i IN (`Type test.ini ^| Find /i TestParameter=`) Do If /i #%%i# EQU #TestParameter# Set TestValue=%%j