Microsoft Azure Startup Task Not Executing - azure

I have a simple file in the root of my Web project (which is tied to a Web worker role). The file is named Startup.cmd. This file contains the following line: dir > directory.txt. It executes properly when I run it from the command line and outputs a list of the directory contents to file named directory.txt as you would expect. Similarly, the line ECHO Write this line to file > output.txt does not appear to work either.
Inside ServiceDefinition.csdef for my Azure Cloud Service project, I have the following lines:
<WebRole name="Website" vmsize="Small">
<Startup>
<Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple"></Task>
</Startup>
....
</WebRole>
I believe it is finding the file, because I have tried changing the path and it will throw a build error that it cannot find it. The issue is that when I check my /bin/ directory after debugging to the Azure Debugging Environment, I see Startup.cmd (I have it set to Copy always) but I do not see directory.txt. I'm not sure of another way to confirm that it executed properly.

I found the following MSDN article useful: http://msdn.microsoft.com/en-us/library/hh180155.aspx.
As a result, I made some changes to my Startup.cmd file. I changed the command to:
ECHO The current version is %MyVersionNumber% >> "%TEMP%\StartupLog.txt" 2>&1
EXIT /B 0
However, this did not appear to put the output in my temporary directory for my system: C:\Users\username\AppData\Local\Temp. I'm going to presume this is because the Azure Compute Emulator uses a different temp directory I am unaware of.
I changed my Startup.cmd to:
ECHO The current version is %MyVersionNumber% >> "c:\temp\StartupLog.txt" 2>&1
EXIT /B 0
And updated my configuration to:
<WebRole name="Website" vmsize="Small">
<Startup>
<Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple">
<Environment>
<Variable name="MyVersionNumber" value="1.0.0.0" />
<Variable name="ComputeEmulatorRunning">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/#emulated" />
</Variable>
</Environment>
</Task>
</Startup>
...
</WebRole>
And this did appear to write the file to C:\temp\ upon starting the debugger.

Related

Azure Cloud Service warmup IIS

referring to this question i've tried to write that example in my WebRole.OnStart and I keep getting the following
Details: Role has encountered an error and has stopped. Unhandled Exception: System.Net.WebException, Details: Exception: The underlying connection was closed: An unexpected error occurred on a send.
at System.Net.HttpWebRequest.GetResponse()
at
and as the publish log specifies the IISConfigurator startup task didn't run yet
is there any other solution
i'm using
cloud-service classic
azure API 2.8.2
Visual Studio 2015 Update 1
You can execute a script when the host VM starts by including the script in your project and adding a startup task to the ServiceDefinition.csdef. In the example below we run Startup.cmd. We use this to disable idleTimeout for our site by calling appcmd.exe from within the script.
Below is the Startup node you add to WebRole as a sibling to Sites in ServiceDefinition.csdef. Also included is how to inject runtime variables that can be accessed via RoleEntryPoint, great article on RoleEntryPoint here.
<Startup>
<Task commandLine="Startup.cmd" executionContext="elevated" taskType="simple">
<Environment>
<Variable name="isEmulated">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/#emulated" />
</Variable>
<Variable name="instanceId">
<RoleInstanceValue xpath="/RoleEnvironment/CurrentInstance/#id" />
</Variable>
<Environment>
</Task>

Adding additional content folders to Azure package

