Monthly Archives: July 2011

Outlook folders

The functions we’ve seen so far have involved iterating through the whole set of Outlook folders. That’s a lot of folders (I have 4 email accounts with lost of folders). The trick is to do this just once and then use the GetFolderFromID method at the Outlook.Session level to access individual mailboxes

The problem is that this method uses the EntryID and the StoreID for the folder.  Examples are shown below

StoreID : 0000000038A1BB1005E5101AA1BB08002B2A56C200006D736E636F6E2E646C6C
0000000000000000E92FEB759650448683B87DE522AA494800433A5C55736572735C526963
686172645C417070446174615C4C6F63616C5C4D6963726F736F66745C4F75746C6F6F6B5C
726963686172645F73696464617761795F686F746D61696C2E6F737400

EntryID : 000000000A9D24A8D4E32445825D043ADB203A6F0100D9539C2261A6BB45B9DA
B62C7081B3C101002100FFFF0000

Path    : \\emailaddress@hotmail.com\Deleted Items

Now I for one don’t want to be typing in the EntryID never mind the StoreID – chances of getting that right range from zero to about … zero

What we can do convert all of our Outlook functions (the two so far and the others I’ve got planned) into a module. In the psm1 file I can put a line that says

$folders = get-mailfolders

That creates a collection of objects containing the path, storeid and entryid for all of the folders. We can then search through that collection much faster than the outlook folders.

We create the collection like this

function get-mailfolders {            
$outlookfolders = @()            
$outlook = New-Object -ComObject Outlook.Application            
foreach ($folder in $outlook.Session.Folders){            
              
  foreach($mailfolder in $folder.Folders ) {            
   $olkf = New-Object PSObject -Property @{            
    Path = $($mailfolder.FullFolderPath)            
    EntryID = $($mailfolder.EntryID)            
    StoreID = $($mailfolder.StoreID)            
   }            
               
   $outlookfolders += $olkf            
               
  }             
}            
$outlookfolders            
}


Loop through the folders as we’ve already seen and create an object that has the path, storeid and entryid. Add the object to the collection and output the collection at the end of the function.



We’ll see how to use this collection in the revised clear-deletedmail function

PowerShell Cheat Sheet

This may be useful for people starting PowerShell. If you can’t remember what punctuation sign does what in PowerShell get a copy of this cheat sheet

http://blogs.lessthandot.com/index.php/DataMgmt/DBAdmin/a-cheat-sheet-for-all

Emptying the Deleted Items Folder

Continuing our look at scripting against Outlook & the hotmail connector

Many of the emails I get end up being read once and deleted. This leaves a ton of stuff in the deleted items folders. Periodically I’ll clean these up. This is one way how it can be accomplished.

function clear-deletedmail {            
            
$outlook = New-Object -ComObject Outlook.Application            
foreach ($folder in $outlook.Session.Folders){            
              
  foreach($mailfolder in $folder.Folders ) {            
    if ($mailfolder.Name -eq "Deleted Items" -and $mailfolder.Items.Count -gt 0){            
      foreach ($item in $mailfolder.Items){$item.Delete()}            
    }               
  }             
}            
}


All I’m doing is looping through my top level folders (email accounts) and for each of them finding a folder called Deleted Items.  If it has any content I will delete it.  Notice that the deletions have to occur on the item not at the folder level.



The contents of the folders can be tested using the function we saw earlier



get-mailitemcount | where {$_.Folder –like “Deleted*”}



A couple of notes on this function:



  1. Its inefficient iterating through all of the folders
  2. It doesn’t necessarily delete all of the items in one pass


The fix to this is use the get-mailitemcount function to test if we need to delete and keep calling the function until the folder is empty.  There is a way to access the folder directly that I will be testing next

Live Mesh Update

Couple of points worth noting if you are going to use Live Mesh

(1) File paths longer than 269 characters (folder paths > 248) won’t sync  - shorten the path to fix

(2) PST files won’t sync – even if they are not in use

 

By default Mesh wants to put the target folder into your Documents area.  The way round it is:

  1. On the source machine open Live Mesh select the folder to synchronise e.g.  c:\scripts
  2. On the target machine create c:\scripts
  3. Open Live Mesh on the target machine
  4. On the folder you want to sync select sync this folder
  5. Select the folder you just created

The synchonisation now happens to the folder you want rather than your profile area.

Otherwise it works as advertised

Outlook Connector & mail folder item count

On my home laptop I use Live Mail to aggregate my hotmail accounts. On my travelling netbook I decided to try the Outlook Connector

http://office.microsoft.com/en-us/outlook-help/microsoft-office-outlook-hotmail-connector-overview-HA010222518.aspx

This add in enables you to access hotmail accounts from Outlook & because I’m using Outlook 2010 I can have multiple mailboxes open at once.

This leads to some interesting PowerShell opportunities as having multiple mailboxes open means that some of the standard approaches won’t work – most scripts you see assume that you are connecting to an Exchange mailbox and that there is only one of them.

As an example consider getting a list of all of the mail folders and the number of items in each

function get-mailitemcount {            
Add-Type -Assembly Microsoft.Office.Interop.Outlook            
$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]            
            
$outlook = New-Object -ComObject Outlook.Application            
foreach ($folder in $outlook.Session.Folders){            
              
  foreach($mailfolder in $folder.Folders ) {            
               
    New-Object -TypeName PSObject -Property @{            
      Mailbox = $($folder.Name)            
      Folder = $($mailfolder.Name)            
      ItemCount = $($mailfolder.Items.Count)            
    } | select Mailbox, Folder, ItemCount            
  }             
}            
}


The first two lines add the interop assembly and create an object representing the default folders. If these are used directly all we get is the folders for the default (first) mailbox.



