PowerShell hash table and output to text files - powershell

I have written a script with the help of #Ansgar. Below is the code for the script. The script checks for Ping, RDP, Remote Registry and WMI checks for a remote computer. The server names are entered in a text file servernames.txt Once the script is exeecuted, the servers that are UP are recorded in a text file named Online.txt and the servers which are DOWN are recorded in Offline.txt The format for recording is below:
ONLINE.TXT
<servername>
PING : SUCCESS
RDP : SUCCESS
Remote Registry : SUCCESS
WMI : SUCCESS
OFFLINE.TXT
<servername>
PING : SUCCESS
RDP : FAIL
Remote Registry : SUCCESS
WMI : SUCCESS
This is the script that I have till now:
#Text file to pick the server names. Path is hard coded to c:\temp\serverlist.txt
$servers = Get-Content "C:\temp\serverlist.txt"
ForEach ($server in $servers)
{
Write-Host `n
Write-Host $server
Write-Host `n
#PING
$ping = Test-Connection -ComputerName $server -Quiet -Count 1
#RDP
$rdp = Test-NetConnection -ComputerName $server -CommonTCPPort RDP -InformationLevel Quiet
#REMOTE REGISTRY
$regkey = [Microsoft.Win32.RegistryKey]::OpenRemoteBaseKey ([Microsoft.Win32.RegistryHive]::LocalMachine,$server)
$ref = $regkey.OpenSubKey("SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall")
#WMI
$wmi = Get-WmiObject -Query "Select * from Win32_PingStatus where Address = '$server'"
$state_noun = #{
$true = 'SUCCESS'
$false = 'FAIL'
}
$state_verb = #{
$true = 'SUCCEEDED'
$false = 'FAILED'
}
$result = #"
PING : $($state_noun[$ping])
RDP : $($state_noun[$rdp])
Remote Registry : $($state_noun[[bool]$ref])
WMI : $($state_noun[[bool]$wmi])
"#
}
How can I output the servers and their results to the text files (online.txt and offline.txt)? Thank you in advance.

Use -and to calculate the overall result of your 4 checks:
$ping -and $rdp -and [bool]$ref -and [bool]$wmi
The -and operator returns true only if both operands are true, so the above statement only becomes true when all 4 checks succeeded.
Write to one or the other output file depending on the outcome of the boolean operation:
if ($ping -and $rdp -and [bool]$ref -and [bool]$wmi) {
$result | Out-File 'C:\path\to\online.txt' -Append
} else {
$result | Out-File 'C:\path\to\offline.txt' -Append
}

Or you could use the -Contains operator as previously suggested and just do something like:
If(#($state_noun[$ping],$state_noun[$rdp],$state_noun[[bool]$ref],$state_noun[[bool]$wmi]) -contains "FAIL"){
$result | Out-File 'C:\path\to\online.txt' -Append
}else{
$result | Out-File 'C:\path\to\offline.txt' -Append
}
Though I would personally use Ansgar Wiechers's solution. I just posted this as a proof of concept (I think that's the right term).

Related

Slow Processing Script in Powershell, Worklfow first steps

