View all posts filed under 'Cmd.exe Shell'

Batch Scripting Howto – Where is it?

Thursday, 5. November 2009 7:38

Initially I intended to migrate the stuff related to batch scripting to the new blog as well. Due to lack of time and motivation I decided to postpone this task or rather to wait if I receive requests like “I’m wondering if you are considering bringing back your old content back”

I will tell you a secret: the old site is still online – check Batch Howto. In order to avoid trouble with the new site I needed to remove the permalinks, therefore I’m afraid your bookmarks/favorites to old site content may be broken.

Category:Cmd.exe Shell, MS-DOS Batch, Scripting | Comments (2) | Author: Frank-Peter

How To Script Downloads With BITS?

Tuesday, 27. May 2008 20:30

When it comes to large file downloads one should use a download manager which at least is able to resume broken downloads. Windows has a built-in download manager service called Background Intelligent Transfer Service(BITS). Some of us at Login Consultants (including me) prefer to script large file downloads with the Microsoft’s BITS Admin Utility – Bitsadmin. This article explains how to use Bitsadmin to download a file.

The BITS service is built into Windows XP, Vista, Server 2003, and Server 2008. For example the Windows Automatic Update, WSUS 3.0, or Microsoft SCCM 2007 depend on BITS to transfer files like Windows Updates and software packages. For one thing BITS has been designed for robustness over slow or unstable network connections, and for another thing BITS is a background process that economizes on bandwidth usage. If a download does not complete due to a network problem or restart of your machine, BITS will automatically try to continue the download from where it left off, and repeat this until the whole file has been retrieved. BITS file transfers can be invoked and managed from the command line with the Bitsadmin utility which is part of the Windows Support Tools.

Please note that this article applies to Bitsadmin 3.0 and the version of BITS that is included in Windows Vista SP1.

In order to download a file with Bitsadmin, respectively BITS, you need to type a series of Bitsadmin commands to create a download job, to add the file the the job, eventually to set credentials and proxy settings, and finally to start the download job. Bitsadmin has many command line switches, for this see also Bitsadmin’s help by typing "bitsadmin" at the command prompt. For our purposes we need the switches CREATE, ADDFILE, SETNOTIFYCMDLINE, COMPLETE, SETCREDENTIALS (maybe), and RESUME.

Let’s say we want to download the english copy of the Automated Installation Kit (AIK) for Windows Vista SP1 and Windows Server 2008. This is a real large download, the ISO file is about 1350 MB. Since the URL string is very large the examples below don’t contain the complete download URL. If you want to reproduce the examples you must use this URL: http://download.microsoft.com/download/9/c/d/9cdfa30e-5901-40e4-b6bf-4a0086ea0a6a/6001.18000.080118-1840-kb3aikl_en.iso

1. Create Job

First of all, we need to create a new download job with Bitsadmin /CREATE

set bits_job=%random%
bitsadmin /create %bits_job%

Bitsadmin will confirm job creation by echoing the job GUID like "Created job {58C6770A-AB4E-477C-8944-33246EC8791E}". For now, the job is created and its state is suspended. (Therefore, we will need to resume the job later in order to start the download process.)

2. Add File

Now we can add the file to the job with Bitsadmin /ADDFILE. We need to specify the job name, the download URL, and the file’s local name.

bitsadmin.exe /addfile %bitsjob% ...aikl_en.iso C:\Downloads\aik_en.iso

Again, Bitsadmin will confirm the action. (Hint: if you want to add multiple files to a job take a look at Bitsadmin’s switch /ADDFILESET which reads each file’s remote URL and local name from a text file.)

3. Optional Settings

The job is still in suspended state, and we are almost ready to start the download. But to start with we should pay attention to three important and useful Bitsadmin switches: COMPLETE, SETNOTIFYCMDLINE, and SETCREDENTIALS

By default, Bitsadmin doesn’t tell anything about a finished file transfer. Even worse, though BITS may have downloaded a file completely you won’t find it unless you have completed the job explicitly. To kill two birds with one stone we will use Bitsadmin /SETNOTIFYCMDLINE to launch Bitsadmin /COMPLETE as loon as the transfer is finished. (Virtually, SETNOTIFYCMDLINE enables you to set a command line to execute for notification when the file download is finished.)

bitsadmin /setnotifycmdline %bitsjob% "%SystemRoot%\system32\bitsadmin.exe" "%SystemRoot%\system32\bitsadmin.exe /complete %bitsjob%"