Create an object for the outlook application and iterate through the folders in the session – these are the individual mailboxes.



For each of those create an object and set the properties. The select ensures the object properties display in the order we need.



I used foreach instead of foreach-object so that I could use a variable rather than $_ as it would have confusing with nested foreachs



There is quite a bit to play with here and some very interesting PowerShell issues.

Live Mesh

One problem I’ve had for a while is how to keep my script library synchronised across a number of machines.  I have a laptop I use for my development work at home and I have two netbooks – at least one of which is always with my when I’m away from home.

I’ve tried using robocopy and keeping everything on a USB stick but it just doesn’t work.

Live Mesh may be the answer

http://explore.live.com/windows-live-mesh?os=other

I can designate folders to sync and they will sync, including subfolders, across all three machines. The sync is in both directions.

Good price point as well!

Not something to contemplate for the enterprise but a good solution for private use.

This doesn’t necessarily take away the need for a backup but it does reduce the pressure on backups as I can accept rebuilding the machine and re-installing software. Its the data I can’t afford to lose.

Network Adapter speed and duplex

One thing that can cause problems on the network is the duplex setting on the network adapter.  If this doesn’t match the switch port then at best you will get performance issues and at worst no connectivity.

The speed of the connection can be obtained from Win32_NetworkAdapter but for the duplex setting we need to go to the registry.

function test-duplex {            
[CmdletBinding()]            
param (            
 [string]$computer="."            
)            
BEGIN {            
 $HKLM = 2147483650            
 $reg = [wmiclass]"\\$computer\root\default:StdRegprov"            
 $keyroot = "SYSTEM\CurrentControlSet\Control\Class\{4D36E972-E325-11CE-BFC1-08002BE10318}"            
}            
            
PROCESS {            
            
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -ComputerName $computer -Filter "IPEnabled='$true'" |            
foreach {            
            
$data = $_.Caption -split "]"            
$suffix = $data[0].Substring(($data[0].length-4),4)            
$key = $keyroot + "\$suffix"            
            
$value = "*PhysicalMediaType"            
$pmt = $reg.GetDwordValue($HKLM, $key, $value)  ## REG_DWORD            
            
## 0=Unspecified, 9=Wireless, 14=Ethernet            
if ($pmt.uValue -eq 14){            
            
$nic = $_.GetRelated("Win32_NetworkAdapter") | select Speed, NetConnectionId            
            
$value = "*SpeedDuplex"            
$dup = $reg.GetStringValue($HKLM, $key, $value)  ## REG_SZ            
            
switch ($dup.sValue) {            
 "0" {$duplex = "Auto Detect"}            
 "1" {$duplex = "10Mbps \ Half Duplex"}            
 "2" {$duplex = "10Mbps \ Full Duplex"}            
 "3" {$duplex = "100Mbps \ Half Duplex"}            
 "4" {$duplex = "100Mbps \ Full Duplex"}            
}             
            
New-Object -TypeName PSObject -Property @{            
  NetworkConnector = $($nic.NetConnectionID )            
  DuplexSetting = $duplex            
  Speed = $($nic.Speed)            
}            
            
} #if            
} #foreach            
} #process            
} #function


Start by defining the information we need to read the registry



Get the Win32_NetworkAdapterConfiguration for those adapters that are IP enabled. We then test the physical media type and if its ethernet we get the duplex setting. The nework connectioid is retrieved to identify the card and an object is created to pull the output together

The New IT ?

A recent headline asked "How will you fit into the New IT?"


My answer is what new IT?


I have been working in IT for well over 20 years and in that time I can't remember a period when there wasn't a significant change coming:


  • introduction of PCs
  • growth of networks
  • Internet
  • Rise of Windows and fall of Novell
  • Token ring giving way to Ethernet
  • Viruses and other malware
  • Virtualisation

The so called new IT is the "cloud" and all its ramifications. We've been hosting applications elsewhere for years but all of a sudden its the only way to run your IT shop - at least according to the experts in the computer press. When was the last time one of these pundits actually worked in IT - if they ever did.


IT is constantly changing - if you don't realise that and can't live with it you shouldn't be in the industry. An IT professional's job is to work out which of the changes are beneficial to their organisation and which are a distraction.


No matter what the "experts" tell you there is no single answer that fits every organisation - pick whats needed and disregard the rest.


The only constant is change

Kindle for PC fix?

I appear to have fixed my problem. In the hope that this may help others in similar position this is what I did:


  1. uninstall Kindle for PC
  2. clean out all folders and content including the My Kindle Content folder. Make sure the C:\Users\Richard\username\Local\Amazon folder is deleted as well as C:\Program Files\Amazon
  3. clean out all registry keys related to Amazon/Kindle - I did a registry search on Amazon
  4. Shut down the machine. A restart does not seem to do the job - it needs to be a cold start
  5. Download the Kindle for PC application. Do not try and run it from the website
  6. Right click the application, select properties and Unblock.
  7. Right click application and select Troubleshoot compatibility
  8. select Try recommended settings
  9. click start program
  10. The install should work and allow you to register the installation
  11. Right click the icon you use to start Kindle and set compatibility to windows XP SP 2
  12. delete the content of the My Kindle content folder

It should now work. Once your content ahas re-synchronised you can remove the compatibility setting


I also found that downloading the installer and performing an install over the top of v1.5 seems to work OK.


Good luck. This is not a well behaved application and there is no excuse for having to go through these hoops especially as Amazon claim the application is compatible with Windows 7

Kindle for PC Update

Just checked my other two machines and they are running v1.5 with NO problem.  The latest version is 1.6.1 and that is the one showing a problem.

After removing all of the Kindle stuff including a registry I did get it to install and register.  It then starts to show the error at the second start.  Bah.

Come on Amazon you’ve bust it – its time you fixed it!