as i was wondering why my script takes so long i was seachring on google and also here in stackoverflow.
But all that i could find any close to helpful was this one here, Powershell Script Running Slowly
As I'm still pretty new to Powershell this is a little complicated to get through and take over to my script as i dont know how to handle those mentiond things anyway as i never heard of it before.
My Script is pretty easy and just gives me some Informations if there is something that returns an echo or not.
I wanted to "scan" our entire Network so I made an csv with out local Networks IP's and pass it to Powershell to "Ping" those.
But I realised that the "was not responing" part takes a long time to execute.
$list = Import-Csv -Path D:\ipcheck3.csv -UseCulture
$x=$list.IP
$ErrorActionPreference = "SilentlyContinue"
foreach ($y in $x)
{
try
{
if(Test-Connection $y -Count 1 -quiet)
{
write-host "$y responded"
$y | Export-Csv -Path D:\PingSucceded.csv -Append
}
else
{
Write-Host "$y was not responding"
$y | Export-Csv -Path D:\Pingfailed.csv -Append
}
}
catch
{
Write-Warning "Other Error occured"
}
}
There are not only Windows Clients out there so WMI is not an option and I don't know how to achvie this otherwise
EDIT:
After the Workflow input this is my "Try Version"
workflow Test-IPrange
{
Param
(
$IPs
)
$tocheck= $IPs.IP
foreach -parallel ($IP in $tocheck)
{
$pingsucceed = Test-Connection $IP -Count 1 -quiet
if($pingsucceed -eq "True")
{
$IP | Export-Csv -Path D:\testj.csv -Append
}
else
{
$IP | Export-Csv -Path D:\testn.csv -Append
}
}
}
Test-IPrange -IPs $(Import-Csv -Path D:\ipcheck3.csv -UseCulture)
My Output of Workflow Try
#TYPE System.String
PSComputerName,"PSShowComputerName","PSSourceJobInstanceId","Length"
localhost,"True","4e208e38-f7c2-492f-9d81-6583a103c3ac","12"
localhost,"True","4e208e38-f7c2-492f-9d81-6583a103c3ac","12"
With the Help of #Fourat
i edited my code to this form
Function Custom-Ping {
Param(
[string]$Address
)
$ping = ping $Address /w 1 /n 1
$result = ![string]::IsNullOrEmpty($ping -Like "*(0% Verlust)*")
return $result
}
$list = Import-Csv -Path D:\ipcheck3.csv -UseCulture
$x=$list.IP
$ErrorActionPreference = "SilentlyContinue"
foreach ($y in $x)
{
try
{
if(Custom-Ping $y)
{
Write-Host "$y responded"
$y | Export-Csv -Path D:\PingsuccededV3.csv -Append
}
else
{
Write-Host "$y was not responding"
$y | Export-Csv -Path D:\PingfailedV3.csv -Append
}
}
catch
{
Write-Warning "Textline from CMD Command or other Error"
}
}
which works properly good and is faster
I think that your process time is spoiled by the timeouts. If all your IPs are in the local network, try to reduce the timeout (because the default value is 5 seconds).
If you have Powershell 6 :
Test-Connection $y -Count 1 -quiet -TimeoutSeconds 1
If you don't, just use ping :
ping 58.47.45.1 /w 1 /n 1
You can also use a parallel for each loop, but it won't help much if you have multiple fails :
ForEach -Parallel ($x in $y)
{
...
}
UPDATE
In order to handle ping results, you can use a function like this (I used the keyword 'perte' because my computer is in French) :
Function Custom-Ping {
Param(
[string]$Address
)
$ping = ping $Address /w 1 /n 1
$result = ![string]::IsNullOrEmpty($ping -Like "*(perte 0%)*")
return $result
}
I've used Workflow to solve this issue my self. It's a few years ago I did it, so something better and newer is out there. But this works great for me...
I've ping over 2000 computers within a few Min...
workflow Test-ComputersConnection
{
Param
(
# Param1 help description
$Computernames#,
# Param2 help description
# [int]
# $Param2
)
foreach -parallel ($ComputerName in $Computernames)
{
$ConnectionTest = Test-Connection -ComputerName $ComputerName -ErrorAction SilentlyContinue -Count 1
if ($ConnectionTest.Address -eq $ComputerName) {
Write-Output $(Add-Member -MemberType NoteProperty -Name "Computername" -Value $ComputerName -InputObject $ConnectionTest -PassThru )
#Write-Verbose -Verbose -Message "[$($ComputerName)]: Replays on Ping."
}
Else {
#Write-Verbose -Verbose -Message "[$($ComputerName)]: Do not replays on Ping."
}
}
}
$OnlineNow0 = Test-ComputersConnection -Computernames $( Import-Csv -Path D:\ipcheck3.csv -UseCulture |
Select-Object -ExpandProperty name)
The code above is a quick edit of what I use... You will need to edit the $(Import ...) statement first, to make sure the PC name is being deliveret to the workflow.
I've just testet on my own computer and it gave me a reply...

Powershell output logging when using a text file to gather server names

