WriteErrorException - invoke-command - powershell

I'm working on a script to execute a .ps1 file remotely on multiple server for testing reasons im only executing it on one server. Here is the code:
#Citrix Optimizer Automation
$computer= Get-ADComputer -LDAPFilter "(name=*XXXXXXXXXXX*)" -SearchBase "OU=Test-Server,OU=CVAD1912,OU=Server,DC=domain,DC=tld"
$computername=$computer.name
foreach ($server in $computername){
$dir = "\\$server\c$\Temp\CitrixOptimizer"
#Remove Citrix Optimizer if exists
Remove-Item $dir -Recurse
#Copy the item from the filesystem to the server
Copy-Item -Path \\fs01\install$\Citrix\CitrixOptimizer -Destination $dir -Recurse
Invoke-Command -ComputerName $server -ScriptBlock{
#Execute the CitrixOptimizer
Set-Location "c:\temp\CitrixOptimizer"
.\CtxOptimizerEngine.ps1 -OutputLogFolder "\\fs01\install$\Citrix\01_OptimizerLogs\$([DateTime]::Now.ToString('yyyy-MM-dd'))_$server" -Mode Analyze
}
#Remove Citrix Optimizer
Remove-Item $dir -Recurse
}
Anyways I always get this Error:
Access Denied
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,CtxOptimizerEngine.ps1
+ PSComputerName : XXXXXXXXXXXXX
The Problem is that it can't write the Logs to my Networkpath. This is the only problem. It is working if i give the -OutputLogFolder a local path.
I tried to send the invoke-command with credentials but this was also not working same with the Parameter -RunAsAdministrator. I know that this is a double-hop problem but i don't know how to solve it. PS: Every User in the Group Domain-Admins must be able to execute this file so just giving creds for one users is not enough.
I would be grateful for help!
Best, cosmo_

Related

how to delete a folder using invoke command in powershell

