Cannot commit configuration changes because the file has changed on disk - asp.net

I would like to have a powershell script that could create an IIS web site.
but I am getting error
New-IISSite : Filename:
\?\C:\Windows\system32\inetsrv\config\applicationHost.config Error:
Cannot commit configuration changes because the file has changed on
disk At C:\projects\salonsecretSrc\RegisterWebSite.ps1:38 char:9
+ New-IISSite -BindingInformation $strIssBindigFormat -Name $st ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [New-IISSite], FileLoadException
+ FullyQualifiedErrorId : System.IO.FileLoadException,Microsoft.IIS.Powershell.Commands.NewIISSiteComman
this is my script:
$strCurrentPath = $MyInvocation.MyCommand.Path
$strWebSiteFolder = Get-ChildItem (dir $strCurrentPath)
$strWebSiteBindingPath = $strWebSiteFolder.Directory.FullName+"\build\WebSite"
$strCurrentFolderName = $strWebSiteFolder.Directory.Name
$strIssSiteName = "$strCurrentFolderName.local"
$strIssBindigFormat = ":80:$strIssSiteName"
Write-Host "Current Script path: $strCurrentPath"
Write-Host "IIS Web Site phycical path: $strWebSiteBindingPath"
Write-Host "IIS SiteName: $strIssSiteName"
Write-Host "IIS Bindindg Format: $strIssBindigFormat"
Write-Host "Creating App Pool - $strIssSiteName"
New-WebAppPool -Name $strIssSiteName -Force
Write-Host "Creating Web Site Pool - $strIssSiteName"
New-IISSite -BindingInformation $strIssBindigFormat -Name $strIssSiteName -PhysicalPath "$strWebSiteBindingPath" -Force
Write-Host "Mapping Pull and Web Site - $strIssSiteName"
Set-ItemProperty "IIS:\Sites\$strIssSiteName" -name applicationPool -value $strIssSiteName
Write-Host "$strIssSiteName WebSite Created"
what could be an issue how to solve ?
it could create an web site first time but second time if I remove it manually it will get this error.

There are many different things that can lock the applicationHost.config file and cause powershell commands like New-IISSite to fail.
In this case, you mentioned you deleted the site manually so perhaps you still have IIS Manager open and it is locking the file. I suggest closing IIS Manager.
As described in this blog post on Powershell and IIS, the makers of Octopus Deploy have found that the only reliable solution to the file-locking problem is to wrap any file-altering commands like New-WebAppPool in try-catch blocks and retry these operations multiple times. The source code for a function to do this is found in the blog.

It seems something really screwy is going on with New-IISSite command. I ended up dropping back to New-Website (via WebAdmistration module), and all the problems went away.

Since this is the first entry in google about this issue, I will describe my findings to the cause of the error message here. It's maybe not related to OPs issue.
Example for failing code
Get-IISAppPool
New-WebAppPool -Name TestAppPool
New-IISSite -Name TestSite -PhysicalPath D:\ -BindingInformation *:80:test
Explaination
If using Get-IISAppPool from the IISAdministration PowerShell Module
followed by New-WebAppPool from the WebAdministration PowerShell Module,
the command Get-IISAppPool will somehow prevent New-WebAppPool from closing the applicationHost.config file and probably leaves it in an open state.
If we now run New-IISSite, we will get the Error:
New-IISSite : Filename: \\?\C:\Windows\system32\inetsrv\config\applicationHost.config Error: Cannot commit configuration changes because the file has changed on disk
I was able to reproduce this with other Commands too if followed the order described above:
Get-*Cmdlet from IISAdministration Module
New-*Cmdlet from WebAdministration Module
New-IISSiteBinding from IISAdministration Module
Prevention of the issue
To workaround this issue I found two solutions.
Remove the IISAdministration Module before executing New-IISSite
Wrap Get-IISAppPool and New-WebAppPool in Start-IISCommitDelay / Stop-IISCommitDelay
Only use one of the Modules. I decided to only use the IISAdministration Module. It's not in the Microsoft Docs but you can create/delete AppPools with it too using the Get-IISServerManager cmdlet as described here.
Workaround 1
Get-IISAppPool
New-WebAppPool -Name TestAppPool
Remove-Module IISAdministration
New-IISSite -Name TestSite -PhysicalPath D:\ -BindingInformation *:80:test
Workaround 2
Start-IISCommitDelay
Get-IISAppPool
New-WebAppPool -Name TestAppPool
Stop-IISCommitDelay
New-IISSite -Name TestSite -PhysicalPath D:\ -BindingInformation *:80:test

