new-pssession in scheduled job - powershell

I want to write script that enables mail forwarding for some user on exchange server and turn it off at specified time.
But when $script_bloc executes in job: New-PSSession returns null without any error.
I can pass to New-PSSession hardcoded credentials, and in that case it works as I expect, but I don't want to do it because my passwords can expire at the moment when job starts.
Any idea why New-PSSession doesn't work in a job? And how to make it work?
$user = 'username1'
$fwdto = 'username2'
$remove_date = '19.04.2018 08:33:00'
Set-Mailbox -Identity $user -DeliverToMailboxAndForward $true -ForwardingAddress $fwdto
$job_date=[datetime]::Parse($remove_date)
$job_date=[datetime]::Now.AddSeconds(20) #for test
$trigger = New-JobTrigger -Once -At $job_date
$job_name="rfw_" + $user
$script_block = {
param($user_param,$job_name_param)
Start-Transcript $env:USERPROFILE\jobs\$job_name_param.log -Verbose -Append
$PSOptions = New-PSSessionOption –SkipCACheck –SkipRevocationCheck -SkipCNCheck
$sess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange.company.org/PowerShell/ –SessionOption $PSOptions
Import-PSSession $sess | Out-Default
Set-Mailbox -Identity $user_param -DeliverToMailboxAndForward $false -ForwardingAddress $null | Out-Default
Remove-PSSession $sess | Out-Default
Unregister-ScheduledJob $job_name_param -Force
Stop-Transcript
}
Register-ScheduledJob -Trigger $trigger -Name $job_name -ScriptBlock $script_block -ArgumentList $user, $job_name

When you register a job in PowerShell, its created as a Task in Task scheduler under Microsoft\Windows\PowerShell folder. So any actions which requires authentication inside a task will fail with access denied error if the credentials are not explicitly mentioned.
You can test it by having a Try{} Catch{} in your ScriptBlock.
You can achieve your task by using -Credential parameter for Register-ScheduledJob cmdlet. Then the task will use that credential for any opration,
$script_block = {
param($user_param,$job_name_param)
Try{
Start-Transcript $env:USERPROFILE\jobs\$job_name_param.log -Verbose -Append
$PSOptions = New-PSSessionOption –SkipCACheck –SkipRevocationCheck -SkipCNCheck
$sess = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://exchange.company.org/PowerShell/ –SessionOption $PSOptions -ErrorAction Stop
$sess > C:\Session.log
Import-PSSession $sess | Out-Default
Set-Mailbox -Identity $user_param -DeliverToMailboxAndForward $false -ForwardingAddress $null | Out-Default
Remove-PSSession $sess | Out-Default
Unregister-ScheduledJob $job_name_param -Force
Stop-Transcript
}
Catch{
$_ > c:\Error.log
}
}
Use above ScriptBlock with and Without -Credetial parameter to Register-ScheduleJob cmdlet. You can see the difference.

Related

Remote execution on Exchange server failed

I want to remote enable the email-address-policy for a single mailbox on a exchange server (2010).
I can do this:
$samaccountname = $args[0] # gets sam from command line
$EncryptedPassword = Get-Content -Path "C:\temp\password.txt"
$SecurePassword = ConvertTo-SecureString -String $EncryptedPassword
$Credential = New-Object System.Management.Automation.PSCredential "xyzdom\sco_admin", $SecurePassword
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://xyzexcas01/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber -CommandName Set-Mailbox
Get-Mailbox -Identity $samaccountname | Set-Mailbox -EmailAddressPolicyEnabled $True
Remove-PSSession $Session
It works if I open a powershell as administrator on the Orchestrator server. Then it executes the command on the exchange server as it should.
But the script does not work if Orchestrator tries to execute it. I do not know what settings Orchestrator uses when executing it. But I have a similar script, which is working with Orchestrator.
$samaccountname = $args[0] # gets sam from command line
$EncryptedPassword = Get-Content -Path "C:\temp\password.txt"
$SecurePassword = ConvertTo-SecureString -String $EncryptedPassword
$Credential = New-Object System.Management.Automation.PSCredential "xyzdom\sco_admin", $SecurePassword
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://xyzexcas01/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber -CommandName enable-mailbox
$username_param = $samaccountname
$emailalias_param = $samaccountname
Invoke-Command -ArgumentList $username_param,$emailalias_param –session $Session -scriptblock {
param($username_exc, $alias_exc)
Enable-Mailbox -Identity $username_exc -Alias $alias_exc -DomainController 'xyzdc01.zfpdom.zfp'
}
Remove-PSSession $Session
This script makes a new mailbox. It is working.
Can anyone show me a solution for the first script? I am totally new in powershell so I can't figure it out. Maybe someone can change my first script to do it with this Invoke-Command scriptblock. I am sure, then it will work.
Thank you.
Greetings
Replace the commands inside the invoke-command, and the variables accordingly. Also, add the get-mailbox commandlet to the session. I am not able to try it, though, so I added the -verbose and -whatif switches as a failsafe. Note that if the samaccountname variable is empty, the Set-Mailbox will run on all mailboxes. The script can be tested standalone before running it in the Orchestrator.
$samaccountname = $args[0] # gets sam from command line
$EncryptedPassword = Get-Content -Path "C:\temp\password.txt"
$SecurePassword = ConvertTo-SecureString -String $EncryptedPassword
$Credential = New-Object System.Management.Automation.PSCredential "xyzdom\sco_admin", $SecurePassword
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://xyzexcas01/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber -CommandName Set-Mailbox,Get-Mailbox
Invoke-Command -ArgumentList $samaccountname –session $Session -scriptblock {
param($username_exc)
Get-Mailbox -Identity $username_exc| Set-Mailbox -EmailAddressPolicyEnabled $True -verbose -whatif # remove the -whatif to perform changes
}
Remove-PSSession $Session
Another working solution I have found out:
#Parameter Laden
$samaccountname = $args[0] # $samaccountname wird übergeben
$EncryptedPassword = Get-Content -Path "C:\temp\password.txt"
$SecurePassword = ConvertTo-SecureString -String $EncryptedPassword
$Credential = New-Object System.Management.Automation.PSCredential "xyzdom\sco_admin", $SecurePassword
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://xyzexcas01/PowerShell/ -Authentication Kerberos -Credential $Credential
Import-PSSession $Session -AllowClobber -CommandName Set-Mailbox,Get-Mailbox
Get-Mailbox -Identity $samaccountname | Set-Mailbox -EmailAddressPolicyEnabled $True
Remove-PSSession $Session