Maybe the file is located on a password protected web server. In this case you can add credentials to a job using Bitsadmin /SETCREDENTIALS. This time you have to go without an example. Please refer to Bitsadmin’s syntax help by typing "bitsadmin" at the command line.

4. Start/Resume Download

Finally, we are ready to resume the download job with Bitsadmin /RESUME:

bitsadmin /resume %bitsjob%

Now, BITS is downloading the file in the background. Since we have defined the launch of an according job completion command on transfer completion we can just wait and see… or check out some Bitsadmin command lines:

5. Monitor or Cancel Job

How to display information about the BITS job?

bitsadmin /info %bitsjob%

How to retrieve the size of the BITS job?

bitsadmin /getbytestotal %bitsjob%

How to retrieve the number of bytes transferred?

bitsadmin /getbytestransferred %bitsjob%

How to monitor the BITS copy manager?

bitsadmin /monitor

How to cancel the BITS job?

bitsadmin /cancel %bitsjob%

How to delete all BITS jobs?

bitsadmin /reset

6. Write a Shell Script

The batch file below, Bits-Download.cmd, simplifies the usage of Bitsadmin:

@ECHO OFF
:: NAME
::	Bits-Download.cmd
::
:: SYNOPSIS
::	Downloads a remote file with BITS.
::
:: SYNTAX
::	Bits-Download remote_url local_name
::
:: DETAILED DESCRIPTION
::	The Bits-Download.cmd batch file uses BITS to download
::	the given remote file. Bits-Download.cmd requires the
::	BITS Admin Utility Bitsadmin.exe.
::
:: NOTES
::	Bits-Download.cmd was developed and tested on Windows Vista.
::
:: AUTHOR
::	Frank-Peter Schultze
::
:: DATE
::	00:18 21.07.2008

SETLOCAL

	IF "%2"=="" (
		TYPE "%~f0" | findstr.exe /R "^::"
		GOTO :END
	)

	SET bits_job=tigbits%RANDOM%

	SET remote_url="%~1"
	IF NOT DEFINED remote_url (
		ECHO %~n0 : Cannot bind argument to parameter 'remote_url' because it is empty.
		GOTO :END
	)

	SET local_name="%~2"
	IF NOT DEFINED local_name (
		ECHO %~n0 : Cannot bind argument to parameter 'local_name' because it is empty.
		GOTO :END
	)

	(SET /P remote_user=User name ^(leave empty if not required^): )
	IF DEFINED remote_user (SET /P remote_pass=Password: )

	bitsadmin.exe /CREATE /DOWNLOAD %bits_job%

	bitsadmin.exe /ADDFILE %bits_job% %remote_url% %local_name%

	bitsadmin.exe /SETNOTIFYCMDLINE %bits_job% "%SystemRoot%\system32\bitsadmin.exe" "%SystemRoot%\system32\bitsadmin.exe /COMPLETE %bits_job%"

	IF DEFINED remote_user IF DEFINED remote_pass (
		bitsadmin.exe /SETCREDENTIALS %bits_job% SERVER BASIC %remote_user% %remote_pass%
	)

	bitsadmin.exe /RESUME %bits_job%

:END
ENDLOCAL

Category:Cmd.exe Shell, Scripting, Utilities | Comment (0) | Author: Frank-Peter

How To Wait As Long As A Program (And Its Sub Processes) Are Running?

Friday, 24. August 2007 0:10

Recently, some talented colleagues of Login Consultants and I worked out a robust batch subroutine that waits for the termination of a setup (or whatever) program including those processes that have been started by that program.

In most cases the START /WAIT command meets the requirement that is to stop batch processing as long as the (setup) program is running. For example, this works fine for MSI based installations. All you have to do is START /WAIT msiexec.exe … and you’re done. The same applies to other installer types like Inno, Wise, or NSIS.

But many InstallShield setups and proprietary setups (like the Oracle installer) do actually nothing more than to call a second process (javaw.exe in case of Oracle) and terminate immediately afterwards. Since START /WAIT does only watch over the specified program it would pass back script control to cmd.exe although the actual setup isn’t yet finished.

TASKLIST.EXE is an external command of Windows XP Professional, Windows Server 2003, and newer. It displays a list of processes and services with their Process ID (PID) for all tasks. Using filters you can query for a specific process.

