PSSession search AD computers Powershell - 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

Related

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 core to powershell

I'm running an Ubuntu EC2 instance with Pwsh installed to remote execute AD commands on one of our servers. 2sd hop is set-up correctly and i'm able to run AD commands but when executing my script i get the following error (Scripts works fine directly on the 2sd hop machine):
The search filter cannot be recognized
+ CategoryInfo : NotSpecified: (:) [Get-ADUser], ADException + FullyQualifiedErrorId : ActiveDirectoryServer:8254,Microsoft.ActiveDirectory.Management.Commands.GetADUser
+ PSComputerName : corpmaint02
#!/usr/bin/pwsh
$employeeEmail = 'myemail#contoso.com'
$session = New-PSSession -ComputerName corpmaint02 -ConfigurationName corpmaint02 -Credential contoso\myadminaccount
Invoke-Command -Session $session -ArgumentList $employeeEmail -ScriptBlock{
Get-ADUser -Filter "EmailAddress -eq '$employeeEmail'" -Properties EmailAddress | Disable-ADAccount
Write-Host $employeeEmail has been 'disabled.'
}
Remove-PSSession -ID $session.ID
[GC]::Collect()
Any help would be appreciated.
Update: new code:
#!/usr/bin/pwsh
$cred=Get-Credential domain\myadmin
$employeeEmail = 'myemail#contoso.com'
Invoke-Command -ComputerName corpmaint02 -Credential $cred -ConfigurationName corpmaint02 -Authentication Negotiate -ArgumentList $employeeEmail -$
Get-ADUser -Filter "EmailAddress -eq '$($Args[0])'" -Properties EmailAddress | Disable-ADAccount -verbose
Write-Host $employeeEmail has been 'disabled.'
}
I modified my code as follow and it works expect for the lack of permissions to disable the account which odd because my admin account has rights to do so.
Insufficient access rights to perform the operation
+ CategoryInfo : NotSpecified: (CN=xxxxx\domain,DC=com:ADUser) [Disable-ADAccount], ADException
+ FullyQualifiedErrorId : ActiveDirectoryServer:8344,Microsoft.ActiveDirectory.Management.Commands.DisableADAccount
+ PSComputerName : corpmaint02
New code to elevate:
#!/usr/bin/pwsh
$cred=Get-Credential domain\myadmin
$employeeEmail = 'user1#contoso.com'
Invoke-Command -ComputerName corpmaint02 -Credential $cred -ConfigurationName corpmaint02 -Authentication Negotiate -ArgumentList $employeeEmail,$cred -ScriptBlock{
$currentUser = New-Object Security.Principal.WindowsPrincipal $([Security.Principal.WindowsIdentity]::GetCurrent())
$testadmin = $currentUser.IsInRole([Security.Principal.WindowsBuiltinRole]::Administrator)
if ($testadmin -eq $false) {
Start-Process powershell.exe -Verb RunAs -ArgumentList ('-noprofile -noexit -file "{0}" -elevated' -f ($myinvocation.MyCommand.Definition))
exit $LASTEXITCODE
}
Get-ADUser -Filter "EmailAddress -eq '$($Args[0])'" -Properties EmailAddress | Disable-ADAccount -verbose -Credential $Args[1]
}
Write-Host $employeeEmail 'has been disabled.'
Invoke-Command isn't running with elevated rights, so you can retrieve data but not make changes.
https://ss64.com/ps/syntax-elevate.html
If you use Invoke-Command to run a script or command on a remote computer, then it will not run elevated even if the local session is. This is because any prompt for elevation will happen on the remote machine in a non-interactive session and so will fail.
You can try self elevating in the Invoke-Command scriptblock (from the link above)
If (-NOT ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))
{
# Relaunch as an elevated process:
Start-Process powershell.exe "-File",('"{0}"' -f $MyInvocation.MyCommand.Path) -Verb RunAs
exit
}
# Now running elevated so launch the script:
& "d:\long path name\script name.ps1" "Long Argument 1" "Long Argument 2"

Check/read registry key value on remote computer with local admin credential

