Token导航 LogoToken导航

Agent Skill · 前端设计

dotnet-msbuild-authoring(dotnet msbuild 创作)

用于辅助安全审计、权限检查、凭据风险、认证流程和常见漏洞排查。它适合让 Agent 梳理敏感配置、检查依赖风险、分析鉴权逻辑或生成安全复核清单。使用时不能把工具输出直接当最终结论,涉及密钥、令牌、用户数据或生产系统时,应先确认最小权限、脱敏方式和操作边界。

dotnet-msbuild-authoring 是前端设计类 Agent Skill,可用宿主为 Codex、Claude、Cursor、Gemini CLI,通过GitHub 仓库获取,权限为需要联网;许可证信息还不明确,第三方扫描已通过,按安装量在前端设计类的 10,216 个 Skill 里排第 7,251。

总安装 396周安装 16GitHub Stars 15下载 124核验 2026-05-01

安装说明

本站只整理中文说明,不托管安装包,也不代用户安装。
GitHub
许可证
unknown

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:dotnet-msbuild-authoring(dotnet msbuild 创作)
来源仓库:https://github.com/wshaddix/dotnet-skills
仓库路径:skills/dotnet-msbuild-authoring
安装命令:
npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-msbuild-authoring
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。该命令会通过 npx skills 从第三方来源获取 Skill;本站只展示命令,不托管安装包,也不自动执行。

skills.shnpx skills
npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-msbuild-authoring

这个 Skill 是做什么的

前端设计类 Skill 关注页面结构、视觉规范和组件写法,输出通常是可运行的界面代码。

用于辅助安全审计、权限检查和凭据风险排查。适合梳理敏感配置或生成安全复核清单。使用时不能将工具输出直接作为结论。dotnet-msbuild-authoring 属于前端设计类 Skill,可作为该场景下的辅助能力补充。涉及密钥或用户数据时应确认最小权限。注意:不覆盖 CI/CD 流程集成等内容。

来源仓库内路径:skills/dotnet-msbuild-authoring

上手步骤

4 步
  1. 1

    确认自己的宿主工具

    公开资料标注支持 Codex、Claude、Cursor、Gemini CLI;先确认自己用的是其中之一,再按对应工具的 Skills 目录放置。

  2. 2

    拿到安装命令

    可以直接复制的命令是 npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-msbuild-…;命令里的占位符换成自己的路径或密钥再执行。

  3. 3

    安装后重启宿主

    命令执行完要完全退出宿主工具再打开,让新装的 Skill 被重新扫描到,否则列表里可能看不到。

  4. 4

    按最小权限试用

    它需要需要联网,先在测试目录或测试账号里跑,确认没问题再放到正式项目。

常见问题

6 条

dotnet-msbuild-authoring 怎么安装?

在终端执行 npx skills add https://github.com/wshaddix/dotnet-skills --skill dotnet-msbuild-authoring。装完完全退出宿主工具再打开,让它重新扫描本地 Skill。

dotnet-msbuild-authoring 支持哪些 AI 工具?

公开资料标注支持 Codex、Claude、Cursor、Gemini CLI。其他工具只要能读取本地 Skill 目录,一般也能手动放进去,但要自己确认触发方式是否一致。

dotnet-msbuild-authoring 需要什么权限?

权限级别是需要联网。该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

dotnet-msbuild-authoring 是免费的吗?

公开资料没有标注明确许可证,收费和商用限制都无法确认。正式使用前请到来源仓库核对授权说明。

dotnet-msbuild-authoring 用的人多吗?

公开数据是累计安装 396 次,近一周安装 16 次,下载 124 次,GitHub 15 星。这些数字来自第三方目录统计,只能当作热度参考,不代表质量或安全性。

dotnet-msbuild-authoring 安全吗?

第三方扫描结果为通过,但这只覆盖已知的静态检查项,不能替代自己读一遍源码和安装命令。

值得选的地方和要先想清楚的地方

值得选的地方

  • 同时适配 4 种工具,换客户端不用重新找替代品。
  • 第三方扫描已通过,常见的高风险行为没有命中。

先想清楚的地方

  • 许可证没有明确标注,能不能商用、能不能再分发都不确定。
  • 第三方目录整理,版本更新和行为细节以来源仓库为准。

适不适合你

