Azure ARR error while enabling disk cache - azure

We have azure hosted service, and now i need to setup the ARR (application request routing) on it. I followed the blog http://robindotnet.wordpress.com/2011/07/ and ARR is working fine. Now I need to enable the diskCaching for this and I'm trying below command:
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/diskCache /+"[path='c:\cache',maxUsage='0']" /commit:apphost >> C:\setDiskCache.txt
But getting below error:
ERROR ( message:New driveLocation object missing required attributes. Cannot add duplicate collection entry of type 'driveLocation' with unique key attribute 'path' set to 'c:\cache'. )
and there no content getting cached in this folder. Any direction or help is appreciated.
Below is complete cmd file for reference:
cd /d "%~dp0"
start /wait msiexec.exe /i webfarm_amd64_en-US.msi /qn /log C:\installWebfarmLog.txt
start /wait msiexec.exe /i requestRouter_amd64_en-US.msi /qn /log C:\installARRLog.txt
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/proxy /enabled:"True" /reverseRewriteHostInResponseHeaders:"False" /preserveHostHeader:"True" /commit:apphost >> C:\setProxyLog.txt
%windir%\system32\inetsrv\appcmd.exe set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 >> C:\setAppPool.txt
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/diskCache /+"[path='c:\cache',maxUsage='0']" /commit:apphost >> C:\setDiskCache.txt
exit /b 0
I can find the same thing here for IIS [http://www.iis.net/learn/extensions/configuring-application-request-routing-(arr)/configure-and-enable-disk-cache-in-application-request-routing], that can be enabled manually. But we need to enable this programmatically.

As is often the case, the error message holds a hint as to the cause. The problem is you can have only one entry per drive location value. Which means that script runs fine the first time, but the second time it will throw because the value has already been applied.
You cannot remove the node using appcmd (it doesn't support clearing a collection), but you can using a text editor (this file: %windir%\System32\inetsrv\config\applicationHost.config). Or you can run a powershell script:
Import-Module WebAdministration
Remove-WebConfigurationProperty -pspath 'MACHINE/WEBROOT/APPHOST' -filter "system.webServer/diskCache" -name "."
In either case, this is the node that will be manipulated:
<driveLocation path="c:\cache" maxUsage="0" />
After that you'll be able to re-run your code.

Related

IIS - Setting the physical path of an Application with appcmd

In IIS, I have a web site "Default Web Site" with an application "test2". I want to set the physical path of that application to "E:\temp\out1". That directory already exists.
When I run this in Powershell (as an administrator):
appcmd.exe set app "Default Web Site/test2" -[path='/'].physicalpath:E:\temp\out1
I get this error message:
ERROR ( message:Malformed collection indexer; format is [#position,name='value',name2='value2',...]. The #position specifier is optional, and be '#start', '#end', or '#N' where N is a numeric index into the collection. )
I have no idea what that means.
Would very much appreciate a working example of using appcmd to set the physical path of an IIS application.
Turns out that the command in my question actually works on Command Prompt. However, I tried to run it from a Powershell prompt, and there I got the error message.
I couldn't find a way to run the command from Powershell. In the end, my solution was to write the command to a temporary .bat file, then execute that file from Powershell.
If I set my double quotes like this it works from Powershell prompt.
appcmd.exe set app "Default Web Site/test2" -"[path='/'].physicalpath:E:\temp\out1"

Azure Website Remote Debugging with git deploy not working

I've been trying out the new Remote Debugging feature for Azure Websites, but I think I may have come across an issue: I can only get it to work properly if I use Web Publish. If I deploy a site with local git deploy, the debugger attaches but the debug symbols aren't loaded (breakpoints show the warning).
I tried both setting the Release configuration to include PDB files (since Azure's git deploy uses the Release configuration by default) and by using a custom deploy script generated by the azure site deploymentscript command detailed here and setting the build command to use the Debug configuration. In both cases, I still get the same issue that the symbols aren't loaded.
I feel like the problem is probably one of the following:
Azure runs some sort of custom action after a Web Publish that must be run in order to allow remote debugging
The build options used by the git deployment scripts are missing some sort of flag that's causing PDB output to not be present for the web application (I don't think this one is likely)
Azure is not honoring the Configuration I use in the deployment script when the site is actually running and compiled on-demand
Ultimately I'm hoping to write some automated deployment scripts and I'd much rather use git deployment than Web Publish to accomplish this. What really baffles me is that this fails even with the Release configuration set to include the PDB files. It really makes me think there must be something extra being done on Azure for Web Publish that's not done for git deployment. Does anyone have any ideas of what may be causing the difference here?
Custom Git Deployment Script
I'm including the custom deployment script generated by azure site deploymentscript for reference and to show the build flags it uses. The relevant parts are after the :: Deployment section.
#if "%SCM_TRACE_LEVEL%" NEQ "4" #echo off
:: ----------------------
:: KUDU Deployment Script
:: Version: 0.1.5
:: ----------------------
:: Prerequisites
:: -------------
:: Verify node.js installed
where node 2>nul >nul
IF %ERRORLEVEL% NEQ 0 (
echo Missing node.js executable, please install node.js, if already installed make sure it can be reached from current environment.
goto error
)
:: Setup
:: -----
setlocal enabledelayedexpansion
SET ARTIFACTS=%~dp0%..\artifacts
IF NOT DEFINED DEPLOYMENT_SOURCE (
SET DEPLOYMENT_SOURCE=%~dp0%.
)
IF NOT DEFINED DEPLOYMENT_TARGET (
SET DEPLOYMENT_TARGET=%ARTIFACTS%\wwwroot
)
IF NOT DEFINED NEXT_MANIFEST_PATH (
SET NEXT_MANIFEST_PATH=%ARTIFACTS%\manifest
IF NOT DEFINED PREVIOUS_MANIFEST_PATH (
SET PREVIOUS_MANIFEST_PATH=%ARTIFACTS%\manifest
)
)
IF NOT DEFINED KUDU_SYNC_CMD (
:: Install kudu sync
echo Installing Kudu Sync
call npm install kudusync -g --silent
IF !ERRORLEVEL! NEQ 0 goto error
:: Locally just running "kuduSync" would also work
SET KUDU_SYNC_CMD=node "%appdata%\npm\node_modules\kuduSync\bin\kuduSync"
)
IF NOT DEFINED DEPLOYMENT_TEMP (
SET DEPLOYMENT_TEMP=%temp%\___deployTemp%random%
SET CLEAN_LOCAL_DEPLOYMENT_TEMP=true
)
IF DEFINED CLEAN_LOCAL_DEPLOYMENT_TEMP (
IF EXIST "%DEPLOYMENT_TEMP%" rd /s /q "%DEPLOYMENT_TEMP%"
mkdir "%DEPLOYMENT_TEMP%"
)
IF NOT DEFINED MSBUILD_PATH (
SET MSBUILD_PATH=%WINDIR%\Microsoft.NET\Framework\v4.0.30319\msbuild.exe
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Deployment
:: ----------
echo Handling .NET Web Application deployment.
:: 1. Restore NuGet packages
IF /I "azure-test.sln" NEQ "" (
call "%NUGET_EXE%" restore "%DEPLOYMENT_SOURCE%\azure-test.sln"
IF !ERRORLEVEL! NEQ 0 goto error
)
:: 2. Build to the temporary path
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
%MSBUILD_PATH% "%DEPLOYMENT_SOURCE%\azure-test\azure-test.csproj" /nologo /verbosity:m /t:Build /t:pipelinePreDeployCopyAllFilesToOneFolder /p:_PackageTempDir="%DEPLOYMENT_TEMP%";AutoParameterizationWebConfigConnectionStrings=false;Configuration=Debug /p:SolutionDir="%DEPLOYMENT_SOURCE%\.\\" %SCM_BUILD_ARGS%
) ELSE (
%MSBUILD_PATH% "%DEPLOYMENT_SOURCE%\azure-test\azure-test.csproj" /nologo /verbosity:m /t:Build /p:AutoParameterizationWebConfigConnectionStrings=false;Configuration=Debug /p:SolutionDir="%DEPLOYMENT_SOURCE%\.\\" %SCM_BUILD_ARGS%
)
IF !ERRORLEVEL! NEQ 0 goto error
:: 3. KuduSync
IF /I "%IN_PLACE_DEPLOYMENT%" NEQ "1" (
call %KUDU_SYNC_CMD% -v 50 -f "%DEPLOYMENT_TEMP%" -t "%DEPLOYMENT_TARGET%" -n "%NEXT_MANIFEST_PATH%" -p "%PREVIOUS_MANIFEST_PATH%" -i ".git;.hg;.deployment;deploy.cmd"
IF !ERRORLEVEL! NEQ 0 goto error
)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
:: Post deployment stub
call %POST_DEPLOYMENT_ACTION%
IF !ERRORLEVEL! NEQ 0 goto error
goto end
:error
echo An error has occurred during web site deployment.
call :exitSetErrorLevel
call :exitFromFunction 2>nul
:exitSetErrorLevel
exit /b 1
:exitFromFunction
()
:end
echo Finished successfully.
Update 2/8/2014
Some fixes were made in WAWS, and it is now possible to make debugging work when using git, by having VS correctly load the server-side PDBs. For it to work, you need to do one of two things (i.e. you don't need to do both). It can work in both VS 2012 and 2013.
Turn off Just My Code debugging: just turn off that setting in the VS debugger settings and try debugging your Azure Web Site.
Build in Debug mode: to do that on the server build, you can go to the Azure Portal and add an ApSetting called SCM_BUILD_ARGS, with value -p:Configuration=Debug (more details here). Then go to the Deployments page and hit the Redeploy button (for the current deployment). Then attach from VS and it should all work!
Original answer
Indeed, this doesn't work today, and we're trying to see how we could make it work. At the root, the problem appears to be the Visual Studio debugger expects to find the PDBs on the client, while in the git case they only exist on the server.
This article discusses changes to how the debugger works between 2010 and the newer versions, and that probably affects things.
More investigation needed, but this is the state of things right now.
I was having this problem with a .Net Core Azure Function project, using the Cloud Explorer right-click functionality to attach. The following github issue speaks to it, but solution didn't solve my problem:
https://github.com/Azure/Azure-Functions/issues/872
I finally stumbled across the answer here:
http://dontcodetired.com/blog/post/Remote-Debugging-Azure-Functions-V2-The-breakpoint-will-not-currently-be-hit-No-symbols-have-been-loaded-for-this-document
It boils down to manually attaching to the process in Azure, rather than relying on the Cloud Explorer right-click functionality.

Java PATH not set when creating a Azure Paas Role

I am creating an Azure PaaS role which sets the PATH variable for java.exe .
I have a background task which does that.
The startupApp.cmd looks like
setx PATH %PATH%;%CD%\jdk\bin\ /m
cscript /NoLogo util\unzip.vbs jdk.zip "%CD%"
Call the bat file to start my application.
When the VM starts I see that the PATH environment variable is correctly set and points to where the jdk\bin folder. My application however fails to start with the error "java is not recognised as an internal or external batch command".
JAVA command to start my app is
java %JAVA_OPTS% %LOG_OPTS% %LOG4J_OPTS% -cp my_app.jar %MAIN_CLASS%
Here is the confusing path,
After I log into the VM and open a command prompt window and type java I see that it works fine.
If I restart the VM, the java command to bring up my app runs fine and I and my app too starts fine.
There is a significant difference between setx and set function:
set takes effect in local cmd context. Meaning once you exit or close the cmd window, you lose the environment variable.
setx takes effect in future cmd context. So you won't see the environment variable and its value in the current cmd. You need to open a new cmd window to see it.
If you want to use it global and immediate you should use both functions side by side.
Description taken from: http://batcheero.blogspot.de/2008/02/set-and-setx.html

Azure Role - Application startup task failed with exit code 1

I tried to include a Task as per MSDN article below:
http://msdn.microsoft.com/en-us/library/windowsazure/jj154098.aspx
However I'm getting the error below on one of the instance;
Recycling (Waiting for role to start... Application startup task failed with exit code 1. [2013-04-13T11:03:22Z])
Could someone please suggest what's really happening and what's the fix if any?
Below is my cmd:
#echo off
#echo Installing "IPv4 Address and Domain Restrictions" feature
%windir%\System32\ServerManagerCmd.exe -install Web-IP-Security
#echo Unlocking configuration for "IPv4 Address and Domain Restrictions" feature
%windir%\system32\inetsrv\AppCmd.exe unlock config -section:system.webServer/security
And CSDF:
<Startup>
<Task commandLine="Startup.cmd" executionContext="elevated"/>
<Task commandLine="startup\startup.cmd" executionContext="elevated"/>
</Startup>
Thank you
I had a similar problem once. I fixed it by adding the following to my start-up script:
exit /b 0
Without this the Azure Fabric didn't register the script as finished and it kept recycling the instance.
I see you use ServerManagerCmd.exe. This command is removed from Windows Server 2012. So make sure your role isn't deployed with the latest OS Family version.
<ServiceConfiguration ... osFamily="1" ...>
What you can do here is RDP into the instance and run the .CMD file manually to see if it's throwing any errors.
I received a similar error when deploying to Azure and it was caused by the startup command raising a dialogue box that required a user input. Essentially the alert box was confirming that a .dll had been registered, that's all, but it was enough to stop the deployment routine in it's tracks.
Here is the contents of my .cmd file:
chcp 1252>NUL
regsvr32 /s .\library\asppdf64.dll
regsvr32 /s .\library\aspjpeg64.dll
exit /b 0
The /s tells the service to run silently (i.e. with dialogues purged). The chcp 1252>NUL sets the code-page.

How to make startup tasks idempotent?

I have a number of startup tasks in batch files. In particular I call IIS's appcmd.exe to configure IIS. Startup tasks in Azure are supposed to idempotent (ie, able to be run repeatedly with the same results), in case the role is restarted for some reason. Unfortunately many of my IIS configuration commands will fail the second time around, eg because they delete a configuration node the first time which is then not present on subsequent runs.
My question is, how do I make these startup tasks idempotent? Is there a way to make appcmd.exe not throw errors? Is there a way to make the shell catch the errors? Is there a way to make the Azure framework ignore the errors?
Here's an example of my startup tasks. This is all contained in a command file, configiis.cmd.
#REM Enable IIS compression for application/json MIME type
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json',enabled='True']" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.webServer/httpCompression /+"dynamicTypes.[mimeType='application/json; charset=utf-8',enabled='True']" /commit:apphost
#REM Set IIS to automatically start AppPools
%windir%\system32\inetsrv\appcmd.exe set config -section:applicationPools -applicationPoolDefaults.startMode:AlwaysRunning /commit:apphost
#REM Set IIS to not shut down idle AppPools
%windir%\system32\inetsrv\appcmd set config -section:applicationPools -applicationPoolDefaults.processModel.idleTimeout:00:00:00 /commit:apphost
#REM But don't automatically start the AppPools that we don't use, and do shut them down when idle
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='Classic .NET AppPool'].startMode:OnDemand" "/[name='Classic .NET AppPool'].autoStart:False" "/[name='Classic .NET AppPool'].processModel.idleTimeout:00:01:00" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0'].startMode:OnDemand" "/[name='ASP.NET v4.0'].autoStart:False" "/[name='ASP.NET v4.0'].processModel.idleTimeout:00:01:00" /commit:apphost
%windir%\system32\inetsrv\appcmd.exe set config -section:system.applicationHost/applicationPools "/[name='ASP.NET v4.0 Classic'].startMode:OnDemand" "/[name='ASP.NET v4.0 Classic'].autoStart:False" "/[name='ASP.NET v4.0 Classic'].processModel.idleTimeout:00:01:00" /commit:apphost
#REM remove IIS response headers
%windir%\system32\inetsrv\appcmd.exe set config /section:httpProtocol /-customHeaders.[name='X-Powered-By']
Aside from #Syntaxc4's answer: Consider the use of a breadcrumb (file) locally. In your script, check for existence of a known file (that you create). If it doesn't exist, go through your startup script, also creating a breadcrumb file. Next time the vm starts up, it would again check for existence of the breadcrumb file and, if it exists, exit the cmd file. If the breadcrumb file disappears, this typically means your vm has been reconstituted somewhere else (either a new instance or a respawned instance maybe on different hardware) and IIS configuration would be needed.
You would have to check to see if the config setting is present before attempting to delete it (add conditional logic). This could be achieved by:
'appcmd.exe list config -details'
Capturing a return value would give you something to compare against, be it length of output or an actual value.
MSDN now contains an excellent guide for doing this by handling error codes from APPCMD.
http://msdn.microsoft.com/en-us/library/windowsazure/hh974418.aspx
Basically after any appcmd operation, you can do the following:
IF %ERRORLEVEL% EQU 183 DO VERIFY > NUL
and ignore any acceptable error code.
Based on David Makogon's suggestion, I added the following to the top of each of my .cmd files. This seems to do the trick. It will create a flag file (what David called a breadcrumb file) in the same directory as the executing script, then check for it on subsequent runs.
#REM A file to flag that this script has already run
#REM because if we run it twice, it errors out and prevents the Azure role from starting properly
#REM %~n0 expands to the name of the currently executing file, without the extension
SET FLAGFILE=c:\%~n0-flag.txt
IF EXIST "%FLAGFILE%" (
ECHO %FLAGFILE% exists, exiting startup script
exit /B
) ELSE (
date /t > %FLAGFILE%
)
I highly recommend using the /config:* /xml on the end of your list command. For more information on how I made iis idempotent please look at: https://github.com/opscode-cookbooks/iis
Chef is one of multiple configuration management platforms and i'm only suggesting looking at it for the code (in ruby) that does idempotent via listing the current settings and comparing them to the settings being requested to change.

Resources