The batch file below, Start-Wait.cmd, uses TASKLIST.EXE. Before actually starting the specified program Start-Wait.cmd gets the PIDs of all processes that have the same name like the specified sub process (for example javaw.exe). This step is important in order to make sure that the script later checks the correct sub process. Let’s say that you want the script to check javaw.exe as a sub process of the Oracle installer on a Citrix terminal server. Maybe at the same time you have started the Management Console (which is based on javaw.exe)… Got it? Talking of terminal servers: Start-Wait.cmd cuts TASKLIST.EXE‘s output down to the processes owned by the user who is executing the script. When done with making out the ignorable PIDs the script start the specified program. Afterwards it uses TASKLIST.EXE again in order to identify the PID of the specified sub process. Finally, the Start-Wait.cmd checks each 5 seconds if the process with that PID is still running.

@ECHO OFF

:: NAME
::	Start-Wait.cmd
::
:: SYNOPSIS
::	Suspend script activity as long as the specified program and its sub
::	process are running
::
:: SYNTAX
::	Start-Wait program subprocess
::	Start-Wait "program arguments" subprocess
::
:: DETAILED DESCRIPTION
::	The Start-Wait.cmd batch file suspends script activity as long as the
::	specified program and its sub process are running. You can use it in a
::	batch script to wait for a setup program to complete completely.
::
:: AUTHOR
::	Frank-Peter Schultze
::
:: DATE
::	17:02 04.04.2008

SETLOCAL ENABLEDELAYEDEXPANSION

IF "%1"=="/?" (
	TYPE "%~f0" | findstr.exe /R "^:: "
	GOTO :END
)

SET Program=%~1
IF NOT DEFINED Program (
	ECHO %~n0 : Cannot bind argument to parameter 'Program' because it is empty.
	GOTO :END
)

SET SubProcess=%2
IF NOT DEFINED SubProcess (
	ECHO %~n0 : Cannot bind argument to parameter 'SubProcess' because it is empty.
	GOTO :END
)

SET IGNOREPIDS=

::-----	First, get all PIDs that we don't want to check later by mistake
FOR /F "tokens=2 skip=3" %%i IN (
	'tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %SubProcess%"'
) DO (
	SET IGNOREPIDS=!IGNOREPIDS! %%~i
)

::-----	Start the program and wait for its termination
START /WAIT %Program%

::-----	Now, get the PID of the sub process that we need to check
FOR /F "tokens=2 skip=3" %%i IN (
	'tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %SubProcess%"'
) DO (
	ECHO #%IGNOREPIDS%# | find.exe "%%~i" >NUL || CALL :TASKWAIT %SubProcess% %%~i
)

:END
ENDLOCAL
EXIT /B

::
:TASKWAIT
::
	ECHO Sleep 5s . . .
	ping.exe -n 6 -w 1000 127.0.0.1 >NUL
	tasklist.exe /FI "USERNAME eq %USERDOMAIN%\%USERNAME%" /FI "IMAGENAME eq %1" /FI "PID eq %2" 2>NUL | find.exe "%1" >NUL && GOTO %0
	ECHO %1 stopped.
	EXIT /B

Category:Cmd.exe Shell, Scripting | Comment (0) | Author: Frank-Peter

Solution4 – Free Scripting Framework

Monday, 13. August 2007 14:00

These days, the Login Consultants are introducing their free scripting framework Solution4 (S4) that automates the setup and management of Citrix Presentation Server environments. With S4 the Login Consultants provide an impressive example how to use Windows Shell Script (Batch Files) in order to realize a complex automation solution.

Solution4 is more than a couple of scripts, it is considered as a scripting framework that helps to realize the setup and management of a Citrix Presentation Server environment in a highly efficient manner.

You can use S4 to automatically…

  • … create an OU stucture with groups, and administrative accounts
  • … install and configure Citrix Presentation Server
  • … install and configure applications
  • … restrict application access (based on NTFS security)
  • … publish applications
  • … manage user profiles and the user desktop
  • … configure CMC settings

Let me refer to Brian Madden elaborating on S4: Login Consultants releases a massive framework that can automate pretty much everything

Category:Cmd.exe Shell, Note, Scripting | Comment (0) | Author: Frank-Peter

How To Make My Script Terminal Server Aware?

Tuesday, 20. September 2005 20:04

