如何在PowerShell中执行MSBuild的GetDirectoryNameOfFileAbove?

时间:2013-01-30 14:00:39

标签: powershell msbuild

在MSBuild中,有GetDirectoryNameOfFileAbove属性函数。

如何使用PowerShell实现相同目标?

应该更好地使用紧凑语法,因为这是您必须粘贴到每个入口点脚本以查找其包含的内容。


这个问题的想法:

  • 源代码控制中有一个很大的解决方案。它的一些部分相对自治。
  • 它在根目录下的已知文件夹中具有共享脚本和可重用功能的位置。
  • 项目周围散布着许多入口点脚本(显式执行的文件),所有这些脚本都包括共享脚本。
  • 从入口点脚本中找到共享脚本的便捷方法是什么?

相对路径变得很糟糕,因为它们看起来像"../../../../../../scripts/smth",很难编写和维护。

注册模块不是一个好的选择,因为(a)你从SCC得到这个,而不是通过安装(b)你通常在不同的光盘位置有不同的版本,所有这些都在同一时间,(c)这是一个当技术上只有本地信息就足够时,对环境的过度依赖。


MSBuild执行此操作的方式(自v4起)如下:删除标记文件(例如,root.here或其他),使用GetDirectoryNameOfFileAbove获取该文件夹的绝对路径,等等!你有了本地root来构建路径。

也许这不是使用PowerShell的正确方法,所以我也很感激这些方向。

2 个答案:

答案 0 :(得分:1)

您可以访问当前文件夹: $ invoker = Split-Path -Parent $ MyInvocation.MyCommand.Path

那个的父母是: $ parent = Split-Path -Parent $ MyInvocation.MyCommand.Path | Split-Path -Parent

答案 1 :(得分:0)

快速而肮脏的解决方案如下所示:

function GetDirectoryNameOfFileAbove($markerfile)
{
    $result = ""
    $path = $MyInvocation.ScriptName
    while(($path -ne "") -and ($path -ne $null) -and ($result -eq "")) 
    { 
        if(Test-Path $(Join-Path $path $markerfile)) {$result=$path}
        $path = Split-Path $path 
    }
    if($result -eq "") {throw "Could not find marker file $markerfile in parent folders."}
    return $result
}

它可以被压缩成一行用于种植到脚本中,但它仍然是C#-ish,我认为它可能会缩短一些PS管道/ LINQ风格的魔法。

UPD:编辑了脚本,发现当从cmdline使用dotsourcing(具有任何上下文级别)调用脚本时,$MyInvocation.MyCommand.Path通常为NULL,因此当前假设为ScriptName