Have a bit of an issue whereby would like to figure out the best way to handle success or failures. Have a powershell query which checks the dcom port range, if it is within the specified value output to a success file, if not a failure file. The issue is, it seems to be outputting the entire serverlist.txt for a success and need to know a way to break this down so it only appends a server (either success/failure) to it, not all at once.
Here is the powershell script contents:
powershell -executionpolicy bypass .\DCOMPortRange.ps1
Where DCOMPortRange.ps1 contains
$computername = Get-Content -Path "C:\Folderpath\serverlist.txt"
$val = (Get-ItemProperty "hklm:SOFTWARE\Microsoft\Rpc\Internet") | Select-Object -ExpandProperty Ports
if($val -eq "50000-50500")
{
Write-Output "$computername" | out-file C:\folderpath\Success.log -append
} Else {
Write-Output "$computername" | out-file C:\folderpath\Failure.log -append
}
The issue is the error path lets say is a success it appends the entire server list.
Please advise?
This is how I would do it. This does require that you do have PSremoting enabled on the servers
$computername = Get-Content -Path "C:\Folderpath\serverlist.txt"
ForEach ($server in $computername) {
$val = Invoke-Command -Computername $server -ScriptBlock {(Get-ItemProperty "hklm:SOFTWARE\Microsoft\Rpc\Internet") | Select-Object -ExpandProperty Ports}
if ($val -ge 50000 -and $val -le 50500) {
Write-Output "$server" | out-file C:\folderpath\Success.log -append
}
Else {
Write-Output "$server" | out-file C:\folderpath\Failure.log -append
}
}
Edit: A change to the if statement
/Anders
$remotecomputername = #("PC1","PC2","RealServerName")
ForEach ($computer in $remotecomputername) {
Invoke-Command -Computername $computer -ScriptBlock { $val = (Get-
ItemProperty "hklm:SOFTWARE\Microsoft\Rpc\Internet") | Select-Object -
ExpandProperty Ports} }
if($val -eq "50000-50500") {
write-host $computer DCOM Port in Range
} else {
write-host $computer DCOM Port not in range
}

Disconnect user from server using session ID

