【问题标题】:Why is my if statement not being read properly?为什么我的 if 语句没有被正确阅读?
【发布时间】:2021-08-03 21:29:04
【问题描述】:

我有一个脚本可以从本地或远程计算机备份用户配置文件并将其放置到共享中:$Global:Shared_BackupPath = "\\server\share\"。我已经对其进行了更多的调整,最后只是将一些变量变成了 全局 变量(不确定这是否是问题 - 不明白为什么会这样)。

这是条件:

if(-not (Get-EventSubscriber)){

我尝试将其更改为 -eq $null 以查看是否有任何不同,但没有。

它只是没有正确分析条件并在所有作业完成之前继续显示我的消息框:它是“应该”等到没有更多事件然后显示消息框:

        Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
        #Start-Sleep -Milliseconds 500
            $eventSubscriber | Unregister-Event
            $eventSubscriber.Action | Remove-Job
            if(-not (Get-EventSubscriber)){
                $Profile_Sum = Get-ChildItem -Path $Global:BackUp_Path -Recurse |
                    Measure-Object -Property length -Sum |
                    Select-Object -ExpandProperty Sum
                        $Size = try{if($Profile_Sum -lt 1048576){ $TinyByte = "  {0:N2}" -f ($Profile_Sum / 1KB) + " KB"; $TinyByte }
                        elseif($Profile_Sum -gt 1048576 -and $Profile_Sum -lt 1073741824){ $MediumByte = "  {0:N2}" -f ($Profile_Sum / 1MB) + " MB"; $MediumByte }
                        elseif($Profile_Sum -gt 1073741824){ $GiganticByte = "  {0:N2}" -f ($Profile_Sum / 1GB) + " GB"; $GiganticByte } } Catch {}
            
                $Begin_Time = Get-Item -Path $Global:BackUp_Path | Select-Object -ExpandProperty LastWriteTime
               
                $End_Time = Get-Date -Format G  

                Get-Job | Remove-Job 
                [System.Windows.MessageBox]::Show("Copying Complete!`nStart Time: $Begin_Time  `nEnd Time: $End_Time `nProfile Size copied: $Size")
                       
                        }
                    } | Out-Null 
                }

由于活动本身被注册为工作,我觉得我可能有一个想法,但不太确定如何去做,并让它等到完成 所有 个工作后再显示复制完成时通知我的消息框。除此之外,该脚本运行良好,任何阅读此内容的人都可以随意使用它。这是完整的脚本:

