<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Rob's Rhapsody : Q&amp;amp;A</title><link>http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx</link><description>Tags: Q&amp;amp;A</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Macro of the Day: Send Email to [OutlookContact]</title><link>http://blogs.msdn.com/robch/archive/2008/06/09/macro-of-the-day-send-email-to-outlookcontact.aspx</link><pubDate>Mon, 09 Jun 2008 17:32:14 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8585898</guid><dc:creator>robch</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/robch/comments/8585898.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=8585898</wfw:commentRss><description>&lt;p&gt;Today's macro let's you say things like &amp;quot;Send email to Rob&amp;quot;, or &amp;quot;Send email to Rob Chambers&amp;quot;, and as long as I'm a contact in your Outlook Contacts, you can send me mail! It also allows you to say &amp;quot;Send email to Rob Chambers about That cool outlook macro&amp;quot;, it'll open up Outlook, create a new email, put me as the recipient, and it'll set the subject to &amp;quot;That cool outlook macro&amp;quot;. Neat, eh?&lt;/p&gt;  &lt;p&gt;Today's macro was inspired by Brad, over in the ms-speech Yahoo! Group, who asked me if WSR Macros could dynamically create rule content last week. Well, Brad, yes it can! Here's an example.&lt;/p&gt;  &lt;p&gt;The most interesting part of today's macro, is the ruleScript element that allows you to define a rule programmatically. The key to this script is that it will find content to add to the rule by hooking up to Outlook's object model (using Create Object(&amp;quot;Outlook.Application&amp;quot;)), and then call the Rule.Items.AddItem method for each email address it finds. &lt;/p&gt;  &lt;p&gt;That ruleScript looks like this:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&amp;#160; &amp;lt;ruleScript name=&amp;quot;OutlookContact&amp;quot; propname=&amp;quot;EmailAddr&amp;quot; language=&amp;quot;VBScript&amp;quot;&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Call AddOutlookContacts &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Sub AddOutlookContacts &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; REM Debug.DebugBreak     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace chr(13) &amp;amp; &amp;quot;Adding OutlookContacts...&amp;quot; &amp;amp; chr(13) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Const olFolderContacts = 10     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Const olMSG = 3 &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set objOutlook = CreateObject(&amp;quot;Outlook.Application&amp;quot;)     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set objNamespace = objOutlook.GetNamespace(&amp;quot;MAPI&amp;quot;) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set colContacts = objNamespace.GetDefaultFolder(olFolderContacts).Items &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For Each objContact in colContacts     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If TypeName(objContact) = &amp;quot;ContactItem&amp;quot; Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.FullName &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email1Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email1Address, True      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email2Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email2Address, True      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email3Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email3Address, True      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For Each objRuleItem in Rule.Items      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace objRuleItem.Phrase &amp;amp; &amp;quot; (&amp;quot; &amp;amp; objRuleItem.Property &amp;amp; &amp;quot;)&amp;quot; &amp;amp; chr(13)      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace &amp;quot;--&amp;quot; &amp;amp; chr(13) &amp;amp; &amp;quot;Added &amp;quot; &amp;amp; Rule.Items.Count &amp;amp; &amp;quot; items!&amp;quot; &amp;amp; chr(13) &lt;/p&gt;    &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Sub&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;      &lt;br /&gt;&amp;#160; &amp;lt;/ruleScript&amp;gt; &lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;There are a couple other interesting things in today's macro:&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;I used a Debug.DebugBreak method (currently commented out above), to allow me to debug the macro interactively in Microsoft Visual Studio Express. This is a handy way of single stepping over each and every line in the code. If you have VS installed, when the macro hits that line (if you uncomment it), you'll be asked what debugger to use to debug the macro's script. You pick VS, and then you have F10 single-step control over the macro as it executes. You can do fun things like inspect variables, change flow, etc... All really cool stuff that developers using Microsoft Development tools have grown accustomed to doing.&lt;/li&gt;    &lt;li&gt;I also used Debug.Trace to output to VS what's going on in the macro, so even if I'm not single step debugging it, I can see what contacts got added.&lt;/li&gt;    &lt;li&gt;I used the disambiguate tag to allow the user to disambiguate what email address to use if it's ambiguous. So, for example, if I have 3 people named Rob in my contacts, it'll allow me to pick which one I wanted to send email to. In fact, it'll even show me the email addresses in parenthesis after the person's full name.&lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;Here's the entire macro:&lt;/p&gt;  &lt;p&gt;&amp;lt;speechMacros&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;#160; &amp;lt;command priority=&amp;quot;2&amp;quot;&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;send email to [OutlookContact]&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;send email to [OutlookContact] about [subject...]&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;disambiguate title=&amp;quot;Send email to whom?&amp;quot; prompt=&amp;quot;Who would you like to send email to?&amp;quot; timeout=&amp;quot;30&amp;quot; propname=&amp;quot;OutlookContact&amp;quot;/&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;script language=&amp;quot;VBScript&amp;quot;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set outlookApp = CreateObject(&amp;quot;Outlook.Application&amp;quot;) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; olMailItem = 0   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set newMessage = outlookApp.CreateItem(olMailItem) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Recipients.Add(&amp;quot;{[OutlookContact.EmailAddr]}&amp;quot;)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Subject = &amp;quot;{[subject...]}&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Display    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;/command&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;#160; &amp;lt;command priority=&amp;quot;1&amp;quot;&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;send email&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;send email to *&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;send email to * about [subject...]&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;script language=&amp;quot;VBScript&amp;quot;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set contacts = CommandSet.RuleGenerators(&amp;quot;OutlookContact&amp;quot;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For Each item in contacts.Rule.Items    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ChooseFromList.Items.AddItem item.Phrase, item.Property, True    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ChooseFromList.Items.Sort    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; chose = ChooseFromList.Choose(&amp;quot;Send email to whom?&amp;quot;, &amp;quot;Who would you like to send email to?&amp;quot;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If chose &amp;gt; 0 Then    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set outlookApp = CreateObject(&amp;quot;Outlook.Application&amp;quot;) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; olMailItem = 0   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set newMessage = outlookApp.CreateItem(olMailItem)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Recipients.Add(ChooseFromList.Items(chose).Property)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Subject = &amp;quot;{[subject...]}&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; newMessage.Display    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;/command&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;command&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;Refresh ?Outlook Email Contacts&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;listenFor&amp;gt;Refresh Outlook ?Email Contacts&amp;lt;/listenFor&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;script language=&amp;quot;VBScript&amp;quot;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set contacts = CommandSet.RuleGenerators(&amp;quot;OutlookContact&amp;quot;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; contacts.Rule.Items.RemoveAll    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; contacts.Script.AddOutlookContacts    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; contacts.Rule.Commit    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/script&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;/command&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;#160; &amp;lt;ruleScript name=&amp;quot;OutlookContact&amp;quot; propname=&amp;quot;EmailAddr&amp;quot; language=&amp;quot;VBScript&amp;quot;&amp;gt;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;![CDATA[    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Call AddOutlookContacts &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Sub AddOutlookContacts &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; REM Debug.DebugBreak   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace chr(13) &amp;amp; &amp;quot;Adding OutlookContacts...&amp;quot; &amp;amp; chr(13) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Const olFolderContacts = 10   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Const olMSG = 3 &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set objOutlook = CreateObject(&amp;quot;Outlook.Application&amp;quot;)   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set objNamespace = objOutlook.GetNamespace(&amp;quot;MAPI&amp;quot;) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Set colContacts = objNamespace.GetDefaultFolder(olFolderContacts).Items &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For Each objContact in colContacts   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If TypeName(objContact) = &amp;quot;ContactItem&amp;quot; Then    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.FullName &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email1Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email1Address, True    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email2Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email2Address, True    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; If objContact.Email3Address &amp;lt;&amp;gt; &amp;quot;&amp;quot; Then Rule.Items.AddItem objContact.FullName, objContact.Email3Address, True    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End If    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; For Each objRuleItem in Rule.Items    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace objRuleItem.Phrase &amp;amp; &amp;quot; (&amp;quot; &amp;amp; objRuleItem.Property &amp;amp; &amp;quot;)&amp;quot; &amp;amp; chr(13)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Next    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Debug.Trace &amp;quot;--&amp;quot; &amp;amp; chr(13) &amp;amp; &amp;quot;Added &amp;quot; &amp;amp; Rule.Items.Count &amp;amp; &amp;quot; items!&amp;quot; &amp;amp; chr(13) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; End Sub&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ]]&amp;gt;    &lt;br /&gt;&amp;#160; &amp;lt;/ruleScript&amp;gt; &lt;/p&gt;  &lt;p&gt;&amp;lt;/speechMacros&amp;gt; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8585898" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category><category domain="http://blogs.msdn.com/robch/archive/tags/Macros/default.aspx">Macros</category></item><item><title>A new Microsoft Speech Blog</title><link>http://blogs.msdn.com/robch/archive/2007/09/04/a-new-microsoft-speech-blog.aspx</link><pubDate>Tue, 04 Sep 2007 18:16:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:4742604</guid><dc:creator>robch</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/robch/comments/4742604.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=4742604</wfw:commentRss><description>&lt;P&gt;The Speech Components Group (the team I work on) just created a new team blog for all things Speech @ Microsoft. &lt;/P&gt;
&lt;P&gt;This is the spot that people in my team that don't have their own blog will answer questions we get from the community, and where we'll let you all know about the neat new things our team is working on.&lt;/P&gt;
&lt;P&gt;Check it out: &lt;A href="http://blogs.msdn.com/speech/"&gt;http://blogs.msdn.com/speech/&lt;/A&gt;.&lt;/P&gt;
&lt;P&gt;In Mike's first &lt;A class="" href="http://blogs.msdn.com/speech/archive/2007/09/01/windows-speech-recognition-language-support-in-windows-vista.aspx" mce_href="http://blogs.msdn.com/speech/archive/2007/09/01/windows-speech-recognition-language-support-in-windows-vista.aspx"&gt;post&lt;/A&gt;, he talks about language support in Vista. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=4742604" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Windows Speech Recognition - ExactMatchOverPartialMatch</title><link>http://blogs.msdn.com/robch/archive/2007/05/07/windows-speech-recognition-exactmatchoverpartialmatch.aspx</link><pubDate>Mon, 07 May 2007 17:57:27 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2464291</guid><dc:creator>robch</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/robch/comments/2464291.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=2464291</wfw:commentRss><description>&lt;p&gt;A user wrote in over the weekend with a question about how to automatically choose an item when prompted with our clarification user interface in Windows Speech Recognition (WSR). But ... Before I answer that question, I have to give a little background.&lt;/p&gt; &lt;p&gt;&lt;strong&gt;What is our clarification user interface?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;When the recognizer hears the user say something ambiguous and we're not sure what to do, the system will ask the user for clarification (or confirmation). For example, if the user says "File" in an application that both has a "File" menu and a button somewhere that has the word "File" in it (like a toolbar button that is for creating&amp;nbsp;a "New File"), little numbers will fly out and hover over the two items on the screen. The user can then choose, "1", or "2", and then the user can say "OK". &lt;/p&gt; &lt;p&gt;This is related to the feature that David Pogue &lt;a href="http://blogs.msdn.com/robch/archive/2007/01/02/wsr-s-in-david-pogue-s-top-10-list.aspx"&gt;wrote up&lt;/a&gt; as one of 2006's top 10 features of the year. That feature treats everything as ambiguous when the user says "Show Numbers". &lt;/p&gt; &lt;p&gt;There is another form of the clarification user interface, as well, that we use for items that don't have an on screen representation, like applications to start. In this example, if the user says "Start Internet Explorer", the system sees that there are two possible matches, "Internet Explorer" and "Internet Explorer (no add-ins)". Since we're not 100% sure which one the user wanted, we'll ask the user to clarify. &lt;/p&gt; &lt;p&gt;&lt;strong&gt;How do I make it automatically pick?&lt;/strong&gt;&lt;/p&gt; &lt;p&gt;Well, in general, we can't automatically pick the right one because we still haven't perfected "brain wave recognition" yet. :-) But ... Seriously, though ... You can make it better.&lt;/p&gt; &lt;p&gt;There's a feature called ExactMatchOverPartialMatch. It's turned off by default, but you can turn it on by changing a value in the registry. If you're not comfortable changing the registry, don't do this. But if you are, here you go:&lt;/p&gt; &lt;p&gt;key = HKEY_CURRENT_USER\Software\Microsoft\Speech\Preferences&lt;br&gt;value name = ExactMatchOverPartialMatch&lt;br&gt;value type = DWORD&lt;br&gt;value = 1 (default is 0)&lt;/p&gt; &lt;p&gt;After changing this registry setting, you'll have to restart speech. Once that's done, now in the two examples I gave earlier ("File", and "Start Internet Explorer") no clarification user interface will be displayed, because there will be one and only one exact match. "File" == "File", and "Internet Explorer"=="Internet Explorer". &lt;/p&gt; &lt;p&gt;ExactMatchOverPartialMatch wont' solve all your problems, but it will make the system better for a lot of people. Try it out. &lt;a href="mailto:listen@microsoft.com?subject=ExactMatchOverPartialMatch"&gt;Let us know&lt;/a&gt; what you think. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2464291" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Features/default.aspx">Features</category><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>SpeechSaver -- kinda like a screen saver, but for speech recognition's listening state</title><link>http://blogs.msdn.com/robch/archive/2007/04/28/speechsaver-kinda-like-a-screen-saver-but-for-speech-recognition-s-listening-state.aspx</link><pubDate>Sat, 28 Apr 2007 20:33:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2313826</guid><dc:creator>robch</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/robch/comments/2313826.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=2313826</wfw:commentRss><description>&lt;P&gt;I was talking to a customer recently, Greg Duncan, and one of the things that he came up was an idea for a utility to automatically turn the speech recognition engine's state off after a certain amount of idle "speech" time. &lt;/P&gt;
&lt;P&gt;A couple emails later, this morning, Greg had already posted the full source code and a link to an installer for &lt;A class="" href="http://www.codeplex.com/speechsaver/Release/ProjectReleases.aspx?ReleaseId=3822" mce_href="http://www.codeplex.com/speechsaver/Release/ProjectReleases.aspx?ReleaseId=3822"&gt;SpeechSaver&lt;/A&gt;&amp;nbsp;on his &lt;A class="" href="http://coolthingoftheday.blogspot.com/" mce_href="http://coolthingoftheday.blogspot.com/"&gt;blog&lt;/A&gt;. I downloaded it, installed it, and checked it out. It does exactly what it's supposed to. &lt;/P&gt;
&lt;P&gt;Nice job, Greg.&lt;/P&gt;
&lt;P&gt;If you want a solution that automatically turns the microphone off after a set period of time of inactivity, you might want to check it out.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2313826" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Applications/default.aspx">Speech Applications</category><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Windows Speech Recognition in Vista: Dictation Everywhere</title><link>http://blogs.msdn.com/robch/archive/2007/04/23/windows-speech-recognition-in-vista-dictation-everywhere.aspx</link><pubDate>Mon, 23 Apr 2007 17:53:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:2247038</guid><dc:creator>robch</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/robch/comments/2247038.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=2247038</wfw:commentRss><description>&lt;P&gt;Here's a question from a reader about the Dictation Everywhere feature in Windows Speech Recognition in Windows Vista:&lt;/P&gt;
&lt;BLOCKQUOTE&gt;
&lt;P&gt;This feature is thus very important to me and my future as a PC user. 
&lt;P&gt;I have found that in many form fields (such as the one I'm using to send this message) dictation is impossible unless I switch to "Enable dictation everywhere" (otherwise I get "what was that?" messages). There is no short command for switching, and even in that mode I have to confirm every fragment of text I dictate with "one, ok." And then I have to switch out of that mode again for navigation. 
&lt;P&gt;It is very important to me that I find ways around this, or at least that a way around it will soon exist. Would you be so kind as to let me know how I can stay up to date with Vista SR improvements, and whom I can contact about its development? 
&lt;P&gt;Thank you very much for your time; I really appreciate your efforts to communicate to the public about Vista SR.&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;Now, for those of you that don't already know, Windows Speech Recognition allows users to dictate into any text field that supports a few &lt;A href="http://blogs.msdn.com/robch/archive/2005/08/08/448992.aspx" mce_href="http://blogs.msdn.com/robch/archive/2005/08/08/448992.aspx"&gt;standard platform APIs&lt;/A&gt;. These APIs (Application Programming Interfaces) are used by the speech recognition system, the handwriting recognition system, and input method editors for foreign languages. 
&lt;P&gt;However, some text fields in custom applications don't support what's needed. In those cases Windows Speech Recognition has a fall back input method. It's called Dictation Everywhere. You can turn it on by doing this: 
&lt;UL&gt;
&lt;LI&gt;Say, "Show Speech Options" 
&lt;LI&gt;Say, "Options" 
&lt;LI&gt;Say, "Dictation Everywhere"&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;That will toggle it on. Doing those three steps again will turn it off. 
&lt;P&gt;When Dictation Everywhere is turned on, we'll listen for the user to speak dictated text, even when they're not in an text field that doesn't support those APIs I mentioned. But ... Because the field doesn't support the right APIs, instead of just sticking the text in there, we're going to have a miniature correction experience with the user first. Otherwise, the user wouldn't be able to correct the text if there was a recognition error. 
&lt;P&gt;So ... If you're in one of those fields, use the three steps above to turn on dictation, then you can say, "Hello &amp;lt;period&amp;gt; This is a test &amp;lt;period&amp;gt;". The correction dialog will pop up and allow you to pick an alternative from the list. If you don't see what you really said, simple say it again. If you still don't see what you said, you can say "Spell it", and spell what you wanted. 
&lt;P&gt;This is the feature that the user was asking about. They'd like to be able to turn the command on and off easily by using a single voice command. 
&lt;P&gt;Unfortunately, since we don't have an end user feature either included directly into Vista at this time, nor do we offer one for download (yet!) for creating macros, end users can't really simulate the same impact of turning this feature on and off with a single voice command. 
&lt;P&gt;At least not easily... 
&lt;P&gt;If you're a programmer (or don't mind dabbling), you certainly could though. In fact, you can create a simple shell script that does this like this: 
&lt;BLOCKQUOTE&gt;
&lt;P&gt;set Recognizer = CreateObject("SAPI.SpSharedRecognizer") 
&lt;P&gt;Recognizer.EmulateRecognition ("show speech options")&lt;BR&gt;WScript.Sleep(1000)&lt;BR&gt;Recognizer.EmulateRecognition ("options")&lt;BR&gt;WScript.Sleep(1000)&lt;BR&gt;Recognizer.EmulateRecognition ("dictation everywhere") 
&lt;P&gt;set Recognizer = Nothing&lt;/P&gt;&lt;/BLOCKQUOTE&gt;
&lt;P&gt;When you run this it will connect to the shared recognizer that Windows Speech Recognition uses, it will pretend that the user spoke "show speech options", then wait for 1 second, then pretend that the user said "options", again wait for another 1 second, then again, pretend the user said "dictation everywhere". 
&lt;P&gt;In fact, you can even save this text as a file called "Dictation Everywhere Toggle.vbs" in your start folder (e.g. "c:\documents and settings\{your user name goes here}\start menu\dictation everywhere toggle.vbs") and you'll be able to say to Windows Speech Recognition, "Start Dictation Everywhere Toggle". &lt;/P&gt;
&lt;P&gt;Unfortunately, for all this to work, you actually have to turn &lt;A class="" href="http://blogs.msdn.com/robch/archive/2006/10/20/windows-speech-recognition-and-user-access-control.aspx" mce_href="http://blogs.msdn.com/robch/archive/2006/10/20/windows-speech-recognition-and-user-access-control.aspx"&gt;Access Control (UAC) off&lt;/A&gt;. Otherwise, the shell script can't communicate with the shared recognizer.&lt;/P&gt;
&lt;P&gt;In the future, though, we'll have a true end to end macro facility to deal with this in a secure way. Stay tuned for more info on that front... &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=2247038" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Features/default.aspx">Features</category><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Keeping speech grammars up-to-date</title><link>http://blogs.msdn.com/robch/archive/2007/03/29/keeping-speech-grammars-up-to-date.aspx</link><pubDate>Thu, 29 Mar 2007 20:24:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1989586</guid><dc:creator>robch</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/robch/comments/1989586.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=1989586</wfw:commentRss><description>&lt;P&gt;I've been having a good conversation with some guys that are working on making it easier to program by voice using Python. Their project is called "&lt;A class="" href="http://tech.groups.yahoo.com/group/voicecoder/" mce_href="http://tech.groups.yahoo.com/group/voicecoder/"&gt;VoiceCode&lt;/A&gt;" and they've been working on it for quite some time. Currently it only supports Dragon NaturallySpeaking as a speech recognizer, but I'm helping them to understand how easy it would be to port to Vista. &lt;/P&gt;
&lt;P&gt;One issue that came up recently was: How can they keep their grammars up to date if their grammars change based on what application is running, or what the title is in any given application. I was trying to describe to them in email how they could use the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms696160.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms696160.aspx"&gt;SetWinEventHook&lt;/A&gt; method, but I wasn't being as successful describing it to them as I wanted to... So ... I just wrote about 500 lines of code for them to show them.&lt;/P&gt;
&lt;P&gt;Then, I thought ... Hey, other people might want to see how to do this too. So I posted the code &lt;A class="" href="http://files.wsrguy.com/samples/Win32/ForegroundAppMonitor/ForegroundAppMonitor.cpp" mce_href="http://files.wsrguy.com/samples/Win32/ForegroundAppMonitor/ForegroundAppMonitor.cpp"&gt;here&lt;/A&gt;. Let me know if you have any questions!&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1989586" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Installing additional speech recognizer languages...</title><link>http://blogs.msdn.com/robch/archive/2007/02/20/installing-additional-speech-recognizer-languages.aspx</link><pubDate>Tue, 20 Feb 2007 18:57:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1727273</guid><dc:creator>robch</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/robch/comments/1727273.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=1727273</wfw:commentRss><description>&lt;P&gt;Here's a question that I get from time to time...&lt;/P&gt;
&lt;P&gt;Q: How do I install speech recognition for a language other than the language Windows Vista is running in?&lt;/P&gt;
&lt;P&gt;A: By installing a language pack. &lt;/P&gt;
&lt;P&gt;Language packs are &lt;EM&gt;the&lt;/EM&gt; Windows way of installing additional language support for features included in the OS. By default, when you install Windows Vista (or purchase a PC with Windows Vista already on it), it comes with a single language. &lt;/P&gt;
&lt;P&gt;In Windows Vista Enterprise and Windows Vista Ultimate, you can go to the control panel, search for "display language", and then click on the "Install or uninstall display languages" link.&lt;/P&gt;
&lt;P&gt;Follow the on-screen instructions, and in no time you'll have additional recognizer languages as long as it's a Windows Speech Recognition supported language. In Windows Vista we support&amp;nbsp;US English, UK English, German, French, Spanish, Japanese, Simplified Chinese, and Traditional Chinese.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1727273" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Transfering profiles programatically</title><link>http://blogs.msdn.com/robch/archive/2007/02/19/transfering-profiles-programatically.aspx</link><pubDate>Tue, 20 Feb 2007 08:28:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1722570</guid><dc:creator>robch</dc:creator><slash:comments>0</slash:comments><comments>http://blogs.msdn.com/robch/comments/1722570.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=1722570</wfw:commentRss><description>&lt;P&gt;Last week I wrote about how to &lt;A class="" href="http://blogs.msdn.com/robch/archive/2007/02/15/transferring-windows-speech-recognition-profiles-from-one-machine-to-another.aspx" mce_href="http://blogs.msdn.com/robch/archive/2007/02/15/transferring-windows-speech-recognition-profiles-from-one-machine-to-another.aspx"&gt;transfer profiles using the Easy Transfer Wizard&lt;/A&gt;. That generated some email and some questions in the community about how to do this programmatically.&lt;/P&gt;
&lt;P&gt;That's a good question. But unfortunately, the answer isn't that straight forward currently. &lt;/P&gt;
&lt;P&gt;In the &lt;A class="" href="http://blogs.msdn.com/robch/archive/2007/02/13/windows-speech-recognition-where-s-the-api-documentation.aspx" mce_href="http://blogs.msdn.com/robch/archive/2007/02/13/windows-speech-recognition-where-s-the-api-documentation.aspx"&gt;SAPI documentation&lt;/A&gt;&amp;nbsp;you can read about how some of this works, but there's not a single overview of how all this works. So ... I'll try to summarize how it works here.&lt;/P&gt;
&lt;P&gt;Here goes ...&lt;/P&gt;
&lt;P&gt;In SAPI, recognition profiles are accessed by the engine (and by the application) using the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms720150.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms720150.aspx"&gt;Resource interfaces&amp;nbsp;of SAPI&lt;/A&gt;. Specifically, the ISpObjectTokenCategory, IEnumSpObjectTokens, ISpObjectToken, and ISpDataKey interfaces. &lt;/P&gt;
&lt;P&gt;To get a list of recognition profiles configured by the user you can use the &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/ms717535.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/ms717535.aspx"&gt;SpEnumTokens&lt;/A&gt; helper function (defined in sphelper.h). You'll need to specify the category you want to enumerate. That's the SPCAT_RECOPROFILES category. This will give you an IEnumSpObjectTokens interface, which is a standard derivative of the IEnum* class of interfaces. Using this interface, you can iterate thru the individual "tokens" by calling IEnumSpObjectTokens::Next -- each of the ISpObjectTokens you get back will represent a single recognition profile. &lt;/P&gt;
&lt;P&gt;Given a specific token you can QueryInterface for the ISpObjectToken interface, which derives from ISpDataKey. Then you can ask for the name of the reco profile, by calling &lt;A class="" href="http://msdn2.microsoft.com/en-us/library/aa914233.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/aa914233.aspx"&gt;ISpDataKey::GetStringValue&lt;/A&gt;(NULL, &amp;amp;pszCoTaskMemAllocedProfileName). Be sure and call CoTaskFree on the string returned when you're done with it.&lt;/P&gt;
&lt;P&gt;To back up the profile, there are no special helpers, so you'll just have to do a few things the hard way. &lt;/P&gt;
&lt;P&gt;First, you should make a backup of the ISpDataKey settings. The easiest way to do this is to use the token's ID to open up the registry location directly. You see, typically the object token is simply a wrapper on top of registry access functions. The token ID is typically actually just nothing more than a path into the registry. For example, for my reco profile that I'm using right now, the token id (retrieved by calling &lt;A class="" href="http://search.msdn.microsoft.com/search/Redirect.aspx?title=ISpObjectToken%3a%3aGetID+(SAPI+5.3)+&amp;amp;url=http://msdn2.microsoft.com/en-gb/library/ms718244.aspx" mce_href="http://search.msdn.microsoft.com/search/Redirect.aspx?title=ISpObjectToken%3a%3aGetID+(SAPI+5.3)+&amp;amp;url=http://msdn2.microsoft.com/en-gb/library/ms718244.aspx"&gt;ISpObjectToken::GetID&lt;/A&gt;) is: "HKEY_CURRENT_USER\Software\Microsoft\Speech\RecoProfiles\Tokens\{90E13428-A7A5-419B-8034-EA6453E31906}"&lt;/P&gt;
&lt;P&gt;So, you'll have to write your own code to iterate thru the registry recursively and back up all the keys and values (with their names) that you find. &lt;/P&gt;
&lt;P&gt;There are a few special things that you have to take into consideration when doing this:&lt;/P&gt;
&lt;P&gt;1.) If the token id doesn't live directly under "HKEY_CURRENT_USER\Software\Microsoft\Speech\RecoProfiles\Tokens\", you shouldn't assume that the procedure I'm describing here will actually work to back up the recognition profile. If you see a token ID outside of this area, you should abort the backup.&lt;/P&gt;
&lt;P&gt;2.) While backing up the profile, you will encounter one or more key names called "Files". Under keys named "Files", the values represent "pointers" to files on disk. You'll have to also back up the files that these "file names" point to. &lt;/P&gt;
&lt;P&gt;3.) These files may start with character sequences that look like "%1c%\". If they do, you can replace the values between the percent signs with the text as returned from SHGetFolderPath. For example, one of that data files in my registry under a "Files" key has a "filename" of "%1c%\Microsoft\Speech\Files\TrainingAudio\SP_E18DB2EFB76A432B97889A3DB7210406.wav". The "%1c%" corresponds to a "real" filename of "C:\Documents and Settings\Rob\Local Settings\Application Data\Microsoft\Speech\Files\TrainingAudio\SP_E18DB2EFB76A432B97889A3DB7210406.wav". Again, you can use SHGetFolderPath with the hex value of 0x1c to get the path of "C:\Documents and Settings\Rob\Local Settings\Application Data" and you can put all this together.&lt;/P&gt;
&lt;P&gt;4.) When you restore the profile, you should take special care to restore files with different new filenames. If you don't, there could be some collisions. You can get a new filename by calling the ISpObjectToken::GetStorageFileName method. &lt;/P&gt;
&lt;P&gt;That's basically it.&lt;/P&gt;
&lt;P&gt;Yeah, I know... It's not necessarily the easiest thing you'll ever do, but it is possible, and this is basically how you do it. Hopefully, we'll be able to release an actual example that shows how a real end to end backup and restore works for profiles in the future. But until then, hopefully this post will illuminate some of the magic behind profile management in SAPI. &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1722570" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Customer+Feedback/default.aspx">Customer Feedback</category><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Transferring Windows Speech Recognition profiles from one machine to another</title><link>http://blogs.msdn.com/robch/archive/2007/02/15/transferring-windows-speech-recognition-profiles-from-one-machine-to-another.aspx</link><pubDate>Thu, 15 Feb 2007 18:26:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1684094</guid><dc:creator>robch</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/robch/comments/1684094.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=1684094</wfw:commentRss><description>&lt;P&gt;&lt;BR&gt;Today a customer wrote in and asked: "I was wondering if you knew if Vista stores its data files of a users speech pattern in such a way so it can be transferred to other computers; in particular if I was to re-install my operating system."&lt;/P&gt;
&lt;P&gt;Good question!&lt;/P&gt;
&lt;P&gt;The good news is that not only does Windows Speech Recognition (WSR) store the data files in just such a way, if you can actually use a feature in Windows Vista to do it for you automatically. The feature: the Windows Easy Transfer wizard. This wizard allows you to specify exactly what data you want to copy from one machine to another.&lt;/P&gt;
&lt;P&gt;To use the Windows Easy Transfer Wizard:&lt;BR&gt;1. Click Start&lt;BR&gt;2. Type "Easy Transfer" into the search box&lt;BR&gt;3. Click on "Windows Easy Transfer"&lt;BR&gt;4. Click "Next"&lt;BR&gt;5. Click "Start a new transfer"&lt;BR&gt;6. Click "My old computer"&lt;BR&gt;7. Pick a way to transfer the files (transfer cable, using a network, or removable media)&lt;BR&gt;8. Answer the specific questions about that mode of transfer&lt;BR&gt;9. Click "Advanced options" on the "What do you want to transfer" page&lt;BR&gt;10. Uncheck all the items in the list&lt;BR&gt;11. Expand the node in the tree that corresponds to your log on user name&lt;BR&gt;12. Expand the "Windows Settings" node&lt;BR&gt;13. Expand the "Sound and Speech Recognition" node&lt;BR&gt;14. Check the "Speech Recognition" node&lt;BR&gt;15. Click "Next"&lt;/P&gt;
&lt;P&gt;That's it... All your WSR profiles will be backed up/moved. &lt;/P&gt;
&lt;P&gt;Now, this isn't as easy as I'd like it to be for WSR users, and that's why I hope to update a tool on microsoft.com/downloads in the near future to make this 2-3 steps, instead of 15 steps... Stay tuned for more info!&lt;BR&gt;&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1684094" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Features/default.aspx">Features</category><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item><item><title>Windows Speech Recognition -- Where's the API documentation?!</title><link>http://blogs.msdn.com/robch/archive/2007/02/13/windows-speech-recognition-where-s-the-api-documentation.aspx</link><pubDate>Tue, 13 Feb 2007 22:19:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:1670722</guid><dc:creator>robch</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/robch/comments/1670722.aspx</comments><wfw:commentRss>http://blogs.msdn.com/robch/commentrss.aspx?PostID=1670722</wfw:commentRss><description>&lt;P&gt;I get a lot of email from customers every day. And some days I end up answering the same questions again and again. Don't get me wrong, I love hearing from customers, and I love enabling them to do great things with Microsoft products. &lt;/P&gt;
&lt;P&gt;The real problem isn't that customers ask questions ... it's that&amp;nbsp;the information that they need isn't always easily found. Well ... I'm hopeful that all this blogging is really going to help users. So I'm going to try an experiment and see how it works.&lt;/P&gt;
&lt;P&gt;I'm going to try and start answering customer questions by sending them a link to my blog. If the answer is not already on my blog, I'll put it there, and then send them the freshly coined link... Sound good?&lt;/P&gt;
&lt;P&gt;OK... So what's the first question that I get asked frequently? Well, it's probably not the most common question, but it's one near and dear to my heart as a platforms kind of guy... &lt;/P&gt;
&lt;P&gt;Q: Where can I find Speech API documentation?&lt;/P&gt;
&lt;P&gt;A: On MSDN of course. Try these different locations depending on how you want to call into the speech APIs:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;C# and managed code: &lt;A href="http://msdn2.microsoft.com/en-us/library/system.speech.recognition.aspx"&gt;http://msdn2.microsoft.com/en-us/library/system.speech.recognition.aspx&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;VB and automation clients: &lt;A href="http://msdn2.microsoft.com/en-us/library/ms720592.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms720592.aspx&lt;/A&gt;&lt;/LI&gt;
&lt;LI&gt;C++ and native code: &lt;A href="http://msdn2.microsoft.com/en-us/library/ms723627.aspx"&gt;http://msdn2.microsoft.com/en-us/library/ms723627.aspx&lt;/A&gt;&lt;/LI&gt;&lt;/UL&gt;
&lt;P&gt;Do you have a question? Send it in and I'll try to get it answered... &lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=1670722" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/robch/archive/tags/Speech+Recognition/default.aspx">Speech Recognition</category><category domain="http://blogs.msdn.com/robch/archive/tags/Development/default.aspx">Development</category><category domain="http://blogs.msdn.com/robch/archive/tags/Q_2600_amp_3B00_A/default.aspx">Q&amp;amp;A</category></item></channel></rss>