更适合

  • 已经在用 Codex,想直接扩展它能力的人。
  • 需要处理前端设计类任务、又不想每次都手写提示词的人。

不太适合

  • 需要明确授权才能用到公司项目里的场景。
  • 需要厂商级技术支持和 SLA 的生产系统。

前端设计类 Skill 对比

6 个同类
Skill总安装GitHub 星权限许可证扫描
frontend-design

前端设计 · Codex、Claude

8,823,360126,072只读MIT通过
vercel-composition-patterns

Vercel 组合模式 · Codex、Claude

3,858,81625,893需要联网MIT通过
vercel-react-native-skills

Vercel React native skills 前端 · Codex、Claude

2,468,66425,878只读MIT通过
adapt

adapt 搜索 · Codex、Claude

2,027,04023,125操作浏览器未明确通过
bolder

bolder 分析 · Codex、Claude

2,004,28823,130只读未明确通过
dotnet-msbuild-authoring

dotnet msbuild 创作 · 本页

39615需要联网未明确通过

按安装量取同分类前几名;数字来自第三方目录统计,只作热度参考,不代表质量结论。

SKILL.md 原文

dotnet-msbuild-authoring

Guidance for authoring MSBuild project system elements: custom targets with BeforeTargets/AfterTargets/DependsOnTargets, incremental build with Inputs/Outputs, props vs targets import ordering, items and item metadata (Include/Exclude/Update/Remove), conditions, property functions, well-known metadata, and advanced Directory.Build.props/Directory.Build.targets patterns.

Version assumptions:.NET 8.0+ SDK (MSBuild 17.8+). All examples use SDK-style projects.

Scope boundary: This skill owns MSBuild authoring fundamentals -- custom targets, import ordering, items, conditions, property functions, and advanced Directory.Build patterns. Basic solution layout and shared configuration (Directory.Build.props structure, CPM,.editorconfig) is owned by [skill:dotnet-project-structure]. MSBuild error interpretation and CI drift diagnosis is owned by [skill:dotnet-build-analysis].

Cross-references: [skill:dotnet-project-structure] for solution layout and basic Directory.Build.props structure, [skill:dotnet-build-analysis] for interpreting MSBuild errors and CI drift.


Custom Targets

Targets are the unit of execution in MSBuild. Each target runs a sequence of tasks and can declare ordering relationships with other targets.

Defining a Custom Target

<Target Name="PrintBuildInfo"
        BeforeTargets="Build">
  <Message Importance="high"
           Text="Building $(MSBuildProjectName) v$(Version) for $(TargetFramework)" />
</Target>

Ordering: BeforeTargets, AfterTargets, DependsOnTargets

Three mechanisms control target execution order:

MechanismEffectUse when
BeforeTargets="X"Runs this target before XInjecting into an existing pipeline (e.g., run before Build)
AfterTargets="X"Runs this target after XPost-processing (e.g., copy output after Publish)
DependsOnTargets="A;B"Ensures A and B run before this targetDeclaring prerequisite targets within your own target graph
<!-- Run license check before compile -->
<Target Name="CheckLicenseHeaders"
        BeforeTargets="CoreCompile">
  <Exec Command="dotnet tool run license-check -- --verify" />
</Target>

<!-- Copy native libs after publish -->
<Target Name="CopyNativeLibs"
        AfterTargets="Publish">
  <Copy SourceFiles="@(NativeLibrary)"
        DestinationFolder="$(PublishDir)runtimes/%(NativeLibrary.RuntimeIdentifier)/native/" />
</Target>

<!-- Composite target with dependencies -->
<Target Name="FullValidation"
        DependsOnTargets="CheckLicenseHeaders;RunApiCompat">
  <Message Importance="high" Text="All validations passed." />
</Target>

Prefer BeforeTargets/AfterTargets over DependsOnTargets for injecting into the standard build pipeline. DependsOnTargets is best for orchestrating your own custom target graph.

Extending Existing DependsOn Lists

SDK targets expose *DependsOn properties for extension. Append your target name rather than replacing the list:

<PropertyGroup>
  <BuildDependsOn>$(BuildDependsOn);GenerateVersionInfo</BuildDependsOn>
</PropertyGroup>

