【问题标题】:PowerShell works only when running in a console and not as a PS1 executable filePowerShell 仅在控制台中运行时有效,而不是作为 PS1 可执行文件
【发布时间】:2022-01-27 07:42:01
【问题描述】:

我对 PowerShell 相当陌生,并且在尝试使 PS1 可执行文件正常工作时遇到了挑战。在 PowerShell 控制台中运行脚本完全可以正常工作并复制项目并创建正确的日志文件名。

希望右键单击包含脚本的 PS1 文件,使用“使用 PowerShell 运行”运行脚本,然后在用户提示选择是时允许脚本完成填充日志文件并复制文件。

此时,除了 PS1 文件脚本被大量无法识别的符号/字符替换并将日志文件创建为“Box Project Files.ps1JobFileLocations.log”而不是“JobFileLocations.log”之外,没有任何错误消息.


使用的 PowerShell 版本是 5.1。视窗 10 操作系统。对于 CurrentUser 和 LocalMachine,Set-ExecutionPolicy 设置为 Unrestricted 并确认为 UnrestrictedUnblock-File也试过了。

以下是在 PowerShell 控制台中运行但不能作为 PS1 可执行文件运行的脚本。

# Drawing Tag Searches
$MechDWGFilterList = @('*IFC*','*mech*', '*permit*', '*final*')
$DatabaseFilterList = @('*field*','*software*')

# Root folder and destination folder
$JobNumber = '*'+(Read-Host -Prompt 'Enter in job number')+'*'
$srcRoot = 'C:\Users\username\Box\'
$JobRoot = (Get-ChildItem -Path $srcRoot -Filter "*Active Projects*" -Recurse -Directory -Depth 1).Fullname
$dstRoot = $MyInvocation.MyCommand.Path
# Find job numer pdf file
$JobFolder = (Get-ChildItem -Path $JobRoot -Filter "$JobNumber" -Recurse -Directory -Depth 0).Fullname
$Logfile = $dstRoot+"JobFileLocations.log"

$reply = Read-Host -Prompt "Make a copy of relevant project files to local drive?[y/n]"


# Find sub-folder from job folder
$ProposalFolder = (Get-ChildItem -Path $JobFolder -Filter "*Proposals*" -Recurse -Directory).Fullname
$MechDWGFolder = (Get-ChildItem -Path $JobFolder -Filter "*Plans*" -Recurse -Directory).Fullname
$SubmittalFolder = (Get-ChildItem -Path $JobFolder -Filter "*Submittal*" -Recurse -Directory).Fullname
$DatabaseFolder = (Get-ChildItem -Path $JobFolder -Filter "*Backup*" -Recurse -Directory).Fullname
$EstimateFolder = (Get-ChildItem -Path $JobFolder -Filter "*Estimate*" -Recurse -Directory).Fullname
# Find files from list
$ProposalList = Get-ChildItem -Path $ProposalFolder -Filter '*proposal*.pdf' -r | Sort-Object -Descending -Property LastWriteTime | Select -First 1
$MechDWGList = Get-ChildItem -Path $MechDWGFolder -Filter *.pdf -r | Sort-Object -Descending -Property LastWriteTime 
$SubmittalList = Get-ChildItem $SubmittalFolder -Filter '*submittal*.pdf' -r | Sort-Object -Descending -Property LastWriteTime | Select -First 1
$DatabaseList = Get-ChildItem $DatabaseFolder -Filter *.zip -r | Sort-Object -Descending -Property LastWriteTime | Select -First 1
$EstimateList = Get-ChildItem -Path $EstimateFolder -Filter *.xl* -r | Sort-Object -Descending -Property LastWriteTime
# Log file path location and copy file to local directory

# Function to add items to a log text file
Function LogWrite
{
   Param ([string]$logstring)
   Add-content $Logfile -value $logstring
}

# Log file path location and copy file to local directory
LogWrite "::==========================================::`n||           Project Document Paths         ||`n::==========================================::"
LogWrite "`nNote: If a section has more than one file path, files are listed from most recent to oldest.`n"

LogWrite "----------Scope Document/Proposal(s)----------"
foreach ($file in $ProposalList)
{
    LogWrite $file.FullName
    if ( $reply -match "[yY]" ) 
    { 
        Copy-Item -Path $($file.FullName) -Destination $dstRoot
    }

}

LogWrite "`n-------------Mechanical Drawing(s)------------"
foreach ($file in $MechDWGList)
{
    # Where the file name contains one of these filters
    foreach($filter in $MechDWGFilterList)
    {
        if($file.Name -like $filter)
        {
            LogWrite $file.FullName
            if ( $reply -match "[yY]" ) 
            { 
                Copy-Item -Path $($file.FullName) -Destination $dstRoot
            }
        }
    }
}

LogWrite "`n-------------Controls Submittal(s)------------"
foreach ($file in $SubmittalList)
{
    LogWrite $file.FullName
    if ( $reply -match "[yY]" ) 
    { 
        Copy-Item -Path $($file.FullName) -Destination $dstRoot
    }
}

LogWrite "`n-------------------Database-------------------"
foreach ($file in $DatabaseList)
{
    LogWrite $file.FullName
    if ( $reply -match "[yY]" ) 
    { 
        Copy-Item -Path $($file.FullName) -Destination $dstRoot
    }
}

LogWrite "`n------------------Estimate(s)-----------------"
foreach ($file in $EstimateList)
{
    LogWrite $file.FullName
    if ( $reply -match "[yY]" ) 
    { 
        Copy-Item -Path $($file.FullName) -Destination $dstRoot
    }
}

# If running in the console, wait for input before closing.
if ($Host.Name -eq "ConsoleHost")
{
    Write-Host "Press any key to continue..."
    $Host.UI.RawUI.ReadKey("NoEcho,IncludeKeyUp") > $null
}

有人可以帮我理解将脚本作为 PS1 文件运行有什么问题吗?

【问题讨论】:

  • $dstRoot = $MyInvocation.MyCommand.Path 更改为$dstRoot = Split-Path $MyInvocation.MyCommand.Path -Parent,否则您将提供脚本本身的路径作为目标(我假设您想要父文件夹的路径)。或者$dstRoot = $PSScriptRoot
  • @MathiasR.Jessen 非常感谢您解决这个问题。 $dstRoot = Split-Path $MyInvocation.MyCommand.Path -Parent 完全有道理。现在接下来要学习和理解的是它和$dstRoot = $PSScriptRoot之间的性能差异@
  • 后者肯定会更快,但我不建议陷入那种级别的性能吹毛求疵 - 如果你觉得后者更容易阅读,你应该选择后者:)

标签: powershell


【解决方案1】:

您的脚本的问题在于这一行:

$dstRoot = $MyInvocation.MyCommand.Path

$MyInvocation.MyCommand.Path 将根文件系统路径解析为脚本本身 - 这就是您在日志路径中获得Box Project Files.ps1(可能是脚本的名称)的原因。

获取任意文件路径的父目录路径,可以使用Split-Path -Parent

$dstRoot = Split-Path -LiteralPath $MyInvocation.MyCommand.Path -Parent

话虽如此,从 Windows PowerShell 3.0 开始,目录和脚本文件路径都可以通过 $PSCommandPath$PSScriptRoot 自动变量获得,因此您可以将代码简化为:

$dstRoot = $PSScriptRoot

【讨论】:

  • 会牢记这两点。感谢您的课程和帮助!
猜你喜欢
  • 1970-01-01
  • 2015-08-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-06-23
  • 2023-03-22
  • 2022-11-23
相关资源
最近更新 更多