1

我有一个脚本,可以从本地或远程计算机备份用户配置文件并将其放置到共享上:$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

4

1 回答 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

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

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

于 2021-05-17T19:50:26.077 回答