PowerShell Issue regarding entering a PS Session and setting permissions - powershell

I am currently making a script to create a folder which then creates an AD group and links them together. I then connect to our server in the data centre to set the permissions.
To do this I need to enter a PSSession and find the folder and set the permissions. Unfortunately, it's not working. Any help would be appreciated.
Script
#Get ADM Credentials
$Cred = Get-Credential
# PowerShell's New-Item creates a folder
$Name = Read-Host "What is the name of the folder?"
$Location = Read-Host "What is the folder path? i.e B:\Collaboration\"
New-Item -Path $Location -Name $Name -ItemType "directory"
#Invoke-Item $Location
# Powershell creates an AD group
$Groupname = Read-Host "What is the group name? i.e. SS COLLABORATION BEN"
New-ADGroup -path "OU=StorSimple Centralisation Groups,OU=Groups,OU=Northgate PLC,DC=northgatevehiclehire,DC=net" -Name $Groupname -GroupCategory Security -GroupScope Global -DisplayName $Groupname -Description "Access to $Location" -Credential $cred
#Connect to StudFS01
$Folderpath = Read-Host "What is the path of the folder in StudFS e drive? i.e. Vehicle Sales\TOM Information"
Enter-PSSession -ComputerName Studfs01 -Credential $Cred
Start-Sleep -Seconds 10
Set-Location -Path E:\CentralisedData\Data\$folderpath
#Set Permissions
$rule=new-object System.Security.AccessControl.FileSystemAccessRule ("northgatevehiclehire.net\Domain Admins","FullControl","Allow")
$rule2=new-object System.Security.AccessControl.FileSystemAccessRule ("northgatevehiclehire.net\StorSimple Centralisation Administrators","FullControl","Allow")
$rule3=new-object System.Security.AccessControl.FileSystemAccessRule ("$Groupname","Modify","Allow")
$acl = Get-ACL E:\CentralisedData\Data\$folderpath
$acl.SetAccessRule($rule,$rule2,$rule3)
Set-ACL -Path E:\CentralisedData\Data\$folderpath -AclObject $acl
Error Im getting is below
Set-Location : Cannot find drive. A drive with the name 'E' does not exist.
At C:\Users\ben.curtis-haigh\Documents\New Security Group Script.ps1:19 char:1
+ Set-Location -Path E:\CentralisedData\Data\$folderpath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (E:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
Get-ACL : Cannot find drive. A drive with the name 'E' does not exist.
At C:\Users\ben.curtis-haigh\Documents\New Security Group Script.ps1:25 char:8
+ $acl = Get-ACL E:\CentralisedData\Data\$folderpath
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (E:String) [Get-Acl], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.GetAclCommand
You cannot call a method on a null-valued expression.
At C:\Users\ben.curtis-haigh\Documents\New Security Group Script.ps1:26 char:1
+ $acl.SetAccessRule($rule,$rule2,$rule3)
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Set-Acl : Cannot bind argument to parameter 'AclObject' because it is null.
At C:\Users\ben.curtis-haigh\Documents\New Security Group Script.ps1:27 char:62
+ Set-ACL -Path E:\CentralisedData\Data\$folderpath -AclObject $acl
+ ~~~~
+ CategoryInfo : InvalidData: (:) [Set-Acl], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.SetAclCommand`
Thanks

Instead of Enter-PSSession which is meant for interactive use, you need to establish a new PSSession and then use Invoke-Command against it. Something like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ScriptBlock {
<CODE TO EXECUTE ON REMOTE SYSTEM HERE>
}
If you need to pass parameters/variables, you have two choices. The easiest (in newer versions of PowerShell) is the using statement like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ScriptBlock {
Set-Location -Path E:\CentralisedData\Data\$using:Folderpath
}
Another option is to pass your arguments with -ArgumentList and use Param() in the script block like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ArgumentList $Folderpath -ScriptBlock {
Param($Folderpath)
Set-Location -Path E:\CentralisedData\Data\$Folderpath
}

Instead of Enter-PSSession which is meant for interactive use, you need to establish a new PSSession and then use Invoke-Command against it. Something like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ScriptBlock {
<CODE TO EXECUTE ON REMOTE SYSTEM HERE>
}
If you need to pass parameters/variables, you have two choices. The easiest (in newer versions of PowerShell) is the using statement like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ScriptBlock {
Set-Location -Path E:\CentralisedData\Data\$using:Folderpath
}
Another option is to pass your arguments with -ArgumentList and use Param() in the script block like this:
$PSSession = New-PSSession -ComputerName Studfs01 -Credential $Cred
Invoke-Command -Session $PSSession -ArgumentList $Folderpath -ScriptBlock {
Param($Folderpath)
Set-Location -Path E:\CentralisedData\Data\$Folderpath
}

Related

PSSession search AD computers Powershell

Good afternoon everyone, I need to configure this script to run on AD machines, but I can only run it on the local machine, could you help me
I tried: $session = New-PSSession -ComputerName computer01
$events = Invoke-Command -ComputerName $session -ScriptBlock {`
param($days,$up,$down)
Get-EventLog `
-After (Get-Date).AddDays(-$days) `
-LogName System `
-Source EventLog `
| Where-Object {
$_.eventID -eq $up `
-OR `
$_.eventID -eq $down }
} -ArgumentList $NumberOfDays,$startUpID,$shutDownID -ErrorAction Stop
however it generated the error below:
Invoke-Command : One or more computer names are not valid. If you are trying to pass a URI, use the -ConnectionUri parameter, or pass URI objects instead of
strings.
At line:68 char:15
+ ... $events = Invoke-Command -ComputerName $session -ScriptBlock {`
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (System.String[]:String[]) [Invoke-Command], ArgumentException
+ FullyQualifiedErrorId : PSSessionInvalidComputerName,Microsoft.PowerShell.Commands.InvokeCommandCommand

System Center Configuration Manager - PowerShell Remoting

I have a primary SCCM server - "ABC"
Later I installed SCCM console and PowerShell Module on one more machine - "XYZ"
I am running below script from server - "OPQ" and trying to remote "XYZ" (on which i installed SCCM Console Recently)
Script ::
$Session = New-PSSession -ComputerName "XYZ" -Authentication Kerberos -Credential $Cred -ConfigurationName Microsoft.PowerShell32
Invoke-Command -Session $Session -ScriptBlock {
Import-module "C:\Program Files (x86)\Microsoft Configuration Manager\AdminConsole\bin\ConfigurationManager.psd1"
Set-Location PS1:\
}
ERROR ::
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : OpenError: (PS1:PSDriveInfo) [Import-Module], UnauthorizedAccessException
+ FullyQualifiedErrorId : Drive,Microsoft.PowerShell.Commands.ImportModuleCommand
+ PSComputerName : XYZ
Cannot find drive. A drive with the name '' does not exist.
+ CategoryInfo : ObjectNotFound: (PS1:String) [Set-Location], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.SetLocationCommand
+ PSComputerName : XYZ
Well it appears you have a permissions issue. Here is how I executed a remote command in my SCCM environment, via my PSS:
$device = Invoke-Command -Session $sess -ScriptBlock {
Import-Module (Join-Path (Split-Path $env:SMS_ADMIN_UI_PATH)
ConfigurationManager.psd1)
Push-Location -Path ((Get-WmiObject -Namespace "root\SMS" -Class
"SMS_ProviderLocation" | Select-Object -ExpandProperty SiteCode) + ":")
Get-CMDevice -Name $env:COMPUTERNAME
Pop-Location
}
$device
RunspaceId : cbc7e008-d92c-4ba3-94a3-b75f8005be98
SmsProviderObjectPath : SMS_CM_RES_COLL_SMS00001.ResourceID=16777221
AADDeviceID : 00000000-0000-0000-0000-000000000000
AADTenantID : 00000000-0000-0000-0000-000000000000
ActivationLockBypassState :
ActivationLockState :
ADLastLogonTime : 3/31/2020 11:23:38 PM
ADSiteName : XXXX-XX
...
Note that if you're not remoting to your PSS, you will need to specify your PSS in the Get-WmiObject command, e.g.:
(Get-WmiObject -ComputerName [YOUR PSS] -Namespace "root\SMS" -Class "SMS_ProviderLocation" | Select-Object -ExpandProperty SiteCode) + ":"
I was able to resolve this issue by saving the credentials on the XYZ server and then calling them under my INvoke-Command.
Like This :
$Session = New-PSSession -ComputerName "XYZ"
Invoke-Command -Session $Session -ScriptBlock {
$password = Get-Content -Path D:\Creds\creds.txt | ConvertTo-SecureString
$Cred = New-Object System.Management.Automation.PSCredential ("domain\UserId", $password)
Then the rest of the code. ... .. . . .
}

Powershell v5.1 : Copy from share server to local folder on a remote PC

I have to manage around 10 PC running window 10.
I need to copy some software to those PC from share folder ( \company\folder or \MyPC\SharedFolder)
Manual remote is okay, however, doing copy item from share folder to 10 PC is take time and boring.
I found use Invoke-command and copy-item can help me to do it faster. However, I get error Access is denied
$usr = "UserName"
$pw = convertto-securestring -AsPlainText -Force -String Password
$cred = new-object -typename System.Management.Automation.PSCredential -argumentlist "$usr",$pw
For ($i=1; $i -lt 11; $i++)
{
$computerName=""
if($i -lt 10) {
$computerName="PC000$i"
} else {
$computerName="PC00$i"
}
Write-host "Copy on $computerName"
$session = New-PSSession -ComputerName "ServerA" -Credential $creds -Authentication Kerberos
Invoke-Command -Session $session -ScriptBlock { Copy-Item \\CompanyFolder\Shared\Sample.zip D:\Shared }
}
And below is error
Access is denied
+ CategoryInfo : PermissionDenied: (\\CompanyFolder\Shared\Sample.zip:String) [Copy-Item], UnauthorizedAccessException
+ FullyQualifiedErrorId : ItemExistsUnauthorizedAccessError,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : PC0007
Cannot find path '\\CompanyFolder\Shared\Sample.zip' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\CompanyFolder\Shared\Sample.zip:String) [Copy-Item], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
+ PSComputerName : PC0007
I search around and find similar issues at here but it can not fix my issue. Do you have any idea?
At the end, I find the Solution, and it is workaround solutions for this problem.
Copy-Item -ToSession $session -Path \\CompanyFolder\Shared\Samples.zip -Destination D:\ -Recurse
More information can be found here

Using New-MailContact, Set-MailContact, and Set-Contact inside background jobs

Here's the updated, still getting the same errors.
$UserCredential = Get-Credential
$contacts = Import-Csv "C:\temp\testgal.csv"
Start-Job -Name Loop -ScriptBlock {
param([pscustomobject[]]$contacts, [System.Management.Automation.PSCredential[]]$UserCredential)
$session2 = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $session2
Connect-MsolService -cred $UserCredential
foreach ($c in $contacts){
........
}
} -ArgumentList (,$contacts, $UserCredential)
Wait-Job -State Running | Receive-Job
Get-Job -State Completed | Remove-Job
I'm trying to create a vast number of contacts in 365 using a script and would like to run parallel jobs to speed it up, I built a loop inside a job and tested it worked using the following inside the loop to make sure it could extract the correct variables from the CSV.
$name = $c1.displayname
New-Item -Path "C:\Temp\Output" -Name "$name" -ItemType "file"
Now when I attempt to run the loop with the commands in the title as below
$contacts = Import-Csv "C:\temp\gal\testgal.csv"
Start-Job -Name Loop -ScriptBlock {
param([pscustomobject[]]$contacts)
foreach ($c in $contacts){
$name = $c.displayName
$rawProxy = $c.proxyAddresses
$proxysplit = $rawproxy -split '(?<!\\);'
$proxyquoted = $proxysplit.replace('x500','"x500').replace('x400','"x400').replace('X500','"X500').replace('X400','"X400')
$proxy = $proxyquoted
New-MailContact -ExternalEmailAddress $c.Mail -Name "`"$name`"" -Alias $c.mailNickname -DisplayName $name -FirstName $c.givenName -Initials $c.initials -LastName $c.sn -AsJob
Set-MailContact -Identity $c.mailNickname -CustomAttribute1 "CreatedWithScript" -CustomAttribute3 $c.extensionAttribute3 -EmailAddresses $proxy -AsJob
Set-Contact -Identity $c.mailNickname -City $c.l -Company $c.company -Department $c.department -Office $c.physicalDeliveryOfficeName `
-Phone $c.telephoneNumber -PostalCode $c.postalCode -Title $c.title -AsJob
}
} -ArgumentList (,$contacts)
Wait-Job -State Completed | Receive-Job
Get-Job -State Completed | Remove-Job
It fails saying the following for each loop:
The term 'New-MailContact' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and
try again.
+ CategoryInfo : ObjectNotFound: (New-MailContact:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
The term 'Set-MailContact' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and
try again.
+ CategoryInfo : ObjectNotFound: (Set-MailContact:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
The term 'Set-Contact' is not recognized as the name of a cmdlet,
function, script file, or operable program. Check the spelling of the
name, or if a path was included, verify that the path is correct and
try again.
+ CategoryInfo : ObjectNotFound: (Set-Contact:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
+ PSComputerName : localhost
Is there a trick to running these commands inside background jobs?
You need to import the correct powershell module, in this case the Office365:
Import-Module MSOnline
You will also need to authenticate so pass username and password down to your job and create credentials objects:
$contacts = Import-Csv "C:\temp\gal\testgal.csv"
Start-Job -Name Loop -ScriptBlock {
param([pscustomobject[]]$contacts, [string]$username, [string]$password)
Import-Module MSOnline
$secpasswd = ConvertTo-SecureString $password -AsPlainText -Force
$creds = New-Object System.Management.Automation.PSCredential ($username, $secpasswd)
$O365Session = New-PSSession –ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $creds -Authentication Basic -AllowRedirection
Connect-MsolService –Credential $creds
foreach ($c in $contacts){
...
}
} -ArgumentList (,$contacts, $username, $password)
Wait-Job -State Completed | Receive-Job
Get-Job -State Completed | Remove-Job
NB. This is untested but should put you on the right track.

Copy-Item throws AccessDenied exception

I am trying to copy files from a remote server to my base machine using powershell. This throws an 'Access Denied' exception even though the drives get mapped:
New-PSDrive -Name source -PSProvider FileSystem -Root "\\SERVERNAME1\D$\Temp\Folder" ;
New-PSDrive -Name target -PSProvider FileSystem -Root $destinationRemotePath ;
Copy-Item -Path source:\$($file).zip -Destination target: -Verbose -ErrorAction Stop -Force ;
Approach 2
I am mapping the source drive and using PsSession for target drive but I get
Cannot find drive. A drive with the name 'source' does not exist.
+ CategoryInfo : ObjectNotFound: (source:String) [Copy-Item], DriveNotFoundException
+ FullyQualifiedErrorId : DriveNotFound,Microsoft.PowerShell.Commands.CopyItemCommand
Following is the code being used:
$Username = "UserName";
$Password = ConvertTo-SecureString "Password" -AsPlainText -Force
$cred = New-Object System.Management.Automation.PSCredential($Username, $Password)
$session = new-pssession -computername 'TargetServerName' -credential $cred
New-PSDrive -Name source -PSProvider FileSystem -Root "\\SERVERNAME1\D$\Temp\Folder" ;
Invoke-Command -Session $session -ScriptBlock { Copy-Item -Path $($args[0]) -Destination $($args[1]) -Verbose -ErrorAction Stop } -ArgumentList source:\$($file).zip,'D:\Folder' ;
There are some issues on that second example:
The PSSession has a different scode, it does not know about your PSDrive.
PSSessions do not support authentication to network location like you might be used to from RDP-Sessions. See CredSSP or ' PSSession double hop'
Approach 1 looks like you have no access to that share you want to use. You can specify credentials via -Credential parameter at New-PSDrive. Can you Get-Childitem on Source: and Target:?