Invoke-Command with remote session: Cannot validate argument on parameter

I wrote a script to restart a few ASP.NET websites on a remote server:
$computerName = #...
$password = #...
$secureStringPassword = ConvertTo-SecureString -AsPlainText -Force -String $password
$userName = #...
$credential= New-Object System.Management.Automation.PSCredential ($userName, $secureStringPassword)
$websiteNames = #..., #..., #...
Get-PSSession -ComputerName $computerName -Credential $credential | Remove-PSSession
$psSession = New-PSSession -ComputerName $computerName -Credential $credential
Invoke-Command -Session $psSession -ScriptBlock { $websiteNames | foreach{ Stop-Website -Name $_ } }
Invoke-Command -Session $psSession -ScriptBlock { $websiteNames | foreach{ Start-Website -Name $_ } }
$psSession | Remove-PSSession
For some reasons my Invoke-Command do not run properly, I have the following error message:
Cannot validate argument on parameter 'Name'. The argument is null. Provide a valid value for the argument, and then try running the command again.
When the commands are run after an Enter-PSSession it works fine within a -ScriptBlock it kinda mess up the -Name parameter, any idea how to fix that up?
The remote session cannot access the variables you have defined locally. They can be referenced with $using:variable
Invoke-Command -Session $psSession -ScriptBlock { $using:websiteNames | foreach{ Stop-Website -Name $_ } }
Invoke-Command -Session $psSession -ScriptBlock { $using:websiteNames | foreach{ Start-Website -Name $_ } }
More information in the about_remote_variables help:
get-help about_remote_variables -Full
Actually just needed to pass the arguments to the -ArgumentList of the -ScriptBlock and use $args to reference to it within the function block:
Invoke-Command -Session $psSession -ScriptBlock { $args | foreach{ Stop-Website -Name $_ } } -ArgumentList $websiteNames
Invoke-Command -Session $psSession -ScriptBlock { $args | foreach{ Start-Website -Name $_ } } -ArgumentList $websiteNames

PowerShell Get Users Email Address To Exchange

Trying to do an auto ligation hold script using an ad synced group up to Azure. Would anyone be able to help with the below?
I'm trying to get all my users from the MsolGroup by doing a return of the MsolGroupMembers, I would like to return the users then from that I need to get their UPN/Email Address so I can pipe it into an exchange online command to turn litigation hold on for each of them users from the group.
Import-Module MSOnline
$user="removed"
$file = "removed"
$password = Get-Content $File | ConvertTo-SecureString
$cred = New-Object System.Management.Automation.PsCredential($user,$password)
Connect-MsolService -Credential $cred
$UserCredential = Get-Credential -Credential $cred
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://outlook.office365.com/powershell-liveid/ -Credential $UserCredential -Authentication Basic -AllowRedirection
Import-PSSession $Session
$usersOfGroup = Get-MsolGroupMember -GroupObjectId removedID -All
foreach ($user in $usersOfGroup)
{
$mailbox = Get-Mailbox $user.EmailAddress
Write-Output $mailbox
if ($mailbox.LitigationHoldEnabled -eq $false -and $mailbox.RecipientTypeDetails -eq "UserMailbox")
{
Write-Output "Current mailbox: " $mailbox.UserPrincipalName
Set-Mailbox -Identity $mailbox.UserPrincipalName -LitigationHoldEnabled $true -LitigationHoldDuration 2555 -WarningAction SilentlyContinue
}
}
Remove-PSSession $Session
This should do the trick.
#Useful Microsoft documentation
#https://technet.microsoft.com/en-us/library/dn767952(v=exchg.160).aspx
#Connect to Exchange Online
Import-Module MSOnline
$O365Cred = Get-Credential
$O365Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://ps.outlook.com/powershell" -Credential $O365Cred -Authentication Basic -AllowRedirection
Import-PSSession $O365Session -AllowClobber
Connect-MsolService -Credential $O365Cred
#Filter mailboxes for the HR Department, pipe to the set litigation command for 365 days
Get-Recipient -RecipientTypeDetails UserMailbox -ResultSize unlimited -Filter 'Department -eq "HR"' | Set-Mailbox -LitigationHoldEnabled $true -LitigationHoldDuration 365
Remove-PSSession -Id $O365Session.Id

