【问题标题】:Looping in powershell with 2 foreach使用 2 个 foreach 在 powershell 中循环
【发布时间】:2021-06-09 22:56:20
【问题描述】:

我需要编写一个脚本,该脚本将删除计算机文件夹中的文件和每台计算机上用户文件夹中的文件。我已经编写了大部分脚本,但循环两个 foreach 语句时遇到问题

#Get Computer List
$computers = "C:\Temp\ComputerList.csv"

#Delete Temp Folder Files
foreach (computer in $computers) {
        Remove-Item -Path "C:\Windows\Temp\*" -Recurse -Force
}

#Create list of users from C:\users
Import-CSV -Path "C:\Temp\ComputerList.csv" | foreach {
        dir c:\users | select Name | Export-CSV -Path "C:\temp\users.csv" -NoTypeInformation
}

$list = import-csv -Path "C:\temp\users.csv

#Delete Chrome Cache
taskkill /f /im "chrome.exe"
start-sleep -seconds 5
$Items = @('Archived History',
           'Cache\*',
           'Cookies',
           'History',
           'Login Data',
           'Top Sites',
           'Visited Links',
           'Web Data')
$Folder = "$($env:LOCALAPPDATA)\Google\Chrome\User Data\Default"
$Items | % {
        if (Test-Path "$Folder\$_") {
            Remove-Item "Folder\$_"
        }
}

#Delete Internet Explorer Cache
Import-CSV -Path C:\temp\users.csv | foreach {
        Remove-Item -Path "C:\users\$($_.Name)\AppData\Local\Microsoft\Windows\INetCache\*" -Recurse -Force -EA SilentlyContinue -Verbose
}

#Delete Firefox Cache
Import-CSV -Path C:\temp\users.csv | foreach {
        Remove-Item -Path 
        "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\*" -Recurse 
        -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
        "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\*.*" - 
        Recurse -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
   "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\cache2\entries\*.*" 
        -Recurse -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
         "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\thumbnails\*" 
        -Recurse -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
       "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\cookies.sqlite" 
        -Recurse -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
   "C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\webappstore.sqlite" 
       -Recurse -Force -EA SilentlyContinue -Verbose
        Remove-Item -Path 
"C:\users\$($_.name)\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\chromeappstore.sqlite" 
       -Recurse -Force -EA SilentlyContinue -Verbose
}

有没有一种方法可以让每台机器和该机器上的每个用户配置文件都运行并输出结果,特别是它是成功还是出错了。

我将如何为这样的事情编写输出日志,以便我可以回过头来看看哪些有效,哪些无效?

我知道我的一些代码是多余的,所以我提前道歉。任何帮助将不胜感激。

【问题讨论】:

  • 您应该调用命令来删除路径中的文件,或者提供 UNC。到目前为止,如果要删除远程计算机的文件,您也不会这样做。让我回家,我会帮忙的。你也绝对是对的,很多都是多余的。
  • 我在家,您是在域环境中执行此操作吗?
  • @AbrahamZinala 是的,这一切都是在域环境中完成的。我休息了一天,但早上又把它捡起来。我将尝试对我的脚本进行一些更改,然后在此处更新更改,看看它是否看起来更好。

标签: powershell csv


【解决方案1】:

我个人会采取不同的方法,看看这是否可能是一项重复性任务,我会将其变成一个函数,类似这样的内容:

