setting and reading environment variables in IIS 10 - iis

I can not figure out how to set and read environment variables in Microsoft Internet Information Services (IIS) version 10. I have a Fast CGI app that requires environment variables. In previous versions of IIS I just set system-wide variables in the Windows "System Properties". However in IIS 10 my FCGI app isn't reading them. So my first question is if there are steps that need to be taken so that the IIS process can read system variables?
Alternatively, how do I set environment variables within IIS 10? This Microsoft site explains it but not in enough detail for me to get it working. Specifically, in what file and in which section do you put the <environmentVariables> section? The example XML and the command line example have name="Contoso" (see below) but what is that - the name of the application pool, or my FCGI app, or something else?
<applicationPools>
<add name="Contoso" managedRuntimeVersion="v4.0" managedPipelineMode="Classic">
<environmentVariables>
<add name="foo" value="bar" />
</environmentVariables>
</add>
</applicationPools>
Edit in response to Jokies Ding:
MAP22 and PROJ_LIB are the two environment variables that I need. In C:\Windows\System32\inetsrv\Config\applicationHost.config
I have:
<applicationPools>
<add name="DefaultAppPool" />
<add name=".NET v4.5 Classic" managedRuntimeVersion="v4.0" managedPipelineMode="Classic" />
<add name=".NET v4.5" managedRuntimeVersion="v4.0" />
<add name="ASP.NET v4.0" autoStart="true" managedRuntimeVersion="v4.0" />
<applicationPoolDefaults managedRuntimeVersion="v4.0">
<processModel identityType="ApplicationPoolIdentity" />
<environmentVariables>
<add name="PROJ_LIB" value="/gdal/bin/proj6/SHARE" />
<add name="MAP22" value="/tetonwy/mapserv/main.map" />
</environmentVariables>
</applicationPoolDefaults>
</applicationPools>
and
<fastCgi>
<application fullPath="C:\gdal\bin\ms\apps\mapserv.exe">
<environmentVariables>
<environmentVariable name="MAP22" value="C:\tetonwy\mapserv\main.map" />
<environmentVariable name="PROJ_LIB" value="C:\gdal\bin\proj6\SHARE" />
</environmentVariables>
</application>
</fastCgi>
and in a cmd window the environment variables are visible
C:\>set MAP22
MAP22=C:\tetonwy\mapserv\main.map
C:\>set PROJ_LIB
PROJ_LIB=C:\gdal\bin\proj6\SHARE
So it seems like I've got the variables set all over the place but the app isn't seeing them. C:\gdal\bin\ms\apps\mapserv.exe is the FastCGI app that isn't seeing the environment variables. It's a compiled C program that I have used in previous versions of IIS.

There is an issue with MapServer not reading environment variables on Windows when used through FastCGI.
This is resolved by applying https://github.com/MapServer/MapServer/pull/6304 which will be backported to the 7.x MapServer releases.
See Environment variables ignored using FastCGI and IIS #6289 for more details.

<environmentVariables> section is displayed as a collection under specific application pool.
You could find it in IIS global configuration file C:\Windows\System32\inetsrv\config\applicationhost.config.
"Contoso" is the name of application pool.
I think read system-wide variable is still supported in IIS 10 and PHP FAST-CGI. I can get these configuration by running commandline SET in IIS PHP-CGI.
Could you post the code that you used to read the variable?
In some condition, Your application code require elevated permission. You could try to change application pool identity to local system and set Anonymous authenticated user to Application pool identity

Related

Azure App Service - What modified my web.config?