Im using Azure SDK 2.5
I have a web role in a cloud service project. I would like to add a folder in some fashion such that it is deployed in the parent directory of the approot. I havent found a way to do this which kind of makes me wonder what use is the ability to define virtual directories in csdef.
So I thought I would try adding folders via the Contents/Content xml config in the csdef. I am either fundamentally misunderstanding what this bit of config does or its hopelessly broken.
Assuming this folder structure
/
/CloudService
/SomeOtherContent
If I define the following:
<Contents>
<Content destination="frontend">
<SourceDirectory path="..\SomeOtherContent" />
</Content>
</Contents>
and build I get:
error CloudServices089: Cannot find the source directory
'C:\src\template\src\Template.CloudService\bin\Debug\..\SomeOtherContent'
Ok so its starting the bin\Debug, so I'll just make it ..\..\..\SomeOtherContent
error CloudServices089: Cannot find the source directory
'C:\src\template\src\Template.CloudService\..\..\..\SomeOtherContent'
Yes thats right, the folder at which my relative path is resolved has changed!!! Its no longer bin\Debug. Wtf!? How can this be made to work? It works if i enter a full drive qualified absolute path.
So I solved this by having MSBuild resolve the path and push it in to an environment variable which I called FrontendDir.
<Contents>
<Content destination="frontend">
<SourceDirectory path="%FrontendDir%" />
</Content>
</Contents>
and in the ccproj I added:
<UsingTask
TaskName="SetEnvironmentVariableTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
<ParameterGroup>
<Name ParameterType="System.String" Required="true" />
<Value ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Environment.SetEnvironmentVariable(Name, Value);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild" Condition=" '$(FrontendDir)' == '' ">
<Message Text="Setting Project Dir" Importance="high" />
<SetEnvironmentVariableTask Name="FrontendDir" Value="$(ProjectDir)\..\Template.FrontEnd\dist" />
</Target>
Its preferable to put the entire path into the env var here as you can then override it easily in your different build scenarios by overriding the value (eg. /p:FrontendDir="c:\foo")
So that works and works fairly well. I still say the behaviour I was seeing before with the relative path resolution changing folders is... broken. It just doesn't work with relative paths in any usable way.
You are seeing the same error but from different msbuild targets.
The first error (when using ..\..\) is thrown at PreValidateServiceModel which passes in the Source location and checks the path
ServiceDefinitionFile="#(SourceServiceDefinition)"
ServiceConfigurationFile="#(SourceServiceConfiguration)"
C:\src\Azure\ServiceDefinition.csdef : error CloudServices089: Cannot
find the source directory 'C:\src\Azure\..\..\Installers\' in role
WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "PreValidateServiceModel" in project "Azure.ccproj" -- FAILED.
The second error is thrown at ValidateServiceFiles which passes in the Target location
ServiceDefinitionFile="#(TargetServiceDefinition)"
ServiceConfigurationFile="#(TargetServiceConfiguration)">
C:\src\Azure\bin\Release\ServiceDefinition.csdef : error CloudServices089: Cannot
find the source directory
'C:\src\Azure\bin\Release\Installers\'
in role WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "ValidateServiceFiles" in project "Azure.ccproj" -- FAILED.
If you reflect on C:\Program Files\Microsoft SDKs\Azure.NET SDK\v2.9\bin\ServiceDescription.dll you can see the ProcessRoleContents method doing the validation but using the SourceFile to resolve the location.
One option is to make sure the target folder exists (even if empty) before the build starts.
It would be better if the PreValidation resolved the path and when the Target is saved, it had the full path.
I ended up editing the ccproj, and adding this
<Target Name="BeforeAddRoleContent">
<ItemGroup>
<AzureRoleContent Include="Installers\">
<RoleName>Azure</RoleName>
<Destination></Destination>
</AzureRoleContent>
</ItemGroup>
</Target>
Referencing runtime content from .ccproj (Azure SDK 2.9)

CSPACK sitePhysicalDirectories being ignored?

