通过API调用NuGet与MSBuild时Targets文件未执行问题排查
Let’s walk through the most common reasons your MainFrameworkRegenerateFeatures target isn’t running, and how to fix them:
First, Verify the Target Is Even Being Considered
Before diving into specifics, check if MSBuild is even aware of your target or if it’s being skipped. When calling MSBuild via API, enable detailed logging (set LoggerVerbosity to Detailed in your API code). Look for entries mentioning MainFrameworkRegenerateFeatures—you’ll see if it’s marked as "Skipped" (due to a condition failing) or if it never shows up at all (meaning the targets file isn’t imported properly).
1. Your Condition Might Be Failing
The Exists check on $(ProjectDir)..\packages\SpecFlow.3.0.1\tools\SpecFlow.exe is likely the culprit here, especially if you’re using PackageReference instead of packages.config.
- With PackageReference, NuGet stores packages in a central location (usually
%USERPROFILE%\.nuget\packagesor$(NuGetPackageRoot)), not in apackagesfolder relative to your project. - Fix this by updating the path to use
$(NuGetPackageRoot):<Exec Command=""$(NuGetPackageRoot)specflow/3.0.1/tools/SpecFlow.exe" generateAll "$(ProjectPath)" /force /verbose" Condition="Exists('$(NuGetPackageRoot)specflow/3.0.1/tools/SpecFlow.exe')" /> - Also, wrap paths in quotes (
"in XML) to avoid issues with spaces in project or package paths.
2. The Target Trigger Might Not Be Firing
You’re using BeforeTargets="BeforeBuild", but this only runs if you’re executing the Build or Rebuild target via the MSBuild API. If you’re calling a different target (like Clean or Publish), BeforeBuild won’t trigger.
- Ensure your API call is targeting
Build(e.g., pass/t:Buildas a command-line argument or set the target name in your API code). - For more reliability, consider binding to
CoreCompileinstead—it runs right before the project compiles, regardless of which top-level build target you use:<Target Name="MainFrameworkRegenerateFeatures" BeforeTargets="CoreCompile">
3. Your Targets File Isn’t Imported Into the Project
MSBuild won’t execute targets from a file unless it’s explicitly imported into your .csproj or .vbproj file. Double-check that your project includes:
<Import Project="Path/To/Your/TargetsFile.targets" />
Place this near the end of your project file (after any other imports) to ensure it takes precedence.
4. Logging Level Is Too Low
Your Message task uses Importance="high", but if your MSBuild API call is using a low verbosity level (like Quiet or Minimal), you won’t see this message even if the target runs.
- Set the logger verbosity to
Normalor higher in your API call to confirm the message appears.
Example Fixed Target
Here’s a revised version of your target that addresses most of these issues:
<?xml version="1.0" encoding="utf-8" ?> <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <PropertyGroup> <!-- Define the SpecFlow path clearly for readability --> <SpecFlowExePath>$(NuGetPackageRoot)specflow/3.0.1/tools/SpecFlow.exe</SpecFlowExePath> </PropertyGroup> <Target Name="MainFrameworkRegenerateFeatures" BeforeTargets="CoreCompile" Condition="Exists('$(SpecFlowExePath)')"> <Message Importance="high" Text="Regenerating Feature Files with SpecFlow at: $(SpecFlowExePath)" /> <Exec Command=""$(SpecFlowExePath)" generateAll "$(ProjectPath)" /force /verbose" /> </Target> ... </Project>
内容的提问来源于stack exchange,提问作者Baaleos

