AWS CodeDeploy Powershell Script fail to execute

I have an app that I am deploying using AWS Codedeploy to an EC2 instance running Windows Server 2012 R2 with code deploy installed. Codedeploy is installed onto the instance using the recommended CloudFormation template and has been working fine up until now.

I've created a simple script that should create a folder on the file system and a virtual directory within IIS on the Default Web Site, the script is below:

# Are you running in 32-bit mode?
#   (\SysWOW64\ = 32-bit mode)

if ($PSHOME -like "*SysWOW64*")
{
  Write-Warning "Restarting this script under 64-bit Windows PowerShell."

  # Restart this script under 64-bit Windows PowerShell.
  #   (\SysNative\ redirects to \System32\ for 64-bit mode)

  & (Join-Path ($PSHOME -replace "SysWOW64", "SysNative") powershell.exe) -File `
    (Join-Path $PSScriptRoot $MyInvocation.MyCommand) @args

  # Exit 32-bit script.

  Exit $LastExitCode
}

# Was restart successful?
Write-Warning "Hello from $PSHOME"
Write-Warning "  (\SysWOW64\ = 32-bit mode, \System32\ = 64-bit mode)"
Write-Warning "Original arguments (if any): $args"

# Your 64-bit script code follows here...

# Install IIS Web Server administrator
Import-Module -Name ServerManager
Import-Module WebAdministration
Install-WindowsFeature Web-Server

$folderLoc = 'C:\inetpub\imageprocessorcache'

if (-not (Test-Path $folderLoc))
{
    # Create new folder
    New-Item $folderLoc -type directory

    # Get rule and add new rule to it
    $existingAcl = Get-Acl $folderLoc
    $permissions = 'Users', 'FullControl', 'ContainerInherit, ObjectInherit', 'None', 'Allow'
    $rule = New-Object -TypeName System.Security.AccessControl.FileSystemAccessRule -ArgumentList $permissions
    $existingAcl.AddAccessRule($rule)

    # Apply new rule to the folder
    $existingAcl | Set-Acl -Path $folderLoc

    # Get the ACL for the folder for output purposes
    Get-Acl -Path $folderLoc
}

$virtualPathLocation = 'IIS:\Sites\Default Web Site\imageprocessorcache'

# Check if the virtual directory exists in IIS
if (-not (Test-Path $virtualPathLocation))
{
    # Create it because it doesn't exist yet
    New-WebVirtualDirectory -Name 'imageprocessorcache' -PhysicalPath $folderLoc -Site 'Default Web Site'
}

Here's the appspec file that I have:

version: 0.0
os: windows
files:
  - source: MyWebsite
    destination: c:\temp\CodeDeployFiles
hooks:
  BeforeInstall:
    - location: \Deployment Scripts\IISCreateImageProcessorVirtualDirectory.ps1
      timeout: 900

For some reason the script does not execute as part of the deployment process, it seems as though it is skipped or just fails quietly.

I am able to remote desktop, navigate to the temp folder on the EC2 instance (where the files are copied to during the deployment by CodeDeploy) and right mouse click on IISCreateImageProcessorVirtualDirectory.ps1 and choose 'Run with Powershell' on the copied script. This works just fine, the folder and the virtual directory are created.

I have had success running .ps1 scripts in the past using code deploy with my current setup, but this one doesn't work or leave any error messages.

What could be causing the script not to run?

Thanks for your help.

Codedeploy Log with error

[2016-11-24 21:10:54.909] [d-DSQ9EQ28J]Script - .\Powershell Scripts\IISCreateImageProcessorVirtualDirectory.ps1
[2016-11-24 21:10:55.112] [d-DSQ9EQ28J][stderr]Processing -File 'C:\ProgramData/Amazon/CodeDeploy/c979dfe5-9d99-4cee-870d-cc9e3cb518bc/d-DSQ9EQ28J/deployment-archive/.\Powershell' failed because the file does not have a '.ps1' extension. Specify a valid Windows PowerShell script file name, and then try again.

Solution 1:

This is how the CodeDeploy agent executes your script (source):

powershell.exe -ExecutionPolicy Bypass -File <absolute_path_to_your_script_here>

So try changing your hook to this:

hooks:
  BeforeInstall:
    - location: .\Deployment Scripts\IISCreateImageProcessorVirtualDirectory.ps1
      timeout: 900

The operator .\ allows you to run a script in the current directory.

General Troubleshooting

If you need to troubleshoot further, you can find your recent deployments here: C:\ProgramData\Amazon\CodeDeploy\

And your logs per deployment here: C:\ProgramData\Amazon\CodeDeploy\DEPLOYMENTGROUPIDGOESHERE\DEPLOYMENTIDGOESHERE\logs

You can write to host or stdout/stderr in your scripts, and if they are being run that output will end up in these logs.

Solution 2:

I finally got my Powershell scripts to be run by CodeDeploy once again. It seems that I gave myself the issues by putting the ps1 scripts into a folder within my deployment package and not on the root with my appspec.yml file.

I think it might be something to do with a message that I read when I read the help file of powershell.exe by executing powershell.exe /?:

-File
Runs the specified script in the local scope ("dot-sourced"), so that the functions and variables that the script creates are available in the current session. Enter the script file path and any parameters. File must be the last parameter in the command, because all characters typed after the File parameter name are interpreted as the script file path followed by the script parameters.