Yet another issue with CSPACK...
I have a service definition file like this:
<ServiceDefinition name="core-eur" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition" schemaVersion="2014-01.2.3">
<LoadBalancerProbes>
<LoadBalancerProbe name="discovery.probe" protocol="http" path="/HealthMonitoring" port="80" intervalInSeconds="8" timeoutInSeconds="16" />
</LoadBalancerProbes>
<WebRole name="Discovery.UI" vmsize="ExtraSmall" enableNativeCodeExecution="false">
<Startup>
<Task commandLine="startup\CreateCustomEventSource.cmd" executionContext="elevated" taskType="simple" />
</Startup>
<Sites>
<Site name="main">
<Bindings>
<Binding name="https.root" endpointName="https" hostHeader="testingblah.com" />
</Site>
<Site name="api" physicalDirectory="..\..\..\catalog\Catalog.Search.API">
<Bindings>
<Binding name="https.root" endpointName="https" hostHeader="api.testingblah.com" />
</Bindings>
</Site>
</Sites>
<Endpoints>
<InputEndpoint name="http" protocol="http" port="80" loadBalancerProbe="discovery.probe" />
<InputEndpoint name="https" protocol="https" port="443" certificate="bibliothecatest.com" />
</Endpoints>
<Imports>
<Import moduleName="RemoteAccess" />
<Import moduleName="Diagnostics" />
<Import moduleName="RemoteForwarder" />
</Imports>
<Certificates>
<Certificate name="testingblah.com" storeLocation="LocalMachine" storeName="CA" />
</Certificates>
</WebRole>
The key points are the Sites "main" and "api". I've not included the physical directory because, as expected, when they are put in and point to the project files in the solution, the "api" site is not packaged correctly as the Visual Studio package process will only package the first site (i.e. "api" has all the un-transformed .config files and .cs files in it's packaged folder whereas "main" does not - it is correctly packaged, but this is a known issue so I'm not going to complain too much about this.
So to workaround it, for my build server I want to introduce a CSPACK step to do this properly. I pre-build the "main" and "api" web sites using MSDEPLOY to a temporary location, and then use CSPACK to create the package file.
This fails every time with "CloudService077: Need to specify the physical directory for the virtual path 'main/ of role "Discovery.UI". However, I am including the /sitePhysicalDirectories value in CSPACK, i.e.
cspack %root%\ServiceDefinition.csdef ^
/role:Discovery.UI;%compiled%\discovery\Discovery.UI\ ^
/sitePhysicalDirectories:Discovery.UI;main;%compiled%\discovery\Discovery.UI\ ^
/sitePhysicalDirectories:Discovery.UI;api;%compiled%\catalog\Catalog.Search.Api\ ^
/rolePropertiesFile:Discovery.UI;Properties.txt ^
/out:%output% /copyOnly
If I put the sitePhysicalDirectories attribute back into the ServiceDefinition file, and point it to the project directory location in Visual Studio (e.g.)
<Site name="main" physicalDirectory="..\..\..\discovery\Discovery.UI">
then CSPACK fails with CloudServices079: Cannot find the physical directory "nnn" for virtual path main/
This is despite the fact that the CSPACK command line /sitePhysicalDirectories are correct. What's happening is that CSPACK is taking the ServiceDefinition values, applying the relative path values and pointing to completely the wrong place.
If I update ServiceDefinition to use the same physical location (e.g. C:\....\nnnn as opposed to "......\nnnn" that I'm passing in the CSPACK command line, everything works !
So it seems that CSPACK ignores parameters and cannot override values, which isn't what I really need. Is this correct or should I be passing something else to CSPACK?
Azure SDK 2.3
I know this is long after the fact, but I also had endless trouble with CSPACK. It is basically impossible to find any useful information on it.
What I've found, is that if you don't provide the arguments properly, you get all sorts of "Cannot find the physical directory..." and "Need to specify the physical directory..." errors, sometimes with directories that you did not provide.
Thanks to this powershell script I was able to execute it using the correct format and learned these things:
1. You must specify the /role: argument. The /sites argument is an extension of the role you specify here.
2. Put all your sites in one /sites argument or in one /sitePhysicalDirectories argument. I use the /sites argument for my builds.
For the above example, I would try:
cspack %root%\ServiceDefinition.csdef
/role:Discovery.UI;%compiled%\discovery\Discovery.UI\ /sites:Discovery.UI;main;%compiled%\discovery\Discovery.UI\;api;%compiled%\catalog\Catalog.Search.Api\ /rolePropertiesFile:Discovery.UI;Properties.txt
/out:%output% /copyOnly

Windows Azure Environment.GetEnvironmentVariable("RoleRoot") read access denied error

I have an xml file that I ma tryin to read from
string xmlTemplatePath = Path.Combine(Environment.GetEnvironmentVariable("RoleRoot") + #"\", #"approot\myxml.xml");
Using XDocument doc = XDocument.Load(xmlTemplatePath), however I get an access denied exception both on the cloud and development environment. Any ideas why a read is denied?
I know, old thread... but the answer could be useful to someone nevertheless.
It appears that an azure worker process runs under a custom user (shows up as a GUID in taskmgr). This user account appears to be quite restricted and has no read-access to the filesystem (even inside the approot directory).
My solution was to create a startup script for the azure role (see msdn article) which uses icacls to add permissions to access the files. In this case, I created a file called startup\Install.cmd in my project, containing the following:
#echo off
if "%EMULATED%"=="true" goto :EOF
echo Allowing access to files
cd directory_where_files_exist
icacls *.* /grant Everyone:F
In my ServiceDefinition.csdef file, I instruct the Azure deployment system to run this startup script during deployment by putting this inside the role definition (e.g. <WorkerRole>):
<Startup>
<Task executionContext="elevated" commandLine="startup\Install.cmd">
<Environment>
<Variable name="EMULATED">
<RoleInstanceValue xpath="/RoleEnvironment/Deployment/#emulated" />
</Variable>
</Environment>
</Task>
</Startup>
The variable "EMULATED" is set when the emulator is running - note that in the startup/Install.cmd file above, I skip doing the permission change if running in the emulator.
Looks fine to me. I even grabbed your code and dropped it into a worker role, calling it from OnStart(), after creating myxml.xml in my project root, just to make sure I wasn't missing something obvious.
Check myxml.xml properties: "Build Action" should be "Content" and "Copy to Output Directory" should be "Copy always" or "Copy if newer". If that doesn't fix it, check permissions on that file.

IISExpress Log File Location

IISExpress writes log and configuration data to pre-determined location out of the box.
The directory is an "IISExpress" directory stored in a user's Documents directory.
In the directory is stored the following folders files underneath.
Config
Logs
TraceLogFiles
The location of my home directory is on a network share, determined by group policy
Currently we are encountering scenarios where visual studio locks up when stopping debugging Silverlight applications using IIS Express.
I was looking to change the location for the log & configuration data for IISExpress to see if this fixes the problem of visual studio locking up. Is it possible to change the default location of log & config files ?
1 . By default applicationhost.config file defines following two log file locations. Here IIS_USER_HOME would be expanded as %userprofile%\documents\IISExpress\.
<siteDefaults>
<logFile logFormat="W3C" directory="%IIS_USER_HOME%\Logs" />
<traceFailedRequestsLogging directory="%IIS_USER_HOME%\TraceLogFiles" enabled="true" />
</siteDefaults>
You can update above directory paths to change the log file locations.
2 . If you are running IIS Express from command line, you can use '/config' switch to provide configuration file of your choice. Following link may help you http://learn.iis.net/page.aspx/870/running-iis-express-from-the-command-line/
http://www.iis.net/configreference/system.applicationhost/sites/sitedefaults
<configuration>
<system.applicationHost>
<sites>
<siteDefaults>
<logFile
logFormat="W3C"
directory="%SystemDrive%\inetpub\logs\LogFiles"
enabled="true"
/>
<traceFailedRequestsLogging
enabled="true"
directory="%SystemDrive%\inetpub\logs\FailedReqLogFiles"
maxLogFiles="20"
/>
<limits connectionTimeout="00:01:00" />
<ftpServer serverAutoStart="true" />
<bindings>
<binding
protocol="http"
bindingInformation="127.0.0.1:8080:"
/>
</bindings>
</siteDefaults>
</sites>
</system.applicationHost>
</configuration>
I find web.config documentation is a messy. It is therefore better to provide a complete parent history than a floating snippet with the expectation that the reader naturally knows where it goes.
By default it will be in:
C:\Users\ user_name \Documents\IISExpress\Logs\

Resources