I have an ASP.NET Core website running from Kestrel. It is deployed to Azure App Service in production and another as staging.
I like to configure staging as "production-like" so I set ASPNETCORE_ENVIRONMENTNAME = Production in the Configuration blade of the App Service in the Azure portal. I could see from logs that the code was seeing the environment name as staging still.
It turns out <environmentVariable name="ASPNETCORE_ENVIRONMENTNAME" value="staging" /> is set in the web.config that's on the Azure instance!!
Now, I don't have this set in the web.config or any transforms in my codebase, and I don't use the web.config, in fact I want nothing to do with it or IIS.
My site is deployed via Azure Pipelines. I use environmentName as a build time variable but the YAML only uses it once, to concatenate some text to make up the resource group name.
I then ran dotnet deploy using the same command line as Azure Pipelines runs, but the web.config it writes into the final publish output folder doesn't contain the offending line either.
It was only a few weeks ago I rebuilt and redeployed all my Azure resources. It was all clean, and it's all scripted.
Where on Earth has it come from??!
I'm worried that if I remove it, one day, it'll magically just reappear. It smells very much like someone at Microsoft thought this automagic was a good idea.
Mind you, I've tried to remove it using the App Service Editor and Kudu but I'm not allowed!!
Your app is currently in read only mode because you are running from a package file. To make any changes, please update the content in your zip file and WEBSITE_RUN_FROM_PACKAGE app setting.
So if I'm not setting it, and I'm not allowed to change it, what do I do??
Update 1
I've downloaded the artifacts from Pipelines and the web.config has the setting in place.
The command run, according to the Pipelines log, was this.
dotnet publish --configuration Release --output D:\a\1\s/dotnet-publish-output
But when I run that myself, on my machine, it does not meddle with my web.config.
Wow. So whilst on the school run, it occurred to me that the value that the dotnet command writes into the web.config is correct. How does it know?
The only way it can know is from that environment variable I'm setting in Azure Pipelines and using in my YAML file azureResourceGroup: tz-$(environmentName).
And when I run it on my dev machine vs. running on the Azure build server, that environment variable is not set.
So I set environmentName in the environment on my dev machine before running dotnet publish and, hey presto! It screws up my web.config by adding an environment variable! Amazing.
> $env:environmentName = "undocumented-feature"
> dotnet publish --configuration Release --output C:\DATA\Published
...
> cat C:\DATA\Published\web.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\MyWebsiteYeah.dll" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="inprocess">
<environmentVariables>
<environmentVariable name="ASPNETCORE_ENVIRONMENT" value="undocumented-feature" />
</environmentVariables>
</aspNetCore>
<security>
<requestFiltering>
<requestLimits maxUrl="32768" maxQueryString="262144"/>
</requestFiltering>
</security>
</system.webServer>
</location>
</configuration>
<!--ProjectGuid: 3E05D228-D9AF-4782-8E33-1F0E69992750-->
Isn't that dreadful.
So I solved the whole problem with my websites ignoring the variables set in the portal by changing the variable name in Pipelines to hostEnvironmentName.

Update the apphostconfig file using appcmd

In an azure devops pipeline I try to run an appcmd command to modify the applicationhost.config file to set the ASPNETCORE_ENVIRONMENT variable
It works fine like this:
appcmd set config -section:system.applicationHost/applicationPools /+"[name='api.hostname.net'].environmentVariables.[name='ASPNETCORE_ENVIRONMENT',value='api.hostname.net']"
The problem is that this appcmd command works the first time, but as soon as the environment variable already exist it will throw an error message. Can I somehow ignore errors from appcmd? Or only add the environment variable if it does not exist from before?
I'm running appcmd commands using an azure devops IISWebAppManagementOnMachineGroup#0 task.
You can try to use XML transformation option in the IIS web deploy task. XML transformation supports transforming the configuration files (*.config files) and is based on the environment to which the web package will be deployed.
Transform file sample:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.webServer>
<aspNetCore ...>
<environmentVariables>
<environmentVariable xdt:Transform="Replace" xdt:Locator="Match(name)" name="ASPNETCORE_ENVIRONMENT" value="xxx" />
</environmentVariables>
</aspNetCore>
</system.webServer>
</configuration>
For details ,please refer to this document.
I have a similar requirement, and I have to scriptize these commands, so any UI-based method doesn't work for me. Provide my solution here.
I want to update an existed key named PasswordChangeEnabled which is located in appSettings section.
<appSettings>
<add key="PasswordChangeEnabled" value="false" />
</appSettings>
If I use set config with plus /+
appcmd set config "Site" /section:appSettings /+"[key='PasswordChangeEnabled',value='true']"
I will get an error message:
ERROR (Cannot add duplicate collection entry of type 'add' with unique
key attribute 'key' set to 'PasswordChangeEnabled')
So I changed the syntax to just modify the value:
appcmd set config "Site" /section:appSettings /"[key='PasswordChangeEnabled'].value:true"
This way worked for me.

Error starting application in .netcore

I'm getting the following error when navigating to my IIS published .netcore application:
I have set up my web.config file as so:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="dotnet" arguments=".\KritnerWebsite.dll" stdoutLogEnabled="true" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>
Not sure if this warning is relevant or just outdated:
Severity Code Description Project File Line Source Suppression State
Warning The element 'system.webServer' has invalid child element 'aspNetCore'. List of possible elements expected: 'asp, caching, cgi, defaultDocument, directoryBrowse, globalModules, handlers, httpCompression, webSocket, httpErrors, httpLogging, httpProtocol, httpRedirect, httpTracing, isapiFilters, modules, applicationInitialization, odbcLogging, security, serverRuntime, serverSideInclude, staticContent, tracing, urlCompression, validation, management, rewrite'. KritnerWebsite D:\gitWorkspace\KritnerWebsite\src\KritnerWebsite\web.config 12 Build
The line in the web.config was as per the template, I just changed "false" to "true" for stdoutLogEnabled.
I have also created an empty folder in the root directory "logs" - I wasn't sure if this should get created automatically or not. Either way, nothing is being written to the logs, so I am not sure what to try next.
I have opened the solution in VS2015 on my host, compiled it and ran it successfully through commandline/localhost with dotnet run. This is running it in the production configuration, so pulling from my environment variables for insights key, and connection string. So I'm not sure why the site would run successfully on my host through dotnet run but not when published to IIS
How do I get further information on what the error is?
I'm not sure what exactly caused the logs to start correctly recording in ./logs... but they did. With the exception now being recorded I could see that my connection string I had set up in my Environment Variables was off.
Still not sure what caused the logs to not write out in order for me to determine this faster.
After updating my environment variable and running iisreset as per https://serverfault.com/questions/193609/make-iis-see-updated-environment-path-variable my website is now being served properly.