Related

IIS 10 URLSegmentLength in web.config

I am facing a problem that i have a url segment more that specified 260 chars like below:
https://somedomain.com/xyz/SomeVeryLongSegment
I have the solution as well to set the DWORD value in the Registry for the same. Command line example below
Set-ItemProperty -Path
HKLM:\System\CurrentControlSet\Services\HTTP\Parameters -Name
UrlSegmentMaxLength -Value 5000 -Type "Dword"
But what I do not want to do that since after doing that I will have to restart the http and w3svc. Since I have different applications hosted on the same server I do not want to restart them all.
I tried finding the solution if there is something similar which I can set in web.config per application. With that I already tried is setting maxUrl maxUrlLength maxQueryString maxQueryStringLength etc. etc in httpRuntime and requestLimit section of web.config.
Does anyone knows about the same?

Getting build error while building docker image for asp.net app

I created a simple ASP.NET Web API (4.5.2 framework) application.
This is a simple project I created using file > New > Project > Web > Asp.net web application and selecting ASP.NET Web Api option.
I am trying to create a Docker image getting following error.
Here is my script
#escape=`
# get the build agent image to build the project
FROM sixeyed/msbuild:netfx-4.5.2-webdeploy As build-agent
WORKDIR C:\Users\jason\source\repos\FirstApp\FirstApp
COPY FirstApp\packages.config .
RUN nuget restore packages.config -PackagesDirectory ..\packages
COPY FirstApp\ C:\Users\jason\source\repos\FirstApp\FirstApp
RUN msbuild FirstApp.csproj /p:OutputPath=c:\out /p:DeployOnBuild=true `
/p:VSToolsPath=C:\MSBuild.Microsoft.VisualStuio.Web.targets.14.0.0.3\tools\VSToolsPath
#docker image build --tag firstapp --file .\Dockerfile .
# now build the app
FROM microsoft/aspnet:windowsservercore
SHELL ["powershell"]
WORKDIR c:\web-app
RUN Remove-Website -Name 'Default Web Site'; `
New-Website -Name 'web-app' -Port 80 -PhysicalPath 'C:\web-app'
copy --from=build-agent c:\out\_PublishedWebsites\FirstApp c:\web-app
I am getting following error:
Step 10/11 : RUN Remove-Website -Name 'Default Web Site'; New-Website -Name 'web-app' -Port 80 -PhysicalPath 'C:\web-app'
---> Using cache
---> e37d8f12a4f7
Step 11/11 : copy --from=build-agent c:\out\_PublishedWebsites\FirstApp c:\web-app
docker : COPY failed: CreateFile \\?\Volume{ffe73e3d-cc0b-11e8-a943-00155d1c3a78}\out\_PublishedWebsites\FirstApp: The system cannot find the path specified.
At line:1 char:1
+ docker image build --tag firstapp --file .\Dockerfile .
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (COPY failed: Cr...path specified.:String) [], RemoteException
+ FullyQualifiedErrorId : NativeCommandError
I looked and found, there is no c:\out folder. I do not see this folder after executing this command as well:
RUN msbuild FirstApp.csproj /p:OutputPath=c:\out /p:DeployOnBuild=true `
/p:VSToolsPath=C:\MSBuild.Microsoft.VisualStuio.Web.targets.14.0.0.3\tools\VSToolsPath
Seems like a simple issue but I am not sure where can I see logs and how to fix this issue.

System.UnauthorizedAccessException: Access to path is denied

Good afternoon,
I have recently purchased a server with Plesk 12 as the Control Panel.
I don't have much experience using Plesk.
For testing purposes, I created a simple ASP.NET project which tries to read/write from a txt, as shown below:
String logPath = #"C:\inetpub\vhosts\xxx.com\httpdocs\log_application_error.txt";
StreamWriter textWriter = new StreamWriter(logPath, true);
When the StreamWriter instance is created, I get the following error:
System.UnauthorizedAccessException: Access to the path 'C:\inetpub\vhosts\xxx.com\httpdocs\log_application_error.txt' is denied.
I tried granting read/write permissions to the txt file, and even granted Full Control to "Everyone", but the result was the same.
Plesk seems to hide everything so that it is handled through the Control Panel. I don't see any Applications Pools on the IIS so I am not even sure what is the identity it is running under.
Any help would be greatly appreciated.
Try to set "Additonal write/modify permissions" at "Hosting settings" of your domain:
Try to fix it with following commands:
cacls C:\Windows\assembly\GAC_MSIL /E /R psacln /T /C
cacls C:\Windows\assembly\GAC_MSIL /E /R psaadm /T /C

How to check whether ASP.NET 4.0 registered on IIS 7.5

Is there any reliable way how to check whether ASP.NET 4.0 registered on IIS 7.5 programmatically? I need to test it in the installer as prerequisite, before ASP.NET application installation start.
If ASP.NET 4.0 not registered on the IIS, later during the installation just installed application cannot be run and returns 500 internal server error (and it is too late to solve the problem). Instead, I want to show some warning (and hint how to solve the issue) before any installation steps started. But no reliable solution found yet.
AFAIK, registry entries reading sometimes may not work correctly. So now, I run aspnet_regiis.exe -lv to list versions (as suggested here) and parse the output. But even if .NET not registered correctly my test (falsely) succeeds, because the output is (contains version 4.0):
2.0.50727.0 C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll
4.0.30319.0 C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll
(Win7 32bit)
Running aspnet_regiis.exe -ir can repair it in this case.
It's similar issue as this question, but I need test it programmatically.
Do you have any ideas or experiences?
Using your own answer as a basis, this can also be done using the command line (with elevation):
%WINDIR%\System32\inetsrv\appcmd.exe list apppool /managedRuntimeVersion:v4.0
If anything is returned, ASP.NET 4.0 is registered.
The issue with this approach is that it seems to be possible to create 4.0 application pools manually even if the filter is not installed, and then this method would not work.
EDIT:
I have ended up running these three checks:
aspnet_regiis.exe -lv (should return a line containing "c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll")
appcmd.exe list apppool /managedRuntimeVersion:v4.0 (should return a line containing "MgdVersion:v4.0")
appcmd.exe list config -section:system.webServer/isapiFilters (should return a line containing "c:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll")
Note that I only care about 32bit versions.
If all three checks pass, it can be concluded that ASP.NET 4.0 is registered. Still not 100% false positive-proof though.
This is an old question, but I'm posting an answer because your question is one of the top results on google, and it's unanswered.
The registry key you are looking for is HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\ASP.NET\4.0.30319.0. If that key is present, then .Net 4 has been installed and is registered in IIS.
If you just want to check if .Net 4 is installed, you can check HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\NET Framework Setup\NDP\v4\Full.
In Powershell it could be done like this:
# load the IIS-Commandlets
Import-Module WebAdministration
# get the isapi filters currently loaded
Get-WebConfigurationProperty -Filter "/system.webServer/isapiFilters/filter" -name *
An output could look like this:
name : ASP.Net_4.0_32bit<br/>
path : %windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_filter.dll<br/>
enabled : True<br/>
enableCache : True<br/>
preCondition : runtimeVersionv4.0,bitness32<br/>
ItemXPath : /system.webServer/isapiFilters/filter[#name='ASP.Net_4.0_32bit']<br/>
Attributes : {name, path, enabled, enableCache...}<br/>
ChildElements : {}<br/>
ElementTagName : filter<br/>
Methods :<br/>
Schema : Microsoft.IIs.PowerShell.Framework.ConfigurationElementSchema<br/>
name : ASP.Net_4.0_64bit<br/>
path ........
Based on that we could write this code to check and install .NET 4 if needed:
$DotNet4Missing = $true
# lets make sure we got .net 4 correctly setup
$isapiFilters = Get-WebConfigurationProperty -Filter "/system.webServer/isapiFilters/filter" -name *
"/system.webServer/isapiFilters/filter count: {0}" -f $isapiFilters.Count
foreach ($filter in $isapiFilters)
{
"filter.name: {0}" -f $filter.name
if ($filter.name -eq "ASP.Net_4.0_64bit")
{
"-> Found .NET 4 - GREAT!"
$DotNet4Missing = $false
}
}
if ($DotNet4Missing)
{
"Missing .NET 4 IIS integration - running aspnet_regiis.exe"
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\aspnet_regiis.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = "-iru"
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
$p.Start() | Out-Null
$p.WaitForExit()
$stdout = $p.StandardOutput.ReadToEnd()
$stderr = $p.StandardError.ReadToEnd()
"aspnet_regiis.exe stdout: {0}" -f $stdout
"aspnet_regiis.exe stderr: {0}" -f $stderr
"aspnet_regiis.exe ExitCode: {0}" -f $p.ExitCode
}
Summary: The problem described above occurs on non-server operating system (Win7). The .NET 4.0 is not registered on the IIS even if you install IIS before .NET 4.0 (and so .NET should be registered on IIS correctly). This causes unexpected problems during any ASP.NET application installation -- until aspnet_regiis.exe -ir is ran from the commandline. There is no problem with Win 2008 (i.e. when IIS installed before .NET 4.0 then .NET is registered correctly on IIS and everything works as expected).
So finally my colleague told me what possibly could be solution of the problem. I've verified that following solution works fine (also on Win7). ServerManager from Microsoft.Web.Administration namespace can be employed easily:
public static bool IsAspNetRegistered()
{
using (var mgr = new ServerManager())
{
return mgr.ApplicationPools.Any(pool => pool.ManagedRuntimeVersion == "v4.0");
}
}
In case of successful .NET registration on IIS, there is at least one application pool which runtime version is set to "v4.0" so this fact was used for the check.
Of course, if anybody deletes all application pools, this method can work incorrectly. But this is bit pathological situation I don't care. The main issue is to prevent that although everything is done according our installation recommendations, still not possible to install the application on the machine.

Powershell Get-WebSite name parameter is ignored

I want to retrieve information regarding specific IIS 7 website using the PowerShell Get-Website cmdlet. Unfortunately, Get-Website returns information for all websites regardless of the -Name parameter I pass in. It appears that the -Name parameter is ignored.
For instance, if I use:
Import-Module WebAdministration
Get-Website -Name "Test Website"
I will receive information for all websites on my machine:
Name ID State Physical Path Bindings
---- -- ----- ------------- --------
Default Web Site 1 Started %SystemDrive%\inetpub\wwwroot http *:80:
net.tcp 808:*
net.pipe *
net.msmq localhost
msmq.formatname localhost
Test Website 2 Started C:\websites\test http *:80:test.mydomain.com
According to the documentation Get-Website should return information for the website specified in the -Name parameter. I must be misunderstanding the documentation or misusing the cmdlet, or both.
How should I use Get-Website to return information for a specific website?
According to this forum post, this is a bug in the Get-Website cmdlet. The workaround until this is addressed is to use Get-Item.
$website = "Test"
Get-Item "IIS:\sites\$website"
Be sure to use double quotes, variables are not expanded when single quotes are used.
I realize it's an older post but I ran into this issue recently and found your question. I've had luck with the following syntax too:
get-website | where { $_.Name -eq 'foobar' }
Using wild cards will also get around this issue as mentioned in the work around in the connect topic referenced by #Joey
get-website -name "*Default Web Site*"

Resources