I wrote a script that will refine users that are either disconnected or have an idle time of over than 60 min. I've already set-up these parameters and the filter works well, however; instead of disconnecting the specific user in that server, the script disconnects the server as a whole
I am utilizing two other functions, one of which I added directly into the script. the other comes from Get-LoggedOnUser.ps1 The Disconnect-LoggedOnUser and Get-LoggedOnUser are intended to work together. I kept the instructions for log out script. I've included my full script in this GitHub gist
Any assistance or suggestion is greatly appreciated!
All relevant code below:
Description
-----------
This command dot sources the script to ensure the Disconnect-LoggedOnUser function is available in your current PowerShell session
.EXAMPLE
Disconnect-LoggedOnUser -ComputerName server01 -Id 5
Description
-----------
Disconnect session id 5 on server01
.EXAMPLE
.\Get-LoggedOnUser.ps1 -ComputerName server01,server02 | Where-Object {$_.UserName -eq 'JaapBrasser'} | Disconnect-LoggedOnUser -Verbose
<#My script#>
<#
.SYNOPSIS
Convert output from CMD's 'query.exe user' to usable objects.
.DESCRIPTION
Take the text based output returned by 'query.exe user' and convert it to objects that can be manipulated in PowerShell.
.PARAMETER Name
Computer name to run query.exe against.
.EXAMPLE
PS C:\> Convert-QueryToObjects -Name server01
ComputerName Username SessionState SessionType
------------ -------- ------------ -----------
server01 bobsmith Disconnected
server01 janedoe Active tcp-rdp
#>
function Disconnect-LoggedOnUser {
<#
.SYNOPSIS
Function to disconnect a RDP session remotely
.DESCRIPTION
This function provides the functionality to disconnect a RDP session remotely by providing the ComputerName and the SessionId
.PARAMETER ComputerName
This can be a single computername or an array where the RDP sessions will be disconnected
.PARAMETER Id
The Session Id that that will be disconnected
.NOTES
Name: Disconnect-LoggedOnUser
Author: Jaap Brasser
DateUpdated: 2015-06-03
Version: 1.0
Blog: http://www.jaapbrasser.com
.LINK
http://www.jaapbrasser.com
.EXAMPLE
. .\Disconnect-LoggedOnUser.ps1
Description
-----------
This command dot sources the script to ensure the Disconnect-LoggedOnUser function is available in your current PowerShell session
.EXAMPLE
Disconnect-LoggedOnUser -ComputerName server01 -Id 5
Description
-----------
Disconnect session id 5 on server01
.EXAMPLE
.\Get-LoggedOnUser.ps1 -ComputerName server01,server02 | Where-Object {$_.UserName -eq 'JaapBrasser'} | Disconnect-LoggedOnUser -Verbose
Description
-----------
Use the Get-LoggedOnUser script to gather the user sessions on server01 and server02. Where-Object filters out only the JaapBrasser user account and then disconnects the session by piping the results into Disconnect-LoggedOnUser while displaying verbose information.
#>
param(
[Parameter(
Mandatory,
ValueFromPipeline,
ValueFromPipelineByPropertyName,
Position=0
)]
[string[]]
$ComputerName,
[Parameter(
Mandatory,
ValueFromPipelineByPropertyName
)]
[int[]]
$Id
)
begin {
$OldEAP = $ErrorActionPreference
$ErrorActionPreference = 'Stop'
}
process {
foreach ($Computer in $ComputerName) {
$Id | ForEach-Object {
Write-Verbose "Attempting to disconnect session $Id on $Computer"
try {
rwinsta $_ /server:$Computer
Write-Verbose "Session $Id on $Computer successfully disconnected"
} catch {
Write-Verbose 'Error disconnecting session displaying message'
Write-Warning "Error on $Computer, $($_.Exception.Message)"
}
}
}
}
end {
$ErrorActionPreference = $OldEAP
}
}
function Convert-QueryToObjects
{
[CmdletBinding()]
[Alias('QueryToObject')]
[OutputType([PSCustomObject])]
param
(
[Parameter(Mandatory = $false,
ValueFromPipeline = $true,
ValueFromPipelineByPropertyName = $true,
Position = 0)]
[Alias('ComputerName', 'Computer')]
[string]
$Name = $env:COMPUTERNAME
)
Process
{
Write-Verbose "Running query.exe against $Name."
$Users = query user /server:$Name 2>&1
if ($Users -like "*No User exists*")
{
# Handle no user's found returned from query.
# Returned: 'No User exists for *'
Write-Error "There were no users found on $Name : $Users"
Write-Verbose "There were no users found on $Name."
}
elseif ($Users -like "*Error*")
{
# Handle errored returned by query.
# Returned: 'Error ...<message>...'
Write-Error "There was an error running query against $Name : $Users"
Write-Verbose "There was an error running query against $Name."
}
elseif ($Users -eq $null -and $ErrorActionPreference -eq 'SilentlyContinue')
{
# Handdle null output called by -ErrorAction.
Write-Verbose "Error action has supressed output from query.exe. Results were null."
}
else
{
Write-Verbose "Users found on $Name. Converting output from text."
# Conversion logic. Handles the fact that the sessionname column may be populated or not.
$Users = $Users | ForEach-Object {
(($_.trim() -replace ">" -replace "(?m)^([A-Za-z0-9]{3,})\s+(\d{1,2}\s+\w+)", '$1 none $2' -replace "\s{2,}", "," -replace "none", $null))
} | ConvertFrom-Csv
Write-Verbose "Generating output for $($Users.Count) users connected to $Name."
# Output objects.
foreach ($User in $Users)
{
Write-Verbose $User
if ($VerbosePreference -eq 'Continue')
{
# Add '| Out-Host' if -Verbose is tripped.
[PSCustomObject]#{
ComputerName = $Name
Username = $User.USERNAME
SessionState = $User.STATE.Replace("Disc", "Disconnected")
SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
IdleTime = $User.'IDLE TIME'
ID = $User.ID
LogonTime =$User.'Logon Time'
} | Out-Host
}
else
{
# Standard output.
[PSCustomObject]#{
ComputerName = $Name
Username = $User.USERNAME
SessionState = $User.STATE.Replace("Disc", "Disconnected")
SessionType = $($User.SESSIONNAME -Replace '#', '' -Replace "[0-9]+", "")
IdleTime = $User.'IDLE TIME'
LogonTime = $User.'Logon Time'
ID = $User.ID
}
}
}
}
}
}
$Servers = Get-Content 'H:\demo\computernames.txt'
$Queries = foreach ($Server in $Servers) {
#Query each server that pings, save it in a variable for reuse
if (Test-Connection $Server -Count 1 -Quiet) {
Convert-QueryToObjects $Server -ErrorAction SilentlyContinue
}
}
#Open servers are ones that responded to the query.
$Queries |
Select-Object -ExpandProperty ComputerName -Unique |
Out-File 'H:\demo\session\openservers.txt'
#Use the saved query information, filter with Where-Object, loop over to disconnect.
$Queries |
Where-Object { ($_.SessionState -eq 'Disconnected') -or (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))} |
ForEach-Object {
Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose
}
The issue is that H:\WindowsPowerShell\Get-LoggedOnUser.ps1 -ComputerName $Server| Disconnect-LoggedOnUser -Verbose isn't filtered with Where-Object. So you need to save the information of which users sessions need to be disconnected, then use that filtered information to disconnect.
Here's one way to approach it, comments inline.
$Servers = Get-Content 'H:\demo\computernames.txt'
$Queries = foreach ($Server in $Servers) {
#Query each server that pings, save it in a variable for reuse
if (Test-Connection $Server -Count 1 -Quiet) {
Convert-QueryToObjects $Server -ErrorAction SilentlyContinue
}
}
#Open servers are ones that responded to the query.
$Queries |
Select-Object -ExpandProperty ComputerName -Unique |
Out-File 'H:\demo\session\openservers.txt'
#Use the saved query information, filter with Where-Object, loop over to disconnect.
$Queries |
Where-Object { ($_.SessionState -eq 'Disconnected') -or (($_.IdleTime -like "*:*") -and ($_.IdleTime -gt "00:59"))} |
ForEachObject {
Disconnect-LoggedOnUser -ComputerName $_.ComputerName -Id $_.ID -Verbose
}