How to check registry key value on computer which is not in domain??
I think that I must use local admin credential for this but I dont know how
I tried this:
$user = "admin"
$password = "pass" | ConvertTo-SecureString -asPlainText -Force
$computer = "computer"
$domain=$computer
$username = $domain + "\" + $user
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password
$key = '\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters'
$valuename = 'DiskSpaceThreshold'
$wmi = Get-Wmiobject -list "StdRegProv" -namespace root\default -Computername $computer -Credential $Credential
$value = $wmi.GetStringValue($HKEY_Local_Machine,$key,$valuename).svalue
$wmi
$value
But the result:
Get-Wmiobject : Could not get objects from namespace root\default. Serwer RPC jest niedostępny. (Wyjątek od HRESULT: 0x800706BA) At line:12 char:8
+ $wmi = Get-Wmiobject -list "StdRegProv" -namespace root\default -Comp ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (:) [Get-WmiObject], COMException
+ FullyQualifiedErrorId : INVALID_NAMESPACE_IDENTIFIER,Microsoft.PowerShell.Commands.GetWmiObjectCommand You cannot call a method on a null-valued expression. At line:13 char:1
+ $value = $wmi.GetStringValue($HKEY_Local_Machine,$key,$valuename).sva ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH : ReturnValue : 6 uValue : PSComputerName :
So I tried something else
# file with computer name
$computers = Get-Content F:\IT\!Set_NTP_Time\ReadRegistry\servers.txt | ?{$_ -notmatch "^#"};
#Registry Hives
[long]$HIVE_HKROOT = 2147483648
[long]$HIVE_HKCU = 2147483649
[long]$HIVE_HKLM = 2147483650
[long]$HIVE_HKU = 2147483651
[long]$HIVE_HKCC = 2147483653
[long]$HIVE_HKDD = 2147483654
# registry
$HKLM = 2147483650
$main = "Localmachine"
$keyPath = "System\CurrentControlSet\Services\W32Time"
$keyName = "Start"
#$computer ='.'
$reg = [WMIClass]"ROOT\DEFAULT:StdRegProv"
$Key = "W32Time"
#$Value = "HistoryBufferSize"
#$results = $reg.GetDWORDValue($HKEY_LOCAL_MACHINE, $Key, $keyName)
#"Current History Buffer Size: {0}" -f $results.uValue
<#
Param($computer)
$HKEY_Local_Machine = 2147483650
$reg = [WMIClass]"\\$computer\ROOT\DEFAULT:StdRegProv"
$Key = "SOFTWARE\Wow6432Node\Symantec\Symantec Endpoint Protection\CurrentVersion\SharedDefs"
$ValueName = "DEFWATCH_10"
$results = $reg.GetStringValue($HKEY_LOCAL_MACHINE, $Key, $ValueName)
write $results.sValue
#>
# credentials
$user = "admin"
$user1 = "admin1"
$password = "pass" | ConvertTo-SecureString -asPlainText -Force
# Start processing
foreach($computer in $computers) {
$domain=$computer
$username = $domain + "\" + $user
$username1 = $domain + "\" + $user1
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password
$Credential1 = New-Object System.Management.Automation.PSCredential -ArgumentList $username1,$password
try {
if (($computer -eq "comp1") -or ($computer -eq "comp2") -or ($computer -eq "name_of_computer") -or ($computer -eq "other_computer")) {
#$wmi = Get-Wmiobject -list "StdRegProv" -namespace root\default -Computername $computer -Credential $Credential1
#$value = $wmi.GetStringValue($HKLM,$keyPath,$keyName).svalue
#Write-Host -ForegroundColor DarkYellow $computer $value
#$value = Invoke-Command -Scriptblock {Get-Item $HKLM,$keyPath,$keyName} -Computername $computer -Credential $Credential1
$reg = Get-WmiObject -List -Namespace root\default -ComputerName $Computer -Credential $Credential1 | Where-Object {$_.Name -eq "StdRegProv"}
#$HKLM = 2147483650
#$value = $reg.GetStringValue($HKLM,$keyPath,$keyName).sValue
$value = $reg.GetDWORDValue($HKEY_LOCAL_MACHINE, $Key, $keyName)
Write-Host -ForegroundColor DarkYellow $computer $reg $value
} else {
#$wmi = Get-Wmiobject -list "StdRegProv" -namespace root\default -Computername $computer -Credential $Credential
#$value = $wmi.GetStringValue($HKLM,$keyPath,$keyName).svalue
#Write-Host -ForegroundColor DarkYellow $computer $value
#$value = Invoke-Command -Scriptblock {Get-Item $HKLM,$keyPath,$keyName} -Computername $computer -Credential $Credential
$reg = Get-WmiObject -List -Namespace root\default -ComputerName $Computer -Credential $Credential | Where-Object {$_.Name -eq "StdRegProv"}
#$HKLM = 2147483650
#$value = $reg.GetStringValue($HKLM,$keyPath,$keyName).sValue
$value = $reg.GetDWORDValue($HKEY_LOCAL_MACHINE, $Key, $keyName)
Write-Host -ForegroundColor DarkYellow $computer $reg $value
}
<#
if($value -eq 2)
{
Write-Host -ForegroundColor DarkYellow $computer "YES"
} else {
Write-Host -ForegroundColor Red $computer "NO"
}
#>
} catch {
Write-Host -ForegroundColor Red "$computer access denied.$_";
}
}
Result for this script
comp1 \COMP1\ROOT\default:StdRegProv System.Management.ManagementBaseObject
comp2 \COMP2\ROOT\default:StdRegProv System.Management.ManagementBaseObject
comp3 \COMP3\ROOT\default:StdRegProv System.Management.ManagementBaseObject
Personally, as I am used to use powershell remoting to gather information from remote machines, I would proceed like this:
Establish remote PS session
Run script on remote machine
Profit
So in your case, something like (If you are retrieving a value named DiskSpaceThreshold inside of HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters)
$user = "admin"
$password = "pass" | ConvertTo-SecureString -asPlainText -Force
$computer = "computer"
$domain=$computer
$username = $domain + "\" + $user
$Credential = New-Object System.Management.Automation.PSCredential -ArgumentList $username,$password
$session = New-PSSession $computer -Credential $Credential
$r = Invoke-Command -Session $session -ScriptBlock { Get-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters -Name "DiskSpaceThreshold" }
Remove-PSSession $session
Write-Host $r.DiskSpaceThreshold
The effect of trying to run the script from P-L user post
New-PSSession : [computer] Connecting to remote server computer failed with the following error message : WinRM cannot process the
request. The following error with errorcode 0x80090311 occurred while using Kerberos authentication: There are currently no
logon servers available to service the logon request.
Possible causes are:
-The user name or password specified are invalid.
-Kerberos is used when no authentication method and no user name are specified.
-Kerberos accepts domain user names, but not local user names.
-The Service Principal Name (SPN) for the remote computer name and port does not exist.
-The client and remote computers are in different domains and there is no trust between the two domains.
After checking for the above issues, try the following:
-Check the Event Viewer for events related to authentication.
-Change the authentication method; add the destination computer to the WinRM TrustedHosts configuration setting or use HTT
PS transport.
Note that computers in the TrustedHosts list might not be authenticated.
-For more information about WinRM configuration, run the following command: winrm help config. For more information, see
the about_Remote_Troubleshooting Help topic.
At line:9 char:12
+ $session = New-PSSession $computer -Credential $Credential
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : OpenError: (System.Manageme....RemoteRunspace:RemoteRunspace) [New-PSSession], PSRemotingTran
sportException
+ FullyQualifiedErrorId : AuthenticationFailed,PSSessionOpenFailed
Invoke-Command : Cannot validate argument on parameter 'Session'. The argument is null or empty. Provide an argument that is
not null or empty, and then try the command again.
At line:10 char:30
+ $r = Invoke-Command -Session $session -ScriptBlock { Get-ItemProperty -Path HKLM ...
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Invoke-Command], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.InvokeCommandCommand
Remove-PSSession : Cannot validate argument on parameter 'Id'. The argument is null. Provide a valid value for the argument,
and then try running the command again.
At line:11 char:18
+ Remove-PSSession $session
+ ~~~~~~~~
+ CategoryInfo : InvalidData: (:) [Remove-PSSession], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.PowerShell.Commands.RemovePSSessionCommand
The username and password are good.

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.