I've been following a very helpful blog post by Xinyang Qiu for adding gacAssembly
elements to my Web Deploy site manifest. Unfortunately, the gacAssembly provider doesn't appear to be able to package a local assembly (that is, one not in the GAC) for deployment to the 开发者_C百科GAC. At package time, I receive the following error:
One or more entries in the manifest 'sitemanifest' are not valid. The library '<full path>\<assembly>' could not be loaded. The given assembly name or codebase was invalid. (Exception from HRESULT: 0x80131047)
I think it's interpreting the path I'm supplying as part of the assembly name, which of course isn't what I mean.
Is there some way around this? Is it possible to stick an assembly sitting in my local directory into a Web Deploy package for deployment to a server's GAC?
Web Deploy 2.0 has a new provider that meets exactly your requirements: the gacInstall provider (see http://technet.microsoft.com/en-us/library/gg607836(WS.10).aspx) allows for an assembly embedded in a source package to be GAC'd at the destination.
Given a simple manifest like this:
<sitemanifest>
<gacInstall path="C:\Temp\MyAssembly.dll" />
</sitemanifest>
..you can create a package that contains the assembly like this:
msdeploy -verb:sync -source:manifest="path to manifest.xml" -dest:package="path to package.zip"
..and then install it in the GAC on a remote machine using that package:
msdeploy -verb:sync -source:package="path the package.zip" -dest:auto,computerName=REMOTEMACHINENAME
(Provided the assembly has a strong name, of course!)
Now, the same principle can be applied to a VS Web project. You need to make sure, though, that Web Deploy 2.x is installed on both, the development machine as well as on the target web server. And instead of specifying <MsDeploySourceManifest Include="gacAssembly">
it has to be <MsDeploySourceManifest Include="gacInstall">
.
Here's a complete {projectName}.wpp.targets file I've tried this out with (based on the one from the blog post mentioned in the question):
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<CreatePackageOnPublish>True</CreatePackageOnPublish>
<IncludeGacAssemblyForMyProject>True</IncludeGacAssemblyForMyProject>
<UseMsdeployExe>False</UseMsdeployExe>
</PropertyGroup>
<PropertyGroup>
<!--Targets get execute before this Target-->
<OnBeforeCollectGacAssemblyForPackage Condition="'$(OnBeforeCollectGacAssemblyForPackage)'==''">
</OnBeforeCollectGacAssemblyForPackage>
<!--Targets get execute after this Target-->
<OnAfterCollectGacAssemblyForPackage Condition="'$(OnAfterCollectGacAssemblyForPackage)'==''">
</OnAfterCollectGacAssemblyForPackage>
<CollectGacAssemblyForPackageDependsOn Condition="'$(CollectGacAssemblyForPackageDependsOn)'==''">
$(OnBeforeCollectGacAssemblyForPackage);
Build;
</CollectGacAssemblyForPackageDependsOn>
<AfterWriteItemsToSourceManifest>
$(AfterWriteItemsToSourceManifest);
_PrintSourceManifests;
</AfterWriteItemsToSourceManifest>
</PropertyGroup>
<PropertyGroup>
<IncludeGacAssemblyForMyProject Condition="'$(IncludeGacAssemblyForMyProject)'==''">False</IncludeGacAssemblyForMyProject>
<AfterAddContentPathToSourceManifest Condition="'$(AfterAddContentPathToSourceManifest)'==''">
$(AfterAddContentPathToSourceManifest);
CollectGacAssemblyForPackage;
</AfterAddContentPathToSourceManifest>
</PropertyGroup>
<Target Name="CollectGacAssemblyForPackage"
DependsOnTargets="$(CollectGacAssemblyForPackageDependsOn)"
Condition="$(IncludeGacAssemblyForMyProject)">
<ItemGroup>
<MyGacAssembly Include="@(ReferencePath)" Condition="'%(ReferencePath.GacInstall)'=='true'" />
</ItemGroup>
<Message Text="MsDeployPath: $(MSDeployPath)" /> <!-- For debugging -->
<Message Text="Adding [gacInstall]: %(MyGacAssembly.Identity)" />
<ItemGroup>
<MsDeploySourceManifest Include="gacInstall" Condition="$(IncludeGacAssemblyForMyProject)">
<Path>%(MyGacAssembly.Identity)</Path>
</MsDeploySourceManifest>
</ItemGroup>
<CallTarget Targets="$(OnAfterCollectGacAssemblyForPackage)" RunEachTargetSeparately="false" />
</Target>
<Target Name="_PrintSourceManifests">
<!-- Just for debugging -->
<Message Text="Exporting Manifests:" />
<Message Text=" @(MsDeploySourceManifest) : %(MsDeploySourceManifest.Path)" />
</Target>
</Project>
One other thing I've added is how the gacInstall assemblies are selected, namely via a metadata entry <GacInstall>True</GacInstall>
added to the respective <Reference/>
tags inside the project.csproj file:
<Reference Include="System.Data">
<GacInstall>True</GacInstall>
</Reference>
<Reference Include="MyAssembly, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f430b784831ac64e, processorArchitecture=MSIL">
<HintPath>..\..\LIB\MyAssembly.dll</HintPath>
<GacInstall>True</GacInstall>
</Reference>
And that works no matter if you're referencing a GAC assembly or a local one.
Hope that helps :)
精彩评论