问题
Im using Azure SDK 2.5 I have a web role in a cloud service project. I would like to add a folder in some fashion such that it is deployed in the parent directory of the approot. I havent found a way to do this which kind of makes me wonder what use is the ability to define virtual directories in csdef.
So I thought I would try adding folders via the Contents/Content xml config in the csdef. I am either fundamentally misunderstanding what this bit of config does or its hopelessly broken.
Assuming this folder structure
/
/CloudService
/SomeOtherContent
If I define the following:
<Contents>
<Content destination="frontend">
<SourceDirectory path="..\SomeOtherContent" />
</Content>
</Contents>
and build I get:
error CloudServices089: Cannot find the source directory 'C:\src\template\src\Template.CloudService\bin\Debug\..\SomeOtherContent'
Ok so its starting the bin\Debug, so I'll just make it ..\..\..\SomeOtherContent
error CloudServices089: Cannot find the source directory 'C:\src\template\src\Template.CloudService\..\..\..\SomeOtherContent'
Yes thats right, the folder at which my relative path is resolved has changed!!! Its no longer bin\Debug. Wtf!? How can this be made to work? It works if i enter a full drive qualified absolute path.
回答1:
So I solved this by having MSBuild resolve the path and push it in to an environment variable which I called FrontendDir.
<Contents>
<Content destination="frontend">
<SourceDirectory path="%FrontendDir%" />
</Content>
</Contents>
and in the ccproj I added:
<UsingTask
TaskName="SetEnvironmentVariableTask"
TaskFactory="CodeTaskFactory"
AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v$(MSBuildToolsVersion).dll">
<ParameterGroup>
<Name ParameterType="System.String" Required="true" />
<Value ParameterType="System.String" Required="true" />
</ParameterGroup>
<Task>
<Using Namespace="System" />
<Code Type="Fragment" Language="cs">
<![CDATA[
Environment.SetEnvironmentVariable(Name, Value);
]]>
</Code>
</Task>
</UsingTask>
<Target Name="BeforeBuild" Condition=" '$(FrontendDir)' == '' ">
<Message Text="Setting Project Dir" Importance="high" />
<SetEnvironmentVariableTask Name="FrontendDir" Value="$(ProjectDir)\..\Template.FrontEnd\dist" />
</Target>
Its preferable to put the entire path into the env var here as you can then override it easily in your different build scenarios by overriding the value (eg. /p:FrontendDir="c:\foo")
So that works and works fairly well. I still say the behaviour I was seeing before with the relative path resolution changing folders is... broken. It just doesn't work with relative paths in any usable way.
回答2:
You are seeing the same error but from different msbuild targets.
The first error (when using ..\..\
) is thrown at PreValidateServiceModel
which passes in the Source location and checks the path
ServiceDefinitionFile="@(SourceServiceDefinition)"
ServiceConfigurationFile="@(SourceServiceConfiguration)"
C:\src\Azure\ServiceDefinition.csdef : error CloudServices089: Cannot find the source directory 'C:\src\Azure\..\..\Installers\' in role WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "PreValidateServiceModel" in project "Azure.ccproj" -- FAILED.
The second error is thrown at ValidateServiceFiles
which passes in the Target location
ServiceDefinitionFile="@(TargetServiceDefinition)"
ServiceConfigurationFile="@(TargetServiceConfiguration)">
C:\src\Azure\bin\Release\ServiceDefinition.csdef : error CloudServices089: Cannot find the source directory 'C:\src\Azure\bin\Release\Installers\' in role WebHost. [C:\src\Azure\Azure.ccproj]
Done building target "ValidateServiceFiles" in project "Azure.ccproj" -- FAILED.
If you reflect on C:\Program Files\Microsoft SDKs\Azure.NET SDK\v2.9\bin\ServiceDescription.dll you can see the ProcessRoleContents
method doing the validation but using the SourceFile to resolve the location.
One option is to make sure the target folder exists (even if empty) before the build starts.
It would be better if the PreValidation resolved the path and when the Target is saved, it had the full path.
I ended up editing the ccproj, and adding this
<Target Name="BeforeAddRoleContent">
<ItemGroup>
<AzureRoleContent Include="Installers\">
<RoleName>Azure</RoleName>
<Destination></Destination>
</AzureRoleContent>
</ItemGroup>
</Target>
Referencing runtime content from .ccproj (Azure SDK 2.9)
来源:https://stackoverflow.com/questions/27956869/adding-additional-content-folders-to-azure-package