CZEMacLeod / MSBuild.SDK.SystemWeb

This MSBuild SDK is designed to allow for the easy creation and use of SDK (shortform) projects targeting ASP.NET 4.x using System.Web.
MIT License
151 stars 8 forks source link

GenerateBindingRedirects task failed unexpectedly with System.UnauthorizedAccessException #45

Closed mungk closed 1 year ago

mungk commented 1 year ago

Hi. When auto-generating binding redirects, I'm receiving build errors if the web.config file is checked in to source control (TFVC, and is therefore readonly).

<Project Sdk="MSBuild.SDK.SystemWeb/4.0.81"> <PropertyGroup> <!-- removed other stuff for brevity --> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <GeneratedBindingRedirectsAction>Overwrite</GeneratedBindingRedirectsAction> </PropertyGroup>

This throws this error during the build process which goes away if I manually check out the web.config before building:

Severity Code Description Project File Line Suppression State Error MSB4018 The "GenerateBindingRedirects" task failed unexpectedly. System.UnauthorizedAccessException: Access to the path 'c:\path to my project\web.config' is denied. at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath) at System.IO.FileStream.Init(String path, FileMode mode, FileAccess access, Int32 rights, Boolean useRights, FileShare share, Int32 bufferSize, FileOptions options, SECURITY_ATTRIBUTES secAttrs, String msgPath, Boolean bFromProxy, Boolean useLongPath, Boolean checkHost) at System.IO.FileStream..ctor(String path, FileMode mode, FileAccess access, FileShare share, Int32 bufferSize, FileOptions options) at Microsoft.Build.Shared.FileUtilities.OpenWrite(String path, Boolean append, Encoding encoding) at Microsoft.Build.Tasks.GenerateBindingRedirects.Execute() at Microsoft.Build.BackEnd.TaskExecutionHost.Microsoft.Build.BackEnd.ITaskExecutionHost.Execute() at Microsoft.Build.BackEnd.TaskBuilder.d__26.MoveNext() Internal C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Current\Bin\amd64\Microsoft.Common.CurrentVersion.targets 2422

Is there anyway to have the process checkout the web.config file automatically before overwriting the changes?

Thanks!

leusbj commented 1 year ago

Thats an interesting question. I traditionally have the "Check out automatically" set as the behavior for both "Saving" and "Editing", so perhaps that has prevented me from experiencing this (or that the binding redirects are recalculated most frequently after changing NuGet Packages, which also triggers alterations to the web.config).

image

My expectation that attempting to perform a checkout via build scripts would be challenging, as it would likely need to tell the difference between TFVC and git style repos, and have a different behavior for each.

mungk commented 1 year ago

I have the same settings that you do and have for as long as I can remember. If it's working for you with those settings, perhaps there's something else throwing this wrench at me. Maybe the failure is not with MSBuild SDK but rather with something else that's preventing the automatic checkout from happening as it should. Thanks for the reply, I'll keep investigating.

leusbj commented 1 year ago

@mungk I created a simple solution with a small project and a single dependency that will trigger a binding redirect (which is intentionally not currently in the web.config)

Checked into a TFVC style repo in AzureDevops, the solution containing my project and the web.config that is intentionally missing a binding redirect

The Local Build (Visual Studio -> Right Click -> Build) Succeeds for me

The Azure Devops Build (Build Pipeline) Succeeds for me

I think there might be something specific about your workspace or workstation.

mungk commented 1 year ago

@leusbj Thanks for taking the time to recreate this. Unfortunately, I still have the problem but can't really figure out why. I have the same settings as you:

image

Under Team | Team Project Settings | Source Control... multiple check-outs are enabled:

image

And under Team Project Collection Settings, we are using Server workspaces rather than local.

image

In your recreation, did you happen to use Local or Server workspaces?

CZEMacLeod commented 1 year ago

@mungk I haven't tested this personally, but you might be able to get the correct operation, even with readonly forced for checked in files, which is the default on Server workspaces.

  <Target Name="SystemWebProject_TFVC_CheckOutForBindingRedirects"
          DependsOnTargets="SystemWebProject_ChooseConfigFileForGenerateBindingRedirects"
          BeforeTargets="GenerateBindingRedirects" 
          Condition="'$(AutoGenerateBindingRedirects)' == 'true' and '$(GenerateBindingRedirectsOutputType)' == 'true' and @(SuggestedBindingRedirects-&gt;Count()) &gt; 0 ">
    <PropertyGroup>
      <TF>$(VSAPPIDDIR)CommonExtensions\Microsoft\TeamFoundation\Team Explorer\tf.exe</TF>
    </PropertyGroup>
    <!-- Automticly checkout files -->
    <Exec Condition="( '$(GeneratedBindingRedirectsAction)' == 'Preview' or '$(GeneratedBindingRedirectsAction)' == 'Overwrite' ) and EXISTS('$(_GenerateBindingRedirectsIntermediateAppConfig)')" 
          Command="&quot;$(TF)&quot; checkout /noprompt &quot;$(_GenerateBindingRedirectsIntermediateAppConfig)&quot;">
    </Exec>
  </Target>

Make sure you are using the SDK version 4.0.81 or higher.

You might need other conditions added, as this doesn't actually check that TFVC is in use, and it might not be appropriate or work correctly on a build server etc.

I doubt this is something we would add directly to the SDK, although if it works for you, maybe it could be something we add to the documentation for those still using TFVC.

CZEMacLeod commented 1 year ago

@mungk Have you had a chance to review this option?

CZEMacLeod commented 1 year ago

@mungk 🏓 Ping?

mungk commented 1 year ago

Hi Cynthia, sorry I haven't been able to devote adequate time to this. Thanks for the advice and I'll keep working on it as my time allows. I'm going to go ahead and close the issue, though, since it does seem to be something on my end. Really appreciate everyone's help.