Execute cmd from Power shell script

Dec 20, 2010 at 4:39 PM

Hi All,

I am writing my deployment ps script. I need your help in figuring out the following.

I have a cmd file which calls an msi and passes paramters. I am calling this deploy.cmd file from a powershell script. How can i achive this? 
I am trying the following but it does not work. 
Invoke-Command {& "D:\deploy\ABC_Installed\ABC (QA)_1.0.7.2\en-us\ABC_QA.cmd"} 
It tends to just print the contents of the cmd but does not execute it. So, is it possible to execute a cmd from with in a Power Shell script, if so, how? 
PS - It's not possible to change the cmd to a power shell script since this is already been used for production deployments.

Coordinator
Dec 20, 2010 at 8:03 PM

This should work for calling out to batch scripts, executables, or other PowerShell scripts:

& "D:\deploy\ABC_Installed\ABC (QA)_1.0.7.2\en-us\ABC_QA.cmd"

Regards,

Jason

Dec 21, 2010 at 8:19 AM

Hi Jason,

Thanks for your reply. I am may be missing something here.

This is what my cmd looks like,

Msiexec /i ABCInstaller.msi ^
DB.SERVER=ABC\QA ^
APPLICATION.ENV.TYPE=Qa ^
SVCIDENTITY=SVC-QA@ABC.com ^
SVCPASSWORD=xxx ^
LOCAL.EMAILING="true" ^
EMAIL.GMAT="tarun.arora@abc.com" ^
EMAIL.GMATR="tarun.arora@abc.com" ^
EMAIL.SUCCESSFUL.VALIDATION.SUBJECT="[QA] Successful validation of ABC Message" ^
/lv "ABC_Installer_QA_Log.txt" 

This is what my powershell script looks like,

# Assigning Build Number and Drop Location for the MSI in scope
$buildNumber = $TfsDeployerBuildData.BuildNumber
$dropLocation = $TfsDeployerBuildData.DropLocation

# Assign values
if($buildNumber -eq $null)
{
$buildNumber = $args[0]
$dropLocation = $args[1]
}

# Move old uninstall folder to Archive folder
Move-Item "D:\deploy\ABC_Uninstalled\*" "D:\deploy\ABC_Archive" -force

# Move old build folder to uninstalled folder
Move-Item "D:\deploy\ABC_Installed\*" "D:\deploy\ABC_Uninstalled" -force

# Logging
Add-Content -Path "C:\Log\TfsDeployer_Log.txt" -Value $dropLocation
Add-Content -Path "C:\Log\TfsDeployer_Log.txt" -Value $buildNumber

# Copy the msi from drop location to local physical drive
Copy-Item $dropLocation "D:\deploy\ABC_Installed" -recurse
Add-Content -Path "C:\Log\TfsDeployer_Log.txt" -Value "Copied the Msi to D:\deploy\Installed"

# Start execution
& "D:\deploy\ABC_Installed\$buildNumber\en-us\ETRM_QA.cmd"

This is the email that i get once tfs deployer has processed the request,

Team Project/Build: Etrm to ETRM (QA) Quality Change: * to Under Investigation Drop Location: \\TFSBDEV01LONUK\Drops\ETRM (QA)\ETRM (QA)_1.0.6.31 Build Uri: vstfs:///Build/Build/6539 Script: PrepareForInvestigation.ps1 Executed on Machine: TNKTSAP01LONUK 
Output: C:\WINDOWS\system32>Msiexec /i ABCInstaller.msi ^
DB.SERVER=ABC\QA ^
APPLICATION.ENV.TYPE=Qa ^
SVCIDENTITY=SVC-QA@ABC.com ^
SVCPASSWORD=xxx ^
LOCAL.EMAILING="true" ^
EMAIL.GMAT="tarun.arora@abc.com" ^
EMAIL.GMATR="tarun.arora@abc.com" ^
EMAIL.SUCCESSFUL.VALIDATION.SUBJECT="[QA] Successful validation of ABC Message" ^
/lv "ABC_Installer_QA_Log.txt" /passive T

 The cmd file is not executed :-(

 

Dec 21, 2010 at 9:30 AM

So.....

If i create a simple cmd file (Copy.cmd) which does the following,

Xcopy "C:\Folder 1"  ^
"C:\Folder 2"

And call it in powershell script

& "C:\Copy.cmd"

 

It works.

However if you tend to use Msiexec it just prints the cmd file rather than executing it

So if my (copy.cmd) contains the following

Msiexec /i EtrmInstaller.msi

And the powershell script is

& "C:\Folder 1\ETRM_QA.cmd"

Then the output is

C:\Documents and Settings\tarora\My Documents>Msiexec /i EtrmInstaller.msi

Tp

But nothing is executed!

Dec 21, 2010 at 4:10 PM

I think i have found where the problem is,

& "C:\Folder 1\ETRM_QA.cmd"

 

 

 Works fine if you keep the msi in the 'My Documents' following folder.

So, the question is, why does it look for the msi in the 'My Documents' folder? Is there a way to set the command prompt to start from where the drop location is?

Dec 21, 2010 at 4:11 PM

Done and dusted, the fix is,

The fix is

$path = "C:\ABC (QA)_1.0.7.2\en-us”
pushd $path
.\ABC_QA.cmd
popd

Coordinator
Dec 21, 2010 at 7:34 PM

In general I recommend against relying on the current directory in scripts, but this is especially important when mixing PowerShell and non-PowerShell because the current directory can get out of sync.

In your cmd file, if you are expecting the msi to be in the same folder as the cmd, I would change the first line to this:

msiexec /i "%~dp0ABCInstaller.msi" ^

For more information on what %~dp0 means if you aren't familiar with it, type "help call" from a Command Prompt, but the short answer is it resolves to the drive and path of the running script. You can do similarly with the line that specifies the log file.

If you need script-relative paths in PowerShell, I recommend defining this variable early in the ps1:

$PSScriptRoot = $MyInvocation.MyCommand.Path | Split-Path -Resolve

I choose the name PSScriptRoot because that is the same variable that PowerShell provides automatically if you are writing a PS Module.

Regards,

Jason