Invoke-Command with parameters as a job - powershell

I can run the below command without any problem:
Invoke-Command -ScriptBlock {
Param($rgName,$VMname)
Get-AzureRmVM -Name $VMname -ResourceGroupName $rgName
} -ArgumentList $rgname,$vmname
But what I really need is to be able to run the command as a job, so I tried the below:
Invoke-Command -ScriptBlock {
Param($rgName,$VMname)
Get-AzureRmVM -Name $VMname -ResourceGroupName $rgName
} -ArgumentList $rgname,$vmname -AsJob
And I'm receiving the following error:
Invoke-Command : Parameter set cannot be resolved using the specified named
parameters.
At line:1 char:1
+ Invoke-Command -ScriptBlock { param($rgName,$VMname) Get-AzureRmVM -N ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Invoke-Command], ParameterBindingException
+ FullyQualifiedErrorId : AmbiguousParameterSet,Microsoft.PowerShell.Commands.InvokeCommandCommand
I've also tried to run the command using Start-Job instead but I'm also receiving errors.

You have to pass the argumentlist as an array
[Array]$ArgumentList = #('rg','vm')
[ScriptBlock]$ScriptBlock = {
Param(
[string]$rgName,
[string]$VMname
)
Get-AzureRmVM -Name $VMname -ResourceGroupName $rgName
}
$nj = Invoke-Command -ScriptBlock $ScriptBlock -ArgumentList $ArgumentList -ComputerName $env:COMPUTERNAME -Credential (Get-Credential) -JobName 'NewJobName' |Wait-Job
Interestingly, I found that I had to specify -ComputerName [-Credntial] to get this to work - modified above.
Get the results of the job as follows...
$nj | Receive-Job

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. ... .. . . .
}

Setting Windows local admin password remotely using PowerShell & [ADSI]

So close but so far...
I am trying to change a local administrator password on a Windows server using [ADSI] & PowerShell but I cannot find a way to pass a string variable when invoking and get the following error:
Exception calling "Invoke" with "2" argument(s): "Number of parameters specified does not match the expected number."
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodTargetInvocation
+ PSComputerName : vmdeploytest1
This works, with the string in the statement:
$vmName = "vmdeploytest1"
Invoke-Command -ComputerName $vmName -Credential $creds -ScriptBlock {
$account = [ADSI]("WinNT://localhost/Administrator,user")
$account.psbase.invoke("setpassword","Password123")
}
This doesn't:
$vmName = "vmdeploytest1"
$password = '"Password123"'
$invoke = '"setpassword",'
$invokeStr = $invoke + $password
Invoke-Command -ComputerName $vmName -Credential $creds -ScriptBlock {
$account = [ADSI]("WinNT://localhost/Administrator,user")
$account.psbase.invoke($invokeStr)
}
This doesn't
$vmName = "vmdeploytest1"
$password = '"Password123"'
Invoke-Command -ComputerName $vmName -Credential $creds -ScriptBlock {
$account = [ADSI]("WinNT://localhost/Administrator,user")
$account.psbase.invoke("setpassword",$password)
}
This doesn't:
$vmName = "vmdeploytest1"
$password = 'Password123'
Invoke-Command -ComputerName $vmName -Credential $creds -ScriptBlock {
$account = [ADSI]("WinNT://localhost/Administrator,user")
$account.psbase.invoke("setpassword",$password)
}
All giving the same error. I need to be able to use a variable because I am going to generate a random password.
Jeroen Mostert is Correct
When you pass variables into a ScriptBlock you need to prefix them with $using:
For example:
$vmName = "vmdeploytest1"
$password = 'Password123'
Invoke-Command -ComputerName $vmName -Credential $creds -ScriptBlock {
$account = [ADSI]("WinNT://localhost/Administrator,user")
$account.psbase.invoke("setpassword",$using:password)
}

PowerShell Issue regarding entering a PS Session and setting permissions

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
}

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.