2012-05-31 29 views
10

Windows hizmeti için bir nuget paketi yazıyorum, iş arkadaşlarımın bir windows hizmeti oluşturabilmesi varsayılan kayıt ayarlarının, entlib kitaplıklarının ve diğer ev işleri görevlerinin kendileri için ayarlanacağı.Hedef csproj dosyasında <DependentUpon> öğelerini eklemek için nuget'i (powershell) nasıl alabilirim?

Bana deli olan bir şey dışında çalışmak için neredeyse herşeyi aldım.

Nuget dizininin içerik klasöründe Service.cs ve Service.Designer.cs adreslerim var, bunlar hedef csproj'a eklenir ancak ilişkilendirilmiyorlar.

<Compile Include="Service.cs"> 
    <SubType>Component</SubType> 
</Compile> 
<Compile Include="Service.Designer.cs" /> 

Ama görmek istiyorum: Ben csproj dosyası baktığınızda

Anlıyorum,

<Compile Include="Service.cs"> 
    <SubType>Component</SubType> 
</Compile> 
<Compile Include="Service.Designer.cs"> 
    <DependentUpon>Service.cs</DependentUpon> 
</Compile> 

Herhangi fikirleri o install.ps senaryoyu ama benim powershell içerecektir oldukça emin beceriler var olmayan var mı?

Bir kenara göre, dosyaları silmek/üzerine yazmak için nuget kullanılabilir mi? Şimdiye kadar sadece atlamak gibi görünüyor.

+0