Function PFL-UserBackUp{
[cmdletbinding()]
    Param(
        [Parameter(Mandatory=$false,
                   ValueFromPipeLine=$true,
                   ValueFromPipeLineByPropertyName=$true)]
        [Alias('CN','Computer','server','node')]
        [ValidateLength(1, 15)]
        [String[]]$ComputerName = $env:COMPUTERNAME )
Begin{
    $Global:Shared_BackupPath = "\\server\share\"
    }
Process{
    Foreach($Computer in $ComputerName){
        Try{
            $PSSession  = New-PSSession -ComputerName $Computer -ErrorAction Stop 

            [array]$User_List = Invoke-Command -ScriptBlock { 
                                    Get-ChildItem -Path "C:\Users" -Exclude Public, Default* | 
                                    Sort-Object -Property LastWriteTime -Descending } -Session $PSSession

    $userinfo1 = foreach ($user in $User_List.name) {
      $userinfo = (net user $user /domain | Select-String "Full Name" -ErrorAction SilentlyContinue) -replace "Full Name                    ", "" 2>&1 | Out-String -Stream
        if ($userinfo.Length -lt 4) { "NO DISPLAY NAME in ADUC" }
            elseif($LASTEXITCODE -eq 2) { "ACCOUNT NOT in ADUC" }
            elseif($LASTEXITCODE -eq 0) { $userinfo }
                else { "Error occured" }
                }
 
     $(for($i=0; $i -lt $User_List.Count; $i++){
        [pscustomobject]@{
                'User Display Name    '  = "$($i): $($userinfo1[$i])"
                '    NAME    '           = $User_List.name[$i]
                'Last Modified'          = "$($User_List.LastWriteTime[$i])" 
                'Profile Size '          = Try{
                                             $ProfilePath = $User_List.FullName[$i] 
                                             $Profile_Sum = Invoke-Command -ScriptBlock {
                                                        Get-ChildItem -Path $Using:ProfilePath -Recurse |
                                                                Where-Object {$_.PSParentPath -match "Documents|Desktop|Music|Videos|Downloads|Links|Pictures|Favorites|Contacts" -and $_.DirectoryName -notmatch "OneDrive" } | 
                                                                Measure-Object -Property length -Sum |
                                                                Select-Object -ExpandProperty Sum } -Session $PSSession
                                                                    if($Profile_Sum -lt 1048576){ $TinyByte = "  {0:N2}" -f ($Profile_Sum / 1KB) + " KB"; $TinyByte }
                                                                    elseif($Profile_Sum -gt 1048576 -and $Profile_Sum -lt 1073741824){ $MediumByte = "  {0:N2}" -f ($Profile_Sum / 1MB) + " MB"; $MediumByte }
                                                                    elseif($Profile_Sum -gt 1073741824){ $GiganticByte = "  {0:N2}" -f ($Profile_Sum / 1GB) + " GB"; $GiganticByte } #Profile Size
                                              } Catch { "$($Error[0].Exception.Message.Split('.')[2].Trim())!" }
                                         }
                                    } ) | Out-Host

Write-Host "Press 'Q' to quit."
$ii = Read-Host -Prompt "Enter Number of Profile to Back-Up"
$i  = $ii.Trim() -split ","
    if([String]::IsNullOrEmpty($i) -eq $true) { "Null string"; Break }
    elseif($i.ToLower() -like "q*") {"Q was selected. Stopping script."; Break }


<#    
    " "    
    "     Following Profiles will be Saved:"
    "     ------------------------------------"
        foreach($i in $index) { "$($i.trim()): $($userinfo1[$i])" }
    " "


$Confirm = Read-Host -Prompt "Are you sure you want to continue? [Y/N]"
    if($Confirm.ToLower().TrimStart() -like "n*" -or $Confirm.ToLower() -like "q*"){Break} 
    if([String]::IsNullOrEmpty($Confirm.Trim()) -eq $true) { "Null string"; Break }#>


        $Profile_Path       = "C:\Users\$($User_List.name[$i])"
        $Literal_Name       = $userinfo1[$i].Replace('/','-')
        $Global:BackUp_Path = "$Global:Shared_BackupPath$Literal_Name"
        $Test_Path          = Test-Path -Path $Global:BackUp_Path 
            if($Test_Path -eq $false){
                New-Item -Path $Global:BackUp_Path -ItemType Directory | Out-Null
                Start-Process $Global:BackUp_Path}
            elseif($Test_Path -eq $true){
                $Find_OldName  = Get-ChildItem -Path "$Global:Shared_BackupPath" -Filter "$Literal_Name" -Directory |
                                     Sort-Object -Property LastWriteTime -Descending |
                                     Select-Object -ExpandProperty BaseName -First 1

                 $New_PathName = $Find_OldName + "1"
                    New-Item -Path "$Global:Shared_BackupPath" -Name $New_PathName -ItemType Directory -OutVariable Global:BackUp_Path | Out-Null #Global:BackUp_Path variable declared
                    $Global:BackUp_Path = $Global:BackUp_Path.FullName
                    Start-Process $Global:BackUp_Path}


$Global:Start_Time = Get-Date -Format G


#Favorites Copy   
$FireFox_Favorites = "C:\Users\$($User_List.name[$i])\AppData\Roaming\Mozilla\Firefox\Profiles\*.default\places.sqlite"
$Chrome_Favorites  = "C:\Users\$($User_List.name[$i])\AppData\Local\Google\Chrome\User Data\Default\Bookmarks"
$Chrome_Favorites2 = "C:\Users\$($User_List.name[$i])\AppData\Local\Google\Chrome\User Data\Default\Bookmarks.bak"
$Sticky_Notes      = "C:\Users\$($User_List.name[$i])\AppData\Local\Packages\Microsoft.MicrosoftStickyNotes_8wekyb3d8bbwe\LocalState\plum.sqlite"

$Favorites_Array   = @($FireFox_Favorites,$Chrome_Favorites,$Chrome_Favorites2,$Sticky_Notes)
    Foreach($File in $Favorites_Array){
        $Test_File = Invoke-Command -ScriptBlock { Test-Path -Path $File }
            if($Test_File -eq $true){
                Copy-Item -Path $File -Destination $Global:BackUp_Path -Force -Recurse -FromSession $PSSession 
                        }
                    }                     

#Folders Copy
$Folders = @('Desktop','Documents','Favorites','Links','Downloads','Music','Videos','Pictures','Contacts') 
    Foreach($Folder in $Folders){
        #Create Arugments for seperate thread
        $ArgumentsArray = $null

        $ArgumentsArray = @()
        $ArgumentsArray += "\\$Computer\c$\Users\$($User_List.name[$i])\$Folder"
        $ArgumentsArray += $Global:BackUp_Path
        $job = Start-Job -ScriptBlock { Copy-Item -Path $args[0] -Destination $args[1] -Force -Recurse } -Name $Folder -ArgumentList $ArgumentsArray 

        
        Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
        #Start-Sleep -Milliseconds 500
            $eventSubscriber | Unregister-Event
            $eventSubscriber.Action | Remove-Job
            if(-not (Get-EventSubscriber)){
                $Profile_Sum = Get-ChildItem -Path $Global:BackUp_Path -Recurse |
                    Measure-Object -Property length -Sum |
                    Select-Object -ExpandProperty Sum
                        $Size = try{if($Profile_Sum -lt 1048576){ $TinyByte = "  {0:N2}" -f ($Profile_Sum / 1KB) + " KB"; $TinyByte }
                        elseif($Profile_Sum -gt 1048576 -and $Profile_Sum -lt 1073741824){ $MediumByte = "  {0:N2}" -f ($Profile_Sum / 1MB) + " MB"; $MediumByte }
                        elseif($Profile_Sum -gt 1073741824){ $GiganticByte = "  {0:N2}" -f ($Profile_Sum / 1GB) + " GB"; $GiganticByte } } Catch {}
            
                $Begin_Time = Get-Item -Path $Global:BackUp_Path | Select-Object -ExpandProperty LastWriteTime
               
                $End_Time = Get-Date -Format G  

                Get-Job | Remove-Job 
                [System.Windows.MessageBox]::Show("Copying Complete!`nStart Time: $Begin_Time  `nEnd Time: $End_Time `nProfile Size copied: $Size")
                       
                        }
                    } | Out-Null 
                }

" "
Write-Output -InputObject "Copying will be done in background."
Write-Output -InputObject "You will be notified when copying is done."

            } catch [System.Management.Automation.Remoting.PSRemotingTransportException]{
                "Unable to connect to PC: $Computer `nError: $($Error[0].Exception.Message.Split('.')[2].Trim())!"
                }
            }
        }
    }

