Trying to verify that a remote server can access CIF share - powershell

I am trying to verify that a remote server has access to a CIF share
$RemoteMoteMachineName = 'ServerName'
$ShareToAccess='\\Share\Level1Folder'
$RemoteSession = New-PSSession -ComputerName $RemoteMachineName
$RemoteTest = Invoke-Command -Session $RemoteSession -ScriptBlock {Test-Path -PATH -ArgumentList $using:ShareToAccess}
If I run the above commands manually with hard coded values, it works.
If I try to use the variables I receive
Test-Path: A positional parameter cannot be found that accepts argument '\Share\Level1\Folder'
Ideas?

Resolved, used instead (create a fake drive and remove if successful:
$RemoteTest = Invoke-Command -Session $RemoteSession -ScriptBlock {New-PSDrive -Name TestName -PSProvider FileSystem -Root $using:ShareToAccess}
If ($RemoteTest){
Write-Host "Remote test pass $RemoteMachine to $ShareToAccess"
Invoke-Command -Session $RemoteSession -ScriptBlock {Remove-PSDrive -Name TestName }
Else {Write-Host "Share access Fail"}

Related

Remotely setting wallpaper on demand via powershell

I have created a function Set-Wallpaper:
Function Set-WallPaper($Value)
{
Set-ItemProperty -path 'HKCU:\Control Panel\Desktop\' -name wallpaper -value $value
rundll32.exe user32.dll, UpdatePerUserSystemParameters
}
and can run it locally to use a network path to the desired jpg
Set-Wallpaper -value "\\server\share\image.jpg"
and it works.
Now I want to run this function on a remote PC, I tried
Invoke-Command -ComputerName TARGETPC Set-Wallpaper -value "\\server\share\image.jpg"
but it errors out with
Invoke-Command : A parameter cannot be found that matches parameter name 'value'.
what am I missing?
$session= new-pssession -Computername "yourClientname"
$reslt= Invoke-Command -Session $session -ScriptBlock {your code}
If u want to ahnd over an argument use it like this
$reslt= Invoke-Command -Session $session -argumentlist $argument -ScriptBlock {param ($argument) your code with $argument[0]}

Powershell leaving RemoteDrive Sessions open

Minimal Question:
How do I properly dispose of the remote Session Connection left behind after doing:
$session = New-PSSession -ComputerName $VM -Credential $CurrentUser
Invoke-Command -Session $session -ScriptBlock {
$drive = New-PSDrive -Credential $Using:CurrentUser "dummyDriveName" -Root (Split-Path $Using:TargetPath) -PSProvider "FileSystem"
Set-Location $Using:TargetPath
}
Invoke-Command -Session $session -ScriptBlock {
Remove-PSDrive "dummyDriveName"
}
Remove-PSSession -Session $session
I'm running code that looks roughly like this:
$VMs = #(
"vm1.foo.lan",
"vm2.foo.lan",
"vm3.foo.lan"
)
$TargetPath = "\\$env:ComputerName\bar\bin\Debug"
$CurrentUser = (Get-Credential -Credential $env:UserName)
[System.Management.Automation.Runspaces.PSSession[]]$Sessions = #()
foreach ($VM in $VMs) {
$session = New-PSSession -ComputerName $VM -Credential $CurrentUser
$Sessions = $Sessions + $session
Invoke-Command -Session $session -ScriptBlock {
$drive = New-PSDrive -Credential $Using:CurrentUser "dummyDriveName" -Root (Split-Path $Using:TargetPath) -PSProvider "FileSystem"
Set-Location $Using:TargetPath
#Actually do something here, but it's not relevant ... I can reproduce with this line commented out.
}
}
# Wait until Target.exe are known to be complete.
foreach ($session in $Sessions) {
Invoke-Command -Session $session -ScriptBlock {
Remove-PSDrive "dummyDriveName"
}
Remove-PSSession -Session $session
}
My intent is to get a set of remote machines to all invoke an exe sitting on my machine, exposed via a remote share.
Broadly speaking, I:
Connect to the remote machine as myself.
Capture that connection.
Set up a remote drive connecting it to me
(This is REQUIRED to avoid the double hop issue without resorting to CredSsp See: https://learn.microsoft.com/en-us/powershell/scripting/setup/ps-remoting-second-hop)
Do some stuff
Repeat for all machines.
Wait until remote processes are completed.
Reconnect to all the machines to remove the drive and the connection session.
At the end of this, I still have:
These sessions do eventually seem to decay, but not reliably, and it's been able to saturate the max # sessions allowed and thus cause errors saying:
No more connections can be made to this remote computer at this time because there are already as many connections as the computer can accept
+ CategoryInfo : InvalidOperation: (dummy:PSDriveInfo) [New-PSDrive], Win32Exception
+ FullyQualifiedErrorId : CouldNotMapNetworkDrive,Microsoft.PowerShell.Commands.NewPSDriveCommand
+ PSComputerName : build7.foo.lan
UPDATE:
Thanks to #jrider who has suggested Get-SmbSession.
Running that after the rest of my script returns:
PS C:\WorkingDirectoty> Get-SmbSession
SessionId ClientComputerName ClientUserName NumOpens
--------- ------------------ -------------- --------
773228331225 10.xxx.yyy.89 FOO\MDM 785
773228331233 10.xxx.yyy.60 FOO\MDM 637
773228331245 10.xxx.yyy.89 FOO\MDM 239
773228331253 10.xxx.yyy.54 FOO\MDM 136
773228331261 10.xxx.yyy.54 FOO\MDM 882
773228331269 10.xxx.yyy.60 FOO\MDM 389
I obviously don't want this script to blindly close EVERY session irrespective of whether it relates to this script, so I guess I want to map my sessions to IP addresses and close anything with that IP address?
Does anyone JustKnow the necessary PowerShell incantation to achieve that?
To Close the SMB sessions by computer name(Updated to include Brondahl's suggestion):
$vmName = $env:ComputerName
$IP = [System.Net.Dns]::GetHostAddresses($vmName).IPAddressToString
Get-SmbSession | Where-Object {$_.ClientComputerName -eq $IP} | Close-SmbSession -Force
For final reference, my complete cleanup code looks like this:
foreach ($session in $Sessions) {
Write-Host ""
$vmName = $session.ComputerName
$vmIPAddress = [System.Net.Dns]::GetHostAddresses($vmName).IPAddressToString
Write-Host "*** Killing any active Target.exe processes on $vmName ***"
Invoke-Command -Session $session -ScriptBlock {
Stop-Process -Name "Target" -Force
}
Write-Host "*** Disconnecting the remote Drive created to give $vmName easy access to $RepositoryShare***"
Invoke-Command -Session $session -ScriptBlock {
Remove-PSDrive "dummyDriveName"
}
Write-Host "*** Closing any open PS connections to $vmName ***"
Remove-PSSession -Session $session
Write-Host "*** Closing the still-open Windows Share connection from $vmName to $env.ComputerName ***"
Get-SmbSession | Where-Object {$_.ClientComputerName -eq $vmIPAddress} | Close-SmbSession -Force
}

How to get local computer name after New-PSSession -Computername?

I am getting the below error, please advise how to fix this error for null-valued expression
You cannnot call a method on a null-valued expression
+CategoryInfo : InvalidOoperation: (:)[], RuntimeException
+FullyQualifiedErrorId: InvokeMethodonNull
+PSComputerName: DC1
Code below
function myfunction (){
$remoteserver = 'DC1'
$Session = New-PSSession -Computername $remoteserver -Credential $Cred
Import-Module ActiveDirectory
$local= $env:COMPUTERNAME
Invoke-Command -ComputerName $remoteserver -Credential $cred -ScriptBlock
{$using:local
if($local.substring(5,3) -imatch "Sys") {
Get-ADComputer $local | Move-ADObject -Targetpath "ou=PRD,ou=Servers,dc=com,dc=Companycorp,dc=net"}
}
} #end function
Invoke-Command -ComputerName $remoteserver -ScriptBlock ${Function:myFunction}
What you're looking for is the $using: scope. If you define variables that you want to use in your remote execution, you need to access them like:
$PC = $env:ComputerName
Invoke-Command -Computer DC01 -ScriptBlock { $using:PC <# logic #> }
If you mean you want to remote into DC01 to run commands against localhost, you're going to run into the second-hop problem due to Kerberos.
Update: Your new example looks pretty convoluted. Here's an example that should work:
$MyPC = $env:ComputerName
$Session = New-PSSession -Credential (Get-Credential) -ComputerName 'DC1'
Invoke-Command -Session $Session -ScriptBlock {
Import-Module -Name 'ActiveDirectory'
$PC = $using:MyPC
If ($PC.Substring(5,3) -eq 'sys')
{
Get-ADComputer -Identity $PC |
Move-ADObject -TargetPath 'ou=PRD,ou=Servers,dc=com,dc=Companycorp,dc=net'
}
}
What I think you're asking is 'how do I open a session on a remote pc, but then still run commands on my local PC'. If that's so, then let's walk through it.
First, we can open a remote connection to another computer in PowerShell by creating a new PSSession, as you're doing here:
$session = New-PSSession -Computername DC01 -Credential $cred
You can then either step into the remote computer wholly using Enter-PSSession, or just send individual commands to the remote computer using:
Invoke-Command -ScriptBlock {#Commands to run on the remote PC}`
-Session $session
Once you enter the remote PC, you can return to your own PC using the Exit-PSSession command.
#Enter Remote PC
Enter-PSSession $session
DC01> hostname
*DC01*
#Step out of Remote PC
Exit-PSSession
PS> hostname
*YOURPCNAME*
If this isn't what you want to do, let me know and we'll get you sorted.
You have to use Invoke-Command :
$session = New-PSSession -Computername DC01 -Credential $cred
Invoke-Command -Session $session -ScriptBlock {
$remoteComputerName = $env:computername
}

adding printer in remote machine is not working: invalid printer name

I have gone through many blogs for finding solution for this issue, but never find a solution.
$CompName = "test.domain.com"
$Printer = "\\122.21.10.11\PRINTER-NAME-1"
Invoke-Command -ComputerName $CompName -Scriptblock {
Param($p)
(New-Object -Com Wscript.Network).AddWindowsPrinterConnection($p)
} -ArgumentList $Printer
I have even tried PSRemoting and tried to execute the ps1 file from remote machine. the same script is working in local and not working remote.
Enter-PSSession -ComputerName "testserver.testdomain.com" -Authentication Credssp -Credential Get-Credential
Error:
Exception calling "AddWindowsPrinterConnection" with "1" argument(s): "The printer name is invalid. (Exception from HRESULT: 0x80070709)"
Updates:
Working without CredSSP:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Get-ChildItem C:\Users\myusername\Desktop
}
Working with CredSSP:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Get-ChildItem \\sharedmac\sharef
} -Authentication Credssp -Credential mydomain\myusername
Script is working, but not showing network printers:
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
(New-Object -ComObject WScript.Network).EnumPrinterConnections()
} -Authentication Credssp -Credential mydomain\myusername
Script gives error: Invalid Printer name
$Printer = "\\172.26.30.13\SDB1-FLOOR1-B2" # I have tried this input in single, double, with and without escape character
Invoke-Command -ComputerName remotemac.mydomain.com -ScriptBlock {
Param($p)
(New-Object -Com WScript.Network).AddWindowsPrinterConnection("$p")
} -ArgumentList $Printer -Authentication Credssp -Credential mydomain\myusername
I'm totally stuck.
I heard we can use Group Policy, is there anyway we can automate this using group policy?

PSSession will not change the working directory

I have a script I'm trying to implement. If I run each line seperately, it works just fine. But if I place it in a function, or run with PowerGUI or Powershell ISE, it errors out. The problem is the script isn't changing the working directory, therefore the file that Invoke-Command is calling isn't found.
$DLUpdate = New-PSSession -ComputerName msmsgex10wprd03 -Credential $DLUpdateCred -Name DLUpdate
Enter-PSSession -Session $DLUpdate
$UpdateDLPath = 'c:\users\mascott2\Desktop\Distrolist\Updates\'
Set-Location $UpdateDLPath
Invoke-Command -ScriptBlock {cmd.exe "/c updatedls.bat"}
Exit-PSSession
Remove-PSSession -Name DLUpdate
You shouldn't be using Enter-PSSession in a script like that. Put all the commands you want into the scriptblock you use with Invoke-Command and run it against your session:
$DLUpdate = New-PSSession -ComputerName msmsgex10wprd03 -Credential $DLUpdateCred -Name DLUpdate
Invoke-Command -Session $DLUPdate -ScriptBlock {
$UpdateDLPath = 'c:\users\mascott2\Desktop\Distrolist\Updates\'
Set-Location $UpdateDLPath
cmd.exe "/c updatedls.bat"
}
Remove-PSSession -Name DLUpdate