11

私はWindowsサービス用のnugetパッケージを作成しています。同僚がWindowsサービスを作成してパッケージをインストールすると、デフォルトのログ設定、entlibライブラリ、その他のハウスキープタスクがすべてセットアップされるという考えです。

私は、私を狂わせている1つのことを除いて、ほとんどすべてが機能するようになりました。

nugetディレクトリのコンテンツフォルダにService.csとService.Designer.csがあり、これらはターゲットcsprojに追加されていますが、関連していません。

csprojファイルを見ると、次のように表示されます。

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

しかし、私は見たいです:

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

install.psスクリプトが含まれることは確かですが、私のPowerShellスキルは存在しませんか?

余談ですが、nugetを使用してファイルを削除/上書きできますか?これまでのところ、スキップしているようです。

4

3 に答える 3

11

powershellとmsbuildhellを約2日間使用した後、ようやく実用的なソリューションが得られました。下記参照。project.Save()を呼び出す警告の言葉は非常に重要です。これがないと、「競合するファイルの変更が検出されました」という警告が表示されます。最初にproject.Save()を呼び出すと、完了したらソリューションをリロードするように求められるだけです。

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)

恥知らずな自己プラグイン:ブログcianm.comで遭遇した解決策と問題を完全に書き留めます 。これにより、誰かが時間を節約できることを願っています。

于 2012-06-05T03:09:29.323 に答える
6

$projectこれを行うためのより簡単な方法(そしておそらくよりサポートされている方法)は、DTEプロジェクトを指す変数を使用することだと思います。

注:私は1年後にこれに参加しますが、同様の問題に直面しています。この答えを見つけて使い始めましたが、PowerShellスクリプトの最後にあるSave呼び出しで問題が発生しました。PowerShellスクリプトのパッケージに依存するパッケージが1つインストールされている場合、Save呼び出しは「問題を解決」します。他のパッケージは正しくインストールできませんでした。とにかく、私は現在NuGet 2.5を使用していますが、DTEはVS 2003以降、重要な変更はありません。したがって、これは、使用していた古いNuGetでも機能するはずです。

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)

うまくいけば、それは将来、似たようなことを成し遂げようとしている人々に役立つでしょう。このようにすることで、プロジェクトがパッケージのインストールの途中で保存されるために、依存するパッケージのインストールが失敗するという問題を回避できます。

于 2013-05-15T15:41:22.923 に答える
1

これは、VisualStudio2010+の一部であるBuild.Evaluationを使用した短い例です。

$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()
于 2012-09-06T02:46:41.607 に答える