Enabling powershell to run scripts with registry permissions.

As part of my powershell work I obviously need to run powershell scripts. I tried to run one last night and got the usual message about scripts needing to be signed. I had previously changed the settings on my XP machine, but this was obviously the first time I had run a script on my Windows7 machine.

Running the usual “set-executionpolicy remotesigned” I got the following error message “Execution Policy Change. The execution policy helps protect you from scripts that you do not trust. Changing the execution policy might expose you to the security risks described in the about_Execution_Policies help topic. Do you want to change the execution policy?”

Answering Yes to the prompt I then got the following error message – “Set-ExecutionPolicy : Access to the registry key ‘HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell’ is denied”. Sure enough I don’t have permission to this registry key.

I checked with our admin to ensure this wasn’t set in group policy before I started fiddling around. Found out that there is another setting that is user specific that can be set with “Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy RemoteSigned

After doing this I was then able to run scripts, and more importantly my profile script runs. Seeing as though this is my workstation I don’t really care about anyone else’s powershell scripts on my machine 😉

However, if you want to set it for all users, then set the Scope Parameter to be LocalMachine

To set it domain wide, you need to download the PowerShell group policy templates from Microsoft and follow the instructions to set up a policy.

Security warning pops up when using Outlook2007 and Exchange 2007

After a recent migration of mail to Exchange2007, we’ve just started getting users logging tickets where a security window pops up saying “The name of the security certificate is invalid or does not match the name of the site”. This can happen even when the client is not at their desk. It took a few seconds to work out what was causing it – the clue was that the window had an icon in the taskbar for outlook. Searching in Google found Microsoft’s KB article 940726 with the resolution to the fix which involves changing various internal url attributes.
The instructions are fairly straightforward but I wanted to see what the values were set to before making the change. As I’m not very familiar with powershell it took me a while to work out what I needed.
For the command

Set-ClientAccessServer -Identity Servername -AutodiscoverServiceInternalUri https://name.contoso.com/autodiscover/autodiscover.xml

you want to run the command

Get-ClientAccessServer -Identity Servername | fl
The pipe fl provides all the values in a list – if you don’t include this part of the code you will end up with one line containing the name of the server – a value that you hopefully know already!
I really need to get cracking on my powershell skills – I still prefer good old fashioned dos batch programming but now that we’ve started to roll out powershell across all machines, powershell skills will be in demand more and more.

Powershell script to retrieve email from archived mailbox in Exchange2007

The other powershell script I worked on was to retrieve a detached mailbox that was still retained in exchange, archive the mail to a pst file, move the pst file to the managers home directory and then delete the mailbox again.
The following script does this – note some paths are hardcoded and I already have a temporary account in AD called tempuser that does not have a mailbox. This is the account that the deleted mailbox is attached to.
The main disadvantage to this method is that at the end of the script all of the detached mailboxes will appear as tempuser in the exchange console. In this particular script I also do very little error checking as this was designed for my use but hopefully helps others too.

$user=$args[0] #user is the first parameter passed
$fname=$args[1] #first name
$lname=$args[2] #last name
$fullname=$fname + " " + $lname
$manager=$args[3] #manager windows accountname is the last parameter passed
if ($manager -eq $null) {exit} # if not enough parameters are provided then quit the script

write-host $user
write-host $manager
$Host.UI.RawUI.WindowTitle = "attaching mailbox to tempuser account"

$result=Connect-Mailbox -Identity $fullname -Database 'servername\First Storage Group\Standard User Mailbox' -User 'domain\tempuser' -Alias 'tempuser'

$Host.UI.RawUI.WindowTitle = "Sleeping 60 until moving mailbox"
start-sleep -s 60 # sleep 60 seconds after moving mailbox to tempuser account before doing the export

$Host.UI.RawUI.WindowTitle = "exmerging mailbox"
export-mailbox tempuser -pstfolderpath d:\mailboxes -confirm:$false

$Host.UI.RawUI.WindowTitle ="sleep 20 seconds"
start-sleep -s 20 # sleep 20 seconds after exporting mailbox to tempuser account before doing the mailbox move

$Host.UI.RawUI.WindowTitle = "Moving pst file to managers mailbox"
$newdir="\\archiveserver\c$\users\" + $manager + "\" + $user
$result=mkdir $newdir
$newpst=$newdir + "\" + $user + ".pst"
Move tempuser.pst $newpst

$Host.UI.RawUI.WindowTitle = "disabling tempuser mailbox for reuse"
disable-mailbox tempuser -confirm:$false

Note that I use the $Host.UI.RawUI.WindowTitle statement a lot – this enables me to easily see whereabouts in the script I have got to. I much preferred to use the command title in my batch files to do the same thing. Likewise the $null = $host.UI.RawUI.ReadKey(“NoEcho,IncludeKeyDown”) is the equivalent of the batch command pause

Powershell script to retrieve list of emails from Exchange2007 in the past 24 hours.

As in my previous post I needed to obtain a list of emails that have gone through a mail server within the past 24 hours (so it can be run on a daily basis). I struggled with the code initially but ended up with the following.

$yesterday = (get-date).adddays(-1).tostring(“g”)
$rightnow = (Get-Date).ToString(“g”)
get-messagetrackinglog -Start $Yesterday -End $rightnow -EventID RECEIVE -Result size 5000| select-object EventID,Sender,@{name=’Recipients’;expression={[string]::join(“;”,($_.Recipients))}},MessageSubject,TimeStamp | export-csv receive.csv
get-messagetrackinglog -Start $Yesterday -End $rightnow -EventID SEND -Resultsize 5000| select-object EventID,Sender,@{name=’Recipients’;expression={[string]::join(“;”,($_.Recipients))}},MessageSubject,TimeStamp | export-csv send.csv

My next step is to automate this and send it via email

Twitter helped me with powershell this week.

This week at work I’ve been doing a fair amount of work with powershell. It has been a slow process as I’ve had no training in powershell and was basically teaching myself as I went along. I had two goals in mind.

The first was to automatically attach a mailbox to a temporary account, export the mail within this mailbox to a pst file, move the pst file to a folder and then delete the account again.  As Exchange2007 needs to use powershell to export the data I had to change my user deletion script to run within powershell.

My other goal was to write a report for all mail sent or received through the exchange server in the past 24 hours. Using the exchange tracking logs I was able to pull the information required to do this.

The second problem was causing me more hassles  as I could not work out how to retrieve the time from 1 day ago AND have the result in the format needed for the next part of the script. I could get the current time in the correct format OR I could get the time from 1 day ago but not in the current format. I went onto the #powershell room on irc.freenode.net but it looked like everyone was asleep as I didn’t get any response to my query.  I decided to post a tweet on twitter about the problem and within 5 minutes I had about 3 or 4 responses which was great. At the same time I also got a response in the chatroom. As usual with coding, there are several ways to get an answer.  However Jaykul was very helpful in telling me that “get-date (get-date).addays(-1) -f g”  is 2 ten thousandths of a second quicker than “[datetime]::now.adddays(-1).tostring(“g”)”
Best way to get the Time from 24 hours ago.
Now you can probably see why I was confused and struggling to get the code working!

I’m going to post the resulting code in the next posts to make it easier to search on.