#$computers = "C:\Temp\ComputerList.csv"
Function Clear-BrowserCache {
    Param (

        [Parameter(Mandatory=$true,
                   ValueFromPipeline=$true,
                   ValueFromPipeLineByPropertyName=$true)]
        [String[]]$ComputerName,

        [Parameter(Mandatory=$false)]
        [String[]]$UserName

    )

    Begin {
    
    $Log_Path = Join-Path $env:USERPROFILE -ChildPath "Log Exports"
    $Log_Name = 'BrowserCache_Deletion' + '.csv'
    
    $Start_Time = Get-Date -Format G
    
    }

    Process {
        foreach ($Computer in $ComputerName) {
            try {

                $PSSession = New-PSSession -ComputerName $Computer -EnableNetworkAccess -ErrorAction Stop
                
                $User_List = Invoke-Command -ScriptBlock { Get-ChildItem -Path C:\Users -Directory | Sort-Object -Property LastWriteTime -Descending } -Session $PSSession 

                    foreach ($user in $User_List) {

                        $User_Name    = Find-User -UserName $User
                        $User_Profile = $User.Name

                        $FireFox_Path = "C:\Users\$User_Profile\AppData\Local\Mozilla"
                        $Chrome_Path  = "C:\Users\$User_Profile\AppData\Local\Google\Chrome"
                        $IE_Path      = "C:\Users\$User_Profile\AppData\Local\Microsoft\Windows\INetCache\*"

                        
                        $FireFox_PathTest = Invoke-Command -ScriptBlock { Test-Path -Path $using:FireFox_Path -PathType Container } -Session $PSSession
                        $Chrome_PathTest  = Invoke-Command -ScriptBlock { Test-Path -Path $using:Chrome_Path -PathType Container } -Session $PSSession
                        $IE_PathTest      = Invoke-Command -ScriptBlock { Test-Path -Path $using:FireFox_Path -PathType Any } -Session $PSSession

                            #region Firefox
                            if ($FireFox_Path -eq $true) {
                            
                                $FireFox_Bool = $true

                                $FireFox_List = @( "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\*",
                                                   "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\cache2\entries\*",
                                                   "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\thumbnails\*",
                                                   "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\cookies.sqlite",
                                                   "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\webappstore.sqlite",
                                                   "C:\users\$User_Profile\AppData\Local\Mozilla\Firefox\Profiles\*.default\cache\chromeappstore.sqlite"
                                )

                                
                                $Fox_Process = Invoke-Command -ScriptBlock { Get-Process -Name firefox -ErrorAction SilentlyContinue } -Session $PSSession
                                    if ($null -ne $Fox_Process) {
                                        
                                        $null = Invoke-Command -ScriptBlock { Get-Process -Name firefox | Stop-Process -Force -ErrorAction SilentlyContinue } -Session $PSSession


                                        foreach ($FF_Path in $FireFox_List) {
                                            switch (Test-Path -Path $FF_Path) {
  
                                              $true  { Invoke-Command -ScriptBlock { Remove-Item -Path $using:FF_Path -Recurse } -Session $PSSession  }
                                              $false { "Path Doesn't exist `n`t$FF_Path" }
                                            }
                                        }
                                    }
                            }
                            else {
                                
                                $FireFox_Bool = $false

                            }
                            #endregion Firefox

                        [PSCustomObject]@{

                            'Computer Name'   = $Computer 
                            'User Name'       = $User_Name
                            'Firefox Cleared' = $FireFox_Bool

                        } # | Export-Csv -Path $Log_Name -Force -Append -NoTypeInformation
                    }

            } Catch [System.Management.Automation.Remoting.PSRemotingTransportException] {
                
                #$Error[0].Exception.GetType().FullName - To get this exception
                #in order to 'catch' the error ( .NET Exception )
                $Error[0].Exception.Message

            }

        }
    
    }

    End {

      Get-PSSession | Remove-PSSession -ErrorAction SilentlyContinue

    }
} 