Exchange Powershell - How to run Exchange 2010 command by schedule from inside script?

I'm writing a script that delete redirect mail by shedule.
Here http://www.experts-exchange.com/Programming/Languages/Scripting/Powershell/Q_28316932.html describes how import Exchange function.
Script:
$t = New-JobTrigger –Once –At "08/04/2014 13:58"
$del_redir={
param ([string]$alias)
powershell.exe $ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://myexchsrv.mycompany.local/PowerShell ; Import-PSSession $ExchangeSession ; Set-Mailbox -Identity $alias -ForwardingAddress $null -DeliverToMailboxAndForward $false
}
Register-ScheduledJob -Name Start -ScriptBlock $del_redir -ArgumentList ("usernamealias") -Trigger $t
Separetly lines working.
Set-Mailbox -Identity "usernamealias" -ForwardingAddress $null
work good.
Change
Set-Mailbox -Identity $alias -ForwardingAddress $null
at
$t = "d:\scripts\" + $alias + ".txt" #$alias = "usernamealias"
New-Item $t -type file
work too (test input alias)
$ExchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri http://myexchsrv.mycompany.local/PowerShell
Import-PSSession $ExchangeSession
work too (import Exchange function)
Windows PowerShell run as Administrator
All together don't work. Where am I mistaken?
I see one probable and another possible problem.
First:
$t = New-JobTrigger –Once –At "08/04/2014 13:58"
Then later:
$t = "d:\scripts\" + $alias + ".txt" #$alias = "usernamealias"
It appears you've just destroyed your trigger.
The other possible issue is that your arguments to the scriptblock parameter appear to be wrong (impossible to tell without knowing what the scriptblock looks like), and that -argumentlist parameter is not the last parameter in the command.
The Help on Register-ScheduledJob doesn't say so explicitly, but the other cmdlets that take a scripblock argument and let you specify an argument list require that the argument list be the last parameter, and everything that follows is arguments to the scriptblock. This is so the parser won't confuse arguments to the scriptblock with with might be parameters and arguments to the cmdlet. I suspect the same holds true with Regiester-ScheduledJob, and the -Trigger parameter needs to come before the -Scriptblock parameter.
Working script:
$t = New-JobTrigger –Once –At "10/04/2014 9:30"
$cred = Get-Credential mydomain\administrator
$oo = New-ScheduledJobOption -RunElevated
$del_redir={
param ([string]$alias)
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -command ". 'C:\Program Files\Microsoft\Exchange Server\V14\bin\RemoteExchange.ps1'; Connect-ExchangeServer -auto; Set-Mailbox -Identity $alias -ForwardingAddress `$null -DeliverToMailboxAndForward 0"
}
Register-ScheduledJob -Name Start -ScriptBlock $del_redir -ArgumentList ("usernamealias") -Trigger $t -Credential $cred -ScheduledJobOption $oo
rem `$null; $oo = New-ScheduledJobOption -RunElevated

nested scriptblocks in a powershell remote session

I am trying to run a script block on a remote machine, but i don't to be prompted for credentials, i want to pass them in the script.
Some commands may but the commands i want to run are access denied unless i provide the credential.
for example this command can work:
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {ls }
but this wont work unless -credential is passed (Invoke-Command on target)
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {Invoke-Command -computername $Env:COMPUTERNAME -Credential $Cred -ScriptBlock {ls} }
the same way what i want to achieve causes access denied problem (starting a process)
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $Error -Scriptblock {[System.Diagnostics.Process]::Start("C:\Myprocess.exe", $localArgs, "UserName", $credential.Password, "MyDomain")}
Invoke-Command -Session $session -ErrorAction Stop -ErrorVariable $setError -Scriptblock {$Domain = "domain";$PassSec = ConvertTo-SecureString $( "password") -AsPlainText -Force ; $Cred = New-Object -TypeName System.Management.Automation.PSCredential -argumentlist $($domain + "\" + "userName"),$passSec; Invoke-Command -computername $Env:COMPUTERNAME -Credential $Cred -ScriptBlock {C:\Myprocess.exe } }