我删除了一些可能会给我带来麻烦的信息,但都是化妆品。(:

编辑: 我一定很忙,但是现在一切正常。我所做的唯一更改是在为其赋值之前清除全局变量 ($Global:var = $null)。谢谢大家的建议。我所做的另一项更改是将Copy-Item 更改为Robocopy

【问题讨论】:

  • “我的 if 语句没有正确分析条件” - 我在你的代码中计算了多个 if 语句,哪一个受到影响?
  • 糟糕,对不起!编辑它。这是检查Get-EventSubscriber 中是否没有更多事件的条件。
  • 您使用事件有什么原因吗?您是否尝试过将所有作业添加到数组中并等待它们以这种方式完成? $jobs = @(); $jobs += Start-Job ... ; $jobs | Receive-Job -Wait -AutoRemoveJob; display messagebox
  • @antonyoni,所以我可以有一个交互式控制台。我不禁认为问题出在全局变量上。在我将其更改为全局变量之前它运行良好。虽然我使用Get-ChildItem path | Sort LastWriteTime -Descending | Select -First 1 复制了用户文件夹,但这个问题是不准确的。从某种意义上说是不准确的,如果其他人正在复制到该共享,它将改为获取该文件夹;因此我将它们设为全局备份路径
  • 要从远程机器多线程复制许多小文件,考虑在备份模式下使用robocopy。您可以直接从 powershell 运行它:robocopy $src $dst /b /mir /mt:8 /r:0 /w:0

标签: powershell powershell-5.1


【解决方案1】:

只回答你的问题:

为什么我的 if 语句没有被正确读取?

就在您评估Get-EventSubscriber 之前,您正在取消您的活动订阅,从而删除您的活动订阅者。 Get-EventSubscriber 因此返回 $null,当被否定时,它的计算结果为 $true。总之,if 语句后面的代码总是会立即执行。

注释代码:

Register-ObjectEvent -InputObject $job -EventName StateChanged -Action {
    $eventSubscriber | Unregister-Event    # Here you cancel your event subscription
    $eventSubscriber.Action | Remove-Job
    if (-not (Get-EventSubscriber)) {      # Therefore, Get-EventSubscriber returns $null; not $null evaluates to $true
        ...

Unregister-Event文档中的相关部分:

Unregister-Event cmdlet 取消使用Register-EngineEventRegister-ObjectEventRegister-WmiEvent cmdlet 创建的事件订阅。

取消事件订阅后,事件订阅者将从会话中删除,并且订阅的事件不再添加到事件队列中。当您取消订阅使用 New-Event cmdlet 创建的事件时,新事件也会从会话中删除。

【讨论】:

  • 对,这就是它的目的。它正在寻找的事件是由Start-Job 生成的“StateChanged”。如果从 if {} 块中删除全局变量,它会按照预期的方式工作。因此,该代码的目的是在满足条件之前一直存在。一旦它存在,抹去它自己。 if 语句应该评估队列中没有剩余的任何内容,然后运行其余代码以包含消息框。
  • 所以,它删除自身,只有在状态改变之后。
  • 为了解决您的问题,这不在您的问题范围内,我建议根本不使用事件处理。就像你已经做的那样,循环浏览你的文件夹,开始你的工作,然后使用Wait-Job 等待你的工作完成。然后你可以执行你的 GUI 消息等等。并计算时间....只需保存开始时间之前你运行for循环并在你等待所有作业完成后存储结束时间。
  • 这违背了脚本的目的。我知道我可以从一开始就做到这一点,但我工作的本质是让它完全在后台运行。我们有大量的配置文件,其中包含大量数据,单独等待每一个都不会削减它。谢谢你的建议。
  • 可能有误会。我不建议不同的东西。像您已经在做的那样开始您的后台工作。但是,您可以使用Wait-Job 等待每个作业,而不是尝试等待每个作业触发其“完成”事件。这是完全相同的东西,但使用了现有的内置工具。这至少是一种很好的做法,也可以提高代码的可读性。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-10
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2017-08-25
相关资源
最近更新 更多