First time asking a question here after using it for a long time.
I'm currently making a powershell script to delete userdata when they left the company for a month.
I already tried deleting the folder using the normal remove-item and this works however this is a very slow process when going over the network.
I then found out about the invoke-command function which can run on a remote computer.
Now i can't seem to get this working.
I keep getting the error that the path is not found.
However it seems like powershell is changing my path.
How can i prevent this from happening?
Cannot find path 'C:\Users\admcia\Documents\P$\PERSONAL\JOBA' because it does not exist.
+ CategoryInfo : ObjectNotFound: (C:\Users\admcia...$\PERSONAL\JOBA:String) [Remove-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.RemoveItemCommand
+ PSComputerName : ODNDATA
my code is the following:
Note that P$ is the local drive letter on the server.
Also note That $item.SamAccountName is used for creating foldername. (we use Samaccountname as the name of the users folder.
$localPath1 = "P$" + "\PERSONAL\" + $item.SamAccountName
$serverName = "Remotecompter"
Invoke-Command -ComputerName $serverName -ScriptBlock { Remove-Item $using:localPath1 -Force -Recurse -Confirm:$false }
If as seen from your local machine, the drive is \\Remotecomputer\P$\, then for the remote computer (where the code is executed) the path is just P:\.
To combine strings into a path, I would suggest you better use the Join-Path cmdlet rather than concatenating the strings with '+'
Try
$localPath1 = Join-Path -Path 'P:\PERSONAL' -ChildPath $item.SamAccountName
$serverName = "Remotecompter"
Invoke-Command -ComputerName $serverName -ScriptBlock { Remove-Item $using:localPath1 -Force -Recurse -Confirm:$false }
You can use -ArgumentList in Invoke command,
Invoke-Command -ComputerName $serverName -ScriptBlock {
param($localPath1)
Remove-Item $localPath1 -Force -Recurse -Confirm:$false
} -ArgumentList($localPath1)
make sure your path is correct, and if it does not work try to hardcode the path in your code.

Replicating file to remote server, Issue while joining path of local and remote server copying files in powershell

enter code hereI am facing issue while replicating files to remote server, joining the path failing somehow.
Below is code:
Invoke-Command -ComputerName $RemoteServer -ScriptBlock {param($DestinationDir,$LocalCertResultObj,$RemoteCertResultObj,$SourceDir) Compare-Object $LocalCertResultObj $RemoteCertResultObj -Property Name, Length, FullName | Where-Object {$_.SideIndicator -eq "<="} | ForEach-Object {
{$DestinationDir = Join-Path $DestinationDir $_.FullName.Substring($SourceDir.length)}
Write-Output $DestinationDir
Write-Output $SourceDir
Copy-Item -Path "$SourceDir\$($_.name)" -Destination "$DestinationDir" -Recurse -Force
} } -ArgumentList $DestinationDir,$LocalCertResultObj,$RemoteCertResultObj,$SourceDir -Credential $RemoteMachine_cred
Getting error like below:
$DestinationDir = Join-Path $DestinationDir $_.FullName.Substring($SourceDir.length)
C:\TestFolderR
C:\TestFolder
Cannot find path 'C:\TestFolder\file1.txt' because it does not exist.
+ CategoryInfo : ObjectNotFound: (C:\TestFolder\file1.txt:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
Joining the path looks to be working fine. Copy-Item's error is pretty clear that it can't find C:\TestFolder\file1.txt. Since you're presumably trying to copy this file to the remote server, your ScriptBlock used with Invoke-Command is going to run that entire ScriptBlock on the remote system. It's not going to be able to copy that file over the PowerShell session because it's not aware of your local filesystem - at least, not by using Invoke-Command.
You can establish a New-PSSession to the remote system, and use this with Copy-Item directly from your local session to the remote filesystem:
$Session = New-PSSession -ComputerName server.domain.tld -Credential $RemoteMachine_Cred
Copy-Item -ToSession $Session -Path $localPath-Destination $remotePath
You can even copy an item from the remote filesystem back to your local system, too. Using the same $Session we established above:
Copy-Item -FromSession $Session -Path $remotePath -Destination $localPath

How can I search for software by filepath and then install it if it's missing using PowerShell

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?
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

Error with PowerShell command for copying file to remote server with credential

PS C:\Windows\system32> Copy-Item -ToSession $s C:\Programs\temp\test.txt -Destination C:\Programs\temp\test.txt
Copy-Item : A parameter cannot be found that matches parameter name
'ToSession'. At line:1 char:11
Copy-Item -ToSession $s C:\Programs\temp\test.txt -Destination C:\Programs\temp\ ...
~~~~~~~~~~
CategoryInfo : InvalidArgument: (:) [Copy-Item], ParameterBindingException
FullyQualifiedErrorId : NamedParameterNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
As it is noted in the change list of PoSh V5 here and you tagged your question with V4 the simple answer is probably your version's Copy-Item cmdlet does not provide that parameter
Copy-Item now lets you copy files or folders from one Windows
PowerShell session to another, meaning that you can copy files to
sessions that are connected to remote computers, (including computers
that are running Nano Server, and thus have no other interface). To
copy files, specify PSSession IDs as the value of the new -FromSession
and -ToSession parameters, and add –Path and –Destination to specify
origin path and destination, respectively. For example, Copy-Item
-Path c:\myFile.txt -ToSession $s -Destination d:\destinationFolder.

How to get all (IIS) websites status/state from remote machine using PowerShell?

I was trying to read the status of IIS website from remotely. I tried below code.
$Session = New-PSSession -ComputerName $serverName
$block = {
import-module 'webAdministration'
Get-ChildItem -path IIS:\Sites
}
Invoke-Command -Session $Session -ScriptBlock $block | Out-File -append $WebreportPath
But above command given me only Websites with https binding, when it comes to https it throws below error.
The data is invalid. (Exception from HRESULT: 0x8007000D)
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.GetChildItemCommand
I am trying to renmote a Windows Server 2008 R2 with IIS 7.
Please guide me. Thanks !
Hope this will help for someone. Below is my findings and the answer.
Powershell sends only objects remotely, and render them using available templates.
So need to give a template accordingly. I used "Format-Table".
Be-careful, if you use "Format-Table" outside it results same error. Remember to use it inside the scriptblock.
Error-prone:
Invoke-Command -ComputerName $serverName { Import-Module WebAdministration; Get-ChildItem -path IIS:\Sites} | Format-Table | Out-File -append $WebreportPath
Correct code:
Invoke-Command -ComputerName $serverName { Import-Module WebAdministration; Get-ChildItem -path IIS:\Sites | Format-Table} | Out-File -append $WebreportPath
My refers :
http://forums.iis.net/t/1155059.aspx?IIS+provider+and+PowerShell+remoting
Good Luck !
There seems to be some problem with retrieving the objects using a remote session, but that is no blocking issue (I have run into this as well).
To prevent the error from being written, you can use -ErrorAction like this:
$Session = New-PSSession -ComputerName $serverName
$block = {
Import-Module 'webAdministration'
Get-ChildItem -path IIS:\Sites
}
Invoke-Command -Session $Session -ErrorAction SilentlyContinue -ScriptBlock $block |
Out-File -append $WebreportPath
This way you will not see the remoting error, but you will still receive the data you need.
Note that this hides all errors, so you are possibly hiding an error that you may want to see. For that you will need a fix for the underlying ptoblem, so you can remove the -ErrorAction patch.