Azure configuration with multiple tasks possible? - azure

We have a third party .NET application which comes with its' own deployment tool. This deployment tool generates a custom startup.cmd file. We have an option to modify the CFG file but not the cmd file.
I would like to have my own cmd file. Could someone please confirm whether multiple tasks are allowed in a cloud service definition file?
For example...
<Startup>
<Task commandLine=”thirdpartyPropietryStartup1.cmd” executionContext=”elevated” />
<Task commandLine=”startup\startup2.cmd” executionContext=”elevated” />
</Startup>

Multiple startup tasks should work according to the documentation.
It is not that explicit but it states that
simple tasks are executed synchronously, one at a time, in the order specified in the ServiceDefinition.csdef file.
which would make no sense if multiple tasks would not work.
If there are issues you could always create a combined.cmd which runs thirdpartyPropietryStartup1.cmd and then startup\startup2.cmd (unless your executionContext should be different).

Related

How to get Azure Cloud startup environment variables to persist

For Azure Cloud Services, when you define Startup Tasks in your ServiceDefinition.csdef file, you have the option of setting environment variables. It looks something like this:
<Startup>
<Task commandLine="install.cmd" executionContext="elevated" taskType="simple">
<Environment>
<Variable name="YourEnvironmentVariable" value="YourValue"/>
</Environment>
</Task>
</Startup>
That environment variable only seems to persist for the duration of the Task it's defined in (in this case, running install.cmd). If you RDP into your cloud instance and check the environment variables, you won't see it listed there. Is there a way to get that environment variable to persist?
It doesn't appear as if the Azure Cloud Framework gives you an easy way to do this, but it's possible. I persisted the Environment Variable by having install.cmd manually set it. In my case, install.cmd called a PowerShell script that did the following:
# Make the environment variables defined in ServiceDefinition.csdef persist
[Environment]::SetEnvironmentVariable("YourEnvironmentVariable", "$Env:YourEnvironmentVariable", "Machine")
You could accomplish this without using PowerShell. It would look something like this:
setx YourEnvironmentVariable "%YourEnvironmentVariable%" /M

Schedule IIS Reset on Azure Cloud Service