Duplicated results in Powershell

I have put together a script from various sources, but cannot understand why i am getting duplicated entries in my results..
eg..
I need to check the scheduled tasks on remote servers, and verify which ones didnt complete sucesfully, and then investigate those.
I have a schedulers.csv file, which has two comlumns IP, and Name.
I downloaded the script Get-ScheduledTask.ps1 from https://gallery.technet.microsoft.com/scriptcenter/Get-Scheduled-tasks-from-3a377294
Works great and does what i needed.
I then wanted to from a list retrieve the servers names, run the above script as a parameter, then get back the scheduled tasks in a csv file.
NextRunTime Author Trigger State UserId ComputerName Name LastRunTime LastTaskResult Description NumberOfMissedRuns Enabled Path
The headers for the above script give me Name and LastTaskResult, which is what I wanted to query further.
The LastTaskResult should be 0 if it completed sucesfully, otherwise i would investigate further.
The code i have so far is :
$servers = Import-Csv "C:\test\schedulers.csv"
foreach($server in $servers){
$ServerName = $server.Name
$ServerAddress = $server.IP
Write-Host $ServerName : $ServerAddress
$importfile = Get-ScheduledTask.ps1 -ComputerName $ServerName
|Export-Csv -Path c:\test\scheds.csv -NoTypeInformation
$Lines = Import-Csv "C:\test\scheds.csv"
ForEach($line in $lines){
$lines | %{
$TaskName = $_.name
$taskresult = $_.LastTaskResult
if ($_.LastTaskResult -ne "0")
{
Write-Host $line.LastTaskResult : $_.name : $_.Path
}else{
}
}
}
}
There should be 3 results that show, that have a value of 1 in LastTaskResult, but i get about 38 which is the total amount of tasks on the two servers that i am testing on.
the 3 entries are there also as well, plus all the rest..
please can anyone see where i have gone wrong.. Many Thanks
not tested because i don't have your Get-ScheduledTask.ps1, but here's what i might change
$servers = Import-Csv "C:\test\schedulers.csv"
foreach ($server in $servers) {
$ServerName = $server.Name
$ServerAddress = $server.IP
Write-Host $ServerName : $ServerAddress
$importfile = Get-ScheduledTask.ps1 -ComputerName $ServerName
$importfile | Export-Csv -Path c:\test\scheds.csv -NoTypeInformation
foreach ($line in $importfile) {
if ($line.LastTaskResult -ne '0') {
Write-Host $line.LastTaskResult : $line.Name : $line.Path
}
}
}

Powershell ForEach loop with embedded IF statements