<Target Name="GenerateVersionInfo">
  <WriteLinesToFile File="$(IntermediateOutputPath)Version.g.cs"
                    Lines="[assembly: System.Reflection.AssemblyInformationalVersion("$(InformationalVersion)")]"
                    Overwrite="true" />
  <ItemGroup>
    <Compile Include="$(IntermediateOutputPath)Version.g.cs" />
  </ItemGroup>
</Target>

Incremental Build with Inputs/Outputs

Targets with Inputs and Outputs only run when outputs are missing or older than inputs. This is critical for build performance.

<Target Name="GenerateEmbeddedResources"
        BeforeTargets="CoreCompile"
        Inputs="@(EmbeddedTemplate)"
        Outputs="@(EmbeddedTemplate->'$(IntermediateOutputPath)%(Filename).g.cs')">
  <Exec Command="dotnet tool run template-gen -- %(EmbeddedTemplate.Identity) -o $(IntermediateOutputPath)%(EmbeddedTemplate.Filename).g.cs" />
  <ItemGroup>
    <Compile Include="$(IntermediateOutputPath)%(EmbeddedTemplate.Filename).g.cs" />
  </ItemGroup>
</Target>

How incrementality works:

  1. MSBuild compares timestamps of Inputs items against Outputs items.
  2. If all outputs exist and are newer than all inputs, the target is skipped entirely.
  3. If any input is newer than any output, the full target runs.

Common incrementality failures:

  • Missing Outputs: Target runs every build. Always pair Inputs with Outputs.
  • Volatile outputs: If another target writes to the output path mid-build, timestamps reset and trigger unnecessary rebuilds.
  • Generator side effects: Code generators that write unconditionally (even when content unchanged) break incrementality. Write to a temp file and copy only if content differs.
  • File copy timestamps: Copy task with SkipUnchangedFiles="true" preserves timestamps; without it, every copy updates the timestamp.

Props vs Targets: Import Ordering

MSBuild evaluates project files in a specific order. Understanding this is essential for correct customization.

Evaluation Order

1. Directory.Build.props          (imported by SDK early)
2. <Project Sdk="...">            (SDK props imported)
3. Explicit <Import> in project   (your .props imports)
4. Project body <PropertyGroup>,  (project-level properties)
   <ItemGroup>
5. SDK targets imported            (SDK targets)
6. Directory.Build.targets         (imported by SDK late)
7. Explicit .targets imports       (your .targets imports)

Rules

  • .props files set default property values and define items. They run before the project body, so project-level properties can override them.
  • .targets files define targets and finalize item lists. They run after the project body, so they see all project-level settings.
<!-- MyDefaults.props -- sets defaults, project can override -->
<Project>
  <PropertyGroup>
    <TreatWarningsAsErrors Condition="'$(TreatWarningsAsErrors)' == ''">true</TreatWarningsAsErrors>
    <Nullable Condition="'$(Nullable)' == ''">enable</Nullable>
  </PropertyGroup>
</Project>
<!-- MyTargets.targets -- runs after project evaluation -->
<Project>
  <Target Name="ValidatePackageMetadata"
          BeforeTargets="Pack"
          Condition="'$(IsPackable)' == 'true'">
    <Error Condition="'$(Description)' == ''"
           Text="Description is required for packable projects." />
  </Target>
</Project>

Key rule: Properties in .props files should use Condition="'$(Prop)' == ''" to allow project-level overrides. Properties in .targets files are evaluated last and cannot be overridden by the project.


Items and Item Metadata

Items are named collections of files or values. Each item can carry metadata (key-value pairs).

Item Operations

<ItemGroup>
  <!-- Include: add items matching a glob -->
  <Content Include="assets/**/*.png" />

  <!-- Exclude: remove items matching a pattern from the Include -->
  <Compile Include="**/*.cs" Exclude="**/*.generated.cs" />

  <!-- Update: modify metadata on existing items (does not add new items) -->
  <Content Update="assets/logo.png">
    <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    <Pack>true</Pack>
    <PackagePath>contentFiles/any/any/</PackagePath>
  </Content>

  <!-- Remove: remove items matching a pattern from the item list -->
  <Compile Remove="legacy/**/*.cs" />
</ItemGroup>

**SDK-style projects auto-include *.cs files. Do not add a `<Compile Include="/*.cs" /> -- it causes NETSDK1022 duplicate items. Use Remove first, then Include` for conditional compilation scenarios:

<!-- TFM-conditional compilation -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <Compile Remove="Polyfills/**/*.cs" />
</ItemGroup>

Well-Known Metadata

Every item has built-in metadata accessible via %(ItemName.MetadataName):

MetadataValueExample for src/Models/Order.cs
%(FullPath)Absolute path/repo/src/Models/Order.cs
%(RootDir)Root directory/
%(Directory)Directory relative to rootrepo/src/Models/
%(Filename)File name without extensionOrder
%(Extension)File extension.cs
%(RecursiveDir)Part matched by ** in globModels/ (if glob was src/**/*.cs)
%(Identity)Item spec as declaredsrc/Models/Order.cs

Item Metadata and Batching

Custom metadata enables per-item behavior through MSBuild batching:

<ItemGroup>
  <DbMigration Include="migrations/*.sql">
    <TargetDb>main</TargetDb>
  </DbMigration>
  <DbMigration Include="migrations/audit/*.sql">
    <TargetDb>audit</TargetDb>
  </DbMigration>
</ItemGroup>

<!-- Batching: the task runs once per unique %(TargetDb) value -->
<Target Name="RunMigrations">
  <Exec Command="sqlcmd -d %(DbMigration.TargetDb) -i %(DbMigration.Identity)"
        Condition="'@(DbMigration)' != ''" />
</Target>

%(Metadata) in a task attribute triggers batching. MSBuild groups items by the metadata value and invokes the task once per group.


Conditions

Conditions control whether properties, items, targets, and tasks are evaluated.

Property Conditions

<PropertyGroup>
  <!-- Default: set only if not already defined -->
  <LangVersion Condition="'$(LangVersion)' == ''">latest</LangVersion>

  <!-- TFM condition -->
  <DefineConstants Condition="$(TargetFramework.StartsWith('net8'))">$(DefineConstants);NET8_OR_GREATER</DefineConstants>

  <!-- Configuration condition -->
  <Optimize Condition="'$(Configuration)' == 'Release'">true</Optimize>

  <!-- OS condition -->
  <RuntimeIdentifier Condition="$([MSBuild]::IsOSPlatform('Windows'))">win-x64</RuntimeIdentifier>
</PropertyGroup>

Item and Target Conditions

<!-- Conditional item inclusion -->
<ItemGroup Condition="'$(TargetFramework)' == 'net8.0'">
  <PackageReference Include="Microsoft.Extensions.Hosting" Version="8.0.0" />
</ItemGroup>

<!-- Conditional target execution -->
<Target Name="SignAssembly"
        AfterTargets="Build"
        Condition="'$(Configuration)' == 'Release' AND '$(SignAssembly)' == 'true'">
  <Exec Command="signtool sign /fd SHA256 $(TargetPath)" />
</Target>

Condition Operators

OperatorExample
== / !='$(Config)' == 'Release'
AND / OR'$(A)' == '1' AND '$(B)'!= ''
! (negation)!Exists('$(OutDir)')
Exists()Exists('$(SolutionDir)global.json')
HasTrailingSlash()HasTrailingSlash('$(OutputPath)')

Always single-quote both sides of comparisons. '$(Prop)' == 'value' is correct. Unquoted comparisons fail when the property is empty.


Property Functions

MSBuild properties can call.NET static methods and MSBuild intrinsic functions inline.

.NET Static Method Calls

<PropertyGroup>
  <!-- String manipulation -->
  <NormalizedName>$([System.String]::Copy('$(PackageId)').ToLowerInvariant())</NormalizedName>

  <!-- Path combination (prefer over string concatenation) -->
  <ToolPath>$([System.IO.Path]::Combine('$(MSBuildThisFileDirectory)', 'tools', 'analyzer.dll'))</ToolPath>

  <!-- GUID generation -->
  <BuildId>$([System.Guid]::NewGuid().ToString('N'))</BuildId>

  <!-- Regex replacement -->
  <CleanVersion>$([System.Text.RegularExpressions.Regex]::Replace('$(Version)', '-.*$', ''))</CleanVersion>

  <!-- Environment variable -->
  <CiServer>$([System.Environment]::GetEnvironmentVariable('CI'))</CiServer>
</PropertyGroup>