Sorunun bir parçası haline gelmesi gerektiğini düşündüm. Bunu, [1.8] (http://nuget.codeplex.com/releases) olan en son NuGet sürümüne karşı test etmenizi öneririm. – Sumo

cevap

12

Yaklaşık 2 gün sonra powershell ve msbuild cehennemden sonra sonunda bir çalışma çözümü buldum. Aşağıya bakınız. Project.Save() çağrısı uyarı bir kelime çok önemlidir - bu olmadan bir "çelişen dosya değişikliği tespit" uyarı alırsınız. Önce project.Save() öğesini çağırırsanız, işiniz bittikten sonra çözümü yeniden yüklemeniz istenecektir.

param($installPath, $toolsPath, $package, $project) 

#save the project file first - this commits the changes made by nuget before this  script runs. 
$project.Save() 

#Load the csproj file into an xml object 
$xml = [XML] (gc $project.FullName) 

#grab the namespace from the project element so your xpath works. 
$nsmgr = New-Object System.Xml.XmlNamespaceManager -ArgumentList $xml.NameTable 
$nsmgr.AddNamespace('a',$xml.Project.GetAttribute("xmlns")) 

#link the service designer to the service.cs 
$node = $xml.Project.SelectSingleNode("//a:Compile[@Include='Service.Designer.cs']", $nsmgr) 
$depUpon = $xml.CreateElement("DependentUpon", $xml.Project.GetAttribute("xmlns")) 
$depUpon.InnerXml = "Service.cs" 
$node.AppendChild($depUpon) 

#link the settings file to the settings.designer.cs 
$settings = $xml.Project.SelectSingleNode("//a:None[@Include='ServiceSettings.settings']", $nsmgr) 
$generator = $xml.CreateElement("Generator", $xml.Project.GetAttribute("xmlns")) 
$generator.InnerXml = "SettingsSingleFileGenerator" 
$settings.AppendChild($generator) 

$LastGenOutput = $xml.CreateElement("LastGenOutput", $xml.Project.GetAttribute("xmlns")) 
$LastGenOutput.InnerXml = "ServiceSettings.Designer.cs" 
$settings.AppendChild($LastGenOutput) 

#set the settings designer to be autogen 
$settingsDesigner = $xml.Project.SelectSingleNode("//a:Compile[@Include='ServiceSettings.Designer.cs']", $nsmgr) 
$autoGen = $xml.CreateElement("AutoGen", $xml.Project.GetAttribute("xmlns")) 
$autoGen.InnerXml = "True" 

$DesignTimeSharedInput = $xml.CreateElement("DesignTimeSharedInput", $xml.Project.GetAttribute("xmlns")) 
$DesignTimeSharedInput.InnerXml = "True" 

$AGDependentUpon = $xml.CreateElement("DependentUpon", $xml.Project.GetAttribute("xmlns")) 
$AGDependentUpon.InnerXml = "ServiceSettings.settings" 

$settingsDesigner.AppendChild($autoGen) 
$settingsDesigner.AppendChild($DesignTimeSharedInput) 
$settingsDesigner.AppendChild($AGDependentUpon) 

#fix up the project installer.  
$projectInstallerRes = $xml.Project.SelectSingleNode("//a:EmbeddedResource[@Include='ProjectInstaller.resx']", $nsmgr) 
$projectInstallerResDepUpon = $xml.CreateElement("DependentUpon", $xml.Project.GetAttribute("xmlns")) 
$projectInstallerResDepUpon.InnerXml = "ProjectInstaller.cs" 
$projectInstallerRes.AppendChild($projectInstallerResDepUpon) 

$projectInstallerDesigner = $xml.Project.SelectSingleNode("//a:Compile[@Include='ProjectInstaller.Designer.cs']", $nsmgr) 
$projectInstallerDesignerDepUpon = $xml.CreateElement("DependentUpon", $xml.Project.GetAttribute("xmlns")) 
$projectInstallerDesignerDepUpon.InnerXml = "ProjectInstaller.cs" 
$projectInstallerDesigner.AppendChild($projectInstallerDesignerDepUpon) 

#delete the bundled program.cs file. 
$prog = $xml.Project.SelectSingleNode("//a:Compile[@Include='Program.cs']", $nsmgr) 
$prog.SelectSingleNode("..").RemoveChild($prog) 

#delete the bundled service1 file 
$oldServiceFile = $xml.Project.SelectSingleNode("//a:Compile[@Include='Service1.cs']", $nsmgr) 
$oldServiceFile.SelectSingleNode("..").RemoveChild($oldServiceFile) 

$oldServiceDesignerFile = $xml.Project.SelectSingleNode("//a:Compile[@Include='Service1.Designer.cs']", $nsmgr) 
$oldServiceDesignerFile.SelectSingleNode("..").RemoveChild($oldServiceDesignerFile) 

#save the changes. 
$xml.Save($project.FullName) 

Shameless öz takma: Bu biraz zaman dışarıda birileri kaydeder I'll do a full write up of the solution and issues I encountered on my blog cianm.com Umut.

2

İşte Visual Studio parçası olan Build.Evaluation kullanarak kısa bir örnek 2010+

$buildProject = @([Microsoft.Build.Evaluation.ProjectCollection]::GlobalProjectCollection.GetLoadedProjects($project.FullName))[0] 


$toEdit = $buildProject.Xml.Items | where-object { $_.Include -eq "Service.Designer.cs" } 
$toEdit.AddMetaData("DependentUpon", "Service.cs") 
# ... for the other files 

$project.Save() 
5

bu (ve muhtemelen daha desteklenir) yapmak için daha kolay bir yolu işaret $project değişken üzerinden olduğunu düşünüyorum DTE projesi.

Not: Buna bir yıl sonra geliyorum, ama benzer bir sorunla karşılaşıyorum. Bu cevabı buldum ve kullanmaya başladım, ancak PowerShell betiğinin sonunda kaydetme çağrısı ile ilgili bir sorun yaşadım - PowerShell betiğiyle pakete bağlı bir paketin yüklü olması durumunda, Aramayı kaydet "şeyleri kırdı" diğer paketler düzgün yüklenemedi. Her neyse, şimdi NuGet 2.5 kullanıyorum, ancak DTE, VS 2003'ten beri herhangi bir anlamla değişmedi, bu yüzden kullandığınız eski NuGet'de bile çalışmalı. Gelecekte millet benzer bir şey başarmak isteyen yardımcı olur

param($installPath, $toolsPath, $package, $project) 

# Selections of items in the project are done with Where-Object rather than 
# direct access into the ProjectItems collection because if the object is 
# moved or doesn't exist then Where-Object will give us a null response rather 
# than the error that DTE will give us. 

# The Service.cs will show with a sub-item if it's already got the designer 
# file set. In the package upgrade scenario, you don't want to re-set all 
# this, so skip it if it's set. 
$service = $project.ProjectItems | Where-Object { $_.Properties.Item("Filename").Value -eq "Service.cs" -and $_.ProjectItems.Count -eq 0 } 

if($service -eq $null) 
{ 
    # Upgrade scenario - user has moved/removed the Service.cs 
    # or it already has the sub-items set. 
    return 
} 

$designer = $project.ProjectItems | Where-Object { $_.Properties.Item("Filename").Value -eq "Service.Designer.cs" } 

if($designer -eq $null) 
{ 
    # Upgrade scenario - user has moved/removed the Service.Desginer.cs. 
    return 
} 

# Here's where you set the designer to be a dependent file of 
# the primary code file. 
$service.ProjectItems.AddFromFile($designer.Properties.Item("FullPath").Value) 

Umarım. Bu şekilde gerçekleştirdiğinizde, paket yüklemesinin ortasında proje kaydedildiğinden, bağımlı paket yüklemelerinin başarısız olmasıyla ilgili sorunlardan kaçınabilirsiniz.