<?xml version='1.0' encoding='UTF-8'?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns='http://www.w3.org/2005/Atom' xmlns:openSearch='http://a9.com/-/spec/opensearchrss/1.0/' xmlns:georss='http://www.georss.org/georss' xmlns:gd='http://schemas.google.com/g/2005' xmlns:thr='http://purl.org/syndication/thread/1.0'><id>tag:blogger.com,1999:blog-7178802206594541796</id><updated>2012-01-29T12:01:50.006Z</updated><category term='Team'/><category term='Visual Studio'/><category term='Plugins'/><category term='Evaluation'/><category term='Approval workflow'/><category term='Download'/><category term='Greyed out'/><category term='HTTPS'/><category term='filter icon GridView display'/><category term='BizTalk'/><category term='Online'/><category term='US date format'/><category term='selected records'/><category term='Windows Server 2008 R2'/><category term='Dynamics CRM 4.0'/><category term='InfoPath 2007'/><category term='web service'/><category term='Integer division by zero'/><category term='List'/><category term='email'/><category term='Access Denied'/><category term='Windows Service'/><category term='remote server'/><category term='Dynamics CRM 2011'/><category term='Aspose'/><category term='Forms Services'/><category term='Disabled'/><category term='SharePoint 2007'/><category term='XSLT'/><category term='Security Token Service'/><category term='PDF'/><category term='Lynx'/><category term='Client for Outlook'/><category term='XML'/><category term='Enable'/><category term='SharePoint 2010'/><category term='Word'/><category term='darwin awards'/><category term='data connections'/><category term='WSS'/><category term='user'/><category term='K2 BlackPearl'/><category term='Custom Forms'/><category term='Date Picker'/><category term='permissions'/><category term='Failure'/><category term='annotation'/><category term='Upgrade'/><category term='Fetch XML Reports'/><category term='SourceSafe'/><category term='managed code'/><category term='SSRS'/><category term='Process'/><category term='Trial'/><category term='content type'/><category term='Add Organization'/><category term='error'/><category term='InfoPath'/><category term='attachments'/><category term='TMG'/><category term='attach'/><category term='Destination Node'/><category term='activity'/><category term='customize form'/><category term='Grayed Out'/><category term='posthumous'/><category term='file size'/><category term='Hiding Menu Items'/><category term='mailmerge'/><category term='Event Hamdler'/><category term='Integration'/><category term='Configuration'/><category term='BizTalk Server'/><category term='CRM 4.0'/><category term='drop'/><category term='Mapper'/><category term='Threat Management Gateway'/><category term='commands'/><category term='SMTP'/><category term='UDCX'/><category term='GAC'/><category term='browser'/><category term='saving'/><category term='telnet'/><category term='US Format'/><category term='Windows Azure'/><category term='SSL'/><category term='file'/><category term='Cloud'/><category term='Lists'/><category term='deploy'/><category term='CRM 2011'/><category term='Filtered'/><category term='Reports'/><category term='OrganizationService'/><category term='VSS'/><category term='Transformation'/><category term='deployment'/><category term='SharePoint'/><category term='MSMQ'/><category term='Transform'/><category term='WebDAV'/><category term='Dyamics CRM 2011'/><category term='BizTalk 2010'/><category term='Null'/><category term='Windows Live ID'/><category term='Custom Lists'/><category term='Federated Security'/><category term='KPRX'/><category term='SQL Server Reporting Services 2005'/><category term='invoice'/><category term='Install'/><category term='WCF'/><category term='Document Library'/><category term='My Photo'/><category term='Prefilter'/><category term='ownership'/><category term='Enterprise Single Sign-on'/><category term='SQL Server 2008 R2'/><category term='Invalid handle'/><category term='I-Frame'/><category term='format name'/><category term='Receive Location'/><category term='BizTalk Server 2010'/><title type='text'>No Intelligent Life</title><subtitle type='html'></subtitle><link rel='http://schemas.google.com/g/2005#feed' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/posts/default'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default?max-results=100'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/'/><link rel='hub' href='http://pubsubhubbub.appspot.com/'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><generator version='7.00' uri='http://www.blogger.com'>Blogger</generator><openSearch:totalResults>46</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>100</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6267090580321513306</id><published>2011-11-29T22:44:00.001Z</published><updated>2011-11-29T22:49:46.293Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk'/><category scheme='http://www.blogger.com/atom/ns#' term='Null'/><category scheme='http://www.blogger.com/atom/ns#' term='Destination Node'/><category scheme='http://www.blogger.com/atom/ns#' term='Transformation'/><title type='text'>How to create a null destination node in a BizTalk Map</title><content type='html'>This is the second time recently I came across this requirement so I guess others need it too. This post describes how to set a destintation node to null based upon a condition. &lt;br /&gt;&lt;br /&gt;My situation was the source node contained a DateTime which was either valid or set to a zero length string. As some of you will know setting a date to a zero length string will actually set the date to 0001-01-01.&amp;nbsp; That is the date when the world began, allegedly.&amp;nbsp;&amp;nbsp;My destination node is a date field too so I want to ignore the invalid date.&amp;nbsp; But here's the thing - I need to set the target node to null because I need&amp;nbsp;the node present&amp;nbsp;in the output. &lt;br /&gt;&lt;br /&gt;The solution is to use a logical operator (= or &amp;lt;&amp;gt;) and a value mapping functoid.&amp;nbsp; In my case I am using a Script functoid to convert the source node value from DateTime to Date.&amp;nbsp; So the Script output is a date string.&amp;nbsp; By the way if you are wondering why I just don't test for this in the Script and set the return parameter to null, its becasue this doesn't work!&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-FO-PAisDf8Q/TtVcfeBPivI/AAAAAAAAAFA/oRq5QA70QrA/s1600/BizTalkMap.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" dda="true" src="http://3.bp.blogspot.com/-FO-PAisDf8Q/TtVcfeBPivI/AAAAAAAAAFA/oRq5QA70QrA/s1600/BizTalkMap.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;The &amp;lt;&amp;gt; functoid checks if the output is 0001-01-01 and sends true or false to the Value Mapping Functoid. As you can see I added 0001-01-01 as a constant for the second parameter.&amp;nbsp; Remember this is a Not Equal operator so it will return &lt;strong&gt;true&lt;/strong&gt; if its a valid date and &lt;strong&gt;false&lt;/strong&gt; if it is 0001-01-01.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-VALlGaoXeMQ/TtVc0yVQF6I/AAAAAAAAAFI/pkkuhG3l0x8/s1600/BizTalkMap2.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" dda="true" height="320px" src="http://2.bp.blogspot.com/-VALlGaoXeMQ/TtVc0yVQF6I/AAAAAAAAAFI/pkkuhG3l0x8/s320/BizTalkMap2.jpg" width="251px" /&gt;&lt;/a&gt;&lt;/div&gt;The magic happens in the Value Flattening functoid.&amp;nbsp; The description explains what it does. If the value of the &lt;strong&gt;first&lt;/strong&gt; input parameter is &lt;strong&gt;true&lt;/strong&gt; then the value of the &lt;strong&gt;second&lt;/strong&gt; input parameter is returned.&amp;nbsp;&amp;nbsp;It should add&amp;nbsp;if the first input parameter is &lt;strong&gt;false&lt;/strong&gt;, then the destination node is set to &lt;strong&gt;null&lt;/strong&gt;.&amp;nbsp; &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-CxO5I6nc0VM/TtVc58a9t4I/AAAAAAAAAFQ/Ozuu4nZVHhs/s1600/BizTalkMap3.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" dda="true" height="320px" src="http://1.bp.blogspot.com/-CxO5I6nc0VM/TtVc58a9t4I/AAAAAAAAAFQ/Ozuu4nZVHhs/s320/BizTalkMap3.jpg" width="251px" /&gt;&lt;/a&gt;&lt;/div&gt;So all you have to do is select the correct logical operator (either = or &amp;lt;&amp;gt;) so that its output is true if you want to pass the value to the destination and false when you want to set it to null.&amp;nbsp; But be sure you have the parameters the right way round.&amp;nbsp; The logical operator needs to be at the top, the value of the source node is below.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6267090580321513306?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6267090580321513306/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6267090580321513306' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6267090580321513306'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6267090580321513306'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/11/how-to-create-null-destination-node-in.html' title='How to create a null destination node in a BizTalk Map'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-FO-PAisDf8Q/TtVcfeBPivI/AAAAAAAAAFA/oRq5QA70QrA/s72-c/BizTalkMap.jpg' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8911742097580448811</id><published>2011-11-19T16:30:00.002Z</published><updated>2011-11-19T16:48:11.393Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='US Format'/><category scheme='http://www.blogger.com/atom/ns#' term='Date Picker'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='SSRS'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>Dynamics CRM 2011 Date Picker Displays US format</title><content type='html'>This post will only help if you are using the On Premise version - I don't have a solution for the&amp;nbsp;Online version.&amp;nbsp;BTW, I was using SQL Server 2008 R2.&lt;br /&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none; clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-9m2ZOaT4j3k/TsfW1Bm70fI/AAAAAAAAAEo/ipPpCXk1em4/s1600/parameters.jpg" imageanchor="1" style="cssfloat: left; margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" src="http://4.bp.blogspot.com/-9m2ZOaT4j3k/TsfW1Bm70fI/AAAAAAAAAEo/ipPpCXk1em4/s1600/parameters.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;If&amp;nbsp; you add date parameters&amp;nbsp;to a report that you want to run in Dynamics CRM 2011 then you get prompted to enter the dates.&amp;nbsp;If you set the parameters as type DateTime then a date picker is also displayed.&lt;/div&gt;&lt;/div&gt;&lt;div class="separator" style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none; clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-pWq2-1C7RNQ/TsfbLTohqgI/AAAAAAAAAE4/SaBX5T9Fqzg/s1600/DateTime.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" height="261px" src="http://3.bp.blogspot.com/-pWq2-1C7RNQ/TsfbLTohqgI/AAAAAAAAAE4/SaBX5T9Fqzg/s320/DateTime.jpg" width="320px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;But when you select a date, the picker puts the date in as US format.&amp;nbsp; It will still filter the data correctly but I wanted UK format displayed.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The clue came from this &lt;a href="http://geekswithblogs.net/naijacoder/archive/2008/06/26/123422.aspx"&gt;blog&lt;/a&gt;.&amp;nbsp; Now in fact when I ran my&amp;nbsp;report in Report Server (i.e. outside CRM) the date format displays correctly.&lt;br /&gt;&lt;table style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;div style="border-bottom: medium none; border-left: medium none; border-right: medium none; border-top: medium none;"&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;So I finally found the solution. You need to add Culture="en-GB" to the reportviewer.aspx page located at C:\Program Files\Microsoft Dynamics CRM\CRMWeb\CRMReports\rsviewer.&amp;nbsp; Note its the &lt;strong&gt;rsviewer&lt;/strong&gt; directory not the viewer directory. I added it to&amp;nbsp;the end of the first line - the &amp;lt;%@ Page declaration.&amp;nbsp;&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Then the date displayed in UK format in CRM. &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-cAzC2KPdbaA/TsfZj_YrSMI/AAAAAAAAAEw/GfvhJGR6THU/s1600/Dateformat.jpg" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" src="http://1.bp.blogspot.com/-cAzC2KPdbaA/TsfZj_YrSMI/AAAAAAAAAEw/GfvhJGR6THU/s1600/Dateformat.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;img height="53px" src="http://4.bp.blogspot.com/-9m2ZOaT4j3k/TsfW1Bm70fI/AAAAAAAAAEo/ipPpCXk1em4/s1600/parameters.jpg" style="filter: alpha(opacity=30); left: 589px; mozopacity: 0.3; opacity: 0.3; position: absolute; top: 80px; visibility: hidden;" width="96px" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8911742097580448811?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8911742097580448811/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8911742097580448811' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8911742097580448811'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8911742097580448811'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/11/dynamics-crm-2011-date-picker-displays.html' title='Dynamics CRM 2011 Date Picker Displays US format'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/-9m2ZOaT4j3k/TsfW1Bm70fI/AAAAAAAAAEo/ipPpCXk1em4/s72-c/parameters.jpg' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-226158401105356333</id><published>2011-11-16T21:03:00.001Z</published><updated>2011-11-16T21:06:51.399Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='selected records'/><category scheme='http://www.blogger.com/atom/ns#' term='Prefilter'/><category scheme='http://www.blogger.com/atom/ns#' term='Filtered'/><category scheme='http://www.blogger.com/atom/ns#' term='Fetch XML Reports'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 2011'/><title type='text'>Filtered Fetch XML Reports for CRM 2011 On-line</title><content type='html'>I found very few blogs that explained how to create a Filtered Report for CRM 2011 using Fetch XML. My approach had been to use Advanced Find to create the Fetch XML and then copy and paste that into a Report in Business Intelligence Development Studio.&amp;nbsp; Now that works fine but when you publish the report to CRM it will only run on all records of the entity, it does not work on selected rows or on a single entity record.&amp;nbsp; The report just does not show&amp;nbsp;up as selectable&amp;nbsp;on the entity view of on the entity form.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The missing attributes are on the the entity element of the Fetch XML. &amp;nbsp;Mine is a custom entity called new_identifiedneed and so I need&amp;nbsp;to change &lt;br /&gt;&amp;lt;entity name="new_identifiedneed"&amp;gt;&lt;br /&gt;to&lt;br /&gt;&amp;lt;entity="new_identifiedneed" enableprefiltering="1" prefilterparametername="CRM_Filterednew_identifiedneed"&amp;gt;&lt;br /&gt;&lt;br /&gt;Now what is not made clear is that setting the correct &lt;strong&gt;prefilterparametername&lt;/strong&gt; is crucial. It needs to be the &lt;strong&gt;name of the Filtered View for the entity prefixed by CRM_&lt;/strong&gt;&amp;nbsp; (not CRMAF_ as for SQL based reports).&lt;br /&gt;&lt;br /&gt;If you do this on the query&amp;nbsp; you will find that it will automatically add a parameter to your dataset. When you run the Query you will get this prompt for the parameter.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-xngPGASd6qg/TsQhXNp2idI/AAAAAAAAAEQ/riZ7oHP41X4/s1600/Query+Parameter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" src="http://2.bp.blogspot.com/-xngPGASd6qg/TsQhXNp2idI/AAAAAAAAAEQ/riZ7oHP41X4/s1600/Query+Parameter.png" /&gt;&lt;/a&gt;&lt;/div&gt;Don't bother with entering a value, just click OK and you should get unfiltered results.&amp;nbsp; &lt;br /&gt;Check out the parameters on the DataSet which should look like this:&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://1.bp.blogspot.com/-19h53GreBPM/TsQgyQZvCxI/AAAAAAAAAEI/vvcVkcZd8b0/s1600/Dataset+parameter.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" height="121px" src="http://1.bp.blogspot.com/-19h53GreBPM/TsQgyQZvCxI/AAAAAAAAAEI/vvcVkcZd8b0/s320/Dataset+parameter.png" width="320px" /&gt;&lt;/a&gt;&lt;/div&gt;If that is present you're home free. Make the report look pretty, build it to create the rdl and then load it into CRM.&amp;nbsp; When you add the report be sure to set the Related Records (Identified Needs in my case) and select the Display in properties to include both the Form and the List. &lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-g6NFl2Cic7o/TsQi0-KQspI/AAAAAAAAAEY/i6C_kI_zLIw/s1600/ReportSettings.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" height="320px" src="http://4.bp.blogspot.com/-g6NFl2Cic7o/TsQi0-KQspI/AAAAAAAAAEY/i6C_kI_zLIw/s320/ReportSettings.png" width="319px" /&gt;&lt;/a&gt;&lt;/div&gt;Now go to the entity view and select on or more records. Click on the Run Report icon on the ribbon and you should see your report. When you run it on Selected Records you should see what you wanted.&amp;nbsp; The same applies when you open a form on a selected entity record.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://4.bp.blogspot.com/-AuCy1bMq4X0/TsQlIsEOIBI/AAAAAAAAAEg/zIzQfXxV0G4/s1600/Report+icon.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" hda="true" src="http://4.bp.blogspot.com/-AuCy1bMq4X0/TsQlIsEOIBI/AAAAAAAAAEg/zIzQfXxV0G4/s1600/Report+icon.png" /&gt;&lt;/a&gt;&lt;/div&gt;Happy Reporting!&lt;br /&gt;BTW I found this out by using the Report Wizard for ad hoc reports in CRM. It will not only create the appropriate Fetch XML but gives you an RDL file that you can open up and play with in Business Intelligence Development Studio.&amp;nbsp;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-226158401105356333?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/226158401105356333/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=226158401105356333' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/226158401105356333'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/226158401105356333'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/11/filtered-fetch-xml-reports-for-crm-2011.html' title='Filtered Fetch XML Reports for CRM 2011 On-line'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-xngPGASd6qg/TsQhXNp2idI/AAAAAAAAAEQ/riZ7oHP41X4/s72-c/Query+Parameter.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-4442452330356506543</id><published>2011-11-14T17:13:00.001Z</published><updated>2011-11-14T17:15:37.159Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuration'/><category scheme='http://www.blogger.com/atom/ns#' term='Enterprise Single Sign-on'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk 2010'/><title type='text'>Problems Configuring BizTalk 2010</title><content type='html'>I had two problems configuring BizTalk 2010 in a distributed environment I thought I would share.&amp;nbsp; The first was a problem on assigning the SSO Administrators group.&amp;nbsp; Since I was using a distributed environment I had to replace the local group name with the domain group name.&amp;nbsp; When I did so I got the warning icon with the detail. &lt;br /&gt;&lt;br /&gt;Failed to add the user 'Domain\btsadmin' to the domain group 'Domain\SSO Administrators'&lt;br /&gt;&lt;br /&gt;Now this user was already in the group and I was logged on as a Domain Admin so the message could not be correct. &lt;br /&gt;&lt;br /&gt;There are blogs that say you need to re-register SSOSQL.DLL that is located in C:\Program Files\Common Files\Enterprise Single Sign-On&amp;nbsp;&amp;nbsp; (and also in the sub-directory&amp;nbsp; \Win32) but I had done that.&amp;nbsp; The answer was: delete the existing entry and &lt;strong&gt;manually&lt;/strong&gt; type in the account name -DON'T click on the ellpises (...). Stupid error I know, but that fixes it.&lt;br /&gt;&lt;br /&gt;The second problem arose when configuring BAM.&amp;nbsp; I had installed the pre-requisites including SQLServer2005_NS_x64.MSI&amp;nbsp;as well as installing SQL Server 2008 R2 Integration Services &lt;strong&gt;locally&lt;/strong&gt; which is a requirement.&amp;nbsp; But I got the following error when applying the configuration&lt;br /&gt;&lt;br /&gt;Could not load file or assembly 'Microsoft.SqlServer.Instapi, Version=9.0.242.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The system cannot find the file specified.&lt;br /&gt;&lt;br /&gt;Sure enough, this DLL was not in the GAC, although the 10.0 one was there.&lt;br /&gt;Turns out you need to install the correct &lt;strong&gt;versions&lt;/strong&gt; of the MSIs - I had somehow managed to download the wrong ones.&amp;nbsp; They correct ones are:&lt;br /&gt;&lt;br /&gt;sqlncli_x64.msi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 6430KB&lt;br /&gt;SQLServer2005_NS_x64.msi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 3337KB&lt;br /&gt;SQLServer2005_XMO_x64.msi&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; 15066KB&lt;br /&gt;sqlxml.msi 06&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;12683KB&lt;br /&gt;&lt;br /&gt;They can be downloaded from &lt;a href="http://www.microsoft.com/download/en/details.aspx?displaylang=en&amp;amp;id=11988"&gt;here&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Aftr that, the configuration went smoothly&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-4442452330356506543?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/4442452330356506543/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=4442452330356506543' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4442452330356506543'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4442452330356506543'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/11/problems-configuring-biztalk-2010.html' title='Problems Configuring BizTalk 2010'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-585109678865511000</id><published>2011-10-09T12:57:00.003+01:00</published><updated>2011-10-09T13:04:51.655+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Add Organization'/><category scheme='http://www.blogger.com/atom/ns#' term='Client for Outlook'/><category scheme='http://www.blogger.com/atom/ns#' term='Dyamics CRM 2011'/><title type='text'>There is a problem communicating with the Microsoft Dynamics CRM Server</title><content type='html'>I was trying to configure the CRM Client for Outlook by adding an organization and I ran into this error.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://3.bp.blogspot.com/-jMr6QsQloD4/TpGNxG9rzpI/AAAAAAAAAD4/KLlJviOTY3A/s1600/CRMError.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="51px" kca="true" src="http://3.bp.blogspot.com/-jMr6QsQloD4/TpGNxG9rzpI/AAAAAAAAAD4/KLlJviOTY3A/s400/CRMError.png" width="400px" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;Now I had just deployed my customizations and I was able to access CRM using IE from the same client and could see all my customizations.&amp;nbsp; I didn't get any errors when importing or publishing the customizations.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;What I tried was to create a brand new organization with no customizations and I was able to add that organization to the Outlook client without problems.&amp;nbsp; So the issue was that there was something in the customizations that was causing an error only in the Outlook client.&amp;nbsp; After several days of effort we tracked it down to a site map customization.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;We had added a custom section under Workplace that had some links to a particular view of the Account entity.&amp;nbsp; BAD IDEA.&amp;nbsp; That won't work in the Outlook client. After removing the link I was able to connect to my organization without this error.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Some things you find out the hard way.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-585109678865511000?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/585109678865511000/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=585109678865511000' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/585109678865511000'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/585109678865511000'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/10/there-is-problem-communicating-with.html' title='There is a problem communicating with the Microsoft Dynamics CRM Server'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-jMr6QsQloD4/TpGNxG9rzpI/AAAAAAAAAD4/KLlJviOTY3A/s72-c/CRMError.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8965363153468601851</id><published>2011-09-10T20:16:00.003+01:00</published><updated>2011-09-10T20:29:25.760+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Security Token Service'/><category scheme='http://www.blogger.com/atom/ns#' term='Federated Security'/><category scheme='http://www.blogger.com/atom/ns#' term='WCF'/><title type='text'>Consume a WCF service that uses Federated Security</title><content type='html'>This post is not&amp;nbsp;about Active Directory Federated Security,&amp;nbsp;but it is about using&amp;nbsp;a custom&amp;nbsp;Security Token Service (STS) to create a token.&amp;nbsp; &amp;nbsp;I needed to connect to a third party web service that used Federated Security. Now they supported ADFS but I only needed to access using a single account and I really didn't want to set up ADFS just for that.&amp;nbsp; But&amp;nbsp;I could use&amp;nbsp;a custom&amp;nbsp;STS service to create the token and avoid all the infrastruture overhead of ADFS. &lt;br /&gt;&lt;br /&gt;Setup&amp;nbsp;begins with the third party sending me the url to their STS and a copy of the public key certificate&amp;nbsp;they will use to sign their token. I also need&amp;nbsp;to have the url to their web service I want to call.&lt;br /&gt;&lt;br /&gt;I'll say right away I'm no expert on this.&amp;nbsp;There are examples in the Windows Identity SDK and that is a good starting point.&amp;nbsp;The way it would work is my client application (a&amp;nbsp;&amp;nbsp;Windows Service) would call a local STS and pass it a username and password.&amp;nbsp; My STS would check the credentials and if OK issue a token. Now the token is signed and encrypted by&amp;nbsp;my X509 certificate so I have to get one of those to begin with.&amp;nbsp; I need to install my X509 certificate in the Personal&amp;nbsp; store of&amp;nbsp; the computer I run the code on. &lt;br /&gt;Start MMC, add the Certficate add-in and select the Local Computer. Navigate to the Personal node, and Certificates, right click and import my X509 certificate.&amp;nbsp;&amp;nbsp;Since I am running my Windows Service under the Network Service account I need to assign permissions.&amp;nbsp; On the Certificate, right click, select All Tasks then Manage Private key. On the Security tab, add &amp;nbsp;&amp;nbsp;Network Service and give it full permissions.&amp;nbsp;I can also add the thrid party's certificate here too - it is&amp;nbsp;imported into the Personal Certificate store in the same way but since they gave me the public key,&amp;nbsp;I don't need to bother with the permissions step (its not available anyway).&lt;br /&gt;&lt;br /&gt;I also need to send the public key of my certificate to the third party.&amp;nbsp; Right click on the certificate, select Export and choose the option to export the public key only.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Now the token issued by my STS contains a claim, in my case it is simply the role of Reader.&amp;nbsp; I then pass my token to the third party's STS. These guys will want to check the token is from me and they use the certificate I sent them to do so.&amp;nbsp; They check the claim, and if all is well issue me a token from their STS.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;I suppose I should validate their token with the certificate they sent me, but I'm not going to bother as I'm going to send it straight back to them when I call their web service.&amp;nbsp; &lt;br /&gt;When I look at the WSDL of their STS service I can see it is different from a typical WCF service because it has a section at the bottom which looks like this.&lt;br /&gt;&lt;br /&gt;&amp;lt;identity xmlns="http://schemas.xmlsoap.org/ws/2006/02/addressingidentity"&amp;gt;&lt;br /&gt;&amp;lt;keyinfo xmlns="http://www.w3.org/2000/09/xmldsig#"&amp;gt;&lt;br /&gt;&amp;lt;x509data&amp;gt;&lt;br /&gt;&amp;lt;x509certificate&amp;gt;MIIE8zCCA9ugAwIBAgILAQAAAAABLl3i0lAwDQYwSQY2ZNWvOf2k&amp;lt;/x509certificate&amp;gt; &amp;lt;x509data&amp;gt;&lt;br /&gt;&amp;lt;/keyinfo&amp;gt;&lt;br /&gt;&amp;lt;/identity&amp;gt;&lt;br /&gt;&lt;br /&gt;The trick is to find a way to send my token to their&amp;nbsp;WCF web&amp;nbsp;service.&amp;nbsp;Add a Service Reference to their WCF web service in the usual way.&amp;nbsp;My example uses&lt;span style="font-family: inherit;"&gt; MyWS.Service with the url of &lt;/span&gt;&lt;span style="font-family: inherit;"&gt;http://company.co.uk/service.svc&lt;/span&gt;&lt;span style="font-family: inherit;"&gt;.&amp;nbsp; Note that when I setup the binding to this WCF service I have to include a reference to the issuer of the token (the url to their STS). I also needed to include a reference to the DNS identity.&amp;nbsp; You can usually assume the DNS Identity from the Subject name on the third party certificate so if that &lt;/span&gt;&lt;span style="font-family: inherit;"&gt;is CN=company.co.uk then the DNS Identity will be company.co.uk.&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// add constants for their STS service and DNS identity&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;public const string ServiceAddress = "http://company.co.uk/service.svc";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;public const string DNSIdentity = "company.co.uk";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;public const string STSAddress = "http://security.company.co.uk/security.svc";&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;/span&gt;&amp;nbsp;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;public void RetrieveData(SecurityToken smToken)&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; // Instantiate the ChannelFactory as usual.&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; //Be sure to set the DNS Identity on the Endpoint&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; EndpointAddress endpointAddress = new EndpointAddress(new Uri(ServiceAddress), new DnsEndpointIdentity(DNSIdentity), new AddressHeaderCollection());&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; ChannelFactory&lt;myws.service&gt; clientFactory = new ChannelFactory&lt;myws.service&gt;(GetServiceBinding(ServiceAddress), endpointAddress);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; clientFactory.Credentials.SupportInteractive = false;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;// Make sure to call this prior to using the&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;//CreateChannelWith...()&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; // extension methods on the channel factory that the Windows &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; //Identity Foundation provides.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;clientFactory.ConfigureChannelFactory();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; ICommunicationObject channel = null;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; bool succeeded = false;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; try&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; { // create an instance of the Pension Service client&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyWS.Service client = clientFactory.CreateChannelWithIssuedToken(smToken);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; channel = (ICommunicationObject)client;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Now its plain sailing&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // I can call the method on the WCF service&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // in may case GetData returns an array of objects&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MyWS.MyObject[] psArray = client.GetData();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //&amp;nbsp;TO DO something with psArray&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; channel.Close();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; succeeded = true;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; catch (CommunicationException e)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; // TO DO log error&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; channel.Abort();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; catch (TimeoutException)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp; // TO DO log error&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; channel.Abort();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; finally&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (!succeeded &amp;amp;&amp;amp; channel != null)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; channel.Abort();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; return ;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;public Binding GetServiceBinding(string uri)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{ &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; // Use the standard WS2007FederationHttpBinding&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; WS2007FederationHttpBinding binding = new&amp;nbsp;WS2007FederationHttpBinding();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; binding.Security.Message.IssuerAddress = new EndpointAddress(STSAddress);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; binding.Security.Message.IssuerBinding = GetSMSecurityTokenServiceBinding(STSAddress);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; binding.Security.Message.IssuerMetadataAddress = new&amp;nbsp;EndpointAddress(STSAddress + "/mex");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; return binding;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Good luck.&amp;nbsp;In terms of difficulty on a scale of 1-10 this is a twelve. I wish you success.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8965363153468601851?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8965363153468601851/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8965363153468601851' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8965363153468601851'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8965363153468601851'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/09/consume-wcf-service-that-uses-federated.html' title='Consume a WCF service that uses Federated Security'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-4379898788160376615</id><published>2011-09-10T18:06:00.001+01:00</published><updated>2011-11-18T16:39:25.037Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='attach'/><category scheme='http://www.blogger.com/atom/ns#' term='Visual Studio'/><category scheme='http://www.blogger.com/atom/ns#' term='Greyed out'/><category scheme='http://www.blogger.com/atom/ns#' term='Grayed Out'/><category scheme='http://www.blogger.com/atom/ns#' term='Process'/><category scheme='http://www.blogger.com/atom/ns#' term='Disabled'/><title type='text'>Attach to Process is Greyed Out in Visual Studio</title><content type='html'>If you Google "Attach to Process is greyed out" as I have, all the responses will tell you to make sure you check the boxes "Show processs from all users" and "Show processs in all sessions".&lt;br /&gt;&lt;br /&gt;What if you do that and it's still greyed out?&lt;br /&gt;&lt;br /&gt;Answer: Use a different approach. Add the line&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;System.Diagnostics.Debugger.Launch();&lt;/span&gt;&lt;br /&gt;to your code and it will launch the dialog box which allows you to connect to a new Visual Studio session or an existing one. &lt;br /&gt;&lt;br /&gt;Once you do so, the debugger will stop at the line you just added and allow you to step through the code.&lt;br /&gt;&lt;br /&gt;Tip: If you are using a timer in your windows service then disable the timer before you call the debugger. That way you stop the timer from kicking you back to the start every time it fires.&lt;br /&gt;&lt;br /&gt;For example:&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;timer1.Dispose();&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;System.Diagnostics.Debugger.Launch();&lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-4379898788160376615?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/4379898788160376615/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=4379898788160376615' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4379898788160376615'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4379898788160376615'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/09/attach-to-process-is-greyed-out.html' title='Attach to Process is Greyed Out in Visual Studio'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-9092248750659289196</id><published>2011-09-10T18:05:00.001+01:00</published><updated>2011-09-10T18:07:14.753+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Install'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Service'/><title type='text'>Installing a Windows Service</title><content type='html'>There was a time when you could just create a new project in Visual Studio as a Windows Service and you could install it using the installutil command. &lt;br /&gt;&lt;br /&gt;Somewhere along the way that changed so now you have to add a Project Installer class to the Windows Service. &lt;br /&gt;&lt;br /&gt;So lets assume you've created your windows service and changed the name from Service1 to say MyService. Microsoft explain the steps for adding an installer and I repeat them here. &lt;br /&gt;&lt;br /&gt;1. In Solution Explorer, access Design view for the service for which you want to add an installation component. &lt;br /&gt;&lt;br /&gt;2. Click the background of the designer to select the service itself, rather than any of its contents.&lt;br /&gt;&lt;br /&gt;3. With the designer in focus, right-click, and then click Add Installer. &lt;br /&gt;&lt;br /&gt;4. A new class, ProjectInstaller, and two installation components, ServiceProcessInstaller and ServiceInstaller, are added to your project, and property values for the service are copied to the components. &lt;br /&gt;&lt;br /&gt;5. Click the ServiceInstaller component and &lt;b&gt;verify that the value of the ServiceName property is set to the same value as the ServiceName property on the service itself&lt;/b&gt;. In my example you would have to change &lt;b&gt;Service1 &lt;/b&gt;to &lt;b&gt;MyService&lt;/b&gt;. &lt;br /&gt;&lt;br /&gt;6. Change the StartType to Manual, Automatic or Disabled.&lt;br /&gt;&lt;br /&gt;7. Click on the ServiceProcesInstaller and set the User property to Local serice, Network Service, System or User. &lt;br /&gt;&lt;br /&gt;That's it. Open the Visual Studio command prompt using "Run as Administrator", chage to the directory where your EXE file is and run &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;installutil MyWindowsService.exe&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;You might be interested in my next &lt;a href="http://charlesemes.blogspot.com/2011/09/attach-to-process-is-greyed-out.html"&gt;post&lt;/a&gt;&amp;nbsp;about debugging a Windows Service. Frankly I find debugging Windows Services a pain, so I tend to write and test my code as a Console Application, and then I convert it to a Windows Service when its all working.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-9092248750659289196?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/9092248750659289196/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=9092248750659289196' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/9092248750659289196'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/9092248750659289196'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/09/installing-windows-service.html' title='Installing a Windows Service'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-3243859448026290369</id><published>2011-08-21T12:11:00.003+01:00</published><updated>2011-08-21T12:25:01.243+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='attachments'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='annotation'/><title type='text'>Moving CRM Attachments to SharePoint</title><content type='html'>CRM 2011 allows you to store documents in SharePoint and view them from within CRM.&amp;nbsp; Someone called Maria left me a comment asking if you could move attachments from CRM to SharePoint. My previous blogs about creating SharePoint document locations from CRM were actually prerequisites for doing exactly this.&amp;nbsp; I wanted to take a CRM attachment and move it to SharePoint. In my case it was an attachment on a letter activity as the result of a mailmerge.&amp;nbsp;To be accurate it is an attachment on an annotation (or note) on a letter activity.&amp;nbsp;I needed to move the attachment to SharePoint and then leave a link to the document on the letter activity.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;To achieve this we created a plugin on the PreCreate action of an annotation.&amp;nbsp; Then in the execute method of the plugin&amp;nbsp;you can instantiate the annotation entity&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;if (null != context &amp;amp;&amp;amp; null != context.InputParameters)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;if (context.InputParameters.Contains("Target") &amp;amp;&amp;amp;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; context.InputParameters["Target"] is Entity)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // Obtain the target entity from the input parmameters.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;Entity entity = (Entity)context.InputParameters["Target"];&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;}&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Once you have the annotation then you can get the contents of the attachment as a byte array.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// Retrieve the base64Encoding document body &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// and convert it to byte&amp;nbsp;&lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;base64encoding &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// see below for the DecodeFrom64 function&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;byte[] documentBody = DecodeFrom64(entity.Attributes["documentbody"].ToString());&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;// get the filename&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;System.IO.FileInfo annotationFileInfo = new System.IO.FileInfo(fileName);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To remove the attachment you need to use this code&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;entity.Attributes["documentbody"] = null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;entity.Attributes["filename"] = null;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;entity.Attributes["filesize"] = null;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The helper method for decoding the attachment to a byte array&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;internal static byte[] DecodeFrom64(string encodedData)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; byte[] encodedDataAsBytes &lt;/span&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;= System.Convert.FromBase64String(encodedData);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp; return encodedDataAsBytes;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;To&amp;nbsp;upload the document to SharePoint you should use the CopyIntoItems method of the Copy web service located at http://sharepointurl&lt;sharepointurl&gt;/_vti_bin/Copy.asmx.&amp;nbsp; But before you do, you need to replace any illegal characters in the filename - in our case we replaced an illegal character with a hyphen.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;internal static string ReplaceSpecialCharacters(string input)&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;{&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Regex r = new Regex("(?:[^a-z0-9 ]|(?&amp;lt;=['\"])s)",&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; RegexOptions.IgnoreCase | RegexOptions.CultureInvariant |&amp;nbsp;&amp;nbsp; RegexOptions.Compiled);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return r.Replace(input, "-");&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: &amp;quot;Courier New&amp;quot;, Courier, monospace;"&gt;}&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: Courier New;"&gt;&lt;span style="font-family: Times, &amp;quot;Times New Roman&amp;quot;, serif;"&gt;I may have posted this&amp;nbsp;code too late to help Maria, but I hope someone else finds it useful.&lt;/span&gt;&amp;nbsp; &lt;/span&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-3243859448026290369?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/3243859448026290369/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=3243859448026290369' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3243859448026290369'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3243859448026290369'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/08/moving-crm-attachments-to-sharepoint.html' title='Moving CRM Attachments to SharePoint'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-3884182236291105074</id><published>2011-08-21T11:21:00.000+01:00</published><updated>2011-08-21T11:21:01.832+01:00</updated><title type='text'>Same blog, different theme</title><content type='html'>I've grown bored of the theme that I use for the blog and somebody posted a comment about changing the theme so I've done so.&lt;br /&gt;&lt;br /&gt;I hope this makes the blogs easier to read.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-3884182236291105074?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/3884182236291105074/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=3884182236291105074' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3884182236291105074'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3884182236291105074'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/08/same-blog-different-theme.html' title='Same blog, different theme'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6668001741198316960</id><published>2011-07-04T22:34:00.005+01:00</published><updated>2011-08-21T12:37:22.685+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Mapper'/><category scheme='http://www.blogger.com/atom/ns#' term='Transform'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='XSLT'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk Server'/><title type='text'>Transforming XML using BizTalk Mapper generated XSLT</title><content type='html'>If I have to write XSLT I try and make use of the BizTalk Mapper because it can generate XSLT in a fraction of the time.&amp;nbsp; It also supplies a test harness so you can use an input file to test out your map.&lt;br /&gt;You can add functoids to your map and I make use of the Scripting functoid so that I can write inline C# script.&amp;nbsp; Here is an example of a function that takes a string source element and will truncate it if it is longer than the string length the target element can handle.&amp;nbsp; It writes out an Information message to the event log if the maximum length is exceeded.&lt;br /&gt;The function takes two extra parameters apart from the source element:&amp;nbsp; the name of the source element and the maximum length.&amp;nbsp; Add them by clicking on the ellipses next to Configure Functoid Inputs.&lt;br /&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="http://2.bp.blogspot.com/-fVHapgKrTB4/ThIutrxY-aI/AAAAAAAAAC8/BTe69QSe_ak/s1600/truncateFunctoid.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" height="320px" i$="true" src="http://2.bp.blogspot.com/-fVHapgKrTB4/ThIutrxY-aI/AAAAAAAAAC8/BTe69QSe_ak/s320/truncateFunctoid.png" width="251px" /&gt;&lt;/a&gt;&lt;/div&gt;Here is the inline C# script.&lt;br /&gt;public string Transform(string param1, string fieldname, int32 maxlength)&lt;br /&gt;{&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; if (param1.Length&amp;nbsp;&amp;gt; maxlength)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; System.Diagnostics.EventLog.WriteEntry("Transformation", fieldname + " in excess of " +&amp;nbsp;&amp;nbsp; maxlength.ToString() + " chars, truncating", System.Diagnostics.EventLogEntryType.Warning);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;return param1.Substring(0, 20);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; else&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; {&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; return param1;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;What BizTalk does is to write this out as a function at the botton of the XSLT.&amp;nbsp; To produce the XSLT, use Validate Map and then navigate to where the output window has written the file.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Now I struggled a bit to get this XSLT to work until I finally found the answer was to use an XPathDocument instead of an XmlDocument.&amp;nbsp;That's it. A transformation using the output from the BizTalk Mapper.&amp;nbsp; Deep, deep joy.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Add the following using statements&lt;br /&gt;using System.Xml;&lt;br /&gt;using System.Xml.Xpath;&lt;br /&gt;using System.Xml.Xslt;&lt;br /&gt;&lt;br /&gt;// Transforms an XML document &lt;br /&gt;// using an XSLT generated by BizTalk&lt;br /&gt;// note use of XPathDocument&lt;br /&gt;private XmlDocument Transform()&lt;br /&gt;{&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XslCompiledTransform xslt = new XslCompiledTransform();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp; // load the xslt&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;xslt.Load(@"C:\Projects\Import\MySchema.xsl", new XsltSettings(false, true), new XmlUrlResolver());&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;string filePathName = @"C:\Projects\Import\MyXML.xml";&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Load the XML data file.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; XPathDocument doc1 = new XPathDocument(filePathName);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; // create a memory stream&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; MemoryStream ms = new MemoryStream();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Create an XmlTextWriter to write to the memory stream &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; XmlTextWriter writer = new XmlTextWriter(ms, Encoding.Unicode);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; writer.Formatting = Formatting.Indented;&lt;br /&gt;&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; //Transform the file.&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; xslt.Transform(doc1, null, writer, null);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; ms.Seek(0, SeekOrigin.Begin);&amp;nbsp; // ** UPDATE changed from ms.Position=0 ****//&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; &amp;nbsp;if (ms.Length == 0)&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; Exception ex = new Exception ("Transform error , output is null");&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; throw ex;&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;}&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;// load the memory stream into a XML document&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; XmlDocument output = new XmlDocument();&lt;br /&gt;&amp;nbsp;&amp;nbsp; &amp;nbsp;output.Load(ms);&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; writer.Close();&lt;br /&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; return output;&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6668001741198316960?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6668001741198316960/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6668001741198316960' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6668001741198316960'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6668001741198316960'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/07/transforming-xml-using-biztalk-mapper.html' title='Transforming XML using BizTalk Mapper generated XSLT'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/-fVHapgKrTB4/ThIutrxY-aI/AAAAAAAAAC8/BTe69QSe_ak/s72-c/truncateFunctoid.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7465014480512409838</id><published>2011-04-04T20:17:00.002+01:00</published><updated>2011-04-04T20:21:44.905+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='darwin awards'/><category scheme='http://www.blogger.com/atom/ns#' term='posthumous'/><title type='text'>Darwin Awards 2010</title><content type='html'>A non-technical blog this month, dear reader, forced upon me because of a misleading blog I read today. Imagine that! What is the Internet coming too when you can't trust a blog? &lt;br /&gt;&lt;br /&gt;Anyway, I&amp;nbsp;Googled for the "Darwin Awards 2010" and stumbled on a &lt;a href="http://www.uk-muscle.co.uk/general-conversation/126589-darwin-awards-2011-a.html"&gt;blog&lt;/a&gt; that claimed to announce the Darwin Awards results for 2010. While some of the alleged awards were amusing - I particularly liked the guy who tried to siphon off diesel from a camper van but mistakenly put the hose into the sceptic tank - they were clearly not true Darwin Awards.&amp;nbsp; I need scarcely remind you dear reader that the Darwin Awards "commemorate those who improve our gene pool by removing themselves from it". In short, they are only ever awarded posthumously for unparalleled stupidity.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The real Darwin Awards web site can be found at this &lt;a href="http://darwinawards.com/darwin/darwin2010-08.html"&gt;location&lt;/a&gt;&amp;nbsp;so please don't confuse it with imitations. &lt;br /&gt;&lt;br /&gt;For reasons of good taste, I won't reproduce the winning entry here.&amp;nbsp; However I do recount this runner up which unfortunately has not been confirmed as true. &lt;br /&gt;&lt;br /&gt;In the late fall and early winter months, snow-covered mountains become infested with hunters. One ambitious pair climbed high up a mountain in search of their quarry. The trail crossed a small glacier that had crusted over. The lead hunter had to stomp a foot-hold in the snow, one step at a time, in order to cross the glacier. &lt;br /&gt;&lt;br /&gt;Somewhere near the middle of the glacier, his next stomp hit not snow but a rock. The lead hunter lost his footing and fell. Down the crusty glacier he zipped, off the edge and out of sight. &lt;br /&gt;&lt;br /&gt;Unable to help, his companion watched him slide away. After a while, he shouted out, "Are you OK?" &lt;br /&gt;&lt;br /&gt;"Yes!" came the answer. &lt;br /&gt;&lt;br /&gt;Reasoning that it was a quick way off the glacier, the second hunter plopped down and accelerated down the ice, following his friend. There, just over the edge of the glacier, was his friend...holding onto the top of a tree that barely protruded from the snow.&lt;br /&gt;&lt;br /&gt;There were no other treetops nearby, nothing to grab, nothing but a hundred-foot drop onto the rocks below. As the second hunter shot past the first, he uttered his final epitaph: a single word, which we may not utter lest our mothers soap our mouths.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7465014480512409838?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7465014480512409838/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7465014480512409838' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7465014480512409838'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7465014480512409838'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/04/darwin-awards-2010.html' title='Darwin Awards 2010'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-5268578372810745906</id><published>2011-03-07T15:11:00.000Z</published><updated>2011-03-07T15:11:25.529Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='Plugins'/><category scheme='http://www.blogger.com/atom/ns#' term='Integration'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Azure'/><title type='text'>Windows Azure AppFabric and Integration with CRM 2011 Online</title><content type='html'>This post describes how to send messages in real time from CRM 2011 Online back to a company premises&amp;nbsp;using Windows Azure.&amp;nbsp; If you were using CRM 2011 On Premise you would use a plug-in and attach it to the create or update event of an entity.&amp;nbsp; The plug-in code might write out&amp;nbsp;the mesage in XML format for integration with an internal system.&amp;nbsp; So how do you do this with CRM 2011 Online? The answer is to use the Windows Azure AppFabric because there is built in support for this in CRM 2011 Online.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Basically what you need to do is create a Service Bus on Windows Azure and then create a namespace.&amp;nbsp; So you need to go through the steps of creating a Windows Azure account and set up a unique namespace.&amp;nbsp; That will generate a "Current Management Key" whic you will need when you register the endpoint in the Plugin-tool.&amp;nbsp; This &lt;a href="http://www.mindthecloud.net/?p=244"&gt;post&lt;/a&gt; has a good description on how to do it.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;You need to log into CRM Online and dowlnload the certificate that you need for the Plugin. Goto Settings -&amp;gt; Customizations -&amp;gt; Developer Resources and select download certificate. Make a note of the Issuer name directly above the link (e.g. crm4.dynamics.com).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Back in your development environment you will need to ensure you have the Windows Azure SDK and CRM 2011 SDK installed. You can use the sample code provided in the CRM SDK located at C:\CRMSDK\sdk\samplecode\cs\azure\onewaylistener.&amp;nbsp;&amp;nbsp; This is the application that will listen for messages that are sent to the Azure endpoint.&amp;nbsp; The class implements IServiceEndpointPlugin and the class name serves as your "Contract" (you will use it&amp;nbsp;as the "Path"&amp;nbsp;&amp;nbsp;when you configure the endpoint).&lt;br /&gt;&lt;br /&gt;Open the CRM Plugin tool and configure a Service EndPoint.&amp;nbsp; This &lt;a href="http://www.mindthecloud.net/?p=244"&gt;post&lt;/a&gt; describes how to configure the Service Endpoint. The Solution Namespace is the same as the namespace you created in Azure.&amp;nbsp; The Path is where you enter the class name of your listener application.&amp;nbsp; Click Save and Configure ACS. You will be prompted for the location of the certificate and the issuer name. You are also prompted for the Management Key and this is current Management Key from the Windows Azure namespace.&amp;nbsp; Click on "Save and verify authentication" which should verify the connection with a success message.&amp;nbsp; Click on "Close".&amp;nbsp; &lt;br /&gt;&lt;br /&gt;Beneath the Service Endpoint you can now add a Step and configure it as you would have done for an On Premise plugin only now the event handler is the service endpoint you just created. You could for example set the plugin to fire on the Create event for the Contact entity.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;That done you can now configure the app.comfig with your (Azure) Service Namespace, Isssuer Secret (your Azure Management Key) &amp;nbsp;and the Service Path which is the name of your listener class.&amp;nbsp; Run your OneWayListener application, and that should open a connection to your Azure endpoint and will print out messages as they are received to the console window.&lt;br /&gt;&lt;br /&gt;So now go to CRM 2011 Online and perform the action that your Plugin is attached to (e.g. create contact). After you save the Contact, the Asynchronous process runs and your listener will receive the message.&amp;nbsp; &lt;br /&gt;&lt;br /&gt;The Onewaylistener code uses a RemoteExecutionContext object which has all the information you need from the User Guid to the Organization Guid. The interesting stuff&amp;nbsp; is in the context.InputParameters collection. It contains all the data you entered. Its a simple task to turn this into XML and then you are all set to integrate with whatever you want.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-5268578372810745906?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/5268578372810745906/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=5268578372810745906' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/5268578372810745906'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/5268578372810745906'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/03/windows-azure-appfabric-and-integration.html' title='Windows Azure AppFabric and Integration with CRM 2011 Online'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-3581290336412879986</id><published>2011-03-05T15:25:00.015Z</published><updated>2011-03-06T13:19:03.759Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='data connections'/><category scheme='http://www.blogger.com/atom/ns#' term='Online'/><category scheme='http://www.blogger.com/atom/ns#' term='Cloud'/><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='OrganizationService'/><category scheme='http://www.blogger.com/atom/ns#' term='Windows Live ID'/><title type='text'>Connecting to CRM 2011 in the Cloud</title><content type='html'>Connecting to CRM 2011 in the Cloud is trickier than connecting to CRM 2011 On Premise.&lt;br /&gt;There is a great article by &lt;a href="http://deepakexploring.wordpress.com/2011/02/16/crud-operation-early-bound-classes-using-wcf-services-in-crm-2011/"&gt;Deepak Kumar&lt;/a&gt; but it is worth recapping on his points.&lt;br /&gt;Check c:\Program Files to see if you have Windows Identity Foundation. If not you will need to install it.&lt;br /&gt;&lt;br /&gt;You need to get some device credentials and this is done using a utility in the CRMSDK called DEVICEREGISTRATION. Go to \sdk\tools\deviceregistration directory and load deviceregistration.csproj. Compile the application and navigate to the \bin\debug folder. Open a command window and type&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;deviceregistration.exe /operation:Register&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The Device ID and Password that are generated are used in the method GetDeviceCredentials (that comes next).&lt;br /&gt;&lt;br /&gt;Preparation work done you can now create your VS 2010 project, in this example I am using a WCF Service (I left the default name of Service)&lt;br /&gt;&lt;br /&gt;Copy the CRMServiceHelper.cs file from \sdk\samplecode\cs\helpercode into your project and modify three methods:&lt;br /&gt;&lt;br /&gt;GetDeviceCredentials&lt;br /&gt;GetUserLogonCredentials&lt;br /&gt;GetServerConfiguration&lt;br /&gt;&lt;br /&gt;I used the code in Deepak Kumar's blog and set my Windows LiveID credentials in the GetUserLogonCredentials method. When you set the endpoints in GetServerConfiguration be aware that endpoints vary depending where you are in the world so see this &lt;a href="https://bingsoft.wordpress.com/tag/organizationdata-svc/"&gt;blog &lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;Then if you want Intellisense on your custom entities and attributes you need to generate a class with them all in using CRMSVCUTIL.EXE. This tool is in the SDK too in the \sdk\bin directory. Amend your Environment Path so you have a reference to its location. Open a Command window, navigate to where you want the class to be generated then use&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;CrmSvcUtil.exe /url:https://{organisation}.crm4.dynamics.com/XRMServices/2011/Organization.svc /out:GeneratedCode.cs /username:"windows live id" /password:"live id password" /deviceid:"deviceid" /devicepassword:"device password"&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Add the class you just generated to your project. OK, this takes a while and you will have to keep regenerating it every time you add an attribute but think of the time you'll save by having fewer bugs.&lt;br /&gt;&lt;br /&gt;You will need to add references to the CRM SDK dlls (microsoft.crm.sdk.proxy.dll, microsoft.xrm.sdk.dll and microsoft.crm.sdk.dll) and then add these using statements&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;using Microsoft.Xrm.Sdk;&lt;br /&gt;using Microsoft.Xrm.Sdk.Messages;&lt;br /&gt;using Microsoft.Xrm.Sdk.Query;&lt;br /&gt;using Microsoft.Xrm.Sdk.Client;&lt;br /&gt;using Microsoft.Crm.Sdk.Messages;&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;&lt;br /&gt;&lt;/span&gt;Add 3 declarations in the class Service.&lt;br /&gt;&lt;span style="font-family: arial;"&gt;private OrganizationServiceContext context;&lt;br /&gt;private OrganizationServiceProxy proxy;&lt;br /&gt;private IOrganizationService service;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;In the class constructor add a call to ConsumeIOrganization().&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;public Service()&lt;br /&gt;{&lt;br /&gt;ConsumeIOrganization();&lt;br /&gt;}&lt;/span&gt;Then add two methods&lt;br /&gt;&lt;br /&gt;&lt;span style="font-family: arial;"&gt;public void ConsumeIOrganization()&lt;br /&gt;{&lt;br /&gt;ServerConnection serverConnection = new ServerConnection();&lt;br /&gt;ServerConnection.Configuration serverConfig = serverConnection.GetServerConfiguration();&lt;br /&gt;Connect(serverConfig);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;public void Connect(ServerConnection.Configuration serverConfig)&lt;br /&gt;{&lt;br /&gt;try&lt;br /&gt;{&lt;br /&gt;using (proxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri,&lt;br /&gt;serverConfig.Credentials, serverConfig.DeviceCredentials))&lt;br /&gt;{&lt;br /&gt;proxy.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());&lt;br /&gt;context = new OrganizationServiceContext(proxy);&lt;br /&gt;service = (IOrganizationService)proxy;&lt;br /&gt;}&lt;br /&gt;}&lt;br /&gt;catch (FaultException &amp;lt;microsoft.xrm.sdk.organizationservicefault&amp;gt;)&lt;br /&gt;{&lt;br /&gt;throw;&lt;br /&gt;}&lt;br /&gt;}&lt;/span&gt;&lt;br /&gt;Now you can add your code and reference &lt;em&gt;service&lt;/em&gt; or &lt;em&gt;context&lt;/em&gt; methods depending on which you prefer. Welcome to programming in the cloud!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-3581290336412879986?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/3581290336412879986/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=3581290336412879986' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3581290336412879986'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3581290336412879986'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/03/connecting-to-crm-2011-cloud.html' title='Connecting to CRM 2011 in the Cloud'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6521371234958613542</id><published>2011-02-19T20:11:00.013Z</published><updated>2011-02-20T11:49:27.783Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Integration'/><title type='text'>Create SharePoint Document Locations in CRM 2011 - Part 3</title><content type='html'>This is the last of 3 posts describing how to add SharePoint document locations into CRM. &lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in.html"&gt;Part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_19.html"&gt;Part 2&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;This code should be added to that in the previous blog post. I had a devil of a job with a 401 error, but this finally cracked it. &lt;br /&gt;&lt;br /&gt;Add a web reference to &lt;br /&gt;http://server01/_vti_bin/Lists.asmx and name the reference listservice&lt;br /&gt;http://server01/_vti_bin/Views.asmx and name the reference views&lt;br /&gt;&lt;br /&gt;Add a using statement&lt;br /&gt;using system.Xml;&lt;br /&gt;&lt;br /&gt;Add this method into the code in previous blog post. &lt;br /&gt;&lt;br /&gt; &lt;br /&gt;       private static void CreateSharePointFolder(string docfolderUrl)&lt;br /&gt;        {&lt;br /&gt;            if (docfolderUrl == String.Empty || docfolderUrl.IndexOf("/") == -1)&lt;br /&gt;            {&lt;br /&gt;                return;&lt;br /&gt;            }&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                // last part is the folder name&lt;br /&gt;                string folderName = docfolderUrl.Substring(docfolderUrl.LastIndexOf("/") + 1);&lt;br /&gt;                // remove the folder name&lt;br /&gt;                docfolderUrl = docfolderUrl.Replace("/" + folderName, "");&lt;br /&gt;                // get the document libray name&lt;br /&gt;                string docLib = docfolderUrl.Substring(docfolderUrl.LastIndexOf("/") + 1);&lt;br /&gt;                // now remove the doc lib to leave the sharepoint site url&lt;br /&gt;                string sharePointSiteUrl = docfolderUrl.Replace("/" + docLib, "");&lt;br /&gt;&lt;br /&gt;                listservice.Lists myLists = new listservice.Lists();&lt;br /&gt;                views.Views myViews = new views.Views();&lt;br /&gt;&lt;br /&gt;                myLists.Url = sharePointSiteUrl + "/_vti_bin/lists.asmx";&lt;br /&gt;                myViews.Url = sharePointSiteUrl + "/_vti_bin/views.asmx";&lt;br /&gt;                myLists.UseDefaultCredentials = true;&lt;br /&gt;                myViews.UseDefaultCredentials = true;&lt;br /&gt;&lt;br /&gt;                XmlNode viewCol = myViews.GetViewCollection(docLib);&lt;br /&gt;                XmlNode viewNode = viewCol.SelectSingleNode("*[@DisplayName='All Documents']");&lt;br /&gt;                string viewName = viewNode.Attributes["Name"].Value.ToString();&lt;br /&gt;&lt;br /&gt;                /*Get Name attribute values (GUIDs) for list and view. */&lt;br /&gt;                System.Xml.XmlNode ndListView = myLists.GetListAndView(docLib, viewName);           &lt;br /&gt;&lt;br /&gt;                /*Get Name attribute values (GUIDs) for list and view. */&lt;br /&gt;                string strListID = ndListView.ChildNodes[0].Attributes["Name"].Value;&lt;br /&gt;                string strViewID = ndListView.ChildNodes[1].Attributes["Name"].Value;&lt;br /&gt;                // load the CAML query&lt;br /&gt;                XmlDocument doc = new XmlDocument();&lt;br /&gt;                string xmlCommand;&lt;br /&gt;                xmlCommand = "&amp;lt;Method ID='1' Cmd='New'&amp;gt;&amp;lt;Field Name='FSObjType'&amp;gt;1&amp;lt;/Field&amp;gt;&amp;lt;Field Name='BaseName'&amp;gt;" + folderName + "&amp;lt;/Field&amp;gt; &amp;lt;Field Name='ID'&amp;gt;New&amp;lt;/Field&amp;gt;&amp;lt;/Method&amp;gt;";&lt;br /&gt;                XmlElement ele = doc.CreateElement("Batch");&lt;br /&gt;                ele.SetAttribute("OnError", "Continue");&lt;br /&gt;                ele.SetAttribute("ListVersion", "1");&lt;br /&gt;                ele.SetAttribute("ViewName", strViewID);&lt;br /&gt;&lt;br /&gt;                ele.InnerXml = xmlCommand;&lt;br /&gt;&lt;br /&gt;                XmlNode resultNode = myLists.UpdateListItems(strListID, ele);&lt;br /&gt;&lt;br /&gt;                // check for errors&lt;br /&gt;                NameTable nt = new NameTable();&lt;br /&gt;                XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);&lt;br /&gt;                nsmgr.AddNamespace("tns", "http://schemas.microsoft.com/sharepoint/soap/");&lt;br /&gt;                if (resultNode != null)&lt;br /&gt;                {  // look for error text in case of duplicate folder or invalid folder name&lt;br /&gt;                    XmlNode errNode = resultNode.SelectSingleNode("tns:Result/tns:ErrorText", nsmgr);&lt;br /&gt;                    if (errNode != null)&lt;br /&gt;                    {&lt;br /&gt;                        // Write error to log;&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                throw ex ;&lt;br /&gt;            }&lt;br /&gt;        }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6521371234958613542?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6521371234958613542/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6521371234958613542' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6521371234958613542'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6521371234958613542'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_1870.html' title='Create SharePoint Document Locations in CRM 2011 - Part 3'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6043162778948768180</id><published>2011-02-19T19:32:00.014Z</published><updated>2011-03-05T15:25:12.887Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Integration'/><title type='text'>Create SharePoint Document Locations in CRM 2011 - Part 2</title><content type='html'>This is part 2 of three posts&lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in.html"&gt;Part 1&lt;/a&gt;&lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_1870.html"&gt;Part 3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This code  expects the Guid for the Contact and then returns the SharePointDocumentLocation AbsoluteUrl. For example it should return &amp;lt;a href="http://server01/contact/Charles Emes"&amp;gt;http://server01/contact/Charles Emes&amp;lt;/a&amp;gt;. That folder should exist in the SharePoint document library 'Contact'. Note that the code for creating the SharePoint folder is in the following blog post.  &lt;br /&gt;&lt;br /&gt;Add references to Microsoft.Crm.Sdk.Proxy.dll and Microsoft.Xrm.Sdk.dll to your project. Add the file myorganizationcrmsdktypes.cs into your project.  All of these files you will find in the CRM SDK directory. &lt;br /&gt;&lt;br /&gt;Add the following using statements &lt;br /&gt;using Microsoft.Xrm.Sdk;&lt;br /&gt;using Microsoft.Xrm.Sdk.Query;&lt;br /&gt;using Microsoft.Xrm.Sdk.Client;&lt;br /&gt;using Microsoft.Crm.Sdk.Messages;&lt;br /&gt;&lt;br /&gt;     public class IntegrationService&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        // private static string ContactId = "3E339B88-C632-E011-BCDE-00155D110735";&lt;br /&gt;&lt;br /&gt;        public static string GetSharePointLocation(string ContactId)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                // Connect to the Organization service. &lt;br /&gt;                System.ServiceModel.Description.ClientCredentials cred = new System.ServiceModel.Description.ClientCredentials();&lt;br /&gt;                cred.Windows.ClientCredential = new System.Net.NetworkCredential("Username", "Password", "Domain");&lt;br /&gt;                &lt;br /&gt;                Uri organizationUri = new Uri("http://server01:5555/orgName/XRMServices/2011/Organization.svc");&lt;br /&gt;&lt;br /&gt;                Uri homeRealmUri = null;&lt;br /&gt;                &lt;br /&gt;                OrganizationServiceProxy orgService = new OrganizationServiceProxy(organizationUri, homeRealmUri, cred, null);&lt;br /&gt;               &lt;br /&gt;                // This statement is required to enable early-bound type support.&lt;br /&gt;                // IMPORTANT ADD THIS LINE&lt;br /&gt;                orgService.ServiceConfiguration.CurrentServiceEndpoint.Behaviors.Add(new ProxyTypesBehavior());&lt;br /&gt;              &lt;br /&gt;                Guid  guidSPDocLoc = RetrieveSharePointLocation(orgService, ContactId);&lt;br /&gt;&lt;br /&gt;                string absouteUrl = GetAbslouteUrl(orgService, guidSPDocLoc);&lt;br /&gt;&lt;br /&gt;                orgService.Dispose();&lt;br /&gt;&lt;br /&gt;                return absouteUrl;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            // Catch any service fault exceptions that Microsoft Dynamics CRM throws.&lt;br /&gt;            catch (FaultException&amp;lt;Microsoft.Xrm.Sdk.OrganizationServiceFault&amp;gt; ex)&lt;br /&gt;            {&lt;br /&gt;                // You can handle an exception here or pass it back to the calling method.&lt;br /&gt;                return  ex.Message;&lt;br /&gt;            }&lt;br /&gt;            &lt;br /&gt;        }&lt;br /&gt;        private static Guid RetrieveSharePointLocation(OrganizationServiceProxy orgService, string ContactId)&lt;br /&gt;        {&lt;br /&gt;            Guid _spDocLocId = Guid.Empty;&lt;br /&gt;            // get the fullname from the contactid - that will be foolder name&lt;br /&gt;            string FolderName =  GetEntityNamefromGuid(orgService, ContactId); &lt;br /&gt;            // replace any illegal chars with '-'&lt;br /&gt;            // TO DO&lt;br /&gt;            string fetch2 = @"&lt;br /&gt;                       &amp;lt;fetch mapping='logical'&amp;gt;&lt;br /&gt;                         &amp;lt;entity name='sharepointdocumentlocation'&amp;gt; &lt;br /&gt;                              &amp;lt;attribute name='sharepointdocumentlocationid'/&amp;gt; &lt;br /&gt;&lt;br /&gt;                                  &amp;lt;filter type='and'&amp;gt; &lt;br /&gt;                                &amp;lt;condition attribute='regardingobjectid' operator='eq' value='[GUID]' /&amp;gt; &lt;br /&gt;                              &amp;lt;/filter&amp;gt; &lt;br /&gt;&lt;br /&gt;                         &amp;lt;/entity&amp;gt; &lt;br /&gt;                       &amp;lt;/fetch&amp;gt; ";&lt;br /&gt;            fetch2 = fetch2.Replace("[GUID]", ContactId); &lt;br /&gt;&lt;br /&gt;            EntityCollection result = orgService.RetrieveMultiple(new FetchExpression(fetch2));&lt;br /&gt;            foreach (var c in result.Entities)&lt;br /&gt;            {  &lt;br /&gt;                // TO DO there can be more than one so add condition&lt;br /&gt;                _spDocLocId = (Guid) c.Attributes["sharepointdocumentlocationid"];&lt;br /&gt;            }&lt;br /&gt;            if (_spDocLocId == Guid.Empty)&lt;br /&gt;            {&lt;br /&gt;                // there is no location so create one&lt;br /&gt;                _spDocLocId = CreateSharePointDocLocation(orgService, FolderName, ContactId);&lt;br /&gt;                &lt;br /&gt;                // get the abslouteURL from the doc location just created &lt;br /&gt;                string absouteUrl = GetAbslouteUrl(orgService, _spDocLocId);&lt;br /&gt;                // We still need to create a SharePoint folder&lt;br /&gt;                // THIS METHOD IN FOLLOWING POST **********&lt;br /&gt;                CreateSharePointFolder(absouteUrl);&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            return _spDocLocId;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static string GetEntityNamefromGuid(OrganizationServiceProxy orgService, string ContactId)&lt;br /&gt;        {&lt;br /&gt;            string fetch1 = @"&lt;br /&gt;                       &amp;lt;fetch mapping='logical'&amp;gt;&lt;br /&gt;                         &amp;lt;entity name='contact'&amp;gt; &lt;br /&gt;                              &amp;lt;attribute name='fullname'/&amp;gt; &lt;br /&gt;&lt;br /&gt;                                  &amp;lt;filter type='and'&amp;gt; &lt;br /&gt;                                &amp;lt;condition attribute='contactid' operator='eq' value='[GUID]' /&amp;gt; &lt;br /&gt;                              &amp;lt;/filter&amp;gt; &lt;br /&gt;&lt;br /&gt;                         &amp;lt;/entity&amp;gt; &lt;br /&gt;                       &amp;lt;/fetch&amp;gt; ";&lt;br /&gt;            fetch1 = fetch1.Replace("[GUID]", ContactId);&lt;br /&gt;            string fullname = string.Empty;&lt;br /&gt;            EntityCollection result = orgService.RetrieveMultiple(new FetchExpression(fetch1));&lt;br /&gt;            foreach (var c in result.Entities)&lt;br /&gt;            {   // there can be more than one so add condition&lt;br /&gt;                fullname = c.Attributes["fullname"].ToString();&lt;br /&gt;            }&lt;br /&gt;            return fullname;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static Guid CreateSharePointDocLocation(OrganizationServiceProxy _serviceProxy, string FolderName, string ContactId)&lt;br /&gt;        {&lt;br /&gt;            &lt;br /&gt;            // use the Parent Location Id NOT the SharePointSiteId&lt;br /&gt;            // Parent Location will create url http://sharepoint/contact/CharlesEmes&lt;br /&gt;            // SharePointSiteID will create url http://sharepoint/CharlesEmes&lt;br /&gt;            Guid  _spParentLocId = new Guid("415FF5BA-CA39-E011-92D1-00155D110735");&lt;br /&gt;            // Instantiate a SharePoint document location object.&lt;br /&gt;&lt;br /&gt;            SharePointDocumentLocation spDocLoc = new SharePointDocumentLocation&lt;br /&gt;            {&lt;br /&gt;                Name = "Documents on Default Site 1",&lt;br /&gt;                Description = null,&lt;br /&gt;                // Set the Regarding Object id - in this case its a contact&lt;br /&gt;                RegardingObjectId = new EntityReference(Contact.EntityLogicalName , new Guid(ContactId)),&lt;br /&gt;                &lt;br /&gt;                // Set the Parent Location ID&lt;br /&gt;                ParentSiteOrLocation = new EntityReference(SharePointDocumentLocation.EntityLogicalName, _spParentLocId),&lt;br /&gt;                RelativeUrl = FolderName&lt;br /&gt;            };&lt;br /&gt;&lt;br /&gt;            // Create a SharePoint document location record named Documents on Default Site 1.&lt;br /&gt;            Guid _spDocLocId = _serviceProxy.Create(spDocLoc);&lt;br /&gt;           // Console.WriteLine("{0} created.", spDocLoc.Name);&lt;br /&gt;            return _spDocLocId;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        private static string GetAbslouteUrl(OrganizationServiceProxy orgService, Guid _spDocLocId)&lt;br /&gt;        {&lt;br /&gt;            IOrganizationService _service = (IOrganizationService)orgService;&lt;br /&gt;&lt;br /&gt;            RetrieveAbsoluteAndSiteCollectionUrlRequest retrieveRequest = new RetrieveAbsoluteAndSiteCollectionUrlRequest&lt;br /&gt;            {&lt;br /&gt;                Target = new EntityReference(SharePointDocumentLocation.EntityLogicalName, _spDocLocId)&lt;br /&gt;            };&lt;br /&gt;            RetrieveAbsoluteAndSiteCollectionUrlResponse retrieveResponse = (RetrieveAbsoluteAndSiteCollectionUrlResponse)_service.Execute(retrieveRequest);&lt;br /&gt;&lt;br /&gt;            return retrieveResponse.AbsoluteUrl.ToString();&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;    }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6043162778948768180?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6043162778948768180/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6043162778948768180' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6043162778948768180'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6043162778948768180'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_19.html' title='Create SharePoint Document Locations in CRM 2011 - Part 2'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-4563098897363876062</id><published>2011-02-19T18:51:00.009Z</published><updated>2011-02-21T09:31:15.175Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='CRM 2011'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Integration'/><title type='text'>Create SharePoint Document Locations in CRM 2011 - Part 1</title><content type='html'>This post is the first of three on how to programmatically create SharePoint 2010 Document Folders in CRM 2011 so that documents can be uploaded.&lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_19.html"&gt;Part 2&lt;/a&gt;&lt;br /&gt;&lt;a href="http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in_1870.html"&gt;Part 3&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There is quite a lot of code for this solution which is why I've broken it up into 3 parts. This first part outlines the scenario and the assumptions.&lt;br /&gt;&lt;br /&gt;So here is the scenario. I have CRM 2011 and I want to store documents related to the Contact entity in SharePoint 2010. In my development environment I have both of these on the same virtual image but I've designed the code to work as a web service so it can sit it anywhere.&lt;br /&gt;&lt;br /&gt;What CRM 2011 does is create a document library for each Entity that is enabled for document storage, and then creates a folder for each record. This example focuses on the Contact entity but it can be easily applied to other entities. When a new entity record is created in CRM 2011 and the Document menu item is clicked, it will create a) a SharePointDocumentLocation record in CRM that has the path to the SharePoint folder and b) warns you that it is about to create a document folder. The name of the folder for a Contact if based on full name. So what happens if you have two John Smiths? If the first already has created a document folder it detects that and prompts with 'the folder already exists do you want to use it?' If not, then you can modify the name of the folder to ensure it is unique. &lt;br /&gt;&lt;br /&gt;This is an imprtant point. Assume you have a contact called Robin Wright. When you create a document folder it will be called 'Robin Wright'. When Robin gets married and changes her name to 'Robin Wrigth-Penn' then the document folder name remains the same name. CRM 2011 uses the SharePoint document location record to point to the orginal folder name. So you need to be careful, you can't assume that the full name in CRM is the same as the document folder name. &lt;br /&gt;&lt;br /&gt;For this example I am going to assume you have the Guid for the Contact in question. This unique identifier will be used to determine if there is already a SharePoint Document Location created for this record. If so, it returns the url for you. If not, it will create the SharePoint Document Location in CRM and then create the actual folder in SharePoint based on the full name and finally returns the url to the folder.&lt;br /&gt;&lt;br /&gt;So this code either uses the existing SharePoint Document Location or will create a new one for you and create the folder in SharePoint.&lt;br /&gt;&lt;br /&gt;I have made another assumption. I assume you have created the SharePoint site already with the document library for the entity "Contact". It will help if you have a few SharePoint document locations already created because then you will be able to see how the database field 'ParentSiteorLocation' is populated in the SharePointDocumentLocationBase table. You need to use the 'root' Guid for the Contact document library and it should be obvious what this is if you have a few records in the table.&lt;br /&gt;&lt;br /&gt;You can recognise this row in the table as the relativeurl reads 'contact' and the RegardingObjectID is null. The Guid you need is the SharePointDocumentLocationId from this record. It will become clearer (I hope) when you see the code.&lt;br /&gt;&lt;br /&gt;There is another issue you will need to be aware of. Folder names in SharePoint will not allow certain characters. If they exist in your CRM Contact record e.g. the first name reads 'John &amp;amp; Jane' then CRM replaces the &amp;amp; with -. I have not checked all illegal characters are substituted with hyphen but it is my working assumption. So be warned, you will need to modify full name of contact to replace illegal characters. Also please note this code does NOT handle duplicate names - you will need to check for a duplicate and create a unique folder name.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;So the next blog has the CRM code for using an existing SharePoint Document Location or create a new location. There is a reference in the code to a function that will create the actual SharePoint folder but the code for that is in the last blog.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-4563098897363876062?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/4563098897363876062/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=4563098897363876062' title='6 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4563098897363876062'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4563098897363876062'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/create-sharepoint-document-locations-in.html' title='Create SharePoint Document Locations in CRM 2011 - Part 1'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>6</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1875336962120469360</id><published>2011-02-11T20:59:00.005Z</published><updated>2011-02-11T21:30:03.849Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='error'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk Server 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Receive Location'/><title type='text'>BizTalk Receive Location Error - Verify the schema deployed properly.</title><content type='html'>I was getting an error with Biztalk Server when receiving a file from MSMQ although you get a similar error on FILE receive locations. The message was&lt;br /&gt;&lt;br /&gt;There was a failure executing the receive pipeline: "Microsoft.BizTalk.DefaultPipelines.XMLReceive, Microsoft.BizTalk.DefaultPipelines, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" Source: "XML disassembler" Receive Port: "&lt;em&gt;Portname&lt;/em&gt;" URI: "FORMATNAME:DIRECT=OS:.\PRIVATE$\&lt;em&gt;QNAME&lt;/em&gt;" Reason: Finding the document specification by message type "&lt;em&gt;RootNode&lt;/em&gt;" failed. Verify the schema deployed properly.&lt;br /&gt;&lt;br /&gt;It is caused because the message does not conform to a schema that Biztalk recognises, in my case because the RootNode is not recognised.  The problem is BizTalk has not saved the original message. It's gone. The method described here shows how to keep a copy of the original file. There maybe other solutions but this works well for me.&lt;br /&gt;&lt;br /&gt;The solution I outline is for FILE ports but once you understand the principle you will see how to apply it for MSMQ. The principle is to use a Receive Location and a Send Port Group configured for the Pass Through pipeline.&lt;br /&gt;&lt;br /&gt;The Receive Location becomes the new port which polls for inbound messages that arrive in the directory c:\inbound. The Receive Location is bound to a Recieve Port which I'll call ReceivePort1.&lt;br /&gt;&lt;br /&gt;The Send Port Group has 2 Send Ports in it. Both Send Ports, for the sake of simplicity, are FILE ports that are configured to write out the file using %SourceFileName% to the following directories c:\filecopy and c:\biztalkinbound. Both are configured to use the Pass Through pipeline.&lt;br /&gt;&lt;br /&gt;Got to the Filter on the Send Port Group and add the following filter&lt;br /&gt;BTS.ReceivePortName == ReceivePort1&lt;br /&gt;&lt;br /&gt;Enable the Receive Location and start both Send Ports and the Send Port Group. If you drop a file into c:\inbound it will appear in both directories c:\filecopy and c:\biztalkinbound and it will retain the original file name.&lt;br /&gt;&lt;br /&gt;Your original Receive Location should now point to the location c:\biztalkinbound and it will be configured for whatever pipeline you were using (XML Receive or a custom Flat File pipeline).&lt;br /&gt;&lt;br /&gt;The benefit of this is you always have a copy of the original file in its original format in the directory c:\filecopy. As an added treat I got my orchestration to delete files that were successfully processed from this directory.  So c:\filecopy became the place which stored files that failed to be processed - the classic being that they failed to match the correct schema as described by the error at the beginning of the post.  Send an email alert to the Sysem Administrator and you'll be a hero.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1875336962120469360?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1875336962120469360/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1875336962120469360' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1875336962120469360'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1875336962120469360'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/biztalk-receive-location-error-verify.html' title='BizTalk Receive Location Error - Verify the schema deployed properly.'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1081992235802054941</id><published>2011-02-11T20:35:00.005Z</published><updated>2011-09-16T19:10:14.669+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Windows Server 2008 R2'/><category scheme='http://www.blogger.com/atom/ns#' term='file'/><category scheme='http://www.blogger.com/atom/ns#' term='drop'/><category scheme='http://www.blogger.com/atom/ns#' term='Access Denied'/><category scheme='http://www.blogger.com/atom/ns#' term='GAC'/><title type='text'>Access Denied message when dropping a file into the GAC (or it doesn't work)</title><content type='html'>I was using Windows Server 2008 R2 and trying to add a file to the GAC. As you know the easiest way to do this is to drag and drop the file from one window into a window with the location C:\windows\assembly.&lt;br /&gt;&lt;br /&gt;I kept getting the Access Denied error message. I tried running the command prompt as the Administrator, navigating to C:\Windows\assembly and then typing "Start . " to open an explorer window as the Administrator. Repeated the file drop but got Access Denied again.&amp;nbsp; At the time this was a .NET 3.5 assembly.&amp;nbsp; Now with .NET 4.0 the location of the GAC is no longer C:\Windows\assembly but C:\Windows\Microsoft.Net\assembly and drag and drop is disabled.&lt;br /&gt;&lt;br /&gt;OK, so&amp;nbsp; the other way to install it is to use GACUTIL but guess what, its not installed on&amp;nbsp;the production server. And no you can't use an old version of GACUTIL from .Net Framework 1.1, it has to be the .NET&amp;nbsp;version that your DLL is using. Google said it was in the Microsoft SDK for Windows but I didn't have time to download it.&lt;br /&gt;&lt;br /&gt;I managed to copy it from a Hyper-V image I had which had Visual Studio 2010 installed. The file for .Net v3.5&amp;nbsp;is located in C:\Program Files (x86) \Microsoft SDKs\Windows\v7.0A\bin. You just need to copy GACUTIL.EXE and GACUTIL.EXE.CONFIG.&lt;br /&gt;&lt;br /&gt;For .Net 4.0 the location is C:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin\NETFX 4.0 Tools and you need a third file &lt;span class="goog_qs-tidbit goog_qs-tidbit-1"&gt;1033\gacutlrc.dll for gacutil to work.&amp;nbsp; When you copy this to the production server all 3 files can be in the same directory.&amp;nbsp; &lt;/span&gt;&lt;br /&gt;&lt;br /&gt;The syntax is&lt;br /&gt;gacutil /i myassemblyname.dll /f&lt;br /&gt;&lt;br /&gt;To check the file is in the GAC use&lt;br /&gt;gacutil /l myassemblyname&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; (don't add the .dll)&lt;br /&gt;&lt;br /&gt;Hope this gets you out of the same hole I was in.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1081992235802054941?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1081992235802054941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1081992235802054941' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1081992235802054941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1081992235802054941'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/access-denied-message-when-dropping.html' title='Access Denied message when dropping a file into the GAC (or it doesn&apos;t work)'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1318804571752947273</id><published>2011-02-11T20:30:00.003Z</published><updated>2011-02-11T20:41:33.641Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk Server 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Enable'/><category scheme='http://www.blogger.com/atom/ns#' term='Receive Location'/><category scheme='http://www.blogger.com/atom/ns#' term='Disabled'/><title type='text'>Biztalk Server 2010 Receive Location won't Enable</title><content type='html'>I configured my Receive Location on Biztalk Server 2010 but when I tried to enable it, it remained stubbornly disabled. No error message, it just won't Enable.&lt;br /&gt;&lt;br /&gt;In my case it was a FILE receive port and what I had forgotten to do was to make sure the service account the Biztalk Application Host is running under has FULL permissions on the file location.&lt;br /&gt;&lt;br /&gt;Remember "Read" is not enough because BizTalk insists on deleting the inbound file. That was it. Simples!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1318804571752947273?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1318804571752947273/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1318804571752947273' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1318804571752947273'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1318804571752947273'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/biztalk-server-2010-receive-location.html' title='Biztalk Server 2010 Receive Location won&apos;t Enable'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8590063594723143282</id><published>2011-02-11T19:41:00.006Z</published><updated>2011-02-11T20:41:57.788Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Configuration'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk Server 2010'/><category scheme='http://www.blogger.com/atom/ns#' term='Failure'/><title type='text'>BizTalk Server 2010 ConfigurationFailure</title><content type='html'>I had a failure configuring BizTalk Server 2010. The Enterprise Single Sign-On installed but I got an error with the Group and the BizTalk RunTime. When I tried to run the installation again it showed and error beside the BizTalk Managment database which stated that it had been installed and I needed to choose another database name.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;This told me that the account I was using to inst all BizTalk did have the correct permissions to create databases. The error was because MSDTC was not configured correctly. This needs to be done on BOTH the BizTalk Server and the SQL Server. The correct settings are shown below.&lt;br /&gt;&lt;br /&gt;First though, delete the Biztalk Management database from the SQL Server because you don't want to end up with two. To configure MSDTC on Windows Server 2008 R2 go to Server Manager, select Roles -&gt; Application Server -&gt; Component Services. Select Distributed Transaction Coordinator and then Local DTC. Right click, select Properties then click on the Security tab. Make sure you are using the Network Service account as well as checking the boxes shown.&lt;br /&gt;&lt;br /&gt;Remember you have to do this on both the SQL Server box and the Biztalk Server.&lt;br /&gt;&lt;br /&gt;After I had configured MSDTC I re-ran the Biztalk Server Configuration tool and the configuration completed successfully. Happy Days!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 294px; DISPLAY: block; HEIGHT: 320px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5572530016239347634" border="0" alt="" src="http://3.bp.blogspot.com/-8nTUXYPqCb0/TVWahnYl57I/AAAAAAAAAC0/VlhM45vs_cY/s320/MSDTC.png" /&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8590063594723143282?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8590063594723143282/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8590063594723143282' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8590063594723143282'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8590063594723143282'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/02/biztalk-server-2010-configurationfailur.html' title='BizTalk Server 2010 ConfigurationFailure'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/-8nTUXYPqCb0/TVWahnYl57I/AAAAAAAAAC0/VlhM45vs_cY/s72-c/MSDTC.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-3815217844599756104</id><published>2011-01-21T15:29:00.004Z</published><updated>2011-01-21T16:22:05.336Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='customize form'/><category scheme='http://www.blogger.com/atom/ns#' term='Hiding Menu Items'/><category scheme='http://www.blogger.com/atom/ns#' term='List'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint 2007'/><title type='text'>Hiding Menu Items on a SharePoint List form</title><content type='html'>This might be a bit basic but I thought I would give a step by step guide on how to customise a SharePoint list form. The first step is you need a web control.&lt;br /&gt;&lt;br /&gt;In your Visual Studio project you need a TEMPLATES folder and a CONTROLTEMPLATES folder beneath it. This is where you add your user control. Lets not worry too much about the code on the user control just yet.&lt;br /&gt;&lt;br /&gt;Next we want to make the web control available when the SharePoint list form loads.&lt;br /&gt;To do this add the line &lt;br /&gt;&lt;br /&gt;&lt;%@ Register TagPrefic="xyz" TagName="MyWebControl" src="~/_controltemplates/WebControl.ascx" %&gt;&lt;br /&gt;&lt;br /&gt; into the web page.&lt;br /&gt;Now there are two ways to do this depending on what you want to achieve.&lt;br /&gt;&lt;br /&gt;Firstly you can add the line into the master page so that is available to every page on the site.&lt;br /&gt;&lt;br /&gt;Secondly you can add it to the custom page associated to the list.&lt;br /&gt;&lt;br /&gt;In either event, the result is that the code on the web control is executed when your page loads. Since your web control is injected into the HTML of the page you can do all kindes of things from adding inline css styles that can be applied to the page or by injecting javascript onto the page to hide a menu or menu item.&lt;br /&gt;&lt;br /&gt;One approach is to add an asp:panel onto the ASCX and embed your css styles between the start and end tags of the panel. You can also embed javascript to change the way the page is displayed. &lt;br /&gt;&lt;br /&gt;Your code behind can then determine when to make the panel visible or hidden which will determine if the styles are applied to the page or not.&lt;br /&gt;&lt;br /&gt;If you need to have more control over the javascript go to the code behind and use the RegisterClientScript() method or add a literal control and set the text property to the javascript function.  When the literal control is rendered, the javascript is executed.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-3815217844599756104?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/3815217844599756104/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=3815217844599756104' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3815217844599756104'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3815217844599756104'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/01/hiding-menu-items-on-sharepoint-list.html' title='Hiding Menu Items on a SharePoint List form'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7497434907074341303</id><published>2011-01-21T15:06:00.004Z</published><updated>2011-01-21T15:20:15.530Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Custom Lists'/><category scheme='http://www.blogger.com/atom/ns#' term='Custom Forms'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint 2007'/><title type='text'>SharePoint 2007 Creating Custom Forms for Custom Lists</title><content type='html'>I was recently wondering how I was going to create custom forms (EditForm.aspx, DispForm.aspx) for a custom list.&lt;br /&gt;&lt;br /&gt;Now I want to deploy my custom list as a feature of course so I need to add these forms and the associated schema.xml file into my Visual Studio project.&lt;br /&gt;&lt;br /&gt;But how was I to go about creating the form?&lt;br /&gt;&lt;br /&gt;I though about using SharePoint Designer but a cold shiver ran down my spine.&lt;br /&gt;&lt;br /&gt;Than a friend of mine pointed out this wonderful utility: &lt;a href="http://blog.mastykarz.nl/export-list-definition-free-stsadm-command"&gt;OCDExportList&lt;/a&gt;&lt;br /&gt;It is an extension to the stsadm command and is available as a WSP. It's deployed globally to your SharePoint site.&lt;br /&gt;After that you can use the command&lt;br /&gt;&lt;br /&gt;stsadm -o ocdexportlist -url &lt;a href="http://mysiteurl/"&gt;&lt;em&gt;http://mysiteurl&lt;/em&gt;&lt;/a&gt; -name &lt;em&gt;listname&lt;/em&gt; -dir &lt;em&gt;c:\temp&lt;/em&gt;&lt;br /&gt;&lt;p&gt;and it will generate in the c:\temp directory the schemal.xml file and assoicated forms for this list. Copy this across to the feature folder of the custom list and you should be good to start customizing. &lt;/p&gt;&lt;p&gt;That's a great time saver.&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;em&gt;&lt;br /&gt;&lt;/em&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7497434907074341303?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7497434907074341303/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7497434907074341303' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7497434907074341303'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7497434907074341303'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/01/sharepoint-2007-creating-custom-forms.html' title='SharePoint 2007 Creating Custom Forms for Custom Lists'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7333985278092072251</id><published>2011-01-21T14:22:00.009Z</published><updated>2011-01-21T15:06:00.945Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Approval workflow'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='US date format'/><title type='text'>SharePoint 2007 Approval Workflow US Date format in Emails</title><content type='html'>&lt;div&gt;I am using SharePoint 2007 with SP2 in a 64bit environment. The SharePoint Server regional settings are set to English (UK) and the SharePoint site I am using is also set English UK settings. I am also using the out-of-the-box approval workflow so you would expect that any dates are shown in UK format both in the workflow history and in emails sent by the workflow.&lt;br /&gt;&lt;br /&gt;Wrong. They display in US format (MM/dd/yyyy).&lt;br /&gt;&lt;br /&gt;Now when I Googled this I found this &lt;a href="http://social.msdn.microsoft.com/Forums/en/sharepointworkflow/thread/240d187b-6567-4e45-b5ad-4e0f9b0ccd61"&gt;site&lt;/a&gt; which suggested it is fixed in the October 2008 Cumulative update. Indeed the Microsoft support &lt;a href="http://support.microsoft.com/kb/957691"&gt;page&lt;/a&gt; explicitly states as fixed "Sharepoint workflow notification e-mail messages do not use locale date and time formats".&lt;br /&gt;&lt;br /&gt;Wrong again. &lt;/div&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 320px; DISPLAY: block; HEIGHT: 278px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5564655328880194258" border="0" alt="" src="http://4.bp.blogspot.com/_mnBHRSSHZC8/TTmgie9jctI/AAAAAAAAACo/ICr7OzxTJxA/s320/OverdueMessage.png" /&gt;&lt;br /&gt;&lt;div&gt;Maybe it was fixed back in October 2008 (pre SP2) but I can tell you it's not working post SP2. I raised a support call with Microsoft and proved that the dates are indeed in US format when they shouldn't be.&lt;br /&gt;&lt;br /&gt;You require the August 2010 Cumulative Update from Microsoft to be applied to get this to work. Once the hotfix is applied then it all works prefectly with the due date correctly appearing in UK format both in the workflow history and in the emails. This even works on workflows that are in flight before you applied the hotfix.&lt;br /&gt;&lt;br /&gt;While I am glad to have a solution, Microsoft should be ashamed that something as basic as this has had to be fixed twice. Zero points, Microsoft!&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7333985278092072251?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7333985278092072251/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7333985278092072251' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7333985278092072251'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7333985278092072251'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/01/sharepoint-2007-approval-workflow-us.html' title='SharePoint 2007 Approval Workflow US Date format in Emails'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://4.bp.blogspot.com/_mnBHRSSHZC8/TTmgie9jctI/AAAAAAAAACo/ICr7OzxTJxA/s72-c/OverdueMessage.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1166140822381068480</id><published>2011-01-15T14:12:00.009Z</published><updated>2011-01-15T15:19:14.678Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Trial'/><category scheme='http://www.blogger.com/atom/ns#' term='Evaluation'/><category scheme='http://www.blogger.com/atom/ns#' term='Upgrade'/><category scheme='http://www.blogger.com/atom/ns#' term='BizTalk Server'/><title type='text'>BizTalk Server Evaluation Version Upgrade to Full Version</title><content type='html'>One of my customers had installed an evaulation version of BizTalk Server 2009 for their test environment, and sure enough the version expired and BizTalk stopped working.&lt;br /&gt;So they needed me to upgrade it to the full version (in this case we used the Developer Edition but the same process is used for upgrading to Standard or Enterprise Editions).&lt;br /&gt;But when I started the Install process it immediatley gave the message that you can't upgrade the evaluation version and you must uninstall and reinstall.&lt;br /&gt;At first sight this looks disastrous but infact you can recover everything because unsinstall does not delete the Biztalk databases. But there are a number of steps you should take before uninstalling BizTalk.&lt;br /&gt;&lt;br /&gt;1. Export the applications to MSI files and Export the Bindings just in case it all goes horribly wrong.&lt;br /&gt;&lt;br /&gt;2. Make a screen shot of the host instances in BizTalk Administration because these will be deleted and you will need to recreate them.&lt;br /&gt;&lt;br /&gt;3. The host instances use service accounts and you'll need the passwords for these accounts.&lt;br /&gt;&lt;br /&gt;4. Ensure that the account you are going to use to install BizTalk is the same one you used for the Evaluation version. If like me you don't know, use an account who is a local administrator and is sysadmin on the SQL Server box where the databases are installed (dbowner of all the BizTalk databases may be enough).&lt;br /&gt;&lt;br /&gt;5. Make sure you have a copy of the BTSNTSVC.exe.config file as this may contain configuration settings.&lt;br /&gt;&lt;br /&gt;6. Have a backup of the Enterprise Single Sign-On secret - and you must know what the password is (ideally the password hint will help). This is vital. If you don't have the password for the backup you will be hosed. I don't know if you are able to do the backup once the evalaution has expired. If you can open a command window and navigate to c:\Program Files\Common Files\Enterprise Single Sign-On. Then use&lt;br /&gt;ssoconfig –backupSecret &lt;em&gt;backupfilename&lt;restore&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/em&gt;OK, now you can uninstall the evaluation version and install the full version. Next you need to run the BizTalk Configuration wizard. Be sure to select Custom configuration and enter the database server name and the account credentials for services.&lt;br /&gt;The Enterprise SSO option is currently configured so select Join an existing SSO system. You will get a warning symbol indicating you may need to restore the SSO master secret (you will definitely need to).&lt;br /&gt;On the Group otion select Join an existing BizTalk Group. On the BizTalk Server RunTime do not Create In-Process Host and Instance because In-Process Host is still present. Liekwise do not create Isolated Host and Instance.&lt;br /&gt;Configure the other options appropriately and Apply the Configuration.&lt;br /&gt;If all goes well the Configuration will complete successfully. But you are not done.&lt;br /&gt;&lt;br /&gt;7. First open a command window and navigate to c:\Program Files\Common Files\Enterprise Single Sign-On. Then use&lt;br /&gt;ssoconfig –restoreSecret &lt;em&gt;backupfilename&lt;/em&gt;&lt;restore&gt;&lt;br /&gt;It will prompt you for the password showing you the password hint. This is why point 6 was so important if you don't have a backup or you don't know the password you are stuffed.&lt;br /&gt;&lt;br /&gt;8.Open BizTalk Administration go to the Host Instances and add the ones that were originally there (which is why we did point 2 above). Use the same accounts and passwords and start them up.&lt;br /&gt;&lt;br /&gt;9. Edit the BTSNTSvc.exe.config file and add any custom entries that you saved from point 5. Stop and restart the BizTalk Service(s).&lt;br /&gt;&lt;br /&gt;That should be it, you should be up and running again. One last thing, track down the person that installed the evaluation version and cut off their hands. :-)&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1166140822381068480?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1166140822381068480/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1166140822381068480' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1166140822381068480'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1166140822381068480'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2011/01/biztalk-server-evaluation-version.html' title='BizTalk Server Evaluation Version Upgrade to Full Version'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6033992469217357611</id><published>2010-10-06T14:01:00.004+01:00</published><updated>2010-10-06T15:10:10.405+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SSL'/><category scheme='http://www.blogger.com/atom/ns#' term='Threat Management Gateway'/><category scheme='http://www.blogger.com/atom/ns#' term='TMG'/><category scheme='http://www.blogger.com/atom/ns#' term='InfoPath'/><category scheme='http://www.blogger.com/atom/ns#' term='HTTPS'/><category scheme='http://www.blogger.com/atom/ns#' term='browser'/><title type='text'>InfoPath 2007 and Forms Services - Deployment Part 2</title><content type='html'>Forgive me reader, it has been a while since my last post.&lt;br /&gt;&lt;br /&gt;I have a project that involved deploying three InfoPath browser-enabled forms made available on a SharePoint 2007 site.  The site is an extranet site, accessed over the Internet by users who use an AD account and password to login. &lt;br /&gt;&lt;br /&gt;The infrastruture uses ForeFront Threat Management Gateway (the successor to ISA server). Now TMG is a bit of a God-send for developers because it handles SSL for you. TMG hold the Server Certificate and takes all inbound https requests and maps them to http requests on port 80.  Very neat, because it means that I can focus on developing the SharePoint site and not worry about SSL.  Not quite. &lt;br /&gt;&lt;br /&gt;I ran into some issues with the InfoPath forms. They worked absolutely fine when called internally: reading data from a web service upon load and then submitting to a web service on Submit.  When I called the same forms when accessing the site externally, then I got several problems.&lt;br /&gt;&lt;br /&gt;1. I could not load the forms at all initially.&lt;br /&gt;&lt;br /&gt;2. When the form did load, the company logo would not display.  IE gave me a warning message about unsecure content on the page and I could not disable it even by allowing Mixed Content in IE options. &lt;br /&gt;&lt;br /&gt;3. The third error came when I tried to submit. "The form cannot be submitted to the Web server either because your computer is offline or because the host server is currently unavailable".&lt;br /&gt;&lt;br /&gt;4. When the form closed, I got an error whereas it should have redirected back to the calling page. Again it was working fine internally.&lt;br /&gt;&lt;br /&gt;The first problem is due to the supposed complexity of the url used to call the form (its the passed parameters).  This is TMG rejecting the url.  It is solved by modifying the HTTP policy on the Firewall rule to &lt;strong&gt;uncheck&lt;/strong&gt; the options "Blocking high bit characters " and "Verify Normalization".&lt;br /&gt;&lt;br /&gt;The second problem is fixed by the same solution as the third problem.  If you take a look at the source code there is a variable g_objCurrentFormData that holds the content for the form.  Buried in there you will find the url for the location of the xsn and its "Source" (the url it will return to) but InfoPath replaces the http:// with http:\u002f\u002f.  Isn't that obscure?  The issue is that it is using http and not https so you need to create a Link Translation on the Firewall policy that maps  http:\u002f\u002fcontoso.com  with https:\u002f\u002fcontoso.com.  When that is done it, the form submitted successfully and also displayed the company logo without any warning messages from IE.&lt;br /&gt;&lt;br /&gt;The fourth problem is due to the url for calling the form. It includes an &amp;amp;Source= parameter that is the return url for the form.  But it uses the http url and that won't work externally.  Trying to change it to be https also gave an error.  So in the end I simply removed it, and the form still managed to return to the originating url.  By the way, to force the form in the browser append &amp;amp;OpenIn=Browser.&lt;br /&gt;&lt;br /&gt;So in the end I didn't have to make any changes to my form to make it work externally, it was all down to settings in TMG. &lt;br /&gt;&lt;br /&gt;Go in peace -  and say twenty Hail Mary's.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6033992469217357611?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6033992469217357611/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6033992469217357611' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6033992469217357611'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6033992469217357611'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/10/infopath-2007-and-forms-services.html' title='InfoPath 2007 and Forms Services - Deployment Part 2'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6221802118842897767</id><published>2010-07-18T13:34:00.004+01:00</published><updated>2010-07-18T13:47:04.487+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='remote server'/><category scheme='http://www.blogger.com/atom/ns#' term='MSMQ'/><category scheme='http://www.blogger.com/atom/ns#' term='format name'/><title type='text'>Writing to MSMQ</title><content type='html'>I was recently trying to write a message to MSMQ on a remote server. I knew there were two steps but I didn't realize there was a third.&lt;br /&gt;&lt;br /&gt;1. Modify the Queue name to the correct format&lt;br /&gt;2. On the MSMQ queue give write access to the account you are running under&lt;br /&gt;3. Install MSMQ on the source server&lt;br /&gt;&lt;br /&gt;MSMQ name&lt;br /&gt;The MSMQ format name is a particular structure you need to get right - including the case:&lt;br /&gt;FormatName:DIRECT=OS:&amp;lt;servername&amp;gt;\private$\&amp;lt;queuename&amp;gt;&lt;br /&gt;&lt;br /&gt;Write Access&lt;br /&gt;If your code was running as a web service as mine was, then the App Pool identity must be a domain account and that account needs to have write access to the MSMQ on the target server.&lt;br /&gt;&lt;br /&gt;Install MSMQ locally&lt;br /&gt;I hadn't relaized this. You must install MSMQ in the local server where the code is running. The reason is that it logs messages in an Outbound Queue. This is what you would need if you were running in an off-line situation and then wanted the messages forwarded when you were on-line. I did not relaize that it would also do this even with a permanently connected enviroment. So install MSMQ locally and life will be good.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6221802118842897767?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6221802118842897767/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6221802118842897767' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6221802118842897767'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6221802118842897767'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/07/writing-to-msmq.html' title='Writing to MSMQ'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1991349002969636252</id><published>2010-07-18T12:58:00.006+01:00</published><updated>2010-07-23T17:15:11.327+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='data connections'/><category scheme='http://www.blogger.com/atom/ns#' term='InfoPath 2007'/><category scheme='http://www.blogger.com/atom/ns#' term='deployment'/><category scheme='http://www.blogger.com/atom/ns#' term='managed code'/><category scheme='http://www.blogger.com/atom/ns#' term='UDCX'/><title type='text'>InfoPath 2007 and Forms Services - Deployment</title><content type='html'>I've always hated deploying InfpPath forms to a Production environment because I couldn't figure out how to change the path of any data connections without modifying the data connections with the appropriate url which means installing InfoPath in a Production environment.&lt;br /&gt;&lt;br /&gt;I recently found that with an InfoPath form with managed code you can modify the manifest.xsf manually in NotePad and modify any urls. Publishing the form from VS will then create an XSN with the correct urls. This avoids using the data connection wizrd which will try to access the url.&lt;br /&gt;Now I already new that you can convert the data connections into a UDCX file and then store that in a local data connections library but the path to the data connections library was still hard coded in the XSN with the server name. So if you deploy to production the InfoPath form is looking for the data connection library you used in development. It seemed like a ridiculous situation.&lt;br /&gt;&lt;br /&gt;But finally I stumbled on this &lt;a href="http://creativesharepoint.posterous.com/solution-packaging-infopath-forms-for-sharepo"&gt;post&lt;/a&gt; which explains what to do. The post deploys the InfoPath form as a feature and uses WSP builder to bundle it as a solution.&lt;br /&gt;&lt;br /&gt;The trick is to select "centrally managed data connection library (advanced)" when you modify the data connections. Copy the UDCX out of the data connection library that you used, modify it as desribed in the post. Then upload it in Central Administration -&gt; Application Management -&gt; Manage data connection files. Then deploy your InfoPath forms. Note that if you have managed code, the DLL not only has to be in the GAC but it also needs to be in the Feature folder .&lt;br /&gt;&lt;br /&gt;I have to confess that we had major problems trying to create a feature for the InfoPath forms. It kept saying the form was not browser enabled which it clearly was.  In the end because we only had 3 forms we gave up and installed it manually.  Low and behold it worked in the browser perfectly.  I should add that the forms are really quick to load, so much better than using the InfoPath client.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1991349002969636252?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1991349002969636252/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1991349002969636252' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1991349002969636252'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1991349002969636252'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/07/infopath-2007-and-forms-services.html' title='InfoPath 2007 and Forms Services - Deployment'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-4614553220700218968</id><published>2010-05-13T20:59:00.007+01:00</published><updated>2010-07-18T14:04:44.994+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Forms Services'/><category scheme='http://www.blogger.com/atom/ns#' term='deploy'/><category scheme='http://www.blogger.com/atom/ns#' term='InfoPath'/><category scheme='http://www.blogger.com/atom/ns#' term='browser'/><title type='text'>InfoPath 2007 and Forms Services</title><content type='html'>&lt;div&gt;I struggle to remember how to deploy an InfoPath 2007 form to SharePoint when it is a browser version. So here's the deal.&lt;br /&gt;&lt;br /&gt;Create the InfoPath form and make sure the compatibility is set for browser version and that you make the form Fully Trusted and sign it with a digital certificate.&lt;br /&gt;&lt;br /&gt;Now publish to form to a network location - its a temporary location and you can make it a local directory if you want. But when prompted to provide an alternate name for the form, leave this blank. &lt;/div&gt;&lt;img style="TEXT-ALIGN: center; MARGIN: 0px auto 10px; WIDTH: 320px; DISPLAY: block; HEIGHT: 239px; CURSOR: hand" id="BLOGGER_PHOTO_ID_5495231371734487826" border="0" alt="" src="http://3.bp.blogspot.com/_mnBHRSSHZC8/TEL70U7RExI/AAAAAAAAACU/1TimB48Y8UM/s320/InfoPathPublish.png" /&gt;&lt;br /&gt;&lt;br /&gt;&lt;div&gt;Now go to Central Administration and Application Centre and then select Upload Form template under InfoPath Form Services.&lt;br /&gt;&lt;br /&gt;On the screen click Browse and navigate to where you uploaded the InfoPath template to. Click Verify and check for errors, if OK, then use Upload to upload the form template.&lt;br /&gt;&lt;br /&gt;Go to Manage Form Templates and wait for the form to be installed and then right click and activate it to a site collection. What happens is the form is copied to the Form Template document library of the site collection (use View Site Content on the site collection in question to see the Form Templates library). It also adds the for as a site content type.&lt;br /&gt;&lt;br /&gt;So now go to the top site of the site collection, choose Site Actions and Site Content Types. Scroll down the screen until you see the Content Type under Form Content types.&lt;br /&gt;&lt;br /&gt;If you go to a Form Library and set it for supporting content types, you will be able to add en existing content type and then add the new form template.&lt;br /&gt;&lt;br /&gt;If you go back to the Form Library and select New you should see the new Form type under the list. That will open the form template in the browser window.&lt;br /&gt;&lt;br /&gt;So how is this different when the form has managed "code behind"? Answer: it's the same. In the case of an InfoPath form with managed code, you would create a Visual Studio project as an InfoPath form template and use your XSN as the source form. You will need to have installed the Office 2007 Visual Studio templates. Click on the Manifest.XSF to Open the form. The FormCode.cs has the code behind. From the Project menu you will be able to Build and then Publish the form. The same wizard is displayed and you would publish to a local directory leaving the laternate name of the form blank. The DLL that is created with the form is embedded in the XSN. Upload the form template in the same way.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-4614553220700218968?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/4614553220700218968/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=4614553220700218968' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4614553220700218968'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/4614553220700218968'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/05/infopath-2007-and-forms-services.html' title='InfoPath 2007 and Forms Services'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mnBHRSSHZC8/TEL70U7RExI/AAAAAAAAACU/1TimB48Y8UM/s72-c/InfoPathPublish.png' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6169208487421439974</id><published>2010-05-11T21:14:00.006+01:00</published><updated>2010-05-12T21:37:56.625+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDF'/><category scheme='http://www.blogger.com/atom/ns#' term='mailmerge'/><category scheme='http://www.blogger.com/atom/ns#' term='XML'/><category scheme='http://www.blogger.com/atom/ns#' term='Word'/><category scheme='http://www.blogger.com/atom/ns#' term='Aspose'/><category scheme='http://www.blogger.com/atom/ns#' term='invoice'/><title type='text'>Converting XML to PDF</title><content type='html'>I was looking for an application that would convert an XML file into a PDF document. In fact I was trying to create an invoice as a PDF file were the invoice had originated from Great Plains (an application from the Microsoft Dynamics suite that claims to be an accounts package).&lt;br /&gt;&lt;br /&gt;A colleague recommended Aspose.Words for .NET to me as he was using it for another project. It uses a Word document as a template and sets it up as a mailmerge. Now this made me a bit wary. I've had first hand expereince of programming a Word mailmerge and it wasn't a pleasant outcome. So the thought of doing a mailmerge in Word wasn't appealing. But it turns out that Aspose.Words for .Net has a single line API call that does the mailmerge for you.  Brilliant!&lt;br /&gt;&lt;br /&gt;   doc.MailMerge.ExecuteWithRegions(GetTestOrderTotals());&lt;br /&gt;&lt;br /&gt;But the second problem is a failing in Word 2007 - it doesn't support mailmerge with XML documents as a datasource. So I started looking at the examples that ship with Aspose.Words and stumbled on a Sales Invoice demo. In this case the Word document was using the NorthWinds Access database as the mailmerge source. In fact it was using 3 different views for the order header, the order line items and the order totals.&lt;br /&gt;&lt;br /&gt;So how was I going to make that work with my XML source? A few minutes Googling gave me the answer. Word is simply using DataTables as the datasource so all I had to do was create a new DataTable with the same name as the one the Word document expected and create the appropriate columns with the correct data types. Then create a new row in the datatable and pass in the values extracted from the XML document. Bingo.&lt;br /&gt;&lt;br /&gt; string Total = GetFieldFromXml(xmldoc, "eConnect/SOPTransactionType/taSopHdrIvcInsert/DOCAMNT");&lt;br /&gt; // other strings declared and assigned here&lt;br /&gt; ds.Tables.Add("OrderTotals");&lt;br /&gt; ds.Tables[0].Columns.Add("OrderID");&lt;br /&gt; ds.Tables[0].Columns.Add("Subtotal");&lt;br /&gt; ds.Tables[0].Columns.Add("Freight");&lt;br /&gt; ds.Tables[0].Columns.Add("Total");&lt;br /&gt; ds.Tables[0].Rows.Add(OrderID, Subtotal, Freight, Total);&lt;br /&gt;&lt;br /&gt;The order line items was easy to solve - I just created a DataRow for each node within my list of line items in the XML message.&lt;br /&gt;&lt;br /&gt;What about creating the PDF document? Easy, just one line of code in Aspose.Words to specify that a PDF version is required and to open in the Web browser. I just did the usual trick of specifying the Response.ContentHeader to be application/pdf.&lt;br /&gt;&lt;br /&gt;  HttpResponse resp = Context.Response;&lt;br /&gt;  System.Text.Encoding enc = System.Text.Encoding.GetEncoding("ISO-8859-1");&lt;br /&gt;  resp.ContentEncoding = enc;&lt;br /&gt;  resp.ContentType = "application/pdf";&lt;br /&gt; // now display PDF in browser&lt;br /&gt;  doc.Save("Aspose.Words.Demos.pdf", SaveFormat.Pdf, SaveType.OpenInBrowser, resp);&lt;br /&gt;&lt;br /&gt;I was amazed how simple it was to create a PDF invoice. The great benefit of Aspose.Words is the use of the Word document as a template. It's a snip to modify the layout to get what you want. If you want to add extra fields you'll need to modify the views in Access to produce extra columns. No problem for me because I'm an old hand at Access but if you are unfamiliar with it then you might want to reconsider this option.  But this is a great solution for my needs.  Watch out though there is license cost to pay!&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6169208487421439974?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6169208487421439974/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6169208487421439974' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6169208487421439974'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6169208487421439974'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/05/converting-xml-to-pdf.html' title='Converting XML to PDF'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8525657351508841490</id><published>2010-01-21T13:56:00.009Z</published><updated>2010-01-21T14:20:34.318Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='telnet'/><category scheme='http://www.blogger.com/atom/ns#' term='SMTP'/><category scheme='http://www.blogger.com/atom/ns#' term='email'/><category scheme='http://www.blogger.com/atom/ns#' term='commands'/><title type='text'>Telnet commands to Send Email</title><content type='html'>I can never remember the commands to send an email via Telnet so here they are again mostly for my benefit. Examples of &amp;lt;smtp server&amp;gt;  are &lt;br /&gt;localhost&lt;br /&gt;smtp.domain.com&lt;br /&gt;&lt;br /&gt;C:\windows&amp;gt;telnet &amp;lt;smtp server&amp;gt; 25&lt;br /&gt;&lt;em&gt;Which should return &lt;/em&gt;&lt;br /&gt;Connected to &amp;lt;smtp server&amp;gt;&lt;br /&gt;&lt;br /&gt;HELO &amp;lt;smtp server&amp;gt;&lt;br /&gt;&lt;br /&gt;MAIL FROM: admin@domain.com&lt;br /&gt;&lt;br /&gt;RCPT TO: chuck@disney.com&lt;br /&gt;&lt;br /&gt;DATA&lt;br /&gt;Subject:  Subject line of email&lt;br /&gt;This text goes in the body of the email&lt;br /&gt;&amp;lt;CR&amp;gt;.&amp;lt;CR&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;em&gt;Which should return &lt;/em&gt;&lt;br /&gt;250 2.0.0 ???????? Message accepted for delivery&lt;br /&gt;or&lt;br /&gt;250 2.0.0 ???????? Message queued&lt;br /&gt;&lt;br /&gt;IMPORTANT: The MAIL FROM email address should be a valid email address. Not only must the domain.com be the same domain the SMTP server is in, but don't assume that a made up email name will work.  I've wasted hours trying to figure out why an email was not sent just because I didn't use a valid "mail from" address.  &lt;br /&gt;&lt;br /&gt;Should you not be able to connect to the SMTP server using the telnet command it may be because you have a firewall on the server that is blocking all outbound traffic on port 25.  Or you've get the wrong SMTP server name.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8525657351508841490?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8525657351508841490/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8525657351508841490' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8525657351508841490'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8525657351508841490'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/01/telnet-commands-to-send-email.html' title='Telnet commands to Send Email'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-3684384981820140875</id><published>2010-01-21T13:29:00.005Z</published><updated>2010-01-21T14:17:16.942Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Invalid handle'/><category scheme='http://www.blogger.com/atom/ns#' term='SourceSafe'/><category scheme='http://www.blogger.com/atom/ns#' term='VSS'/><category scheme='http://www.blogger.com/atom/ns#' term='error'/><title type='text'>Invalid handle error in Visual Source Safe</title><content type='html'>I was getting an "Invalid handle" error message the other day when trying to access Visual Source Safe and it drove me mad for a couple of days until I found a solution. So I thought I would blog it in case you run across the same problem.&lt;br /&gt;I was at a customer site using my laptop which was not connected to the customer's domain.  When I plug in the network cable I get issued an IP address from their DHCP server.  I then fire up my Virtual Machine with my development environment on it including Visual Source Safe 2005.  The virtual machine network connections are configured so that it too is issued an IP address from the customer's DHCP.  &lt;br /&gt;Using the logon credentials the customer has issued me, I can connect to servers and file shares on their domain.  &lt;br /&gt;Now the Visual Source Safe database was located on one of the customer's servers and I noticed that the network connection was unreliable.  At times when I pinged the server I got "request timed out" or "host destination unreachable". The result was when I opened Visual Source Safe sometimes it would work just fine and other times it would give me the "Invalid handle" error.  It got to a point where I was unable to connect to Source Safe for several days.&lt;br /&gt;The solution as it turned out was quite simple.  I mapped a drive letter to  a network share on the VSS server.  Note it's important to map a drive letter, just using "Run" to connect to the share was not enough.  Now of course if you can't even ping the server then mapping the drive won't work either. But I found that once I was able to map the drive the "Invalid handle" error would go away - at least for the rest of the day.  I still find that each day I need to disconnect the drive and then reconnect but it's a small price to pay to have access to VSS for the rest of the day.  &lt;br /&gt;So if you come across the same situation I hope this helps you to solve it.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-3684384981820140875?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/3684384981820140875/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=3684384981820140875' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3684384981820140875'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/3684384981820140875'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2010/01/invalid-handle-error-in-visual-source.html' title='Invalid handle error in Visual Source Safe'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7255014402917556847</id><published>2009-05-21T20:25:00.004+01:00</published><updated>2009-05-21T21:15:08.949+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDF'/><category scheme='http://www.blogger.com/atom/ns#' term='content type'/><category scheme='http://www.blogger.com/atom/ns#' term='Integer division by zero'/><category scheme='http://www.blogger.com/atom/ns#' term='Download'/><category scheme='http://www.blogger.com/atom/ns#' term='Lynx'/><title type='text'>Lynx Text Browser - Downloading Document Error</title><content type='html'>I was developing an Accessible web site the other day which included downloading of documents (either Word, Excel or PDF).  It just contains an anchor tag for the document which will open the document in Acrobat Reader allowing the user to "Save As".  It worked as designed in Internet Explorer and FireFox but gave an error when I tried it in the Lynx Text Browser.  The error message was:&lt;br /&gt;&lt;br /&gt;The exception Integer division by zero.&lt;br /&gt; (0xc0000094) occurred in the application at location 0x00451c24.&lt;br /&gt;&lt;br /&gt;There is not a lot of technical help around Lynx and Google didn't offer any meaningful results.  But I found that I could download a text file in Lynx without problem so I figured it must be something to do with the inability to recognise the PDF file type.  &lt;br /&gt;&lt;br /&gt;After some more research I found an obscure attribute for the Anchor tag in HTML.  This is the "type" attribute in which you can add the content type. So to the Anchor tag for the document I added &lt;br /&gt;&lt;br /&gt;type="application/pdf" &lt;br /&gt;&lt;br /&gt;and that did the trick.  It appears that Lynx requires this extra hint of the file type to avoid the error shown above.  I also added the type attribute for the other file types for good measure and it all works fine now.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7255014402917556847?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7255014402917556847/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7255014402917556847' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7255014402917556847'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7255014402917556847'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/lynx-text-browser-downloading-document.html' title='Lynx Text Browser - Downloading Document Error'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-2402992059238550508</id><published>2009-05-18T19:48:00.009+01:00</published><updated>2009-05-18T20:51:14.484+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Lists'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='Reports'/><category scheme='http://www.blogger.com/atom/ns#' term='SQL Server Reporting Services 2005'/><title type='text'>Creating a SQL Server Reporting Services Report from a SharePoint List</title><content type='html'>Although I've found blogs that explain how you can create a SQL Server Reporting Services (SSRS) report from a SharePoint list I've found just as many that say it can't be done.  The explanation for the two conflicting views is (IMHO) because there is an epectation that because SharePoint lists are stored in SQL Server that you can query them directly at the database level. That is certainly not the case. If you try accessing the database directly then you deserve all the bad things that will befall you! &lt;br /&gt;&lt;br /&gt;The correct answer is yes, you can use SharePoint lists as a datasource but via the SharePoint web services. The SharePoint web services can be found in the _vti_bin directory of each SharePoint web application and the web service you want to interrogate to get at Lists is called lists.asmx. This &lt;a href="http://www.codeproject.com/KB/reporting-services/ReportFromSharePoint.aspx"&gt;blog&lt;/a&gt; on Code Project explains how to do it quite well.&lt;br /&gt;&lt;br /&gt;So here is how you go about it. Start off in VS 2005 and create a new Reporting Services project. Add a Shared Datasource and make it of type XML, then add the url to the web service:  e.g. http://&lt;servername&gt;/_vti_bin/lists.asmx.  You can optionally add the full path to the site e.g. http://&lt;servername&gt;/sites/&lt;sitename&gt;/_vti_bin/lists.asmx because this still works although you won't find this path in IISAdmin.  &lt;br /&gt;Then create a new report based on this datasource and add the following for the Query string &lt;br /&gt;&lt;br /&gt;&amp;lt;Query&amp;gt;&lt;br /&gt;   &amp;lt;SoapAction&amp;gt;http://schemas.microsoft.com/sharepoint/soap/GetListItems&amp;lt;/SoapAction&amp;gt;&lt;br /&gt;   &amp;lt;Method Namespace="http://schemas.microsoft.com/sharepoint/soap/" Name="GetListItems"&amp;gt;&lt;br /&gt;      &amp;lt;Parameters&amp;gt;&lt;br /&gt;         &amp;lt;Parameter Name="listName"&amp;gt;&lt;br /&gt;            &amp;lt;DefaultValue&amp;gt;{DCED6771-E498-4BC5-B44D-BE71C5D7B6C8}&amp;lt;/DefaultValue&amp;gt;&lt;br /&gt;         &amp;lt;/Parameter&amp;gt;&lt;br /&gt;         &amp;lt;Parameter Name="viewName"&amp;gt;&lt;br /&gt;            &amp;lt;DefaultValue&amp;gt;{C63CFF34-647C-4FFA-9E20-DA1B6737380A}&amp;lt;/DefaultValue&amp;gt;&lt;br /&gt;         &amp;lt;/Parameter&amp;gt;&lt;br /&gt;         &amp;lt;Parameter Name="rowLimit"&amp;gt;&lt;br /&gt;            &amp;lt;DefaultValue&amp;gt;9999&amp;lt;/DefaultValue&amp;gt;&lt;br /&gt;         &amp;lt;/Parameter&amp;gt;&lt;br /&gt;      &amp;lt;/Parameters&amp;gt;&lt;br /&gt;   &amp;lt;/Method&amp;gt;&lt;br /&gt;   &amp;lt;ElementPath IgnoreNamespaces="True"&amp;gt;*&amp;lt;/ElementPath&amp;gt;&lt;br /&gt;&amp;lt;/Query&amp;gt;&lt;br /&gt;&lt;br /&gt;Although only the listName parameter is mandatory you should always add viewName because otherwise the default view is used and this can be changed by a user and may mess up you report.  Also be sure to add rowLimit because the default is 100 rows and you want to be sure you report on all the data. &lt;br /&gt;&lt;br /&gt;Note that all the parameter names are case sensitive and you need to use the GUID rather than the name of the list and view.  You might get some success with using the name but several other bloggers have reported this doesn't always work.  You can find the GUID in SharePoint by simply editing the list or the view and you will see it in the URL of the Internet Explorer address bar.   Just replace %2D with a hyphen and the %7B and %7D with curly braces {}. &lt;br /&gt;&lt;br /&gt;Once you added this as your query string you should see a list of fields which you can add to your report. Note that SSRS doesn't recognise the data type of the fields and everything returned is treated as a string. Use the CInt and CDate functions (and the other converstion functions) to convert the data into the correct format - particularly if you want to include totals in your reports. &lt;br /&gt; &lt;br /&gt;The 'lookup'  and 'people and groups' fields are of the format  99#;text  where 99 is the ID.  To handle this goto Visual Studio, select the Report menu -&gt; Report Properties and select the Code tab and then embed a function to strip off the stuff you don't need. This &lt;a href="http://www.hezser.de/blog/archive/2007/02/22/reporting-on-sharepoint-lists.aspx"&gt;blog&lt;/a&gt; had a good example of the code you need.&lt;br /&gt;&lt;br /&gt;Once you've built your report, then deploy it to Reporting Services in the same way but create a datasource in Report Manager using the same approach you did in Visual Studio (connection type: XML, connection string: http://&lt;servername&gt;/_vti_bin/lists.asmx). Set the credentials to be Windows Integrated and be sure that users running the report are able to access the SharePoint list.&lt;br /&gt;&lt;br /&gt;One final point. If you were hoping to combine data from multiple lists within a site collection (where the list structure is identical) then you will have to write your own web service to do this and then call it from SSRS using the XML connection type. Performance won't be blistering if you have a lot of sites but you can get around this by scheduling the report to run at night.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-2402992059238550508?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/2402992059238550508/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=2402992059238550508' title='7 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/2402992059238550508'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/2402992059238550508'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/creating-sql-server-reporting-services.html' title='Creating a SQL Server Reporting Services Report from a SharePoint List'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>7</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6071669813572802006</id><published>2009-05-16T08:39:00.006+01:00</published><updated>2011-08-24T21:39:04.028+01:00</updated><title type='text'>SharePoint Datasheet View Error - "The selected cells are read-only"</title><content type='html'>The other day when editing a list in the datasheet view in MOSS 2007 I got "The selected cells are read-only" error. I found a few posts that indicated that not all of a lists data types are supported in datasheet view, but that wasn't my problem because I only had single line text, number and currency data types.&lt;br /&gt;&lt;br /&gt;The problem was that I needed folders in my list and although I could edit the datasheet at the root level, I got the read-only error whenever I tried to edit the datasheet within a folder. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://3.bp.blogspot.com/_mnBHRSSHZC8/Sg5vzSSpCQI/AAAAAAAAACE/kA-cwwocKjQ/s1600-h/AccessIcon.JPG"&gt;&lt;img alt="" border="0" id="BLOGGER_PHOTO_ID_5336325535354652930" src="http://3.bp.blogspot.com/_mnBHRSSHZC8/Sg5vzSSpCQI/AAAAAAAAACE/kA-cwwocKjQ/s320/AccessIcon.JPG" style="cursor: hand; float: left; height: 200px; margin: 0px 10px 10px 0px; width: 251px;" /&gt;&lt;/a&gt;On one of my VPC images I had no problems and then I spotted the little Access icon in the top left hand corner of the datasheet. Comparing this to the VPC image where I was getting the error I noticed that the Access icon was missing. On this VPC Office 2007 was installed EXCEPT for Access. So&amp;nbsp;I just installed Access and the error went away. &lt;br /&gt;&lt;br /&gt;Please note that the datasheet view does require the Office Web Components to be installed on the CLIENTS for datasheet view to work at all. What I haven't checked yet is whether clients needs Access 2007 in order to edit cells when in a folder of a list. When I find out I'll update this post.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6071669813572802006?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6071669813572802006/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6071669813572802006' title='5 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6071669813572802006'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6071669813572802006'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/sharepoint-datasheet-view-error.html' title='SharePoint Datasheet View Error - &quot;The selected cells are read-only&quot;'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://3.bp.blogspot.com/_mnBHRSSHZC8/Sg5vzSSpCQI/AAAAAAAAACE/kA-cwwocKjQ/s72-c/AccessIcon.JPG' height='72' width='72'/><thr:total>5</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8307005438756614771</id><published>2009-05-15T14:27:00.007+01:00</published><updated>2009-05-15T14:55:52.457+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='Event Hamdler'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='activity'/><category scheme='http://www.blogger.com/atom/ns#' term='CRM 4.0'/><title type='text'>SharePoint EventHandler that creates a CRM 4.0 activity</title><content type='html'>In a previous &lt;a href="http://charlesemes.blogspot.com/2009/05/view-sharepoint-documents-in-i-frame-in.html"&gt;post&lt;/a&gt; I referrred to linking CRM 4.0 to a SharePoint document library to display documents in an I-Frame.  I also wanted to demonstrate how adding a document into a SharePoint library could create a CRM activity (in my case a completed one).  &lt;br /&gt;&lt;br /&gt;There seems to be very few CRM 4.0 examples on the web and the SDK is not much use. So I hope this makes your life easier although I confess I am blogging it so I can find this code again!&lt;br /&gt;&lt;br /&gt;A few limitations of this approach: I've used a flat folder structure in SharePoint for each instance of the CRM entity I'm connecting to. I'm also using the incident id as the folder name because I'm using the service request entity. The GUID folder name is not something you could roll out in production. &lt;br /&gt;&lt;br /&gt;I've created the activity as the same person (the administrator) and I've been lazy again and hard-coded the GUID. You'll need to change this line:&lt;br /&gt;activity.ownerid.Value = new Guid("{5D76458D-D728-DE11-99E5-0003FF6875B2}");&lt;br /&gt;&lt;br /&gt;You will also need to change the service.url and the credentials. Don't forget to add a web reference to the CRMService.asmx and call it CrmService.  &lt;br /&gt;&lt;br /&gt;I've put the event handler on the ItemAdding event which is not ideal as you can cancel from adding the document but the event will still be created. &lt;br /&gt;&lt;br /&gt;This by the way is how I got the document path into the Letter entity so that I could use it for rendering the document in this &lt;a href="http://charlesemes.blogspot.com/2009/05/view-pdf-file-stored-in-sharepoint.html"&gt;post&lt;/a&gt;. &lt;br /&gt;&lt;br /&gt;namespace CreateCRMActivity&lt;br /&gt;{&lt;br /&gt;    public class CreateActivityEventHandler : SPItemEventReceiver&lt;br /&gt;    {&lt;br /&gt;        public override void ItemAdded(SPItemEventProperties properties)&lt;br /&gt;        {&lt;br /&gt;            SPWeb webOrig = null;&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                webOrig = properties.OpenWeb();&lt;br /&gt;                CreateActivity(properties);&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                // record error message&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                webOrig.Close();&lt;br /&gt;            }&lt;br /&gt;        }&lt;br /&gt;        private void CreateActivity(SPItemEventProperties properties)&lt;br /&gt;        {&lt;br /&gt;            SPWeb webOrig = properties.OpenWeb();&lt;br /&gt;            string docpath = "";&lt;br /&gt;            string entityID = "";&lt;br /&gt;            string name = "";&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                docpath = properties.AfterUrl;&lt;br /&gt;// docpath of the form http://servername/sites/sitename/Shared%20Documents/AD66458D-D728-DE11-99E5-0003FF6875C2/mydocument.pdf&lt;br /&gt;                &lt;br /&gt;                int start = docpath.IndexOf("Documents/") + 10;&lt;br /&gt;                int end = docpath.LastIndexOf("/");&lt;br /&gt;                entityID = docpath.Substring(start, end - start); &lt;br /&gt;                // e.g. AD66458D-D728-DE11-99E5-0003FF6875C2&lt;br /&gt;&lt;br /&gt;                name = docpath.Substring(end + 1, docpath.Length - end - 5);  &lt;br /&gt;                 // remove the extension  e.g. mydocument&lt;br /&gt;&lt;br /&gt;                // Set up the CRM Service.&lt;br /&gt;                CrmService.CrmAuthenticationToken token = new CrmService.CrmAuthenticationToken();&lt;br /&gt;                // You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.&lt;br /&gt;                token.AuthenticationType = 0;&lt;br /&gt;                token.OrganizationName = "MyDemo";&lt;br /&gt;&lt;br /&gt;                CrmService.CrmService service = new CrmService.CrmService();&lt;br /&gt;                service.Url = "http://localhost:5555/mscrmservices/2007/crmservice.asmx";&lt;br /&gt;                service.CrmAuthenticationTokenValue = token;&lt;br /&gt;                service.Credentials = new System.Net.NetworkCredential("Administrator", "Password1", "Integration");        //CredentialCache.DefaultCredentials;&lt;br /&gt;                letter activity = new letter();&lt;br /&gt;                // activitypointer activity = new activitypointer();&lt;br /&gt;                activity.subject = "Letter - " + name;&lt;br /&gt;                activity.regardingobjectid = new Lookup();&lt;br /&gt;                activity.regardingobjectid.type = EntityName.incident.ToString();&lt;br /&gt;                activity.regardingobjectid.Value = new Guid("{" + entityID + "}");&lt;br /&gt;&lt;br /&gt;                activity.uklg_linkeddocument = properties.WebUrl + "/" + docpath;&lt;br /&gt;&lt;br /&gt;                activity.ownerid = new Owner();&lt;br /&gt;                activity.ownerid.type = EntityName.systemuser.ToString();&lt;br /&gt;                activity.ownerid.Value = new Guid("{5D76458D-D728-DE11-99E5-0003FF6875B2}");&lt;br /&gt;                Guid activityguid = service.Create(activity);&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;                // task is created now set it to completed&lt;br /&gt;                SetStateLetterRequest Lstate = new SetStateLetterRequest();&lt;br /&gt;                Lstate.EntityId = activityguid;&lt;br /&gt;                Lstate.LetterState = LetterState.Completed;&lt;br /&gt;                Lstate.LetterStatus = 4;&lt;br /&gt;&lt;br /&gt;                SetStateLetterResponse stateSet = (SetStateLetterResponse)service.Execute(Lstate);&lt;br /&gt;                service.Dispose();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;                throw ex;&lt;br /&gt;            }&lt;br /&gt;            finally&lt;br /&gt;            {&lt;br /&gt;                webOrig.Close();&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        &lt;br /&gt;    }&lt;br /&gt;}&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8307005438756614771?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8307005438756614771/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8307005438756614771' title='4 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8307005438756614771'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8307005438756614771'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/sharepoint-eventhandler-that-creates.html' title='SharePoint EventHandler that creates a CRM 4.0 activity'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>4</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8208183743344444917</id><published>2009-05-15T13:30:00.010+01:00</published><updated>2009-05-15T14:25:55.118+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='WSS'/><category scheme='http://www.blogger.com/atom/ns#' term='Document Library'/><category scheme='http://www.blogger.com/atom/ns#' term='I-Frame'/><category scheme='http://www.blogger.com/atom/ns#' term='Dynamics CRM 4.0'/><title type='text'>View SharePoint Documents in an I-Frame in CRM 4.0</title><content type='html'>Many CRM 4.0 users want to be able to store documents against entities. While attaching documents is one approach a better solution is to use SharePoint as the document store.  You don't have to use full blown SharePoint, WSS is perfectly adequate for this solution.  &lt;br /&gt;The approach I've taken is to use a SharePoint document library and create folders for each instance of a CRM entity (in my case service requests).  You'll need some code in CRM 4.0 that will create a new folder in SharePoint when a service request is created.  And you'll need some way of labelling the folder so it's obvious which service request its referring to (the Case Reference appended with the Customer name might be a good solution).  I've been lazy and just used the incidentid as the folder name for this example.  &lt;br /&gt;I created a 'Correspondence' tab on the Service Request form. I added an I-Frame and the url to my web page.  I checked the option to "Pass record object type code and unique identifier as parameters".&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1qHybvIvI/AAAAAAAAAB8/Qj41d0t8ca0/s1600-h/WSSdocList.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 167px;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1qHybvIvI/AAAAAAAAAB8/Qj41d0t8ca0/s320/WSSdocList.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5336037815533642482" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;Obvioulsy if you click on the link, it opens the document from SharePoint.  &lt;br /&gt;&lt;br /&gt;The ASP.net page just has a literal on it which will render a table of documents from the relevant document library folder.  It passes the incident id onto a web service.  &lt;br /&gt;So the Page_Load event code is &lt;br /&gt;        string CRMGUID = "";&lt;br /&gt;        if (Request.QueryString["id"] != null)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;        CRMGUID = Request.QueryString["id"].ToString();&lt;br /&gt;        Service ws = new Service();&lt;br /&gt;        XmlDocument xmldom = new XmlDocument();&lt;br /&gt;        xmldom = ws.GetSPSDocs(CRMGUID);&lt;br /&gt;&lt;br /&gt;        Literal1.Text = xmldom.InnerXml;&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;The Web Service code is given below. Note that I am returning a fragment of HTML wrapped up in a top level DIV tag so I can return it as XML.  &lt;br /&gt;Also note that this solution assumes that the folders are all in a flat structure underneath the document library.  You'll need a more scalable solution if the number of documents will be large.  It would be better to use a CAML query to return just the documents you are interested in rather than the approach I use in this example, but I was in a hurry.  It also needs to be changed to support other file types than the three I chose.  &lt;br /&gt;&lt;br /&gt;    [WebMethod]&lt;br /&gt;    public XmlDocument  GetSPSDocs(string CRMGUID) {&lt;br /&gt;&lt;br /&gt;        SPLists.Lists ws = new SPLists.Lists();&lt;br /&gt;        ws.Url = "http://biztalkcrm:8080/sites/complaints";&lt;br /&gt;&lt;br /&gt;        string sharePointSiteUrl = "http://biztalkcrm:8080/sites/complaints";&lt;br /&gt;        string strListName = "SharedDocuments";&lt;br /&gt;        string m_UserName = "Administrator";&lt;br /&gt;        string m_Domain = "BIZTALKCRM.local";&lt;br /&gt;        string m_Pword = "Password1";&lt;br /&gt;        XmlDocument xmldom = new XmlDocument();&lt;br /&gt;        string html = "";&lt;br /&gt;        // {} not used in folder names&lt;br /&gt;        CRMGUID = CRMGUID.Replace("{", "");&lt;br /&gt;        CRMGUID = CRMGUID.Replace("}", "");&lt;br /&gt;&lt;br /&gt;   &lt;br /&gt;        NameTable nt = new NameTable();&lt;br /&gt;        XmlNamespaceManager nsmgr = new XmlNamespaceManager(nt);&lt;br /&gt;&lt;br /&gt;        nsmgr.AddNamespace("rs", "urn:schemas-microsoft-com:rowset");&lt;br /&gt;        nsmgr.AddNamespace("z", "#RowsetSchema");&lt;br /&gt;        string filename = "";&lt;br /&gt;        string fileurl = "";&lt;br /&gt;        XmlNodeList results = null;&lt;br /&gt;        DateTime lastmodified ;&lt;br /&gt;        html += "&amp;lt;div&amp;gt;&amp;lt;table width=\"80%\" border=\"1\" style=\"border-collapse: collapse;\" title=\"Document list\"&amp;gt;";&lt;br /&gt;        html += "&amp;lt;tr&amp;gt;&amp;lt;th class=\"tableheader\"&amp;gt;Type&amp;lt;/th&amp;gt;&amp;lt;th  class=\"tableheader\"&amp;gt;Name&amp;lt;/th&amp;gt;&amp;lt;th  class=\"tableheader\"&amp;gt;Last modified&amp;lt;/th&amp;gt;&amp;lt;/tr&amp;gt;";&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            &lt;br /&gt;            XmlNode nodeList = GetListByName(sharePointSiteUrl, strListName, null, m_UserName, m_Domain, m_Pword);&lt;br /&gt;            if (nodeList != null)&lt;br /&gt;            {&lt;br /&gt;                results = nodeList.SelectNodes("//z:row[@ows_FileRef[contains(.,'" + CRMGUID + "')]]", nsmgr);&lt;br /&gt;                //results = nodeList.SelectNodes("//z:row", nsmgr);&lt;br /&gt;            }&lt;br /&gt;            if (results != null)&lt;br /&gt;            {&lt;br /&gt;                foreach (XmlNode nodeDoc in results)&lt;br /&gt;                {&lt;br /&gt;                    XmlDocument xDoc = new XmlDocument();&lt;br /&gt;&lt;br /&gt;                    xDoc.LoadXml(nodeDoc.OuterXml);&lt;br /&gt;&lt;br /&gt;                    html += "&amp;lt;tr&amp;gt;";&lt;br /&gt;                    html += "&amp;lt;td&amp;gt;";&lt;br /&gt;                    if (GetXmlAttribute(xDoc, "//@ows_LinkFilename", nsmgr).IndexOf("pdf") &amp;gt; 0)&lt;br /&gt;                    {&lt;br /&gt;                        html += "&amp;lt;img src=\"http://localhost:8080/_layouts/images/pdf.jpg\" /&amp;gt;";&lt;br /&gt;                    }&lt;br /&gt;                    if (GetXmlAttribute(xDoc, "//@ows_LinkFilename", nsmgr).IndexOf("msg") &amp;gt; 0)&lt;br /&gt;                    {&lt;br /&gt;                        html += "&amp;lt;img src=\"http://localhost:8080/_layouts/images/icmsg.gif\" /&amp;gt;";&lt;br /&gt;                    }&lt;br /&gt;                    if (GetXmlAttribute(xDoc, "//@ows_LinkFilename", nsmgr).IndexOf("doc") &amp;gt; 0)&lt;br /&gt;                    {&lt;br /&gt;                        html += "&amp;lt;img src=\"http://localhost:8080/_layouts/images/icdoc.gif\" /&amp;gt;";&lt;br /&gt;                    }&lt;br /&gt;                    html += "&amp;lt;/td&amp;gt;";&lt;br /&gt;                    filename = GetXmlAttribute(xDoc, "//@ows_LinkFilename", nsmgr);&lt;br /&gt;                    fileurl = GetXmlAttribute(xDoc, "//@ows_FileRef", nsmgr);&lt;br /&gt;                    fileurl = fileurl.Substring(fileurl.IndexOf("#") + 1, fileurl.Length - fileurl.IndexOf("#") - 1);&lt;br /&gt;                    fileurl = "http://biztalkcrm:8080/" + fileurl;&lt;br /&gt;                    html += "&amp;lt;td&amp;gt;";&lt;br /&gt;                    html += "&amp;lt;a href='" + fileurl + "'&amp;gt;" + filename + "&amp;lt;/a&amp;gt;";&lt;br /&gt;                    html += "&amp;lt;/td&amp;gt;";&lt;br /&gt;                    lastmodified = Convert.ToDateTime(GetXmlAttribute(xDoc, "//@ows_Modified", nsmgr));&lt;br /&gt;                    html += "&amp;lt;td&amp;gt;";&lt;br /&gt;                    html += lastmodified.ToString("dd/MM/yyyy HH:mm");&lt;br /&gt;                    html += "&amp;lt;/td&amp;gt;";&lt;br /&gt;                    html += "&amp;lt;/tr&amp;gt;";&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        catch (Exception ex)&lt;br /&gt;        {&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;&lt;br /&gt;        html += "&amp;lt;/table&amp;gt;&amp;lt;/div&amp;gt;";&lt;br /&gt;        xmldom.LoadXml(html);&lt;br /&gt;&lt;br /&gt;        return xmldom;&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;The two other procedures are GetListByName and GetXmlAttribute. Please note that you must change the line in GetListByName where I have hard-coded the Guid of the 'All documents' view on my document library.  &lt;br /&gt;string viewName = "{FAD1A412-359A-4FF6-BC1E-0A53934791CD}";&lt;br /&gt;&lt;br /&gt;&lt;br /&gt; public XmlNode GetListByName(string sharePointSiteUrl, string strListName, XmlNode query, string m_UserName, string m_Domain, string m_Pword)&lt;br /&gt;    {&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            SPLists.Lists lists = new SPLists.Lists();&lt;br /&gt;            SPViews.Views views = new SPViews.Views();&lt;br /&gt;&lt;br /&gt;            lists.Url = sharePointSiteUrl + "/_vti_bin/lists.asmx";&lt;br /&gt;            views.Url = sharePointSiteUrl + "/_vti_bin/views.asmx";&lt;br /&gt;&lt;br /&gt;            System.Net.NetworkCredential cred = new System.Net.NetworkCredential(m_UserName, m_Pword, m_Domain);&lt;br /&gt;            lists.Credentials = cred;&lt;br /&gt;            views.Credentials = cred;&lt;br /&gt;&lt;br /&gt;            XmlNode nodeList = null;&lt;br /&gt;&lt;br /&gt;            string strRealListName = "";&lt;br /&gt;&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;                switch (strListName)&lt;br /&gt;                {&lt;br /&gt;                    case "SharedDocuments":&lt;br /&gt;                        strRealListName = "Shared Documents";&lt;br /&gt;                        break;&lt;br /&gt;&lt;br /&gt;                }&lt;br /&gt;              //  string query = "&lt;queryOptions xmlns:SOAPSDK9=\"http://schemas.microsoft.com/sharepoint/soap/\" &gt;’ &lt;Query/&gt;&lt;QueryOptions&gt;&lt;ViewAttributes Scope=\"Recursive\"/&gt;&lt;/QueryOptions&gt;&lt;/queryOptions&gt;";&lt;br /&gt;                XmlDocument temp = new XmlDocument();&lt;br /&gt;              //  search thro all folders&lt;br /&gt;                XmlNode queryOptions =  temp.CreateNode(XmlNodeType.Element,"QueryOptions","");&lt;br /&gt;                queryOptions.InnerXml = "&lt;ViewAttributes Scope=\"Recursive\"/&gt;";&lt;br /&gt;&lt;br /&gt;                // cheat for view name of All documents&lt;br /&gt;                string viewName = "{FAD1A412-359A-4FF6-BC1E-0A53934791CD}";&lt;br /&gt;                nodeList = lists.GetListItems(strRealListName, viewName, query, null, "",queryOptions, null);&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;               // record error message&lt;br /&gt;            }&lt;br /&gt;            return nodeList;&lt;br /&gt;        }&lt;br /&gt;        catch (Exception ex)&lt;br /&gt;        {&lt;br /&gt;            throw ex;&lt;br /&gt;        }&lt;br /&gt;    }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;    public string GetXmlAttribute(XmlNode zrowOuterNode, string XPath, XmlNamespaceManager nsmgr)&lt;br /&gt;    {&lt;br /&gt;&lt;br /&gt;        string strInnerText = "";&lt;br /&gt;        XmlNode thisNode = zrowOuterNode.SelectSingleNode(XPath, nsmgr);&lt;br /&gt;        if (thisNode != null)&lt;br /&gt;        {&lt;br /&gt;            strInnerText = thisNode.InnerText;&lt;br /&gt;        }&lt;br /&gt;        return strInnerText;&lt;br /&gt;&lt;br /&gt;    }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8208183743344444917?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8208183743344444917/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8208183743344444917' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8208183743344444917'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8208183743344444917'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/view-sharepoint-documents-in-i-frame-in.html' title='View SharePoint Documents in an I-Frame in CRM 4.0'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1qHybvIvI/AAAAAAAAAB8/Qj41d0t8ca0/s72-c/WSSdocList.JPG' height='72' width='72'/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-8608954995078865155</id><published>2009-05-15T12:52:00.008+01:00</published><updated>2009-05-15T13:28:59.865+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='PDF'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='WSS'/><category scheme='http://www.blogger.com/atom/ns#' term='WebDAV'/><category scheme='http://www.blogger.com/atom/ns#' term='CRM 4.0'/><title type='text'>View PDF file stored in SharePoint using WEBDAV</title><content type='html'>WEBDAV is a great way to retrieve documents from SharePoint if all you want to do is display them. I was preparing a demo using CRM 4.0 and wanted to display a PDF file stored in a WSS document library within an I-Frame of the letter entity. I have the full url to the file stored in a custom attibute of CRM (uklg_linkeddocument) so I used an ASPX page to render the PDF file.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1ffXn114I/AAAAAAAAAB0/WDio_TCav0M/s1600-h/BlogLetterPDF.JPG"&gt;&lt;img style="cursor:pointer; cursor:hand;width: 320px; height: 234px;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1ffXn114I/AAAAAAAAAB0/WDio_TCav0M/s320/BlogLetterPDF.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5336026126025611138" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;I was only interested in displaying PDF files but it is easy enough to extend to other file formats.&lt;br /&gt;&lt;br /&gt;CRM 4.0:&lt;br /&gt;I edited the Letter Form to include an I-Frame that points to the web page the I create below. Check the option to "Pass record object type code and unique identifier as parameters". I added a custom string attribute called uklg_linkeddocument. {How I poulate this field is covered in another post].&lt;br /&gt;You need to publish the cusomtizations AND refresh the CRM web service to get the new attributes to appear in Intellisense in VS. To do this got to Settings -&gt; Customizations -&gt; Download Web Service Description (WSDL) files. Click on the CRMService.ASMX and copy the url from the browser window that opens.&lt;br /&gt;&lt;br /&gt;VS 2005 Web Project: Include a Web Reference to the CRMService using the url copied in the CRM step. Call the Web Reference: CrmService.&lt;br /&gt;Edit the ASPX of the web page and remove everything except the &lt;@Page&gt; declaration at the top.  &lt;br /&gt;&lt;br /&gt;In the .ASPX.CS file add the following namespaces:&lt;br /&gt;&lt;br /&gt;using System.IO;&lt;br /&gt;using System.Net;&lt;br /&gt;using System.Text;&lt;br /&gt;using CrmService;&lt;br /&gt;&lt;br /&gt;You'll need to change the Organization name for CRM 4.0, the service.url and the credentials you need for accessing CRM 4.0 and SharePoint.&lt;br /&gt;&lt;br /&gt;The Page_Load event code is below:&lt;br /&gt;&lt;br /&gt;protected void Page_Load(object sender, EventArgs e)&lt;br /&gt;    {&lt;br /&gt;        string doc = "";&lt;br /&gt;        string strSourceURL = "";&lt;br /&gt;        try&lt;br /&gt;        {&lt;br /&gt;            if (Request.QueryString["id"] != null)&lt;br /&gt;            {&lt;br /&gt;                // Set up the CRM Service.&lt;br /&gt;&lt;br /&gt;                CrmAuthenticationToken token = new CrmAuthenticationToken();&lt;br /&gt;                // You can use enums.cs from the SDK\Helpers folder to get the enumeration for Active Directory authentication.&lt;br /&gt;                token.AuthenticationType = 0;&lt;br /&gt;                token.OrganizationName = "MyDemo";&lt;br /&gt;&lt;br /&gt;                CrmService.CrmService service = new CrmService.CrmService();&lt;br /&gt;                service.Url = "http://localhost:5555/mscrmservices/2007/crmservice.asmx";&lt;br /&gt;                service.CrmAuthenticationTokenValue = token;&lt;br /&gt;                service.Credentials = new System.Net.NetworkCredential("Administrator", "Password1", "Integration");        //CredentialCache.DefaultCredentials;&lt;br /&gt;&lt;br /&gt;                // letter activity = new letter();&lt;br /&gt;                Guid createdLetterId = new Guid(Request.QueryString["id"].ToString());&lt;br /&gt;                letter activity = (letter)service.Retrieve(EntityName.letter.ToString(), createdLetterId, new AllColumns());&lt;br /&gt;                // path to the linked document&lt;br /&gt;                strSourceURL = activity.uklg_linkeddocument;&lt;br /&gt;&lt;br /&gt;                service.Dispose();&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;            if (strSourceURL != "")&lt;br /&gt;            {&lt;br /&gt;&lt;br /&gt;                doc = strSourceURL;        &lt;br /&gt;&lt;br /&gt;                WebRequest req = WebRequest.Create(strSourceURL);&lt;br /&gt;                req.Method = "GET";&lt;br /&gt;&lt;br /&gt;                // Network Credentials.&lt;br /&gt;                NetworkCredential cred = new NetworkCredential(&lt;br /&gt;                    ConfigurationManager.AppSettings["username"],&lt;br /&gt;                    ConfigurationManager.AppSettings["password"],&lt;br /&gt;                    ConfigurationManager.AppSettings["domain"]);&lt;br /&gt;&lt;br /&gt;                req.Credentials = cred;&lt;br /&gt;&lt;br /&gt;                WebResponse resp = req.GetResponse();&lt;br /&gt;                Stream str = resp.GetResponseStream();&lt;br /&gt;&lt;br /&gt;                int len = (int)resp.ContentLength;&lt;br /&gt;&lt;br /&gt;                byte[] buffer = new byte[len];&lt;br /&gt;                str.Read(buffer, 0, len);&lt;br /&gt;                str.Close();&lt;br /&gt;                str.Dispose();&lt;br /&gt;                resp.Close();&lt;br /&gt;&lt;br /&gt;                Response.Charset = "windows-1252";&lt;br /&gt;                if (doc.EndsWith("pdf"))&lt;br /&gt;                {&lt;br /&gt;                    Response.ContentType = "application/pdf";&lt;br /&gt;                    Response.BinaryWrite(buffer);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;                if (doc.EndsWith("txt"))&lt;br /&gt;                {&lt;br /&gt;                    Response.ContentType = "text/html";&lt;br /&gt;                    ASCIIEncoding enc = new ASCIIEncoding();&lt;br /&gt;                    Response.Write(enc.GetString(buffer, 0, len));&lt;br /&gt;                }&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;br /&gt;        catch (Exception ex)&lt;br /&gt;        {&lt;br /&gt;            Response.Write(ex.Message);&lt;br /&gt;        }     &lt;br /&gt;                    &lt;br /&gt;    }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-8608954995078865155?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/8608954995078865155/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=8608954995078865155' title='2 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8608954995078865155'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/8608954995078865155'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2009/05/view-pdf-file-stored-in-sharepoint.html' title='View PDF file stored in SharePoint using WEBDAV'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://2.bp.blogspot.com/_mnBHRSSHZC8/Sg1ffXn114I/AAAAAAAAAB0/WDio_TCav0M/s72-c/BlogLetterPDF.JPG' height='72' width='72'/><thr:total>2</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-9113315117734731941</id><published>2008-05-16T22:45:00.007+01:00</published><updated>2008-05-16T23:02:16.839+01:00</updated><category scheme='http://www.blogger.com/atom/ns#' term='filter icon GridView display'/><title type='text'>Filter icon in GridView</title><content type='html'>I was trying to do this the other day: display the filter icon on a gridview. Now when you do a sort an icon is displayed in the heading of the gridview as to whether it's an ascending or descending sort but there is no such default behaviour when filtering. Its a problem because you can't tell if a filter is applied or not unless an icon is displayed. &lt;br /&gt;&lt;br /&gt;So here is the solution which you need to plug into the RowDataBound event. It involves checking the value of the FilterFieldname and if its not blank add an image control to the cell on which the filter is placed.  &lt;br /&gt;&lt;br /&gt;There is no need to have the alternate code to remove the filter as it seems to do this anyway.  The image I was using for the filter comes from the images directory in MOSS 2007.  I've displayed the image to the left of the header text which has a slightly better behaviour than putting it on the right.  Below this text I show how to replace the priority icon with a symbol, again quite a common requirement. &lt;br /&gt;&lt;br /&gt;       void gridView_RowDataBound(object sender, GridViewRowEventArgs e)&lt;br /&gt;        {&lt;br /&gt;           // show the filter icon &lt;br /&gt;            if (gridView.FilterFieldName != "")&lt;br /&gt;            {&lt;br /&gt;                int head = 0;&lt;br /&gt;                if (e.Row.RowType == DataControlRowType.Header)&lt;br /&gt;                {&lt;br /&gt;                    for (int i = 0; i &lt; colsNames.Length; i++)&lt;br /&gt;                    {&lt;br /&gt;                        if (colsNames[i].ToString().ToLower() == gridView.FilterFieldName.ToLower())&lt;br /&gt;                        {&lt;br /&gt;                            head = i ;&lt;br /&gt;                            break;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                    Image img = new Image();&lt;br /&gt;                    img.ImageUrl = "_layouts/images/ewr093.gif";&lt;br /&gt;                    img.ImageAlign = ImageAlign.Left;&lt;br /&gt;                    e.Row.Cells[head].Controls.Add(img);&lt;br /&gt;                }&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;           // show the priority icon&lt;br /&gt;           // replace square brackets for img elemet with angle brackets&lt;br /&gt;            if ((e.Row.RowType == DataControlRowType.DataRow))&lt;br /&gt;            {&lt;br /&gt;                int index = 0;&lt;br /&gt;                    for (int i = 0; i &lt; colsNames.Length; i++)&lt;br /&gt;                    {&lt;br /&gt;                        if (colsNames[i].ToString().ToLower() == "priority")&lt;br /&gt;                        {&lt;br /&gt;                            index = i;&lt;br /&gt;                            break;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;                    string priority = e.Row.Cells[index].Text;&lt;br /&gt;                    switch (priority)&lt;br /&gt;                    {&lt;br /&gt;                        case "High":&lt;br /&gt;                            e.Row.Cells[index].Text = "[img src='../_layouts/images/urgent.gif']";&lt;br /&gt;                            break;&lt;br /&gt;                        case "Low":&lt;br /&gt;                            e.Row.Cells[index].Text = "[img src='../_layouts/images/arrdowni.gif']";&lt;br /&gt;                            break;&lt;br /&gt;                        default:&lt;br /&gt;                            e.Row.Cells[index].Text = "";&lt;br /&gt;                            break;&lt;br /&gt;                    }&lt;br /&gt;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-9113315117734731941?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/9113315117734731941/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=9113315117734731941' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/9113315117734731941'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/9113315117734731941'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2008/05/filter-icon-of-gridview.html' title='Filter icon in GridView'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-1613328624730539063</id><published>2008-05-10T23:20:00.011+01:00</published><updated>2009-07-19T15:53:29.127+01:00</updated><title type='text'>Custom Installer and MSIs</title><content type='html'>When deploying software into a Test or Production environment, it’s worth spending the time developing an automated deployment. In the long run it will save time and will hopefully avoid mistakes if a file or a configuration setting is forgotten.  &lt;br /&gt;For me, automated deployment means developing an MSI. You could try zipping files that need to be deployed and writing batch files to install them but you really can’t beat MSIs. An MSI has two outstanding features: they are easy to install and include the ability to uninstall. We are fallible creatures and make mistakes so the ability to uninstall and try again is a necessity. &lt;br /&gt;&lt;br /&gt;Easy installation is important for a Production environment where access may be restricted and you need to provide installation instructions for someone else. Frankly, if I was responsible for a Production environment, I wouldn’t let someone like me anywhere near it! Processes and change management are crucial in a Production environment and this is a different mind set to when you’re developing. &lt;br /&gt;&lt;br /&gt;Anyway, back to MSIs. The point about an MSI is that it will perform checking for disk space and check if the correct software is installed (like .NET Framework 2.0) and will install your files to a target location.  It can add files to the GAC too and then when you uninstall it will delete all trace of the files.   Terrific, but I want to do more. I’ve got a web site and it's got a WEB.CONFIG file that has a number of ‘appsetings’. I need to amend these ‘appsettings’ to be suitable for the target environment. I also need to create a web site and configure the IIS attributes on it (e.g. Integrated Windows authentication and anonymous access disabled). You can get the MSI to do all of this for you by using a Custom Installer.  When you run the MSI wizard you can prompt for the values you want to set in the WEB.CONFIG and then the Custom Installer can complete all the other steps for you. And yes, it can also reverse these steps when you uninstall. &lt;br /&gt;&lt;br /&gt;Start by creating the Custom Installer first. Create a New Project that is a Class Library. Set the namespace and rename the Class to say CustomWebSiteInstaller. Add the following references :&lt;br /&gt;System.Configuration&lt;br /&gt;System.Configuration.Install&lt;br /&gt;System.DirectoryServices&lt;br /&gt;&lt;br /&gt;Add the using declarations at the top of the class and add the following attribute just above the class declaration:&lt;br /&gt;[System.ComponentModel.RunInstallerAttribute(true)]&lt;br /&gt;&lt;br /&gt;Make the class inherit the Installer class by adding after the class name:&lt;br /&gt;: System.Configuration.Install.Installer&lt;br /&gt;&lt;br /&gt;Then you need to override four methods:&lt;br /&gt;public override void Install(System.Collections.IDictionary stateSaver)&lt;br /&gt;{   base.Install(stateSaver);&lt;br /&gt;}&lt;br /&gt;public override void Uninstall(System.Collections.IDictionary savedState)&lt;br /&gt;{&lt;br /&gt;base.Uninstall(savedState);&lt;br /&gt;}&lt;br /&gt;public override void Rollback(System.Collections.IDictionary savedState)&lt;br /&gt;{&lt;br /&gt;base.Rollback(savedState);&lt;br /&gt;}&lt;br /&gt;public override void Commit(System.Collections.IDictionary savedState)&lt;br /&gt;{&lt;br /&gt;base.Commit(savedState);&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;The main method you are going to add code into is the Install but don’t neglect Uninstall and Rollback because if you want to reverse any actions that you add to the Install method you will need to enter them here.  The Rollback method is executed if you hit the Cancel button when running the MSI wizard. The stateSaver is a collection of name/value pairs allowing you to save and restore settings (its how the MSI knows where you’re files are when you want to uninstall because it’s saved the target directory).&lt;br /&gt;&lt;br /&gt;You should be able to compile your Custom Installer now. We’ll come back to add the code in a while because next you need to add a new Setup Project to the solution (you will find it under Other Project Types and ‘Setup and Deployment’. The Setup Project will create the MSI for you so give it a name like WebSiteInstaller. In Solution Explorer right click on ‘WebSiteInstaller’ and select Custom Actions, User Interface and then File System. &lt;br /&gt;&lt;br /&gt;The File System shows 3 default folders:&lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_mnBHRSSHZC8/SCYg7fPHMYI/AAAAAAAAAAU/s3EjfursncY/s1600-h/FileSystem1.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_mnBHRSSHZC8/SCYg7fPHMYI/AAAAAAAAAAU/s3EjfursncY/s320/FileSystem1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198879026215072130" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;The Application Folder is by default &lt;br /&gt;[ProgramFilesFolder][Manufacturer]\[ProductName]&lt;br /&gt;Where Manufacturer and Product name are properties of the Setup Project. It means that the files you add to the Application Folder will be copied into \Program Files\MyCompany\MyProduct but of course you can change this during the installation. &lt;br /&gt;&lt;br /&gt;You might want to add subfolders to the Application Folder, for example a bin directory. &lt;br /&gt;&lt;br /&gt;In the right pane, use right click to add files and assemblies and project output.&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYhcvPHMZI/AAAAAAAAAAc/MryAPa_e_Bo/s1600-h/AddOutput.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYhcvPHMZI/AAAAAAAAAAc/MryAPa_e_Bo/s320/AddOutput.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198879597445722514" /&gt;&lt;/a&gt;&lt;br /&gt;First let’s add the Custom Installer. Select Project Output. In the dialog, select the CustomWebSiteInstaller project and then Primary output and click OK. &lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYh3vPHMaI/AAAAAAAAAAk/Xd8q4vLabQI/s1600-h/PrimaryOutput.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYh3vPHMaI/AAAAAAAAAAk/Xd8q4vLabQI/s320/PrimaryOutput.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198880061302190498" /&gt;&lt;/a&gt;&lt;br /&gt;This will add the DLL into the Application Folder directory as part of the installation and this is mandatory so that you can run your custom actions.  &lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYiIvPHMbI/AAAAAAAAAAs/FFptF6ZJBa8/s1600-h/PrimaryOutput1.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYiIvPHMbI/AAAAAAAAAAs/FFptF6ZJBa8/s320/PrimaryOutput1.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198880353359966642" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;To the Solution you will need to add the Project you need to deploy and then you use this same dialog to add files, assemblies or Project Output. It is aware of dependencies so will add your dependent DLLs automatically.  So add the other files that will make up your application.&lt;br /&gt;&lt;br /&gt;Select the User Interface tab. Note that the user interface displays a list of the default screens which are displayed when you run the MSI wizard. Right click on Start and select Add Dialog. You’ve now got a list of custom screens that you can add into the wizard.  The ones we are interested in are labelled ‘Textboxes (A) , (B) and (C).&lt;br /&gt; &lt;br /&gt;&lt;a href="http://1.bp.blogspot.com/_mnBHRSSHZC8/SCYiWfPHMcI/AAAAAAAAAA0/s_fOIktGmyo/s1600-h/CustomUI.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://1.bp.blogspot.com/_mnBHRSSHZC8/SCYiWfPHMcI/AAAAAAAAAA0/s_fOIktGmyo/s320/CustomUI.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198880589583167938" /&gt;&lt;/a&gt;&lt;br /&gt;If you add Textboxes (A) you will see under properties you have four textboxes referred to as Edit1 through to Edit4 where each has four properties &lt;br /&gt;EditXLabel &lt;br /&gt;EditXProperty&lt;br /&gt;EditXValue&lt;br /&gt;EditXVisible&lt;br /&gt;The Label is the prompt you will see to the left of the text box.  The Property is how you can reference the textbox in code (it’s always uppercase and without spaces). Value is a default value that will be shown. Visible is obvious and you select it as true if you don’t want to show one of the text boxes.  All three dialogs are the same so you can prompt for a maximum of 12 parameters during installation.  &lt;br /&gt;&lt;br /&gt;If you want more or you have more sophisticated requirements then just simple text boxes then you can create your own form in the Custom Installer and refer to the controls on that. Its more effort because all the controls are dynamically created and you have to set size and position etc. So I try and use these 3 built-in dialogs whenever possible.  &lt;br /&gt;So for one of the textboxes set the Label as ‘K2 Server: ’ then set the Property as ‘K2SERVER’.&lt;br /&gt;&lt;br /&gt;Now go to the Custom Actions screen where you will see you have four items each corresponding to the Actions of the Installer: Install, Commit, Rollback, Uninstall.  On the Install item, right click and select Custom Action. &lt;br /&gt;&lt;br /&gt;In the Dialog box double click on the Application Folder.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYipvPHMdI/AAAAAAAAAA8/yihr3UPb3JQ/s1600-h/AddPrimary.JPG"&gt;&lt;img style="float:left; margin:0 10px 10px 0;cursor:pointer; cursor:hand;" src="http://2.bp.blogspot.com/_mnBHRSSHZC8/SCYipvPHMdI/AAAAAAAAAA8/yihr3UPb3JQ/s320/AddPrimary.JPG" border="0" alt=""id="BLOGGER_PHOTO_ID_5198880920295649746" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;There you will see the Primary output of the Custom Installer. Select it so that it adds it under the Install item in the left pane. &lt;br /&gt;When you select this item on the left, the Properties window will show the all important ‘CustomActionData’.  In here you will need to add the parameters you want to pass to the Custom Installer.  So far we just have one: the K2SERVER so you want to enter:&lt;br /&gt;/k2server="[K2SERVER]"&lt;br /&gt;The syntax is important; get it wrong and you won’t be able to access the parameter. The quotes too are important, without them it won’t allow spaces in your parameters.  &lt;br /&gt; UPDATE: I've been getting an error when running the MSI "System.IO.FileNotFound" and it references a file in C:\Windows\System32\Files\...  &lt;br /&gt;I finally found the cause. It's because one of the values of the parameters entered ends with a backslash. It doesn't occur if the backslash is anywhere else in the text, only at the end does it cause a problem. Presumably "\" is acting like an escape character. I've not found a way round this yet - just avoid the need to have a final backslash. END OF UPDATE &lt;br /&gt;Add other parameters in the same way using a space to separate. If you are wondering what the /k2server= is for its because these are also used as command line switches for the MSI so you have to be able to identify the parameter by name. &lt;br /&gt;&lt;br /&gt;The MSI is just about done. Go back to the Custom Installer.  To refer to the parameters in the Custom Installer you can use the Context class and within that there is a Parameters collection. The syntax is:&lt;br /&gt;&lt;br /&gt;string myk2server = Context.Parameters[“K2SERVER”].ToString() ;&lt;br /&gt;&lt;br /&gt;I use a function to access the Parameters collection because you need to trap for null values. &lt;br /&gt;There are some built-in parameters in this collection and the most important of these is ‘assemblypath’ . This gives the full path to your custom installer including its name so it you strip off this last part what you have is the target directory. From there you can access the files you want. &lt;br /&gt;&lt;br /&gt;The last part is then dealing with the actions that you want to perform during the install.  I have a bunch of utilities in a DLL that will do the business from modifying the WEB.CONFIG, adding Identity Impersonate=true, adding registry entries, and running an executable.  &lt;br /&gt;I’ve added the code for the ExecuteProcess below.  The example below will create a web site by using a batch file and pass a parameter to it.  It takes a bit of effort to get the syntax right – try writing the message out to the event log and checking it before you try executing it.  &lt;br /&gt;&lt;br /&gt;utils.ExecuteProcess(TARGETDIR + @"\CreateIISWebSite.cmd", @" WebSite " + "\"" + strRootWeb + "\"");&lt;br /&gt;&lt;br /&gt;Now you can run most executables with this method but note that the process you call needs to return that all important ExitCode.  If it doesn’t then your MSI will sit there 95% complete but never actually finish.  The main culprit of no ExitCode is MSBUILD.EXE.  The solution is to write a batch file, passing the parameters you need and just to be certain add the Exit command as the last line.  Works a treat. It’s a long time since I wrote batch files so I have to brush up on them.   &lt;br /&gt;&lt;br /&gt;And that brings me to my last point, I litter the event log with Information Messages from the Installer.  I write out every member of the Parameters collection. Believe me it’s worth it. If the person doing the install claims there is a problem either during the install or post-install then you are going to want to know what values were entered. Get them to send you the Event Log and that will help you to figure out what they did wrong.   You will also find that the Event Log includes the output from the batch file so you should ALWAYS check the event log to ensure it all worked.  Your batch file might not actually do what it’s supposed to and if you don’t raise an error the MSI is going to report a successful install when in fact it wasn’t.  &lt;br /&gt;&lt;br /&gt;Good luck with your install!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;// you need to add              using System.Diagnostics; &lt;br /&gt;  public void ExecuteProcess(string fileNameString, string argumentsString)&lt;br /&gt;        {&lt;br /&gt;            Process process1 = new Process();&lt;br /&gt;            process1.StartInfo.FileName = fileNameString;&lt;br /&gt;            process1.StartInfo.Arguments = argumentsString;&lt;br /&gt;            process1.StartInfo.UseShellExecute = false;&lt;br /&gt;            process1.StartInfo.CreateNoWindow = true;&lt;br /&gt;            process1.StartInfo.RedirectStandardOutput = true;&lt;br /&gt;            process1.StartInfo.RedirectStandardError = true;&lt;br /&gt;            process1.StartInfo.RedirectStandardInput = true;&lt;br /&gt;            process1.Start();&lt;br /&gt;            process1.WaitForExit();&lt;br /&gt;            if (process1.ExitCode != 0)&lt;br /&gt;            {&lt;br /&gt;               // Log(string.Concat(new object[] { fileNameString, " failed - ExitCode=", process1.ExitCode, " Output: \n", process1.StandardOutput.ReadToEnd() }));&lt;br /&gt;            }&lt;br /&gt;            else&lt;br /&gt;            {&lt;br /&gt;               // Log(fileNameString + " succeeded - Output: \n" + process1.StandardOutput.ReadToEnd());&lt;br /&gt;            }&lt;br /&gt;        }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-1613328624730539063?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/1613328624730539063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=1613328624730539063' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1613328624730539063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/1613328624730539063'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2008/05/custom-installer-and-msis.html' title='Custom Installer and MSIs'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_mnBHRSSHZC8/SCYg7fPHMYI/AAAAAAAAAAU/s3EjfursncY/s72-c/FileSystem1.JPG' height='72' width='72'/><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6034779042643058254</id><published>2008-05-09T11:31:00.011+01:00</published><updated>2008-05-09T12:23:44.335+01:00</updated><title type='text'>Voyages with BlackPearl - 5. Environment Variables and Deployment</title><content type='html'>I have to admit that I just don’t understand Environments in K2 [blackpearl]. The first time I wanted to create an Environment variable of my own I did what I guess most people would do and added it to the Development environment.  I didn’t think it through.  My mistake became obvious when I wanted to deploy it to a Test environment on a customer site. The Test environment was just like Production and did not have Visual Studio installed, which is fine because that is what the MSBUILD files are for. &lt;br /&gt;&lt;br /&gt;If you’re not familiar with these files they are created when you use ‘Deploy’ from Visual Studio. A new directory is created under ‘obj\Debug’ called Deployment and in there you will see the .msbuild file and your compiled workflow(s) and ExtenderProjects in the Bin directory.  So if your Test server doesn’t have Visual Studio installed you just need to copy the contents of the Deployment directory over to the server and then use the MSBUILD.EXE to do the deployment.  MSBUILD.EXE  is a utility found in the directory C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 so you may want to add this path to the Environment Settings of the server.&lt;br /&gt;&lt;br /&gt;The syntax for deployment is as follows:&lt;br /&gt;MSBUILD.EXE [k2proj].msbuild /p:Environment=[environment]&lt;br /&gt;&lt;br /&gt;For example&lt;br /&gt;MSBUILD MyK2Proj.msbuild /p:Environment=Development&lt;br /&gt;&lt;br /&gt;Now what the /p:Environment switch is doing is determining which settings to use within the .msbuild file.  You need to open the .msbuild file to understand what is going on. &lt;br /&gt;Under the root node ‘Project’ there is a collection of nodes which look like this:&lt;br /&gt;[PropertyGroup condition="$(Environment) == 'Development'"]&lt;br /&gt;Beneath that is the [EnvironmentFields] node which contains all of the [Fields] in the template.&lt;br /&gt;&lt;br /&gt;When the .msbuild file was created it created an Environment node for all of the environments on the server (the two defaults are Development and Production) and then you use the /p:Environment switch to tell MSBUILD which node to use. &lt;br /&gt;&lt;br /&gt;But when you execute the command it will fail and that is because MSBUILD uses one of the built-in connection strings (I think it’s the ‘Workflow Server’ one) to make a connection to the K2 server. It fails because the Test environment has a different K2 Server name and if you are not using Integrated authentication  it has a different Administrator account, a different domain and/or a different password.  &lt;br /&gt;&lt;br /&gt;The only solution is to fix the connection strings in the Environment fields to match what they should be in this Test environment. If you are doing it manually then you can copy the values from the K2 Workspace.  I wanted to automate the process so I wrote some utilities that will parse the XML and replace each of the attributes (K2 Server, Domain etc) with the correct values (see below). &lt;br /&gt;I call these utilities within an MSI file but I’ll describe that in more detail in the next post. &lt;br /&gt;&lt;br /&gt;It was about this time I realised my mistake. I tend to use the same development image for several projects and I realised the .msbuild file contained all the Environment variables that I had added, not just the ones for this project.  This will get in a right mess because you won’t be able to tell which environment variables apply to which workflow. What about if you have two workflow processes that each require different ‘FromEmailAddress’ values? &lt;br /&gt;&lt;br /&gt;The approach I now adopt is to totally ignore the default Environment libraries and create a brand new library of the same name as my K2PROJ file.  That way I don’t get confused with the environment variables.  I toyed with the idea of creating development, test and production versions but in the end decided I would have just one environment library per project and amend it for each target server.&lt;br /&gt;&lt;br /&gt;The other thing to note about the MSBUILD deployment is what happens when you do successfully deploy the workflows using your custom Environment library.  You go to the K2 workspace, open the K2 Server and open the Environment Library section. You drill down to Templates, Default Template and Environments and, GULP!, your newly created Environment library is not there. No worries because you don’t need a template library. The template is just a step towards creating the String Table and it’s the String Table that the workflow uses.  I get so used to looking at Environments that I realised I was looking in the wrong place. The String Table is nestled away under the Process. &lt;br /&gt;&lt;br /&gt;The two utilties are below (note the first is an extract, just repeat the section that I’ve marked).&lt;br /&gt;In order to call them I load the .msbuild file into an XmlDocument using the Load method then pass the XmlDocument to the functions. I then use the Save method to save it back to its original location. &lt;br /&gt;&lt;br /&gt;I’m still not sure that I understand Environments but I have something that works for me.&lt;br /&gt;// replaces values in connection string&lt;br /&gt;        public XmlDocument ModifyMSBuild(XmlDocument xmldom, string Environment, string OldDomain, string NewDomain, string OldK2Server, string NewK2Server,string OldAdminAccount, string NewAdminAccount, string OldPassword, string NewPassword)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                XmlNodeList nodeList = null;&lt;br /&gt;                XmlNode node = null;&lt;br /&gt;&lt;br /&gt;                node = xmldom.SelectSingleNode("//Root[@Name='" + Environment + "']");&lt;br /&gt;                // Replace the Domain Name&lt;br /&gt;                nodeList = node.SelectNodes("./Field[contains(@Value,'" + OldDomain + "')]");&lt;br /&gt;                string strAttribValue = "";&lt;br /&gt;                foreach (XmlNode domNode in nodeList)&lt;br /&gt;                {&lt;br /&gt;                    string x = domNode.OuterXml;&lt;br /&gt;                    if (domNode.Attributes.Count &gt; 0)&lt;br /&gt;                    {&lt;br /&gt;                        strAttribValue = domNode.Attributes["Value"].Value.ToString();&lt;br /&gt;                        {&lt;br /&gt;                            strAttribValue = strAttribValue.Replace(OldDomain, NewDomain);&lt;br /&gt;                            domNode.Attributes["Value"].Value = strAttribValue;&lt;br /&gt;                        }&lt;br /&gt;                    }&lt;br /&gt;                }&lt;br /&gt;                // repeat for the Host Server, Admin Account and Password like this:&lt;br /&gt;           //     nodeList = node.SelectNodes("./Field[contains(@Value,'" + OldK2Server + "')]");&lt;br /&gt;          //  foreach loop again&lt;br /&gt;          &lt;br /&gt;                return xmldom;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;             //   log.WriteToLog(ex.Message, "CustomError");&lt;br /&gt;                return xmldom;&lt;br /&gt;            }&lt;br /&gt;}&lt;br /&gt;&lt;br /&gt;// updates values in a specific environment variable&lt;br /&gt;   public XmlDocument ModifyEnvironmentField(XmlDocument xmldom, string Environment, string EnvironmentField, string newValue)&lt;br /&gt;        {&lt;br /&gt;            try&lt;br /&gt;            {&lt;br /&gt;                XmlNode nodeField = null;&lt;br /&gt;                XmlNode node = null;&lt;br /&gt;&lt;br /&gt;                node = xmldom.SelectSingleNode("//Root[@Name='" + Environment + "']");&lt;br /&gt;&lt;br /&gt;                nodeField = node.SelectSingleNode("./Field[@Name= '" + EnvironmentField + "']");&lt;br /&gt;                if (nodeField != null)&lt;br /&gt;                {&lt;br /&gt;                    nodeField.Attributes["Value"].Value = newValue;&lt;br /&gt;                }&lt;br /&gt;               &lt;br /&gt;                return xmldom;&lt;br /&gt;            }&lt;br /&gt;            catch (Exception ex)&lt;br /&gt;            {&lt;br /&gt;               // log.WriteToLog(ex.Message, "CustomError");&lt;br /&gt;                return xmldom;&lt;br /&gt;            }&lt;br /&gt;&lt;br /&gt;        }&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6034779042643058254?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6034779042643058254/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6034779042643058254' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6034779042643058254'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6034779042643058254'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2008/05/voyages-with-blackpearl-4-environment.html' title='Voyages with BlackPearl - 5. Environment Variables and Deployment'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6598640097099970803</id><published>2007-11-28T22:27:00.000Z</published><updated>2007-11-28T22:47:22.944Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='attachments'/><category scheme='http://www.blogger.com/atom/ns#' term='K2 BlackPearl'/><category scheme='http://www.blogger.com/atom/ns#' term='InfoPath'/><category scheme='http://www.blogger.com/atom/ns#' term='web service'/><title type='text'>Voyages with BlackPearl - 4. Replace InfoPath Attachments</title><content type='html'>&lt;span style="font-family:arial;"&gt;I am using InfoPath as the user interface to a K2 BlackPearl workflow. The form allows attachments to be added and they will need to be accessible to other users as the workflow progresses. Since the attachments are quite large, I wanted to strip the attachments off and replace them with a link. This workflow allows mutliple attachments and there are several different files that can be attached. The workflow itself makes no refrence to the attachments. I would have used the K2 wizard to store the attachment to a SharePoint document library but it doesn't work for repeating nodes of file attachments and I would need extra code to find the file name and store this in the InfoPath form as a hyperlink, and then delete the original attachment.&lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;My solution was to build a web service that does exactly what I want. Remove the attachment, store it in SharePoint, put the path to the document on another field and repeat this for all occurrences in the repeating node. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;The challenge then is to forward the now amended InfoPath form onto the K2 InfoPathService.asmx. &lt;/span&gt;&lt;br /&gt;&lt;span style="font-family:Arial;"&gt;Here is how its done. You'll need a class defined for an XmlNode Array because that is how the InfoPath form is submitted to the InfoPathService.asmx.&lt;/span&gt;&lt;br /&gt;[System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "2.0.50727.42")] [System.SerializableAttribute()] [System.Diagnostics.DebuggerStepThroughAttribute()] [System.ComponentModel.DesignerCategoryAttribute("code")] [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "&lt;a href="http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11"&gt;http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11&lt;/a&gt;")] [System.Xml.Serialization.XmlRootAttribute(Namespace = "&lt;a href="http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11"&gt;http://schemas.microsoft.com/office/infopath/2003/myXSD/2007-05-17T16:24:11&lt;/a&gt;", IsNullable = false)]&lt;br /&gt;public class nodeArray { [System.Xml.Serialization.XmlArray()] [System.Xml.Serialization.XmlAnyElement()] public System.Xml.XmlNode[] node; }&lt;br /&gt;&lt;br /&gt;Then the web service method looks like this:&lt;br /&gt;public void InfoPathReplaceAttachment(Object infoPathFormXml) {&lt;br /&gt;nodeArray nodes = new nodeArray();&lt;br /&gt;nodes.node = (System.Xml.XmlNode[]) infoPathFormXml;&lt;br /&gt;string s = System.Web.HttpUtility.HtmlDecode(nodes.node[0].OuterXml);&lt;br /&gt;// load the string into an XML dom called myDoc and replace the attachments&lt;br /&gt;//.....&lt;br /&gt;//Finally submit the XML to the InfoPathService.asmx&lt;br /&gt;// do this to use escaped XML&lt;br /&gt;XmlNode escNode = myDoc.CreateTextNode(myDoc.OuterXml);&lt;br /&gt;// replace node with the amended version&lt;br /&gt;nodes.node[0] = escNode;&lt;br /&gt;infoPathFormXml = nodes.node;&lt;br /&gt;K2submit.InfoPathService ws = new K2submit.InfoPathService();&lt;br /&gt;ws.Credentials = System.Net.CredentialCache.DefaultCredentials;&lt;br /&gt;ws.SubmitInfoPathData(infoPathFormXml);&lt;br /&gt;ws.Dispose();&lt;br /&gt;myDoc = null;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6598640097099970803?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6598640097099970803/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6598640097099970803' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6598640097099970803'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6598640097099970803'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2007/11/voyages-with-blackpearl-4-replace.html' title='Voyages with BlackPearl - 4. Replace InfoPath Attachments'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>1</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7975742732931116783</id><published>2007-11-28T21:53:00.001Z</published><updated>2007-11-28T22:17:59.026Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='Team'/><category scheme='http://www.blogger.com/atom/ns#' term='ownership'/><category scheme='http://www.blogger.com/atom/ns#' term='user'/><category scheme='http://www.blogger.com/atom/ns#' term='activity'/><title type='text'>Voyages with BlackPearl - 3.Team member becomes owner of a task</title><content type='html'>&lt;p&gt;&lt;span style="font-family:arial;"&gt;I have a task in the workflow that is assigned to a group of users. I want the person that actions the task to then 'own' subsequent tasks which are assigned only to them.&lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;I'm using a workflow that is integrated to InfoPath and there are two InfoPath client activities. Let's call the first activity 'TEAM Activity' and then the subsequent activity 'USER Activity'.&lt;br /&gt;&lt;br /&gt;One of the good things about BlackPearl is the ability to assign a Destination User not just to a user or a role but to a data field.&lt;br /&gt;This solution uses that ability, so I created a DataField called 'DestinationUser' and an Environment variable called 'Domain'. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;It also uses a field from the InfoPath form which stores the current user. Just use the userName() function as the default value and you have the name of the current user. See this post &lt;/span&gt;&lt;a href="http://blogs.msdn.com/timpash/archive/2006/08/22/712663.aspx"&gt;&lt;span style="font-family:arial;"&gt;http://blogs.msdn.com/timpash/archive/2006/08/22/712663.aspx&lt;/span&gt;&lt;/a&gt;&lt;br /&gt;&lt;span style="font-family:arial;"&gt;&lt;br /&gt;1. TEAM Activity is assigned to the Role of the 'A Team' where membership of this role is determined through K2.&lt;br /&gt;2. So when you run through the InfoPath client wizard, select the 'A Team' role in the usual way.&lt;br /&gt;3. Now on the TEAM Activity create a Server Code event and make sure it is underneath the InfoPath client event.&lt;br /&gt;4. In the Server Event add the following code:&lt;br /&gt;&lt;br /&gt;System.Xml.XmlDocument doc = new System.Xml.XmlDocument();&lt;br /&gt;doc.LoadXml(K2.ActivityInstanceDestination.XmlFields["Root"].Value);&lt;br /&gt;&lt;br /&gt;// call custom utility that uses SelectSingleNode to retrieve value of &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;//node using namespace&lt;br /&gt;string CurrentOwner = Utils.GetXMLValue(doc, "my:CurrentOwner");&lt;br /&gt;&lt;br /&gt;K2.ProcessInstance.DataFields["NewOwner"].Value = CurrentOwner;&lt;br /&gt;// Set DestinationUser datafield&lt;br /&gt;K2.ProcessInstance.DataFields["DestinationUser"].Value = K2.StringTable["Domain"] + @"\" + K2.ProcessInstance.DataFields["NewOwner "].Value.ToString();&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Note the use of K2.ActivityInstanceDestination.XmlFields["Root"] on the second line. Using ProcessInstatance won't work because it hasn't been updated yet.&lt;br /&gt;&lt;br /&gt;On the USER Activity when you run through the InfoPath client wizard, select the Destination User to be the 'DestinationUser' data field. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;span style="font-family:arial;"&gt;A word of caution. Bad things happen if you don't set the DataField to a value. K2 will understandably throw a runtime error as it doesn't know who to assign the client activity to. Also think through the implications of redirecting a task. You may need to reset the current user on other activities. But I've found this trick really useful. &lt;/span&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7975742732931116783?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7975742732931116783/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7975742732931116783' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7975742732931116783'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7975742732931116783'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2007/11/voyages-with-blackpearl-3team-member.html' title='Voyages with BlackPearl - 3.Team member becomes owner of a task'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7812171948524174063</id><published>2007-11-26T21:58:00.000Z</published><updated>2007-11-26T22:16:54.722Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='permissions'/><category scheme='http://www.blogger.com/atom/ns#' term='SharePoint'/><category scheme='http://www.blogger.com/atom/ns#' term='K2 BlackPearl'/><category scheme='http://www.blogger.com/atom/ns#' term='InfoPath'/><title type='text'>Voyages with BlackPearl - 2. SharePoint permissions</title><content type='html'>I have a K2 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;BlackPearl&lt;/span&gt; &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_1"&gt;workflow&lt;/span&gt; that is integrated to an InfoPath form.  The &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_2"&gt;workflow&lt;/span&gt; creates a number of InfoPath client events each with a different view.&lt;br /&gt;Users will initiate the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_3"&gt;workflow&lt;/span&gt; from &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_4"&gt;SharePoint&lt;/span&gt;, &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_5"&gt;clicking&lt;/span&gt; on a link on the home page which opens the initial view of the form. As the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_6"&gt;workflow&lt;/span&gt; advances to the next InfoPath client event it adds a copy of the InfoPath form to the form library that I specified when I attached the form to the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_7"&gt;workflow&lt;/span&gt;.&lt;br /&gt;So I was wondering what are the minimum permissions I need to give users to this site in order for them to create &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_8"&gt;workflows&lt;/span&gt; but not edit anything else?&lt;br /&gt;I created a &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_9"&gt;SharePoint&lt;/span&gt; group called '&lt;span class="blsp-spelling-error" id="SPELLING_ERROR_10"&gt;WorkflowUsers&lt;/span&gt;' and added my users (or AD groups if you're smart) as members. I gave the group &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_11"&gt;WorkflowUsers&lt;/span&gt; 'Read' permission to the site. The lists, libraries and other &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_12"&gt;SharePoint&lt;/span&gt; objects inherit this permission.  But Read permission is not enough to initiate &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_13"&gt;workflows&lt;/span&gt; in this situation. &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_14"&gt;WorkflowUsers&lt;/span&gt; also have to have Contribute permissions on the K2 &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_15"&gt;BlackPearl&lt;/span&gt; Data Connection library and on the Form library where the &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_16"&gt;workflow&lt;/span&gt; stores the forms.  This is achieved by navigating to each, change the settings and using the Edit Permissions option to break the inheritance form the site. You can then change permission to Contribute for the WorkflowUser group.   &lt;br /&gt;I give the K2 Service account full permission to the site, which is probably more than is necessary but then it's just a service account.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7812171948524174063?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7812171948524174063/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7812171948524174063' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7812171948524174063'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7812171948524174063'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2007/11/voyages-with-blackpearl-2-sharepoint.html' title='Voyages with BlackPearl - 2. SharePoint permissions'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-6324461274667714238</id><published>2007-11-26T21:22:00.000Z</published><updated>2007-11-26T21:45:15.672Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='KPRX'/><category scheme='http://www.blogger.com/atom/ns#' term='K2 BlackPearl'/><category scheme='http://www.blogger.com/atom/ns#' term='file size'/><category scheme='http://www.blogger.com/atom/ns#' term='saving'/><title type='text'>Voyages with BlackPearl - 1. KPRX size</title><content type='html'>I've create a process in K2 BlackPearl that is quite large. The file size of the KPRX is about 8MB. The trouble is that every time I save it, even if I make no changes, the file size increases - this is with Hotfix 2.01 applied.&lt;br /&gt;I started investigating and found that some redundant nodes are created when a KPRX file is saved.  These nodes are used to define the layout of lines and activities but ghost copies are created every time you save.&lt;br /&gt;These nodes are:&lt;br /&gt;/Process/Views/DocumentView/LinesLayoutData/DocumentViewLineLayoutData and&lt;br /&gt;/Process/Views/DocumentView/ActivitiesLayoutData/DocumentViewActivityLayoutData&lt;br /&gt;Each time I save the KPRX I found that it created another copy of the nodes, each has a different Guid but the Name element (amongst others is blank).&lt;br /&gt;This may sound trivial but with some 25 activities and over 50 lines each time I saved the KPRX it would increase the file size by 100KB. &lt;br /&gt;So I wrote a utility that iterates through all these redundant nodes and removes them from the KPRX. I've used it many times and it has no adverse effect on the KPRX file, but the benefit is that it loads quicker and is less likely to give me an out of memory error. &lt;br /&gt;If you want a copy of this KPRX cleaner ping me an email and I'll send it to you. It's a simple .Net Windows application that will prompt for the location of your KPRX file and creates a copy of the cleansed version.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-6324461274667714238?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/6324461274667714238/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=6324461274667714238' title='0 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6324461274667714238'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/6324461274667714238'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2007/11/voyages-with-blackpearl-1-kprx-size.html' title='Voyages with BlackPearl - 1. KPRX size'/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-7178802206594541796.post-7853600847491921506</id><published>2007-11-26T20:14:00.000Z</published><updated>2007-11-26T20:42:53.193Z</updated><category scheme='http://www.blogger.com/atom/ns#' term='My Photo'/><title type='text'></title><content type='html'>&lt;a href="http://1.bp.blogspot.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s1600-h/CharlesEmes.GIF"&gt;&lt;img id="BLOGGER_PHOTO_ID_5137245529813819282" style="FLOAT: left; MARGIN: 0px 10px 10px 0px; CURSOR: hand" alt="" src="http://1.bp.blogspot.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF" border="0" /&gt;&lt;/a&gt;So I finally got around to creating a blog. I'm going to find it hard to keep it updated. I spend most of the day in front of a computer screen so blogging is not one of my favourite past times. But it is time I shared some of the knowledge I've gained on a K2 BlackPearl project and on other software projects.&lt;br /&gt;I'm determined not to fill it with the the minutia and trivia of every day life that so many other bloggers seem compelled to share. I'm sure that you really don't care how I spent the weekend or to know my opinion on some TV show.&lt;br /&gt;If you find the contents useful well that's great. If not, then there is another blog just a click away.&lt;br /&gt;By the way, 'No Intelligent Life' comes from an entry in a New Scientist competition of a text message that an alien might send home having arrived on earth. It wasn't the winning entry, but it appealed to me.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/7178802206594541796-7853600847491921506?l=charlesemes.blogspot.com' alt='' /&gt;&lt;/div&gt;</content><link rel='replies' type='application/atom+xml' href='http://charlesemes.blogspot.com/feeds/7853600847491921506/comments/default' title='Post Comments'/><link rel='replies' type='text/html' href='http://www.blogger.com/comment.g?blogID=7178802206594541796&amp;postID=7853600847491921506' title='1 Comments'/><link rel='edit' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7853600847491921506'/><link rel='self' type='application/atom+xml' href='http://www.blogger.com/feeds/7178802206594541796/posts/default/7853600847491921506'/><link rel='alternate' type='text/html' href='http://charlesemes.blogspot.com/2007/11/blog-post.html' title=''/><author><name>Charles Emes</name><uri>http://www.blogger.com/profile/11238782194888451239</uri><email>noreply@blogger.com</email><gd:image rel='http://schemas.google.com/g/2005#thumbnail' width='27' height='32' src='http://bp0.blogger.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s320/CharlesEmes.GIF'/></author><media:thumbnail xmlns:media='http://search.yahoo.com/mrss/' url='http://1.bp.blogspot.com/_mnBHRSSHZC8/R0spl1CEH5I/AAAAAAAAAAM/WM6KII4ol_s/s72-c/CharlesEmes.GIF' height='72' width='72'/><thr:total>1</thr:total></entry></feed>
