0

I'm trying to write a PowerShell script that will allow me to search for an old antivirus program on each computer in my domain, and if it has that program, run the Competitor Removal Tool that was given to us by our new AntiVirus software vendor. I also want the script to search for our new AV software, and if it's missing, install it. Both the Competitor Removal Tool and the .exe for the installer are stored on a Domain Controller and accessed via network share. I'm enabling PowerShell remoting in my organization, and I'm hoping that will give me more flexibility. Here's what I have so far:

   #Retrieves list of all computers tied to Active Directory
$computers = Get-Content -Path 'C:\Sophos Results\ADComputers.txt'

#Paths to Sophos Installation and the Sophos Competitor Removal Tool
$SophosInstallPath =  Get-ChildItem -File \\DC-02\netlogon\SophosInstall\Sophos-Installation.bat
$KasperskyRemove = Get-ChildItem -File \\DC-02\netlogon\SophosInstall\AVRemoveW.exe


#Loops through each AD Computer and tests for proper software installation 
ForEach ($computer in $computers)
   {
#Variables that store the path to 32-bit and 64-bit versions of Sophos
$Sophos64 = Test-Path "\\$computer\c$\Program Files\Sophos"
$Sophos32 = Test-Path "\\$computer\c$\Program Files (x86)\Sophos"

#Variables that store the path to 32-bit and 64-bit versions of Kaspersky
$Kaspersky64 = Test-Path "\\$computer\c$\Program Files\Kaspersky Lab"
$Kaspersky32 = Test-Path "\\$computer\c$\Program Files (x86)\Kaspersky Lab"

#The following block will run the Sophos Installation batch file, removing any instance of Kaspersky and installing Sophos
      If ($Sophos64 -eq $false -or $Sophos32 -eq $false) 
      {
      Start-Process -FilePath $SophosInstallPath -Verbose
      Write-Host "Beginning Sophos Installation on $computer"
      }
#The following block will remove Kaspersky from a machine if it is present and Sophos is already installed.
        Elseif (($Kaspersky64 -eq $true -or $Kaspersky32 -eq $true) -and ($Sophos64 -eq $true -or $Sophos32 -eq $true)) 
        {
        Start-Process -FilePath $KasperskyRemove -Verbose
        Write-Host "Removing Kaspersky from $computer"
        }
#The last block will only be executed if Sophos is installed and Kaspersky isn't, and makes no changes to the machine.
        else {Write-Host "$computer has the proper AV software installation"}
   }

At the moment, when I run this against a group of test computers, I don't get any errors, and I know that the script is correctly determining whether or not Kaspersky/Sophos is installed, but it won't launch the Competitor Removal Tool or the install file. I know once PowerShell remoting is enabled there will be a better way to do this, I'm just not sure what that way is. Any suggestions? Thanks in advance

Update:

I enabled PS Remoting on my local machine and tried the following:

Invoke-Command -ComputerName localhost -ScriptBlock { *Script from above* }

I got the following errors:

Access is denied
    + CategoryInfo          : PermissionDenied: (\\dc-02\net...nstallation.bat:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : localhost   Cannot find path '\\dc-02\netlogon\SophosInstall\Sophos-Installation.bat' because it does not exist.
    + CategoryInfo          : ObjectNotFound: (\\dc-02\net...nstallation.bat:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : localhost   Access is denied
    + CategoryInfo          : PermissionDenied: (\\dc-02\net...l\AVRemoveW.exe:String) [Get-ChildItem], UnauthorizedAccessException
    + FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : localhost   Cannot find path '\\dc-02\netlogon\SophosInstall\AVRemoveW.exe' because it does not exist.
    + CategoryInfo          : ObjectNotFound: (\\dc-02\net...l\AVRemoveW.exe:String) [Get-ChildItem], ItemNotFoundException
    + FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
    + PSComputerName        : localhost   Cannot validate argument on parameter 'FilePath'. The argument is null or empty. Provide an argument that is not null or empty, and then try the command  again.
    + CategoryInfo          : InvalidData: (:) [Start-Process], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.StartProcessCommand
    + PSComputerName        : localhost

I'm running PowerShell from my domain admin account so I'm not sure why it would say access denied. Thanks for your help, I'm a bit new to both IT and PowerShell. Two months in on my first job

My last question: When I'm ready to do this on a larger scale, say my test group which has 3 computers (1 with Kaspersky, 1 With Sophos, and 1 with neither) The following should work, yes?:

 $computers = Get-Content -Path 'C:\Sophos Results\TestGroup.txt'

Invoke-Command -ComputerName $computers -ScriptBlock { *Original Script here* }

Any preference between Invoke-Command and Enter-PSSession when dealing with multiple computers? In the description of Invoke-Command it says "To run a single command on a remote computer, use the ComputerName parameter. To run a series of related commands that share data, use the New-PSSession cmdlet" So if I do use Invoke-Command (which seems more straightforward to me) Should I save my script and then call it in the scriptblock? And then that leads me to wonder how I would call a script from my local machine on the remote machine? I apologize for so many questions, my head is just spinning the further I get down the rabbit hole here.

Update 7/19/2018:

Running into one more issue, hoping this is the last one. I copied the files from the remote server on to my local machine to get rid of the second hop problem. I will just copy the files from my local machine to all remote machines in the script. Problem is when I copy from local to remote, it only works when I specify the computer name like so :

Copy-Item -Path C:\Temp\AVInstall -Destination '\\Computer1\c$\Temp\AVInstall' -Recurse

If I try and use a computer variable, like below, I get a network path not found error:

Copy-Item -Path C:\Temp\AVInstall -Destination '\\$computer\c$\Temp\AVInstall' -Recurse

Any reason why that might be?

Sweet T
  • 5
  • 1
  • 5
  • 1
    Well, the way you have the code written it would launch the removal tool on your local computer not the remote computer. At a powershell prompt type `Get-Help Enter-PSSession` – EBGreen Jul 17 '18 at 16:02
  • Please, please, please...update your question with new information regarding things that you have attempted and the results that you got – EBGreen Jul 17 '18 at 17:30
  • 1
    It looks like you're encountering the double-hop problem. As a test, if you copy the items to a target machine and then update the scriptblock to reference the items locally on that target machine, does it work? – Jacob Jul 17 '18 at 17:45
  • Yeah that worked, I updated my original question with more info and more questions lol. Thanks for your help @Jacob – Sweet T Jul 17 '18 at 18:25
  • Personally, I would keep your code for remote execution within the `scriptblock` within your script and then pass it via `Invoke-Command`. `Invoke-Command` can be used to execute a single command, or a pre-scripted set of commands on a remote machine. There's no need to call the script from a remote machine this way either. `Enter-PSSession is more suited when you want to control an interactive shell on a remote machine, See: https://stackoverflow.com/a/34623888/7554519 – Jacob Jul 17 '18 at 20:20

1 Answers1

0

As EBGreen touched on, you are currently running this on the local machine.

You would need to run it on the remote machine either via an interactive PSSession or via invoking the script.

To use Invoke-Command you can place the script to be executed on the remote machine into a scriptblock. This is then invoked on each machine within the string array within the -computername argument.

I can't test this, however I think you may encounter a double-hop problem when trying to retrieve the items $SophosInstallPathand$KasperskyRemove. If this does happen it will most likely manifest along the lines of "access denied". If this occurs the easiest solution would most likely be to copy the items to the machine first, either via copy-item or the more robust robocopy.exe and then remove them once complete.

#Retrieves list of all computers tied to Active Directory
$computers = Get-Content -Path 'C:\Sophos Results\ADComputers.txt'

$scriptblock = {
    #Paths to Sophos Installation and the Sophos Competitor Removal Tool
    $SophosInstallPath = Get-Item -File "\\DC-02\netlogon\SophosInstall\Sophos-Installation.bat"
    $KasperskyRemove = Get-Item -File "\\DC-02\netlogon\SophosInstall\AVRemoveW.exe"

    #Variables that store the path to 32-bit and 64-bit versions of Sophos
    $Sophos64 = Test-Path "\Program Files\Sophos"
    $Sophos32 = Test-Path "\Program Files (x86)\Sophos"

    #Variables that store the path to 32-bit and 64-bit versions of Kaspersky
    $Kaspersky64 = Test-Path "\Program Files\Kaspersky Lab"
    $Kaspersky32 = Test-Path "\Program Files (x86)\Kaspersky Lab"

    #The following block will run the Sophos Installation batch file, removing any instance of Kaspersky and installing Sophos
    If ($Sophos64 -eq $false -or $Sophos32 -eq $false) 
    {
        Start-Process -FilePath $SophosInstallPath -Verbose
        Write-Host "Beginning Sophos Installation on $computer"
    }
    #The following block will remove Kaspersky from a machine if it is present and Sophos is already installed.
    Elseif (($Kaspersky64 -eq $true -or $Kaspersky32 -eq $true) -and ($Sophos64 -eq $true -or $Sophos32 -eq $true)) 
    {
        Start-Process -FilePath $KasperskyRemove -Verbose
        Write-Host "Removing Kaspersky from $env:computer"
    }
    #The last block will only be executed if Sophos is installed and Kaspersky isn't, and makes no changes to the machine.
    else 
    {
        Write-Host "$env:computer has the proper AV software installation"
    }
}

Invoke-Command -ComputerName $computers -ScriptBlock $scriptblock
Jacob
  • 1,182
  • 12
  • 18
  • as you can see in my updated question, I did encounter the second hop issue. I think you're right about copying the files to each computer first. That was a great suggestion, thank you. – Sweet T Jul 17 '18 at 18:07