Starting to write powershell scripts (very new) because SCCM tends to respond better to them (both client and server)
So with the above stated here is my first script:
#Changes the 'ProvisioningMode' Key in the registry to False
$ProvisiongMode = New-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec -Name ProvisioningMode -Value False -Force
#Clears or 'nulls' the SystemTaskExcludes key in the registry
$SystemTaskExludes = New-ItemProperty -Path Registry::HKLM\SOFTRWARE\Microsoft\CCM\CcmExec -Name SystemTaskExcludes - Value "" - Force
#----------------------------------------------------------------------------------------------
$Success = "C:\Path\to.log"
$Failure = "C:\Path\to.log"
$Computers = Import-Csv "C:\Path\to.csv"
$SearchStr = Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | select-object ProvisioningMode
$Online = Test-Conntection -Computername $ComputerName -Count 1 -Quiet
ForEach ($ComputerName in $Computers)
if ($Online -eq 'False')
{
Write-Output $ComputerName`t'Connection Failed' >> $Failure
}
Else
{
if ($SearchStr -eq True)
{
$ProvisioningMode
$SystemTaskExcludes
}
}
#Second Check
if ($SearchStr -eq 'False')
{
Write-Output $ComputerName`t'Registry has been changed' >> $Success
}
The issue in question is the $Online variable. I would like to see if a computer is responsive to ping, if true then proceed to run $ProvisioningMode and $SystemTaskExclude.
Then the other issue is querying that key to see if it changed. The issue with that one is $SearchStr = Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | select-object ProvisioningMode returns
ProvisionMode
-----------------
False
And I cant grab just the false data.
Like I stated; very new at powershell and writing something that I will use helps me learn.
Edit: What I Have tried is
ForEach ($Name in $Computers)
{
Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet | Write-Output $Online
}
if ($Online -eq 'True') {Write-Output $Name`t'Computer is online' >> C:\Online.txt}
And many variations of the same thing.
Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet
Returns Data, which is what I want, but I need to input that into an If statement and still retain the $Name for the $StringStr and log files.
Those of you wondering, this takes the client out of provisioning mode when running an OSD. It fixes the 'No Self-Signed Certificate' issue.
Even though the string representations of boolean values in PowerShell are True and False, the correct way to compare againt such a value is with the $true and $false variables.
Furthermore, assign the result of Test-Connection to $Online with =:
$Online = Test-Connection -BufferSize 2 -Computername $Name.ComputerName -Count 1 -Quiet
if($Online -eq $true){
# Machine responds to ping, do stuff!
}
But the comparison is actually unnecessary. If $Online already equals $frue or $false, you can use it on its own inside the if statement:
if($Online){
# Machine responds to ping, do stuff!
}
I assume that $ProvisionMode, $SystemTaskExcludes and $SearchStr are all statements that you want to execute on the remote machine, not on the SCCM server itself.
To do so, you will need to connect to the machine and instruct it to execute the *-ItemProperty statements.
# Enclosing statements in {} creates a ScriptBlock - a piece of code that can be invoked later!
$ProvisionMode = {
#Changes the 'ProvisioningMode' Key in the registry to False
New-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec -Name ProvisioningMode -Value False -Force
}
$SystemTaskExludes = {
#Clears or 'nulls' the SystemTaskExcludes key in the registry
New-ItemProperty -Path Registry::HKLM\SOFTRWARE\Microsoft\CCM\CcmExec -Name SystemTaskExcludes - Value "" - Force
}
$SearchStr = {
Get-ItemProperty -Path Registry::HKLM\SOFTWARE\Microsoft\CCM\CcmExec | Select-Object -ExpandProperty ProvisioningMode
}
#----------------------------------------------------------------------------------------------
$LogFilePath = "C:\Path\to.log"
$Computers = Import-Csv "C:\Path\to.csv"
foreach($Computer in $Computers){
$Online = Test-Connection -Computername $Computer.Name -Count 1 -Quiet
if(-not $Online)
{
"$ComputerName`t'Connection Failed'" | Out-File -FilePath $LogFilePath -Append
}
else
{
$SearchResult = Invoke-Command -ComputerName $Computer.Name -ScriptBlock $SearchStr
if ($SearchResult)
{
# The call operator (&) invokes the scriptblock
Invoke-Command -ComputerName $Computer.Name -ScriptBlock $ProvisionMode
Invoke-Command -ComputerName $Computer.Name -ScriptBlock $SystemTaskExludes
}
else # SearchStr must be $false, or non-existing
{
"$ComputerName`t'Registry has been changed'" | Out-File -FilePath $LogFilePath -Append
}
}
}
For simplicity, I've used Invoke-Command with the -ComputerName parameter, but in a real world situation, I would set up a PSSession with New-PSSession, and reuse that for the connection with Invoke-Command -Session