Allow loading of JSON files in Visual Studio Express 2013 for Web

I have the problem, that the IIS from Visual Studio Express 2013 for Web doesn't allow the loading of *.json files. When trying to load a *.json file I get a 403 Forbidden and a help page how to configure the IIS allow the loading of JSON files, but don't know what to do with this information / where the IIS is even located.
This is the error page:
HTTP Error 404.3 - Not Found The page you are requesting cannot be
served because of the extension configuration. If the page is a
script, add a handler. If the file should be downloaded, add a MIME
map.
Most likely causes: It is possible that a handler mapping is missing.
By default, the static file handler processes all content. The feature
you are trying to use may not be installed. The appropriate MIME map
is not enabled for the Web site or application. (Warning: Do not
create a MIME map for content that users should not download, such as
.ASPX pages or .config files.) If ASP.NET is not installed.
Things you can try: In system.webServer/handlers: Ensure that the
expected handler for the current page is mapped. Pay extra attention
to preconditions (for example, runtimeVersion, pipelineMode, bitness)
and compare them to the settings for your application pool. Pay extra
attention to typographical errors in the expected handler line. Please
verify that the feature you are trying to use is installed. Verify
that the MIME map is enabled or add the MIME map for the Web site
using the command-line tool appcmd.exe. To set a MIME type, run the
following command in the IIS Express install directory: appcmd set
config /section:staticContent
/+[fileExtension='string',mimeType='string'] The variable
fileExtension string is the file name extension and the variable
mimeType string is the file type description. For example, to add a
MIME map for a file which has the extension ".xyz": appcmd set config
/section:staticContent /+[fileExtension='.xyz',mimeType='text/plain']
Warning: Ensure that this MIME mapping is needed for your Web server
before adding it to the list. Configuration files such as .CONFIG or
dynamic scripting pages such as .ASP or .ASPX, should not be
downloaded directly and should always be processed through a handler.
Other files such as database files or those used to store
configuration, like .XML or .MDF, are sometimes used to store
configuration information. Determine if clients can download these
file types before enabling them. Install ASP.NET. Check the failed
request tracing logs for additional information about this error. For
more information, click here.
Detailed Error Information: Module StaticFileModule Notification
ExecuteRequestHandler Handler StaticFile Error Code 0x80070032
Requested URL http: //localhost:64107/Settings/Settings.json
Physical Path D:\GIT\RepoP_Paneon\Settings\Settings.json Logon
Method Anonymous Logon User Anonymous Request Tracing Directory
C:\Users\stefank\Documents\IISExpress\TraceLogFiles\REPOP_PANEON
More Information: This error occurs when the file extension of the
requested URL is for a MIME type that is not configured on the server.
You can add a MIME type for the file extension for files that are not
dynamic scripting pages, database, or configuration files. Process
those file types using a handler. You should not allows direct
downloads of dynamic scripting pages, database or configuration files.
View more information ยป
After some more googling, and experimenting I found out, that you have to define IIS settings in the Web.config.
After adding the following configuration:
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
it works like a charm.
Full setup file example:
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0"/>
</system.web>
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
</system.webServer>
</configuration>
Better add remove tag in case future IIS has build in json support. This is my web.config section of mimeMap.
<system.webServer>
<staticContent>
<remove fileExtension=".woff" />
<remove fileExtension=".woff2" />
<remove fileExtension=".json" />
<mimeMap fileExtension=".woff" mimeType="application/x-font-woff" />
<mimeMap fileExtension=".woff2" mimeType="application/font-woff2" />
<mimeMap fileExtension=".json" mimeType="application/json" />
</staticContent>
<system.webServer>
Open CMD with administrator privilages.
Go to:
cd C:\Program Files\IIS Express
or
cd C:\Program Files (x86)\IIS Express
Run command:
appcmd set config /section:staticContent /+[fileExtension='JSON',mimeType='application/x-javascript']
We may need to distinguish the Visual Studio development environment (with IIS Express) from local IIS and a remote server (like Azure WebSites). To specifically target IIS Express, for example, we edit %USERPROFILE%\Documents\IISExpress\config\applicationhost.config under system.webServer/staticContent:
<mimeMap fileExtension=".json" mimeType="application/javascript" />
I need to make this distinction because my local (intranet) IIS already has the JSON mime type defined. So when I deploy to Azure websites I use this transformation in Web.Release.config:
<system.webServer>
<staticContent>
<mimeMap fileExtension=".json" mimeType="application/javascript" xdt:Transform="Insert" />
</staticContent>
</system.webServer>

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