In order to detect if a script was started in a terminal server session the script can check the SESSIONNAME environment variable which is only defined if the Terminal Services are installed on Windows 2000 Server, Windows Server 2003, and Windows XP clients (or newer). When a client connects via a RDP or ICA (Citrix) session, this variable is a combination of the connection name, i.e. "RDP-Tcp" or "ICA-Tcp", followed by a pound symbol "#" and then the session number in three figures "nnn". When logging on directly to the machine, this variable returns "Console".

The VScript function below returns True if the SESSIONNAME variable resolve to a value beginning with "RDP" or "ICA"

If fctCheckTS Then
	WScript.Echo "I am running on TS"
End If

Function fctCheckTS

	Dim objWsh
	Set objWsh = WScript.Shell

	Select Case Left(objWsh.ExpandEnvironmentStrings("%SESSIONNAME%"),3)
		Case "RDP", "ICA"   fctCheckTS = True
		Case Else           fctCheckTS = False
	End Select

End Function

Terminal Server aware batch files can use this approach:

CALL :Test-TermServer
IF %TermServer%==True ECHO I am running on TS
GOTO :EOF

:Test-TermServer
SETLOCAL

	SET _=False
	IF DEFINED SESSIONNAME (
		IF /I %SESSIONNAME:~,3%==RDP SET _=True
		IF /I %SESSIONNAME:~,3%==ICA SET _=True
	)

ENDLOCAL & SET TermServer=%_%
GOTO :EOF

Category:Cmd.exe Shell, Scripting, VBScript | Comment (0) | Author: Frank-Peter

How To Change The CD/DVD Drive Letter?

Thursday, 8. September 2005 23:16

The cmd.exe command line below uses mountvol.exe in order to delete the old and to set the new drive letter assignment (where E: represents the old and Z: the new drive letter):

FOR /F %V IN (
	'mountvol.exe E: /L'
) DO (
	mountvol.exe E: /D
	mountvol.exe Z: %V
)

The FOR /F command parses a mountvol command that returns the CD-ROM drive’s volume name. The volume name looks like this:

\\?\Volume{1d926311-403a-11d9-94c8-806d6172696f}\

If FOR /F successfully determines a volume name it executes two mountvol commands, the first one deletes the current drive letter assignment the seconds one sets the new drive letter assignment (using the volume name).

Category:Cmd.exe Shell, Scripting, Utilities | Comment (0) | Author: Frank-Peter

How To Determine The Default User’s Profile Path?

Thursday, 8. September 2005 20:42

The profiles directory, the "All Users" and "Default User" profile folders are values under this registry key:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList

In order to determine the default user’s profile path you need to concatenate the REG_EXPAND_SZ value ProfilesDirectory and the REG_SZ value DefaultUserProfile.

Dim strDefProfile
strDefProfile = GetDefaultUserProfile

Function GetDefaultUserProfile

	Dim objWsh, strRegKey, strProfDir, strDefUser

	Set objWsh = WScript.CreateObject("WScript.Shell")
	strRegKey = "HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList"
	strProfDir = objWsh.RegRead(strRegKey & "\ProfilesDirectory")
	strDefUser = objWsh.RegRead(strRegKey & "\DefaultUserProfile")
	GetDefaultUserProfile = Replace(strProfDir & "\" & strDefUser, "%SystemDrive%", _
	                        objWsh.ExpandEnvironmentStrings("%SystemDrive%"))
	Set objWsh = Nothing

End Function

The script below shows how to determine the default user profile path using cmd.exe shell scripting and reg.exe:

 @Echo Off

::Get the profiles directory
  Set Reg.Key=HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList
  Set Reg.Val=ProfilesDirectory
  For /F "Tokens=2*" %%A In (
   'Reg Query "%Reg.Key%" /v "%Reg.Val%" ^| Find /I "%Reg.Val%"'
  ) Do Call Set ProfilesDirectory=%%B

::Get the default user profile directory
  Set Reg.Val=DefaultUserProfile
  For /F "Tokens=2*" %%A In (
   'Reg Query "%Reg.Key%" /v "%Reg.Val%" ^| Find /I "%Reg.Val%"'
  ) Do Call Set DefaultUser=%%B

::Set DEFAULTUSERPROFILE Variable
  Set DEFAULTUSERPROFILE=%ProfilesDirectory%\%DefaultUser%

Category:Cmd.exe Shell, Scripting, VBScript | Comment (0) | Author: Frank-Peter