MSBuild Intrinsic Functions

<PropertyGroup>
  <!-- OS detection -->
  <IsWindows>$([MSBuild]::IsOSPlatform('Windows'))</IsWindows>
  <IsLinux>$([MSBuild]::IsOSPlatform('Linux'))</IsLinux>
  <IsMacOS>$([MSBuild]::IsOSPlatform('OSX'))</IsMacOS>

  <!-- Arithmetic -->
  <NextVersion>$([MSBuild]::Add($(PatchVersion), 1))</NextVersion>

  <!-- Version comparison (MSBuild 17.0+) -->
  <HasModernSdk>$([MSBuild]::VersionGreaterThanOrEquals('$(NETCoreSdkVersion)', '8.0.100'))</HasModernSdk>

  <!-- Stable hash for deterministic output -->
  <InputHash>$([MSBuild]::StableStringHash('$(InputFile)'))</InputHash>

  <!-- Path resolution: find file by walking up directory tree -->
  <SharedPropsPath>$([MSBuild]::GetPathOfFileAbove('SharedConfig.props', '$(MSBuildProjectDirectory)'))</SharedPropsPath>

  <!-- Normalize path separators -->
  <SafePath>$([MSBuild]::NormalizePath('$(MSBuildProjectDirectory)', '..', 'shared'))</SafePath>
</PropertyGroup>

Useful MSBuild Properties

PropertyValue
$(MSBuildProjectDirectory)Directory containing the current .csproj
$(MSBuildThisFileDirectory)Directory containing the current .props/.targets file
$(MSBuildProjectName)Project name without extension
$(IntermediateOutputPath)obj/ output path
$(OutputPath)bin/ output path
$(TargetFramework)Current TFM (e.g., net10.0)
$(TargetFrameworks)Multi-TFM list (e.g., net8.0;net10.0)
$(Configuration)Debug or Release
$(SolutionDir)Solution directory (only set when building from solution)

Use $(MSBuildThisFileDirectory) in .props/.targets files, not $(MSBuildProjectDirectory). The former resolves to the file's own location, which is correct when the file is imported from a NuGet package or a different directory.


Directory.Build.props/targets Advanced Patterns

Basic Directory.Build layout is covered in [skill:dotnet-project-structure]. This section covers advanced patterns for multi-repo and monorepo scenarios.

Import Chain with GetPathOfFileAbove

In monorepos with nested directories, each level can define its own Directory.Build.props that chains to the parent:

repo/
  Directory.Build.props            (repo-wide defaults)
  src/
    Directory.Build.props          (src-specific overrides)
    MyApp/
      MyApp.csproj
  tests/
    Directory.Build.props          (test-specific overrides)
    MyApp.Tests/
      MyApp.Tests.csproj
<!-- src/Directory.Build.props -->
<Project>
  <!-- Chain to parent Directory.Build.props (with existence guard) -->
  <PropertyGroup>
    <_ParentBuildProps>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..'))</_ParentBuildProps>
  </PropertyGroup>
  <Import Project="$(_ParentBuildProps)" Condition="'$(_ParentBuildProps)' != ''" />

  <PropertyGroup>
    <!-- Source-specific overrides -->
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>
</Project>
<!-- tests/Directory.Build.props -->
<Project>
  <!-- Chain to parent Directory.Build.props (with existence guard) -->
  <PropertyGroup>
    <_ParentBuildProps>$([MSBuild]::GetPathOfFileAbove('Directory.Build.props', '$(MSBuildThisFileDirectory)..'))</_ParentBuildProps>
  </PropertyGroup>
  <Import Project="$(_ParentBuildProps)" Condition="'$(_ParentBuildProps)' != ''" />

  <PropertyGroup>
    <IsPackable>false</IsPackable>
    <IsTestProject>true</IsTestProject>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.NET.Test.Sdk" />
    <PackageReference Include="xunit.v3" />
    <PackageReference Include="xunit.runner.visualstudio" />
  </ItemGroup>
</Project>

Condition Guards

Prevent property values from being overridden by child imports:

<!-- repo/Directory.Build.props -->
<Project>
  <PropertyGroup>
    <!-- Defaults: can be overridden by child Directory.Build.props or project -->
    <TreatWarningsAsErrors Condition="'$(TreatWarningsAsErrors)' == ''">true</TreatWarningsAsErrors>
    <Nullable Condition="'$(Nullable)' == ''">enable</Nullable>
    <ImplicitUsings Condition="'$(ImplicitUsings)' == ''">enable</ImplicitUsings>
  </PropertyGroup>
</Project>

Rule: Properties in .props files should use the Condition="'$(Prop)' == ''" guard so that inner .props files and project-level properties can override them. Properties you want to enforce unconditionally belong in Directory.Build.targets (which evaluates last).

Preventing Double Imports

When multiple Directory.Build.props files chain upward, a shared import could be evaluated twice. Use a sentinel property to guard against this:

<!-- shared/Common.props -->
<Project>
  <!-- Guard: only evaluate once -->
  <PropertyGroup Condition="'$(_CommonPropsImported)' != 'true'">
    <_CommonPropsImported>true</_CommonPropsImported>
    <Authors>My Company</Authors>
    <Company>My Company</Company>
    <Copyright>Copyright (c) My Company. All rights reserved.</Copyright>
  </PropertyGroup>
</Project>

The sentinel and content properties must be in the same PropertyGroup with the != 'true' condition. Putting content in a separate block with == 'true' does not prevent re-evaluation -- it runs on every import because the sentinel is already set.

A cleaner approach uses Condition on the <Import> element:

<!-- Only import if not already imported -->
<Import Project="$(SharedPropsPath)"
        Condition="'$(_CommonPropsImported)' != 'true' AND Exists('$(SharedPropsPath)')" />

Enforcing Settings in Directory.Build.targets

Properties set in .targets files cannot be overridden by project-level PropertyGroup elements because they evaluate after the project body:

<!-- Directory.Build.targets -->
<Project>
  <!-- Enforced: projects cannot override these -->
  <PropertyGroup>
    <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
    <AnalysisLevel>latest-recommended</AnalysisLevel>
  </PropertyGroup>

  <!-- Conditional enforcement: only for src projects -->
  <PropertyGroup Condition="'$(IsTestProject)' != 'true' AND '$(IsPackable)' != 'false'">
    <GenerateDocumentationFile>true</GenerateDocumentationFile>
  </PropertyGroup>
</Project>

Agent Gotchas

  1. Unquoted condition comparisons. Always quote both sides: '$(Prop)' == 'value'. Unquoted $(Prop) == value fails silently when the property is empty or contains spaces.
  2. Using $(MSBuildProjectDirectory) in shared .props/.targets files. This resolves to the importing project's directory, not the file's own directory. Use $(MSBuildThisFileDirectory) to reference paths relative to the .props/.targets file itself.
  3. Setting properties in .targets and expecting project overrides. Properties in .targets evaluate after the project body and override project-level values. If a property should be overridable, set it in .props with a Condition="'$(Prop)' == ''" guard.
  4. Adding `<Compile Include="/*.cs" /> in SDK-style projects.** SDK-style projects auto-include all *.cs files. Explicit inclusion causes NETSDK1022 duplicate items. Use Remove then Include` for conditional scenarios.
  5. Missing Outputs on targets with Inputs. A target with Inputs but no Outputs runs every build. Always pair them for incremental behavior.
  6. Using $(SolutionDir) in .props/.targets files. This property is only set when building through a solution file. Command-line dotnet build MyProject.csproj leaves it empty. Use $([MSBuild]::GetPathOfFileAbove('*.sln', '$(MSBuildProjectDirectory)')) or pass paths relative to $(MSBuildThisFileDirectory).
  7. Putting items in PropertyGroup or properties in ItemGroup. Items (using Include=) must be in <ItemGroup>. Properties (using element value) must be in <PropertyGroup>. Mixing them produces silent evaluation failures.
  8. Forgetting Condition guard on parent import chain. GetPathOfFileAbove returns empty string when no file is found. The <Import> must have Condition="Exists('$(ResolvedPath)')" or the build fails with a file-not-found error.

References

平台分布

Codex

34.89%
按下载量换算43

Claude

27.88%
按下载量换算35

Cursor

18.96%
按下载量换算24

Gemini CLI

9.02%
按下载量换算11

安全审计

Gen Agent Trust Hub

通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。目前只有一个公开来源,建议同时核对源仓库。

继续浏览同类 Skills