Function Find-User {
    Param (
        [Parameter(Mandatory=$true)]
        [string]$UserName
    )
    Begin {

        try {


            $User = [ADSISeacher]"samaccountname=$UserName"
            $UserProperties  = $User.FindOne().Properties
            $UserDisplayName = $UserProperties.displayname 

        } Catch [System.Management.Automation.RuntimeException] {

            $UserDisplayName = $UserName
            
        }
    }

    End {

        $UserDisplayName

    }
}

 
# SIG # Begin signature block
# MIID8wYJKoZIhvcNAQcCoIID5DCCA+ACAQExCzAJBgUrDgMCGgUAMGkGCisGAQQB
# gjcCAQSgWzBZMDQGCisGAQQBgjcCAR4wJgIDAQAABBAfzDtgWUsITrck0sYpfvNR
# AgEAAgEAAgEAAgEAAgEAMCEwCQYFKw4DAhoFAAQUytRTDxUvPNpy4d1nT0Nll5fu
# 3M2gggILMIICBzCCAXCgAwIBAgIQUBW8X0Yzy6FEY17ozWzLSzANBgkqhkiG9w0B
# AQUFADAeMRwwGgYDVQQDDBNEZWxldGUtQnJvd3NlckNhY2hlMB4XDTIxMDYxMDAw
# MDMxOVoXDTI1MDYxMDAwMDAwMFowHjEcMBoGA1UEAwwTRGVsZXRlLUJyb3dzZXJD
# YWNoZTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEArmzAJSlDnDd7oXitfv2m
# rkgo2KIwUf+9mQdUNQYl4kmYQY8dpMzcugxf/TrXkzWH9o5MQrJ4fbZHcJVqI+uc
# TjqNpFnp6k55bBtDCjql8Mrf/gIDi8ej08kLTBwmQZW6BvXNfTikRK78whR79PBU
# eR1Vi5U+ibuiL8eInYjIjlECAwEAAaNGMEQwEwYDVR0lBAwwCgYIKwYBBQUHAwMw
# HQYDVR0OBBYEFO19PFJIojssZEIxu/e++3fdsBi4MA4GA1UdDwEB/wQEAwIHgDAN
# BgkqhkiG9w0BAQUFAAOBgQCdG29Gomhx1E+mMy3kQSOff67bH2KJBx7/14ekAwxj
# V2/sM1HSEYtwTt4I/qLD/MLlNLedVGlsM4HfTfOpEG1T+QmAPPdIsG2BbqQP8eoA
# gHQcoie+06zTr/Ue7ZqVCaVwkmYrG726Xe83pEcI5YRo0fiW2SDo6p38XgQhNdi1
# ozGCAVIwggFOAgEBMDIwHjEcMBoGA1UEAwwTRGVsZXRlLUJyb3dzZXJDYWNoZQIQ
# UBW8X0Yzy6FEY17ozWzLSzAJBgUrDgMCGgUAoHgwGAYKKwYBBAGCNwIBDDEKMAig
# AoAAoQKAADAZBgkqhkiG9w0BCQMxDAYKKwYBBAGCNwIBBDAcBgorBgEEAYI3AgEL
# MQ4wDAYKKwYBBAGCNwIBFTAjBgkqhkiG9w0BCQQxFgQUL83kuZoYz71YjNWmSfhr
# JeO+l3owDQYJKoZIhvcNAQEBBQAEgYB2/oazr3wXTZaR0UbSH0bMOXBKcENfUJ4Q
# SIW1WLIfNON+5gRBk1nTHRI1iWnFbiy2iG5KWcGAOr7AoC7kZEb6vcWAyGY6yHFn
# wmI6XS0MUuxD/UqMWukOynqzVkHM8BakJtVUi2XB2aT3zWKbPsSU7LIU0pRwvhCy
# b2xtU+yK4g==
# SIG # End signature block

概念已经存在,函数的调用方式如下:

  • Clear-BrowserCache -ComputerName ComputerOne
  • Clear-BrowserCache -ComputerName (Get-Content -Path C:\Temp\Comps.txt)
  • Import-CSV -Path "C:\Temp\ComputerList.csv" | Clear-BrowserCache

当然,这是我创建的一个简单示例,但希望您能理解我试图传达的概念。我确实推荐“整洁的打字”,从长远来看,它只会对你有所帮助。我还省略了 Chrome 和可以轻松添加的 IE,并在PSCustomObject 上显示为bool 值,并可选择导出以进行日志记录。 -UserName 有一个参数,它也可以与以下思维过程一起使用:“我只想清除一个配置文件,而不是其他所有人。”,所以也许你可以处理剩下的跳过常规协议以从所有用户中删除所有浏览器缓存的代码,并让它只做一个。

您还缺少很多基础知识,例如远程处理基础知识。我提出这个问题是因为您希望在没有基础设施 的情况下对远程计算机运行脚本来支持远程系统。这应该有助于您理解为了完成这样的任务而应该做什么的概念。请注意,也可以使用 UNC 路径,这只是一个较慢的过程。此外,ping 计算机不是我最喜欢的测试计算机的方式,因为我们可以得到回显回复,并不一定意味着您可以连接到它。在我看来,New-PSSession 是一个更好的选择。此外,在执行此类多项任务时,会话是首选方法,因为我们不想不断关闭并重新打开远程会话,这可能会变得计算成本高

结果是:

PS C:\WINDOWS\system32> Clear-BrowserCache -ComputerName localhost

Computer Name User Name Firefox Cleared
------------- --------- ---------------
localhost     UserTwo             False
localhost     UserOne             False
localhost     Abraham             False
localhost     Public              False

添加了一个 sig-block,以防您被限制为远程签名。此脚本也在实际生产环境中测试,使用风险自负;或在单个“测试”计算机上。

【讨论】:

    猜你喜欢
    • 2016-04-03
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 2020-05-27
    • 2011-12-09
    • 2015-07-04
    • 1970-01-01
    相关资源
    最近更新 更多