I have an Azure Cloud Service that requires some warm up when an application pool comes online (typically 5-10 minutes). Because of this, I like to schedule an IIS\App Pool recycle during off hours. When my recycle takes place mid-day, I get users yelling at me (and I prefer to not get yelled at)
What I've been doing is remoting into the VM, add a cmd file to a local disk and create a scheduled task that runs the cmd file:
net stop "World Wide Web Publishing Service"
net start "World Wide Web Publishing Service"
My problem is, periodically PaaS services get "refreshed", so randomly, any code\files I manually publish to a cloud service VM disappear. I need to remote back into the machines and re-add my cmd and scheduled tasks.
I know cloud services allow you to run startup tasks and the like. Can I do something similar to startup tasks that would allow me to package this cmd file when I publish my app, but schedule these commands externally? If so.. how?
Startup tasks may execute any unattended app/installer you include in your .cspkg. You need to make sure the cmd file in question is bundled properly (e.g add configureSchedule.cmd to project, make sure it's copied to output directory).
Since you're attempting to set up scheduling, you'll likely need to run your cmd in elevated mode:
<Startup>
<Task commandLine="configureSchedule.cmd" executionContext="elevated" taskType="simple" >
<Environment>
<Variable name="MyVersionNumber" value="1.0.0.0" />
</Environment>
</Task>
</Startup>
The better solution is to change the AppPool settings to recycle at a specific time. Do this from a startup script like David Makogan mentioned.
Take a look here:
Set default app pool recycling via command line
Set the recycling time:
https://www.iis.net/configreference/system.applicationhost/applicationpools/add/recycling/periodicrestart
Be sure to uncheck the "regular time interval", otherwise there will be recycle events during the day.
Also, you are stopping the WWW service, a quicker way is to only recycle the application pool. That way a new application pool is started, while the old one handles the last request from users. So there is (almost) no connectivity loss
appcmd recycle apppool /apppool.name: Marketing

Azure start-up task to run after the website is created

I've created a start-up task for an Azure website that does the following:
Creates an AppPool
Converts a Virtual Directory into a Virtual Application
I've created a powershell script that carries out these tasks.
I've set up the startup element in the Service Definition
<Startup>
<Task commandLine="MyStartup.cmd" executionContext="elevated" taskType="simple">
</Task>
</Startup>
All good so far.
However, I've found out, rather late, that:
IIS may not be fully configured during the startup task stage in the
startup process, so role-specific data may not be available.
I take this to mean that the website may not exist on IIS when the powershell script is run. I've tested the script and sure enough it fails because it can't find the virtual directory on IIS.
My question is: Is there a way to ensure the powershell script is run after the website is created on IIS?
Please note, I don't really want to use Microsoft.WindowsAzure.ServiceRuntime.RoleEntryPoint.OnStart if possible.
Thanks in advance.
I followed on from #kwill's suggestion and created the following:
Powershell:
while(!($myWeb = Get-Website -name "*MyWeb*")){
Write-Host "Website not installed. Waiting 30 seconds..."
Start-Sleep 30
}
# Proceed with installation
and configuration
<Task commandLine="MyBackground.cmd" executionContext="elevated" taskType="background">
</Task>
This works.
Check out the role architecture diagram at http://blogs.msdn.com/b/kwill/archive/2011/05/05/windows-azure-role-architecture.aspx. You can see that the startup tasks are executed before IISConfigurator creates the application pool for your website. This means that the only place you can make modifications to the apppool is in OnStart.
I haven't tried this, but you could create a background type startup task which will let the rest of the startup process (ie. running IISConfigurator) proceed while your startup task is still running, and then within that startup just loop until the virtual directory is detected.

Azure COM Objects

I am trying to move a website I am hosting on a server with IIS over to an Azure web site. I'm using a COM object but I'm not sure if I can register this? I found some posts talking about uploading the dll and registering it on start up but the article seems to be missing. Is this possible?
I had this exact problem registering legacy COM Components on Azure. I documented my methodology here:
AspPDF and AspJPEG on Windows Azure
Igorek is correct, you will need to use a Web Role to achieve this. The solution above is based on a single Web Role with a startup script to run regsvr32 as a startup task.
To summarise, there are essentially two parts to achieving this. First create a batch file to run the regsvr32 command:
chcp 1252>NUL
regsvr32 /s .\library\my-com-class.dll
exit /b 0
Then define a startup task in your ServiceDefinition.csdef file:
<Startup>
<Task commandLine="mybatchfile.cmd" executionContext="elevated" taskType="simple" />
</Startup>
This will trigger the command file to run on deployment.
You cannot register a COM object within an Azure Website. You will need to upgrade to Web Roles in order to do this. Registration of com object can happen during the startup scripts then.

Azure: How to execute a startup task delayed?

I have two Sites within my WebRole and have defined a Startup task.
The first line works fine, it creates a new App pool for me:
%WINDIR%\system32\inetsrv\appcmd.exe add apppool /name:"VCPool" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
Now I would like to change my second to this new created AppPool, but adding another line right after, doesn't help.
%WINDIR%\system32\inetsrv\appcmd.exe set app "WebRole_IN_0_VC/" /applicationPool:"VCPool"
It seems the second site is somehow not yet ready.
How can I delay my task by 30 seconds or delay appcmd.exe slightly?
Unless there is a way to create dependencies for this startup task that it shall only be executed when that second site is up and running?
Any help would be highly appreciated,
Many Thanks,
Is there a way to delay this execution by 30 seconds to make sure the second site is up and can be changed?
Update:
Thanks for the hints. I have made further investigation into this matter. I have found OnStart() event.
1) But since I am using silverlight and simply wrap the existing Web project in the Cloud Roles project, I wouldn't have a WebRole.cs as such. Can I just add it to my Silverlight Web project and use it there? Or is it recommended creating a WebRole project from scratch and make it to replace the Silverlight Web project alltogether?
2) Regarding the <Runtime/> tag in the service definition, do I simply add it like this? Would it have any security implications when the webrole runs elevated?
<WebRole name="WebRole" enableNativeCodeExecution="true" vmsize="ExtraSmall">
<Runtime executionContext="elevated"/>
<Sites>
<Site name="WebRole" physicalDirectory="./WebRole">
...
</Sites>
</WebRole>
3) Last but not least how do I run a cmd file or in fact this line
%WINDIR%\system32\inetsrv\appcmd.exe set site /site.name:"WebRole_IN_0_VC" /[Path='/'].applicationPool:"ASP.NET v4.0" >>Log.txt
in the OnStart() method?
Can you explore using PowerShell scripts for performing these tasks. PowerShell has a way to sleep thread. Something like
Batch file
%WINDIR%\system32\inetsrv\appcmd.exe add apppool /name:"VCPool" /managedRuntimeVersion:"v4.0" /managedPipelineMode:"Integrated"
powershell -command "Set-ExecutionPolicy Unrestricted" 2>> err.out
powershell .\sleep.ps1 2>> err.out
%WINDIR%\system32\inetsrv\appcmd.exe set app "WebRole_IN_0_VC/" /applicationPool:"VCPool"
I have not tried but it should work. See this post to know about Powershell integration.
The site, as you have discovered, is created after the 'Task' section runs. Instead, run your code from the 'OnStart' event. The site will have been created by that point. You may need to update your Service Definition file to run your role 'elevated' This can be done by adding this tag:
<Runtime executionContext="elevated"/>
Edited
To answer your further questions:
1) Whatever project you have, you should just be able to add the RoleEntryPoint class. You may have to do this manually.
2) Adding the runtime tag won't add any significant risk to your deployment.
3) Create a cmd file to put your command in (i.e. OnStart.cmd) and use some code like this:
System.Diagnostics.Process.Start("OnStart.cmd")
More information on starting a process here: http://msdn.microsoft.com/en-us/library/53ezey2s.aspx
For those interested ... I just blogged about how to execute AppCmd startup tasks on Windows Azure configure IIS websites - including finding the site by web role name, and executing it delayed so that the site config is already created by Azure's IISConfigurator.exe.
More here: http://mvolo.com/configure-iis-websites-windows-azure-startup-tasks-appcmd/.
Thanks,
Mike

Resources