RuSs
RuSs

Reputation: 1812

Azure Cloud Service Startup task that needs to run a PowerShell script

All,

Note: I have updated the question after some feedback.

Thanks to @jisaak for his help so far.

I have the need to run a PowerShell script that adds TCP bindings and some other stuff when I deploy my Cloud Service.

Here is my Cloud Service Project:

enter image description here

Here is my Cloud Service Project and Webrole project: enter image description here

Here is my task in ServiceDefinition.csdef:enter image description here

And here is the PowerShell script I want to run: enter image description here

here is my attempt at the Startup.cmd: enter image description here

When I deploy I get this in the Azure log: enter image description here

And this in the powershell log: enter image description here

Any help would be very much appreciated.

I think I am nearly there but following other people syntax on the web doesn't seem to get me there.

thanks Russ

Upvotes: 1

Views: 3809

Answers (4)

SimonNZ
SimonNZ

Reputation: 41

I think the issue is that the working directory of the batch command interpreter when it runs Startup.cmd runs is not as expected.

The Startup.cmd is located in the \approot\bin\Startup directory but the working directory is \approot\bin.

Therefore the command .\RoleStartup.ps1 is not able to find the RoleStartup.ps1 as it is looking in the bin directory not in the bin\Startup directory.

Solutions I know to this are:

Solution 1: Use ..\Startup\RoleStartup.ps1 to call the RoleStartup.ps1 from Startup.cmd.

Soltuion 2: Change the current working directory in Startup.cmd so that the relative path .\RoleStartup.ps1 is found. I do this by CHDIR %~dp0 (see here) to change into the directory that contains Startup.cmd.

Solution 3: As Don Lockhart's answer suggested, do not copy the Startup directory to the output, instead leave it set as "Content" in the Visual Studio project. This means the files within it will exist in the \approot\Startup directory on the Azure instance. (You would then want to make sure that the Startup folder is not publically accessible via IIS!). Then update the reference to Startup.cmd in ServiceDefinition.csdef to ..\Startup\Startup.cmd, and update the reference to RoleStartup.ps1 in Startup.cmd to ..\Startup\RoleStartup.ps1. This works on the fact that the working directory is bin and uses ..\Startup to always locate the Startup directory relative to it.

Upvotes: 3

RuSs
RuSs

Reputation: 1812

Ok,

So I am coming back to this after many different attempts to make it work. I have tried using:

  • Startup config in the ServiceDefinition.csdef
  • I have tried registering a scheduled task on the server that scans the Windows Azure log looking for [System[Provider[@Name='Windows Azure Runtime 2.6.0.0'] and EventID=10004]]

Nothing worked either due to security or the timing of events and IIS not being fully setup yet.

So I finally bit the bullet and used my Webrole.cs => public override bool OnStart() method: enter image description here

Combined with this in the ServiceDefinition.csdef: enter image description here

Now it all works. This was not the most satisfying result as some of the other ways to do it felt more elegant. Also, many others posted that they got the other ways of doing it to work. Maybe I would have got there eventually but my time was restricted.

thanks Russ

Upvotes: 0

Don Lockhart
Don Lockhart

Reputation: 914

I've found it easier in the past to not copy the content to the output directory. I have approot\bin as the working directory. My startUp task element's commandLine attribute uses a relative reference to the .cmd file like so:

enter image description here

The .cmd file references the PowerShell script relatively from the working directory as well:

PowerShell -ExecutionPolicy Unrestricted -f ..\StartUp\RoleStartup.ps1

Upvotes: 0

Martin Brandl
Martin Brandl

Reputation: 58931

You don't need to set the executionpolicy within your cmd - just call the script. Also, you should use a relative path because you can't rely that there is C disk.

Change your batch to:

powershell -executionpolicy unrestricted -file .\RoleStartup.ps1

Right click on the RoleStartup.ps1 and Startup.cmdin Visual Studio and ensure that the Copy to Output directory is set to copy always.

If this still doesn't work, remove the startup call in your csdef, deploy the service, rdp into it and try to invoke the script by yourself to retrieve any errors.

Edit:

Try to adopt your script as below:

Import-Module WebAdministration

$site = $null

do # gets the first website until the result is not $null
{
    $site = Get-WebSite | select -first 1
    Sleep 1
}
until ($site)

# get the appcmd path
$appcmd = Join-Path ([System.Environment]::GetFolderPath('System')) 'inetsrv\appcmd.exe'

# ensure the appcmd.exe is present
if (-not (Test-Path $appcmd))
{
    throw "appcmd.exe not found in '$appcmd'"
}

# The rest of your script ....

Upvotes: 0

Related Questions