在 powershell 中使用 %userProfile% 环境变量创建路径时出现意外行为

2024-04-19

我编写了一个脚本来创建一系列符号链接。我想将目标值设置为 $shortpath 其中

$shortpath = "%userprofile%\dir1\dir2\dir3\filename.ext"

$shortpath 变量的值是有效的,我可以从运行命令打开它。 PS 在创建符号链接时尝试写入的字符串与预期不同。我希望它会写入字符串的值,或者至少插入环境变量的值。相反,它添加到我传递给它的字符串中。

New-Item -Path $currpath -ItemType SymbolicLink -Value ($targetpath) -Force

我期望目标值为: c:\Users\UserName\dir1\dir2\dir3\filename.ext 或 %userprofile%\dir1\dir2\dir3\filename.ext

相反,我得到: C:\windows\system32%UserProfile$\dir1\dir2\dir3\filename.ext

写入日志文件的输出示例:

wholepath = C:\Users\UserName\dir1\dir2\dir3\longfilename1.ext
spath = C:\Users\UserName\dir1\dir2\dir3\longfi~1.ext
envpath = C:\Users\UserName\
midpart = dir1\dir2\dir3\
filename = longfi~1.ext
targetpath = %UserProfile%\dir1\dir2\dir3\longfi~1.ext

有人能解释一下为什么会发生这种情况吗?如果我使用 mklink,也会发生同样的事情。我在下面添加了整个脚本:


function Get-ShortPathName
{
    Param([string] $path)

    $MethodDefinition = @'
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, EntryPoint = "GetShortPathNameW", SetLastError = true)]
public static extern int GetShortPathName(string pathName, System.Text.StringBuilder shortName, int cbShortName);
'@

    $Kernel32 = Add-Type -MemberDefinition $MethodDefinition -Name 'Kernel32' -Namespace 'Win32' -PassThru
    $shortPath = New-Object System.Text.StringBuilder(500)
    $retVal = $Kernel32::GetShortPathName($path, $shortPath, $shortPath.Capacity)
    return $shortPath.ToString()

    }

    $logfile="C:\SwSetup\SymLinkScript\log.txt"
    
    <#paths to orignials and place to copy to#>
    $src = $env:userprofile + "\Firestone Technical Resources, Inc\Firestone Technical Resources, Inc Team Site - Documents\Danielle"
    $dest = "C:\SwSetup\asdfg\"
    $src = $src.Replace("\","\\")


    <#  grab the root object, and its children, from the src#>
    $i = Get-ChildItem -LiteralPath $src -Recurse

    <# recurse through the root and process, for lack of a better term, each object#>
    $i | ForEach-Object { 
        Process {
            $apath = $_.FullName -Replace $src,""
            $cpath = $dest + $apath

            <# Create Directory if it does not exist#>
            If(!(Test-Path (Split-Path -Parent $cpath))){
                New-Item -ItemType Directory -Force -Path (Split-Path -Parent $cpath)
            }
            
            <#
            Create the SymLink if it does not exist
            mklink syntax         | PowerShell equivalent       
            mklink /D Link Target | new-item -path <path to location> -itemtype symboliclink -name <the name> -value <path to target>
            #>
            If(!$_.PSIsContainer){
                If(!(Get-Item $cpath -ErrorAction SilentlyContinue)){
                    <#establish 8.3path#>
                    $wholepath = ([WildcardPattern]::Escape($_.FullName))
                    $shortPath = Get-ShortPathName($wholepath)
                    $envpath = $shortpath.substring(0,18)
                    $midpart = ((Split-path $shortpath -parent).trimstart($envpath)) +"\"
                    $filename = Split-Path $shortpath -leaf
                    $targetpath = "%UserProfile%\" + $midpart + $filename
                    
                    <#write to log file#>
                    "wholepath = " + $wholepath >> $logfile
                    "spath = " + $Shortpath >>$logfile
                    "envpath = " + $envpath >> $logfile
                    "midpart = " +$midpart >>$logfile
                    "filename = " + $filename >> $logfile
                    "targetpath = " + $targetpath >> $logfile
                    "cpath = " + [string]$cpath >> $logfile
                    "----------" >>$logfile
                    " " >>$logfile
                    
                    <#create symlink#>
                    New-Item -Path $cpath -ItemType SymbolicLink -Value ($targetpath) -Force

                    <#cmd /c mklink $cpath $targetpath#>

                    <#create shortcut
                    $WshShell = New-Object -comObject WScript.Shell
                    $Shortcut = $WshShell.CreateShortcut($targetpath.substring(0,$targetpath.Length-4) + '.lnk')
                    $Shortcut.TargetPath = $targetpath
                    $Shortcut.Save()#>
                }
            }
        }
    }

  • 快捷方式文件 (.lnk) do支持cmd.exe-style 环境变量引用(例如%USERPROFILE%)在他们的属性中,但是有一个caveat:

    • 当使用 WshShell COM 对象创建或修改快捷方式文件时.CreateShortcut() https://learn.microsoft.com/en-us/previous-versions//xsy6k3ys(v=vs.85) API:

      • 分配财产价值,比如说,.TargetPath = '%USERPROFILE%\Desktop'按预期工作 - 即字符串按原样存储以及对环境变量的引用%USERPROFILE%只是扩大了在运行时,即当快捷方式文件是opened.

      • 然而,querying通过此 COM API 获得此类属性also进行扩展,这样你就无法得到raw定义,并且无法区分.TargetPath属性包含%USERPROFILE%\Desktop并且,说,verbatim C:\Users\jdoe\Desktop

    • 当对给定的内容有疑问时.lnk文件的实际属性值,通过检查它文件管理器.

  • 符号链接(符号链接)做not.

符号链接的目标必须指定为literal path,在你的情况下意味着使用PowerShell 的环境变量语法 https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_Environment_Variables (e.g., $env:UserProfile) 以便解析变量对其值的引用up front:

# This results in a *literal* path, because $env:UserProfile is
# instantly resolved; the result can be used with New-Item / mklink
$literalTargetPath = "$env:UserProfile\" + $midpart + $filename

通过类似的东西'%USERPROFILE%\Desktop' to the -Value / -Target的参数New-Item -Type SymbolicLink因此确实not工作(按预期),但症状取决于您运行的 PowerShell 版本:

  • Windows PowerShell您正在使用的,尝试预先验证目标路径是否存在,因此无法创建符号链接,因为它解释了%USERPROFILE%\Desktop verbatim, as a relative路径(相对于当前目录,这就是为什么要在前面添加后者的路径),该路径不存在。

  • PowerShell(核心)7+也解释了路径verbatim,但它允许创建符号链接尚未存在目标,因此符号链接创建本身会成功。然而,试图use生成的符号链接会失败,因为其目标不存在。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在 powershell 中使用 %userProfile% 环境变量创建路径时出现意外行为 的相关文章

  • 如何在powershell中使用system.tuple?

    只是出于好奇 这不是 我必须拥有它 而是如何在 powershell 中使用 system tuple 类声明元组 我正在使用 powershell exe config 加载框架 4 0 但无法创建元组 尝试这个 PS C ps1 gt
  • 使用 powershell 和 regexp 替换整行文本?

    我有编程背景 但对 powershell 脚本和正则表达式还相当陌生 正则表达式一直困扰着我 我之前的项目也从未 强迫 我学习它 考虑到这一点 我有一个文件 其中有一行文本需要替换 我不能依赖于知道该行存在于哪里 它前面是否有空格 或者被替
  • 如何在 Powershell 中为特定命令设置别名?

    有一个命令我经常输入 java jar foo param1 param2 param n 如何创建命令别名来运行此命令 如下所示 launch foo param3 where launch foo被翻译成完整的命令 你必须创建一个函数
  • Powershell send-mailmessage - 向多个收件人发送电子邮件

    我有这个 powershell 脚本来发送带有附件的电子邮件 但是当我添加多个收件人时 只有第一个收件人收到消息 我已经阅读了文档 但仍然无法弄清楚 谢谢 recipients Marcel lt email protected cdn c
  • PowerShell 中一个命令中的多个前景色

    我想用一个语句输出许多不同的前景色 PS C gt Write Host Red ForegroundColor Red Red 该输出为红色 PS C gt Write Host Blue ForegroundColor Blue Blu
  • next.js 环境变量未定义(Next.js 10.0.5)

    我正在使用 Next js 编写一个网站 并尝试添加谷歌标签管理器 我按照 Next js Github 示例上的教程进行操作 但由于某些原因我无法访问我的环境变量 它说我的变量未定义 我在项目文件夹中创建了一个文件 env local 与
  • powershell有method_missing()吗?

    我一直在研究 powershell 的动态功能 我想知道一些事情 powershell 中是否有类似于 Ruby 的 method missing 的东西 您可以在其中设置 捕获所有方法 来动态处理对对象上不存在的方法的调用 不 不是真的
  • 使用 powershell 在 MS-Access 中创建查询

    我需要自动从 Microsoft Access DB 中提取一些数据 数据库是由第三方提供给我的 因此我无法控制收到数据库时的内容 我需要使用 Powershell 自动从数据库中提取数据 有没有办法使用powershell在accessD
  • 如何使用 powershell Az 模块为 Azure AD 应用程序提供所需权限的访问权限

    我正在尝试重写 powershell 脚本来创建 Azure AD 应用程序并为其分配权限 该脚本使用 AzureAD 模块 我想使用新的 Az 模块 这样我就可以在 Linux MacOS 上运行它 创建新应用程序很容易 New AzAD
  • Kubernetes Pod 动态环境变量

    我需要能够将自定义环境变量分配给 Pod 的每个副本 一个变量应该是一些随机的 uuid 另一个唯一的数字 怎么可能实现呢 我更愿意继续使用带有副本的 部署 如果这不是开箱即用的 如何通过自定义复制控制器 控制器管理器来实现 有没有可用的钩
  • 跳转到脚本中的某些位置

    有没有办法让脚本跳转到命令提示符中的特定位置 例如 GOTO 我想让脚本结束时跳到开头 tag1 Read Host Enter tag cls sc exe tag1 start RemoteRegistry cls Start Slee
  • 尝试从 npm 安装 Angular 2 Material - 源文本中无法识别的标记

    我从 PowerShell 尝试以下命令 以管理员身份 npm install angular2 material 并得到错误 Unrecognized token in source text At line 1 char 13 npm
  • 为什么“Get-ChildItem -File | Get-FileHash”有效?

    我对 Bash 比对 Powershell 更熟悉 有时我对后者的对象模型感到困惑 看着Get FileHash 的文档 https learn microsoft com en us powershell module microsoft
  • Gradle 环境变量。从文件加载

    我是 Gradle 新手 目前我有这个任务 task fooTask doLast exec environment FOO KEY 1234567 Load from file here commandLine fooScript sh
  • 用于根据源列表移动文件的 Powershell 脚本 (.txt

    我的目录中有数千个文件 pdf xls doc 它们都有相似的命名约定 类型 始终是常量字符串 即 账单或发票 帐户名称 帐号 type pdf 帐户名称 帐号 type doc 帐户名称 帐号 type xls 手头的任务是接收帐户名和帐
  • 保留 PowerShell 函数返回类型

    在我的 PowerShell 脚本中 我需要使用以下签名调用 NET 方法 class CustomList System Collections Generic List
  • Bash 中的 Shellshock 漏洞背后的行为是有记录的还是有意为之?

    最近的一个漏洞 CVE 2014 6271 http web nvd nist gov view vuln detail vulnId CVE 2014 6271 如何Bash http en wikipedia org wiki Bash
  • 无法在 Windows docker 容器中配置 ASP.NET HTTPS 端点

    在 Windows docker 容器中运行 ASP NET Core 时出现此错误 Unhandled Exception System InvalidOperationException Unable to configure HTTP
  • 无法在 PowerShell 中完全解析 XML

    我有一个 XML 文件 我想解析该文件并检索特定信息 为了便于理解 下面是 XML 文件的屏幕截图 我想解析 XML 并为每个Item节点 检索屏幕截图中指示的字段 检索到的每个值都需要针对每个项目节点进行格式化 最后 我希望能够指定一个要
  • Powershell:如何捕获主机的输出

    我正在使用 powershell 自动执行一些与 TFS 中签出 合并相关的任务 当我打电话时 tf get recurse 我得到一堆关于正在检出的文件的数据滚动 该命令生成的最后一行 假设成功 是告知签到号码的行 我想解析它 以便稍后在

随机推荐