在我的场景中,我必须在我的 ASP.Net 网站上附带一个 Perl 解释器(不要问我为什么需要 Perl,很抱歉我提前这样做了!),其中包括导致 aspnet_compiler 的 .c 文件。 exe 出错,正如其他人提到的那样,这是他们的问题。perl 目录在我的 bin 文件夹中,在运行时需要。
我发现的问题是当你attrib +H
使用该文件夹时,它确实被 aspnet_compiler 跳过了,但不会出现在我的发布输出文件夹中。所以我不得不通过隐藏文件夹、编译视图、取消隐藏文件夹,然后将文件夹复制到正确的位置来进一步破解它。这涉及修改原始AspNetPreCompile
任务。见下文:
<!-- Overwrite AspNetPreCompile task because it was trying to compile .c files found in the Perl directory. This prevents that but still copies Perl to publish file. -->
<!-- Taken from: C:\Program Files (x86)\Microsoft Visual Studio\2017\Professional\MSBuild\Microsoft\VisualStudio\v15.0\Web\Transform -->
<Target Name="AspNetPreCompile" DependsOnTargets="$(AspNetPreCompileDependsOn)" Condition="'$(AspNetPreCompile)' != 'false'">
<PropertyGroup Condition="'$(UseMetabasePath)' == 'true'" >
<_PreAspnetCompileMergeSingleTargetFolderFullPath></_PreAspnetCompileMergeSingleTargetFolderFullPath>
<_AspNetCompilerVirtualPath></_AspNetCompilerVirtualPath>
</PropertyGroup>
<PropertyGroup Condition="'$(UseMetabasePath)' != 'true'" >
<_PreAspnetCompileMergeSingleTargetFolderFullPath>$([System.IO.Path]::GetFullPath($(_PreAspnetCompileMergeSingleTargetFolder)))</_PreAspnetCompileMergeSingleTargetFolderFullPath>
</PropertyGroup>
<PropertyGroup>
<_PostAspnetCompileMergeSingleTargetFolderFullPath>$([System.IO.Path]::GetFullPath($(_PostAspnetCompileMergeSingleTargetFolder)))</_PostAspnetCompileMergeSingleTargetFolderFullPath>
</PropertyGroup>
<!-- Modification #1. -->
<Exec Command="attrib +H "$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\perl"" />
<AspNetCompiler
PhysicalPath="$(_PreAspnetCompileMergeSingleTargetFolderFullPath)"
TargetPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)"
VirtualPath="$(_AspNetCompilerVirtualPath)"
Force="$(_AspNetCompilerForce)"
Debug="$(DebugSymbols)"
Updateable="$(EnableUpdateable)"
KeyFile="$(_AspNetCompileMergeKeyFile)"
KeyContainer="$(_AspNetCompileMergeKeyContainer)"
DelaySign="$(DelaySign)"
AllowPartiallyTrustedCallers="$(AllowPartiallyTrustedCallers)"
FixedNames="$(_AspNetCompilerFixedNames)"
Clean="$(Clean)"
MetabasePath="$(_AspNetCompilerMetabasePath)"
ToolPath="$(AspnetCompilerPath)"
/>
<!-- Modification #2. -->
<Exec Command="attrib -H "$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\perl"" />
<!--
Removing APP_DATA is done here so that the output groups reflect the fact that App_data is
not present
-->
<RemoveDir Condition="'$(DeleteAppDataFolder)' == 'true' And Exists('$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data')"
Directories="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\App_Data" />
<CollectFilesinFolder Condition="'$(UseMerge)' != 'true'"
RootPath="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)" >
<Output TaskParameter="Result" ItemName="_AspnetCompileMergePrecompiledOutputNoMetadata" />
</CollectFilesinFolder>
<ItemGroup Condition="'$(UseMerge)' != 'true'">
<FileWrites Include="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\**"/>
</ItemGroup>
<!-- Modification #3. -->
<ItemGroup>
<Perl Include="$(IntermediateOutputPath)AspnetCompileMerge\Source\bin\perl\**\*.*" />
</ItemGroup>
<!-- Modification #4. -->
<Copy SourceFiles="@(Perl)" DestinationFolder="$(_PostAspnetCompileMergeSingleTargetFolderFullPath)\bin\perl\%(RecursiveDir)"></Copy>
</Target>
不要修改原始 .targets 文件,将其复制到您的 .csproj 文件中作为<project>
节点的子文件。
关键要点:
在通过 AspNetCompiler 任务运行 aspnet_compiler.exe 之前和之后使用Exec
命令。attrib +H Directory
attrib -H Directory
创建一个ItemGroup
以吸入所有仍需要复制的文件。
运行Copy
任务,利用它将ItemGroup
文件放在需要的位置,以便发布任务的其余部分包含它们。我们可以使用 Microsoft 在创作此任务时创建的所有变量,因此我们也可以在此处使用这些变量。
修改原始任务的专业人士:对正常行为的改变很少,所以它应该仍然可以工作。
修改原始任务的可能骗局:微软将来可能会更改此任务,使我们的副本过时。
如果你没有我奇怪的要求,更简单的隐藏文件夹的解决方案如下:
<Target Name="Test" BeforeTargets="AspNetPreCompile">
<Exec Command="attrib +H Directory" />
</Target>
<Target Name="Test" AfterTargets="AspNetPreCompile">
<Exec Command="attrib -H Directory" />
</Target>
受 Arthur Nunes 回答中的评论 twamley 启发的回答。