<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Terry's Worklog &#187; C#</title>
	<atom:link href="http://people.oregonstate.edu/~reeset/blog/groups/programming/c/feed" rel="self" type="application/rss+xml" />
	<link>http://people.oregonstate.edu/~reeset/blog</link>
	<description>On my work (programming, digital libraries, cataloging) and other stuff that perks my interest (family, cycling, etc)</description>
	<lastBuildDate>Sat, 21 Nov 2009 10:07:38 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Using MarcEdit to reuse (and maybe import) items in Dspace</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/485</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/485#comments</comments>
		<pubDate>Thu, 03 Jan 2008 04:38:10 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[Dspace]]></category>
		<category><![CDATA[MarcEdit]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/485</guid>
		<description><![CDATA[I&#8217;ve been thinking a little bit about some of the things that I use MarcEdit for and have been pushing some of this work off my desk to some of the staff in our technical services department.&#160; We actually use MarcEdit quite a bit when it comes to sharing metadata from our Dspace instance with [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;ve been thinking a little bit about some of the things that I use MarcEdit for and have been pushing some of this work off my desk to some of the staff in our technical services department.&nbsp; We actually use MarcEdit quite a bit when it comes to sharing metadata from our Dspace instance with other systems, like OCLC&#8217;s WorldCat and our online Catalog.&nbsp; For example, we use MarcEdit to automatically generate MARC21 records for our theses submitted through Dspace.&nbsp; The process seems to work fairly well, and has been very easy for our staff to learn.&nbsp; Should write an article documenting this process and how its working at OSU at some point.&nbsp; </p>
<p>To that end, I&#8217;m writing a plug-in for MarcEdit that may enable me to mainstream the processing of web page archiving in Dspace.&nbsp; At this point, the process is a bit too manual for my tastes.&nbsp; Along with spidering a site (using whatever the chosen depth may be), there is this pesky manual step of flattening the site and making the urls relative.&nbsp; Not a big deal (unless there are file name collisions [which there always are] when reading depths), but it takes time.&nbsp; So, I spent some time this afternoon and wrote a threaded web crawler.&nbsp; Seems to work well.&nbsp; At this point, I just need to add the logic to flatten all paths, and come up with a naming schema to re-write all urls to provide unique file names.&nbsp; Once I get that down, building the batch import package for Dspace should be fairly trivial.&nbsp; Not sure how much time I&#8217;ll have to work on this over the week/weekend, but would be a pretty cool project to finish I think.&nbsp; It would certainly allow the library to provide site archiving as a dspace option (at this point, its only done under very special circumstances) and should simplify the process enough to the point that it could probably become a mainstream process.&nbsp; </p>
<p>Anyway, if I do get a chance to get this finished, I&#8217;ll certainly make it available as a plug-in (with source).&nbsp; Of course, if someone has already developed a simplified process that requires no manual processing after harvest, I would love to hear it.</p>
<p>&#8211;TR</p>
<div class="wlWriterSmartContent" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:f149c8e9-a3fd-41d9-b075-a3ebf0e7dd6a" style="padding-right: 0px; display: inline; padding-left: 0px; float: none; padding-bottom: 0px; margin: 0px; padding-top: 0px">Technorati Tags: <a href="http://technorati.com/tags/dspace" rel="tag">dspace</a>,<a href="http://technorati.com/tags/marcedit" rel="tag">marcedit</a>,<a href="http://technorati.com/tags/plug-ins" rel="tag">plug-ins</a></div>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/485/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>MarcEdit 5.x and OCLC Plug-in Update</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/482</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/482#comments</comments>
		<pubDate>Wed, 26 Dec 2007 07:41:48 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[MarcEdit]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/482</guid>
		<description><![CDATA[I took a couple of minutes and made a few changes to MarcEdit and the OCLC plug-in to provide some additional functionality to the plug-in framework and fix an error in the OCLC plug-in.&#160; 
Changes:
MarcEdit:

One real change.&#160; In the MacroInterfaces.dll (the library that allows the Scripting interface and the Plug-in interface access to the MarcEditor [...]]]></description>
			<content:encoded><![CDATA[<p>I took a couple of minutes and made a few changes to MarcEdit and the OCLC plug-in to provide some additional functionality to the plug-in framework and fix an error in the OCLC plug-in.&nbsp; </p>
<p><strong>Changes:</strong></p>
<p><em>MarcEdit:</em></p>
<ul>
<li>One real change.&nbsp; In the MacroInterfaces.dll (the library that allows the Scripting interface and the Plug-in interface access to the MarcEditor and its functions) I&#8217;ve added two new functions: AddButton and RemoveButton.&nbsp; These two functions allow users to have plug-ins place buttons on the toolbar of the application (at least, on specific windows).&nbsp; </li>
</ul>
<p><em>OCLC Plug-in:</em></p>
<ul>
<li>I&#8217;ve added the code to initiate a button and interact when it is clicked to the MarcEditor toolbar.</li>
<li>I&#8217;ve corrected the 007 error.&nbsp; See: <a title="http://oregonstate.edu/~reeset/blog/archives/480" href="http://oregonstate.edu/~reeset/blog/archives/480">http://oregonstate.edu/~reeset/blog/archives/480</a></li>
</ul>
<p>So what will you see with the changes.&nbsp; Well, the big change you will see is when you initialize the plug-in in the MarcEditor.&nbsp; Once you have downloaded the update to both MarcEdit and the Plug-in (you need both), you will see the following when the plug-in is executed:</p>
<p><a href="http://oregonstate.edu/~reeset/blog/wp-content/mslive_images/MarcEdit5.xandOCLCPluginUpdate_1458A/image.png" target="_blank"><img style="border-right: 0px; border-top: 0px; border-left: 0px; border-bottom: 0px" height="413" alt="image" src="http://oregonstate.edu/~reeset/blog/wp-content/mslive_images/MarcEdit5.xandOCLCPluginUpdate_1458A/image_thumb.png" width="644" border="0"></a> </p>
<p>The new button added has been highlighted.&nbsp; This button now acts as the new <strong>Save</strong> button when you have made your changes to the OCLC data records.&nbsp; This will move the data back into the OCLC Save File.&nbsp; Remember &#8212; at this point, you will want to make a backup of your Save Files before you make your changes &#8212; just in case there are other fields in OCLC&#8217;s XML format that are different than I would have expected.&nbsp; </p>
<p>If you have downloaded the OCLC Plug-in and would like to update it.&nbsp; At this point, the process isn&#8217;t as streamlined as I&#8217;d like (I&#8217;ll fix that this week while I&#8217;m taking some time off to recharge).&nbsp; Essentially, you need to Uninstall the plug-in (using the plug-in manager or, delete the oclc_helper.dll from the marcedit plug-ins directory (generally, c:\program files\marcedit 5.0\plugins\).&nbsp; If you uninstall with the plug-in manager, you will need to close and restart MarcEdit.&nbsp; Then open the plug-in manager and download the new plug-in.&nbsp; If you delete the library directly from the plug-ins directory &#8212; just open MarcEdit, select the plug-in manager and download the plug-in.</p>
<p>I&#8217;ve updated a new version of MarcEdit: <a href="http://oregonstate.edu/~reeset/marcedit/software/development/MarcEdit51_Setup.exe" target="_blank">MarcEdit51_Setup.exe</a>.&nbsp; I&#8217;ve also uploaded a new version of the plug-in (download this through plug-in manager [see above]).&nbsp; Source can be downloaded from: <a href="http://oregonstate.edu/~reeset/marcedit/software/development/plugins/source/oclc_helper.zip" target="_blank">oclc_helper.zip</a>.</p>
<p>If you have a strong desire to see how this type of interaction is accomplished in C#, please see the following post and sample project file: <a title="http://oregonstate.edu/~reeset/blog/archives/481" href="http://oregonstate.edu/~reeset/blog/archives/481">http://oregonstate.edu/~reeset/blog/archives/481</a>.</p>
<p>&nbsp;</p>
<p>&#8211;TR</p>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/482/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>C# plug-ins continued &#8212; Interacting with one&#8217;s hosted application</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/481</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/481#comments</comments>
		<pubDate>Tue, 25 Dec 2007 03:57:01 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[General Computing]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/481</guid>
		<description><![CDATA[Example Project Source: PluginProject.zip
Because I&#8217;ve been doing a lot of work with MarcEdit and plug-ins, I thought I&#8217;d post some sample code for anyone interested in how this might work.  Essentially, the sample project includes 3 parts &#8212; a host application, a set of Interfaces and a Shared library.  Making this work requires a couple [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Example Project Source: </strong><a target="_blank" href="http://oregonstate.edu/~reeset/marcedit/examples/PluginProject.zip">PluginProject.zip</a></p>
<p>Because I&#8217;ve been doing a lot of work with MarcEdit and plug-ins, I thought I&#8217;d post some sample code for anyone interested in how this might work.  Essentially, the sample project includes 3 parts &#8212; a host application, a set of Interfaces and a Shared library.  Making this work requires a couple of important parts. </p>
<p>First, the host application (either the form or class), need to implement the set of interfaces.  So for example, if interaction with a form in the hosted application was need, you would configure the form to implement a set of interfaces.  This would look like:<br />
<code>using System;<br />
using System.Collections.Generic;<br />
using System.ComponentModel;<br />
using System.Data;<br />
using System.Drawing;<br />
using System.Text;<br />
using System.Windows.Forms;</p>
<p>namespace HostApp<br />
{<br />
    public partial class Form1 : Form, HostInterfaces.IHost<br />
    {<br />
        //...<br />
    }</code></p>
<p>This implements the IHost class (link to msdn) &#8212; a generic class that allows you to</p>
<p>pass objects between dynamically loaded libraries.  .NET includes a IScript interface that allows for scripting functionality as well. </p>
<p>Anyway, the interfaces are simply like delegates &#8212; they define the visible functions/methods that will be accessible to a foreign assembly.  This is the simpliest file to create.  It looks something like this:</p>
<p><code>using System;<br />
using System.Collections.Generic;<br />
using System.Text;</p>
<p>namespace HostInterfaces<br />
{<br />
    public interface IHost<br />
    {<br />
        System.Windows.Forms.Label label { get;}<br />
        System.Windows.Forms.ToolStripButton AddButton(string caption);<br />
        void RemoveButton(System.Windows.Forms.ToolStripButton t);</p>
<p>    }<br />
}</code><br />
Finally, the Dynamic assembly has the ability to work with any function/object within the host application that has been made public through the interface.  For this sample project, I&#8217;ve shown how to modify a label (on the host application), add a button to a toolbar and respond to click events from that button. </p>
<p>The project is a simple one &#8212; but should go a long way towards showing how this works.</p>
<p>Cheers,</p>
<p>&#8211;TR</p>
<p style="display: inline; margin: 0px; padding: 0px" id="scid:0767317B-992E-4b12-91E0-4F059A8CECA8:aa03ed7a-9808-413c-9d38-5947ae2db419" class="wlWriterSmartContent">Technorati Tags: <a rel="tag" href="http://technorati.com/tags/C#">C#</a>,<a rel="tag" href="http://technorati.com/tags/plug-ins">plug-ins</a>,<a rel="tag" href="http://technorati.com/tags/interfaces">interfaces</a></p>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/481/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>OCLC&#8217;s Connexion XML &#8212; why, oh why?</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/480</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/480#comments</comments>
		<pubDate>Fri, 21 Dec 2007 17:35:17 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[General Computing]]></category>
		<category><![CDATA[MarcEdit]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/480</guid>
		<description><![CDATA[As I&#8217;d noted previously (http://oregonstate.edu/~reeset/blog/archives/479), some early testers had found that the Connexion plug-in that I&#8217;d written for MarcEdit stripped the 007.&#160; I couldn&#8217;t originally figure out why &#8212; it&#8217;s just a control field and their syntax for control fields is pretty straightforward.&#160; However, after looking at a few records with 007 records, I could [...]]]></description>
			<content:encoded><![CDATA[<p>As I&#8217;d noted previously (<a title="http://oregonstate.edu/~reeset/blog/archives/479" href="http://oregonstate.edu/~reeset/blog/archives/479">http://oregonstate.edu/~reeset/blog/archives/479</a>), some early testers had found that the Connexion plug-in that I&#8217;d written for MarcEdit stripped the 007.&nbsp; I couldn&#8217;t originally figure out why &#8212; it&#8217;s just a control field and their syntax for control fields is pretty straightforward.&nbsp; However, after looking at a few records with 007 records, I could see why.&nbsp; In Connexion, OCLC lets folks code the 007 using delimiters like a normal variable MARC field (when its not) &#8212; and they save it as such &#8212; using delimiters.&nbsp; For example:</p>
<pre class="csharpcode">&lt;v007 i2=<span class="str">" "</span> i1=<span class="str">" "</span> im=<span class="str">"0"</span>&gt;
  &lt;sa&gt;
    &lt;d&gt;s&lt;/d&gt;
  &lt;/sa&gt;
  &lt;sb&gt;
    &lt;d&gt;d&lt;/d&gt;
  &lt;/sb&gt;
  &lt;sd&gt;
    &lt;d&gt;f&lt;/d&gt;
  &lt;/sd&gt;
  &lt;se&gt;
    &lt;d&gt;s&lt;/d&gt;
  &lt;/se&gt;
  &lt;sf&gt;
    &lt;d&gt;n&lt;/d&gt;
  &lt;/sf&gt;
  &lt;sg&gt;
    &lt;d&gt;g&lt;/d&gt;
  &lt;/sg&gt;
  &lt;sh&gt;
    &lt;d&gt;n&lt;/d&gt;
  &lt;/sh&gt;
  &lt;si&gt;
    &lt;d&gt;n&lt;/d&gt;
  &lt;/si&gt;
  &lt;sj&gt;
    &lt;d&gt;z&lt;/d&gt;
  &lt;/sj&gt;
  &lt;sk&gt;
    &lt;d&gt;u&lt;/d&gt;
  &lt;/sk&gt;
  &lt;sl&gt;
    &lt;d&gt;u&lt;/d&gt;
  &lt;/sl&gt;
  &lt;sm&gt;
    &lt;d&gt;u&lt;/d&gt;
  &lt;/sm&gt;
  &lt;sn&gt;
    &lt;d&gt;d&lt;/d&gt;
  &lt;/sn&gt;
&lt;/v007&gt;</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>I&#8217;ll admit &#8212; I have no idea why they went with this format.&nbsp; From my perspective, its clunky.&nbsp; The 007, as a single control field, is fairly easy to parse as it can have up to 13 bytes, with number of bytes specified 0 byte of the data element.&nbsp; In this format, you actually have to create 9 different templates for the different possibilities in order to account for different field lengths, byte combinations and delimiter settings.&nbsp; Honestly, my first impression when looking at this was that its a perfect example of how something so simple can become much more difficult than need be.&nbsp; Personally, I would have been happier had they broke from their MARCXML like syntax for this one field to create an special 007 element.&nbsp; Again, this is something that could have been easily abstracted in the XSLT translation &#8212; but to be fair, I don&#8217;t think that they figured anyone but OCLC&#8217;s connexion team would ever be trying to work with this.&nbsp; </p>
<p>So how I&#8217;m solving it?&nbsp; Well, one of the cool things working with XSLT (and .NET in general) is the ability to use extensions to help fill in missing functionality in the XSLT language (in my case, the ms:script extension in the msxml library).&nbsp; Since this transformation isn&#8217;t one that I&#8217;m really sharing (outside the plug-in), I&#8217;m not too worried about its portability.&nbsp; So, what I&#8217;ve done is created a number of helper C# functions and embedded them within the xslt document to aid processing.&nbsp; For example, </p>
<pre class="csharpcode">&lt;xsl:stylesheet version=<span class="str">"1.0"</span>
xmlns:marc=<span class="str">"http://www.loc.gov/MARC21/slim"</span>
 xmlns:xsi=<span class="str">"http://www.w3.org/2001/XMLSchema-instance"</span>
 xmlns:xsl=<span class="str">"http://www.w3.org/1999/XSL/Transform"</span>
 xmlns:ms=<span class="str">"urn:schemas-microsoft-com:xslt"</span>
 xmlns:osu=<span class="str">"urn:oregonstate-edu:xslt"</span>
 extension-element-prefixes=<span class="str">"osu"</span>&gt;
  &lt;xsl:output method=<span class="str">"xml"</span> indent=<span class="str">"yes"</span> /&gt;
  &lt;ms:script language=<span class="str">"C#"</span> implements-prefix=<span class="str">"osu"</span>&gt;
    &lt;![CDATA[
        <span class="kwrd">public</span> <span class="kwrd">int</span> length(<span class="kwrd">string</span> s) {
          s = s.ToLower();
          <span class="kwrd">if</span> (s==<span class="str">"c"</span>) {
             <span class="kwrd">return</span> 14;
          } <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"d"</span>) { <span class="kwrd">return</span> 6;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"a"</span>) { <span class="kwrd">return</span> 8;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"h"</span>) { <span class="kwrd">return</span> 13;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"m"</span>) { <span class="kwrd">return</span> 10;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"k"</span>) { <span class="kwrd">return</span> 6;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"g"</span>) { <span class="kwrd">return</span> 9;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"r"</span>) { <span class="kwrd">return</span> 11;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"s"</span>) { <span class="kwrd">return</span> 14;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"f"</span>) { <span class="kwrd">return</span> 10;}
          <span class="kwrd">else</span> <span class="kwrd">if</span> (s==<span class="str">"v"</span>) { <span class="kwrd">return</span> 9;}
          <span class="kwrd">else</span> { <span class="kwrd">return</span> 8;}
        }
      ]]&gt;
  &lt;/ms:script&gt;</pre>
<pre class="csharpcode">&nbsp;</pre>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
<p>This is a simple function that I&#8217;m using to track the number of elements needed for the processing template.&nbsp; This is because I don&#8217;t want to create 9 different XSLT templates for each processing type, so I&#8217;m using some embedded C# to simplify the process.&nbsp; On the plus side, using these embedded scripts make the translation process much faster on the .NET side (since .NET compiles xslt to byte code anyway before running any translation process), and this is a technique that I&#8217;ve never really had to use before so I was able to get a little practical experience.&nbsp; Still don&#8217;t like it though.</p>
<p>&#8211;TR</p>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/480/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Dynamically loading and Unloading Assemblies in C#</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/466</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/466#comments</comments>
		<pubDate>Mon, 19 Nov 2007 08:15:42 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/466</guid>
		<description><![CDATA[While working on a plugin manager for a program written in C#, I found myself with a need to be able to load and unload assemblies dynamically be an application.&#160; In C#, loading assemblies is a fairly easy prospect &#8212; one just needs to make use of the System.Reflection class.&#160; Something like the following:

System.Reflection.Assembly assembly [...]]]></description>
			<content:encoded><![CDATA[<p>While working on a plugin manager for a program written in C#, I found myself with a need to be able to load and unload assemblies dynamically be an application.&nbsp; In C#, loading assemblies is a fairly easy prospect &#8212; one just needs to make use of the System.Reflection class.&nbsp; Something like the following:</p>
<div class="csharpcode">
<pre class="alt">System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFile(<span class="str">@"c:\yourassembly.dll"</span>);</pre>
</div>
<p><style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</p>
<p>However, if you need to unload the assembly &#8212; good luck.&nbsp; The .NET assembly class doesn&#8217;t include an unload method.&nbsp; If you have a need to be able to dynamically load an unload assemblies, you need to work with the AppDomain class.&nbsp; The .NET framework works on an Application Domain model, so for items like plugins (where you may need to load, unload or modify an assembly), you need to create an Application Domain manager to load assemblies onto.&nbsp; This way, when you need to unload an assembly, you use the Unload method found within the AppDomain class.&nbsp; </p>
<p>Of course, when dealing with plugins, you likely will need to create a new application domain for each plugin to be loaded.&nbsp; This is because the you unload the appdomain, not the assemblies attached to the domains.&nbsp; So for my project, I decided to create something much like the TempFileCollection.&nbsp; In a global class, I decided to create a hash that stories a domain name and the domain object.&nbsp; Using this method, I can do something like the following:</p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">string</span> path = cglobal.mglobal.AppPath() + <span class="str">"plugins"</span> + System.IO.Path.DirectorySeparatorChar;</pre>
<pre><span class="lnum">   2:  </span>            <span class="kwrd">string</span>[] files = System.IO.Directory.GetFiles(path);</pre>
<pre class="alt"><span class="lnum">   3:  </span>&nbsp;</pre>
<pre><span class="lnum">   4:  </span>            lstInstalled.Items.Clear();</pre>
<pre class="alt"><span class="lnum">   5:  </span>            <span class="kwrd">foreach</span> (<span class="kwrd">string</span> f <span class="kwrd">in</span> files)</pre>
<pre><span class="lnum">   6:  </span>            {</pre>
<pre class="alt"><span class="lnum">   7:  </span>                <span class="kwrd">try</span></pre>
<pre><span class="lnum">   8:  </span>                {</pre>
<pre class="alt"><span class="lnum">   9:  </span>                    System.AppDomain domain = System.AppDomain.CreateDomain(System.IO.Path.GetFileName(f));</pre>
<pre><span class="lnum">  10:  </span>                    System.IO.StreamReader reader = <span class="kwrd">new</span> System.IO.StreamReader(f, System.Text.Encoding.GetEncoding(1252), <span class="kwrd">false</span>);</pre>
<pre class="alt"><span class="lnum">  11:  </span>&nbsp;</pre>
<pre><span class="lnum">  12:  </span>                    <span class="kwrd">byte</span>[] b = <span class="kwrd">new</span> <span class="kwrd">byte</span>[reader.BaseStream.Length];</pre>
<pre class="alt"><span class="lnum">  13:  </span>                    reader.BaseStream.Read(b, 0, System.Convert.ToInt32(reader.BaseStream.Length));</pre>
<pre><span class="lnum">  14:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  15:  </span>                    domain.Load(b);</pre>
<pre><span class="lnum">  16:  </span>                    System.Reflection.Assembly[] a = domain.GetAssemblies();</pre>
<pre class="alt"><span class="lnum">  17:  </span>                    <span class="kwrd">int</span> index = 0;</pre>
<pre><span class="lnum">  18:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  19:  </span>                    </pre>
<pre><span class="lnum">  20:  </span>                    </pre>
<pre class="alt"><span class="lnum">  21:  </span>&nbsp;</pre>
<pre><span class="lnum">  22:  </span>                    <span class="kwrd">for</span> (<span class="kwrd">int</span> x = 0; x &lt; a.Length; x++)</pre>
<pre class="alt"><span class="lnum">  23:  </span>                    {</pre>
<pre><span class="lnum">  24:  </span>                        <span class="kwrd">if</span> (a[x].GetName().Name + <span class="str">".dll"</span> == System.IO.Path.GetFileName(f))</pre>
<pre class="alt"><span class="lnum">  25:  </span>                        {</pre>
<pre><span class="lnum">  26:  </span>                            index = x;</pre>
<pre class="alt"><span class="lnum">  27:  </span>                            <span class="kwrd">break</span>;</pre>
<pre><span class="lnum">  28:  </span>                        }</pre>
<pre class="alt"><span class="lnum">  29:  </span>                    }</pre>
<pre><span class="lnum">  30:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  31:  </span>                    System.Windows.Forms.ListViewItem item = <span class="kwrd">new</span> ListViewItem();</pre>
<pre><span class="lnum">  32:  </span>&nbsp;</pre>
<pre class="alt"><span class="lnum">  33:  </span>                    item.Text = a[index].GetName().Name + <span class="str">".dll"</span>;</pre>
<pre><span class="lnum">  34:  </span>                    item.SubItems.Add(a[index].GetName().Version.ToString());</pre>
<pre class="alt"><span class="lnum">  35:  </span>                    item.SubItems.Add(reader.BaseStream.Length.ToString());</pre>
<pre><span class="lnum">  36:  </span>                    lstInstalled.Items.Add(item);</pre>
<pre class="alt"><span class="lnum">  37:  </span>                    reader.Close();</pre>
<pre><span class="lnum">  38:  </span>                    cglobal.mglobal.domains.Add(System.IO.Path.GetFileName(f), domain);</pre>
<pre class="alt"><span class="lnum">  39:  </span>                    </pre>
<pre><span class="lnum">  40:  </span>                }</pre>
<pre class="alt"><span class="lnum">  41:  </span>                <span class="kwrd">catch</span> { }</pre>
<pre><span class="lnum">  42:  </span>            }</pre>
<pre>&nbsp;</pre>
<p><font face="Trebuchet MS" size="3">Then, if we need to unload the assembly, we can unload the domain that its attached to.&nbsp; Something like:</font></p>
<div class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">for</span> (<span class="kwrd">int</span> x = 0; x &lt; lstInstalled.Items.Count; x++)</pre>
<pre><span class="lnum">   2:  </span>            {</pre>
<pre class="alt"><span class="lnum">   3:  </span>                <span class="kwrd">if</span> (lstInstalled.Items[x].Selected == <span class="kwrd">true</span>) {</pre>
<pre><span class="lnum">   4:  </span>                    <span class="kwrd">try</span> {</pre>
<pre class="alt"><span class="lnum">   5:  </span>                        <span class="kwrd">if</span> (System.IO.File.Exists(cglobal.mglobal.AppPath() + <span class="str">"plugins"</span> + System.IO.Path.DirectorySeparatorChar + lstInstalled.Items[x].Text)) {</pre>
<pre><span class="lnum">   6:  </span>                            System.AppDomain.Unload((System.AppDomain)cglobal.mglobal.domains[lstInstalled.Items[x].Text]);</pre>
<pre class="alt"><span class="lnum">   7:  </span>                            cglobal.mglobal.domains.Remove(lstInstalled.Items[x].Text);</pre>
<pre><span class="lnum">   8:  </span>                            System.IO.File.Delete(cglobal.mglobal.AppPath() + <span class="str">"plugins"</span> + System.IO.Path.DirectorySeparatorChar + lstInstalled.Items[x].Text);</pre>
<pre class="alt"><span class="lnum">   9:  </span>                        }</pre>
<pre><span class="lnum">  10:  </span>                    }</pre>
<pre class="alt"><span class="lnum">  11:  </span>                    <span class="kwrd">catch</span> {}</pre>
<pre><span class="lnum">  12:  </span>                }</pre>
<pre class="alt"><span class="lnum">  13:  </span>            }</pre>
</div>
<style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</div>
<p><style type="text/css">.csharpcode, .csharpcode pre
{
	font-size: small;
	color: black;
	font-family: consolas, "Courier New", courier, monospace;
	background-color: #ffffff;
	/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt 
{
	background-color: #f4f4f4;
	width: 100%;
	margin: 0em;
}
.csharpcode .lnum { color: #606060; }
</style>
</p>
<p>Seems a little more involved that it has to be, but once you know how it works, its not that big of a deal.</p>
<p>&#8211;TR</p>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/466/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>.NET 64-bit processor memory issues when using sendmessage to access a winform element</title>
		<link>http://people.oregonstate.edu/~reeset/blog/archives/444</link>
		<comments>http://people.oregonstate.edu/~reeset/blog/archives/444#comments</comments>
		<pubDate>Wed, 01 Aug 2007 07:40:00 +0000</pubDate>
		<dc:creator>Administrator</dc:creator>
				<category><![CDATA[C#]]></category>
		<category><![CDATA[MarcEdit]]></category>
		<category><![CDATA[Microsoft]]></category>

		<guid isPermaLink="false">http://oregonstate.edu/~reeset/blog/archives/444</guid>
		<description><![CDATA[I&#8217;m posting this in hopes that it will save someone else a lot of time or someone that knows .NET a bit better than I can provide a better solution. 
Problem:
Last week, I had someone ping me regarding MarcEdit and a problem that they were running into with the Editor running it on a 64-bit version of [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;m posting this in hopes that it will save someone else a lot of time or someone that knows .NET a bit better than I can provide a better solution. </p>
<p><strong>Problem:</strong></p>
<p>Last week, I had someone ping me regarding MarcEdit and a problem that they were running into with the Editor running it on a 64-bit version of Windows 2003 Server.  MarcEdit is compiled for any processor, so in theory, the framework should adjust the variable types to the current CPU type and go on it&#8217;s merry way.  And was it not that I have to work with some unmanaged code within my application, I&#8217;m sure that this would be the case.  However, when opening the MarcEditor, the user was getting the following error message:</p>
<p><a atomicselection="true" href="http://oregonstate.edu/~reeset/blog/wp-content/mslive_images/a51.NET64bitprocessormemoryissueswhenusi_15125/load_error2.png"><img border="0" width="609" src="http://oregonstate.edu/~reeset/blog/wp-content/mslive_images/a51.NET64bitprocessormemoryissueswhenusi_15125/load_error_thumb.png" height="243" style="border: 0px" /></a></p>
<p>This is odd because I test MarcEdit on every version of Windows from 98 to Vista.  The problem however, is I&#8217;ve never ran the program in a 64-bit version of Windows. </p>
<p><strong>Background:</strong></p>
<p>I did a little bit of research, and found what I thought to be the problem.  The 64-bit version of windows shares many of the same signatures as its 32-bit counter-part, but one place where the signatures differ is in the Messaging Queue.  SendMessage, for example, which uses integers to pass values between processes had been updated to 64 bit integers and would crash if the wrong data type is sent into the function.  No problem, I fixed the signature issue, but the error message remained.  What I didn&#8217;t realize is that this wasn&#8217;t the actual problem (though it was a problem).  The real problem seemed to be related to simply accessing the RichTextbox Handle and passing it the callback.  Anytime the Handle was touched and passed, this error would be generated.</p>
<p><strong>Solution:</strong></p>
<p>So, Microsoft does make the Enterprise version of Windows 2003 Server available on a trial basis for developers wanting to test their software.  So, I dug up a box with an AMD-64 bit processor and set to installing the software.  Next, I installed <a target="_blank" href="http://www.icsharpcode.net/OpenSource/SD/">SharpDevelop,</a> an Open Source IDE for .NET.  I created a small sample program to isolate the code that was causing me problems.  In my case, the code that was causing the problem is necessary because of MARC being a UTF8 encoded data format.  Microsoft&#8217;s Richtext library supports the loading of plaintext (ASCII), Unicode text, text with OLE objects and text in just about any character format, including UTF8.  Unfortunately, the .NET framework only exposes plaintext and Unicode text as supported formats.  This means that in order to load UTF8 data and utilize the components streaming nature to minimize the memory footprint during loading, we need to essentially write our own EditStreamCallback function, create the delegates, the EDITSTREAM struct, etc.  And in that, there is the rub.  When compiling the code in SharpDevelop, I specified that the code should be targeted specifically for a 64-bit processor.  During compile, I got two warning messages that two core .NET components are compiled specifically for 32-bit processors.  Since the signatures on the 64 and 32 bit machines are identical, one can generally ignore these compilation warnings, as the framework does it&#8217;s magic.  However, the fact that I&#8217;m utilizing functionality from one of these two components within an unmanaged code block causes the problem.  Within the .NET (and 64-bit environment in general), an 64-bit process cannot load a library compiled for a 32-bit process.  A 32-bit process can run within a 64-bit environment, they just cannot share processes between themselves.  My best guess is that this is what was happening.  Since these two .NET components were compiled specifically for the 32-bit processors, my attempts to load them into a 64-bit process and utilize them within an unmanaged code block caused issues.  The solution is a simply one &#8212; for the GUI application of MarcEdit (which doesn&#8217;t do much anyway), the program simply needs to be complied to target 32-bit processors.  Now it runs just fine within a 64-bit environment, and will remain so until Microsoft cleans up these two core libraries.  With that said, if anyone has a better way of dealing with this problem (code is attached, so if you can make it work, I&#8217;d love to here from you), I&#8217;d love to hear about it.</p>
<p><strong>RichText Code:</strong></p>
<p>Finally, it&#8217;s pretty difficult to find example code dealing with the Richtext components in C#.  I think this is primarily because most folks that use high level languages like C# either don&#8217;t have a need for it or don&#8217;t have the background in C++ to understand what is actually happening at the Proc level.  Anyway, to that end, I&#8217;m posting the source to my small sample program (get it <a target="_blank" href="http://oregonstate.edu/~reeset/marcedit/anonymous/WindowsApplication3.zip">here</a>) that I used to diagnosis this problem.  The trick to doing this type of interaction is to avoid the use of integer class variables.  In .NET, you have to remember that you are dealing with managed code, so when you make the call to a API like SendMessage, you should be Marshalling all your data, and passing it into the function via the IntPtr structure.  The only exception to that with the SendMessage API is the message argument, which microsoft defines and an unsigned 32-bit integer on all platforms, though for practical purposes, the message argument should be classed as a 32-bit integer.</p>
<p><em>API/Delegate Declarations</em></p>
<p class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span><span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> SF_USECODEPAGE = 0x020;</pre>
<pre><span class="lnum">   2:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> SF_TEXT = 0x001;</pre>
<pre class="alt"><span class="lnum">   3:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> SF_RTF = 0x002;</pre>
<pre><span class="lnum">   4:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> CP_UTF8 = 65001;</pre>
<pre class="alt"><span class="lnum">   5:  </span> </pre>
<pre><span class="lnum">   6:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> WM_SETREDRAW      = 0x000B;</pre>
<pre class="alt"><span class="lnum">   7:  </span> </pre>
<pre><span class="lnum">   8:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> WM_USER = 0x400;</pre>
<pre class="alt"><span class="lnum">   9:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_STREAMIN = WM_USER + 73;</pre>
<pre><span class="lnum">  10:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_GETEVENTMASK   = (WM_USER + 59);</pre>
<pre class="alt"><span class="lnum">  11:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_SETEVENTMASK   = (WM_USER + 69);</pre>
<pre><span class="lnum">  12:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_STREAMOUT = WM_USER + 74;</pre>
<pre class="alt"><span class="lnum">  13:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ENM_NONE =    0;</pre>
<pre><span class="lnum">  14:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_SETTEXTMODE        = WM_USER + 89;</pre>
<pre class="alt"><span class="lnum">  15:  </span> </pre>
<pre><span class="lnum">  16:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> TM_PLAINTEXT       = 1;</pre>
<pre class="alt"><span class="lnum">  17:  </span> </pre>
<pre><span class="lnum">  18:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_AUTOWORDSELECTION = 0x00000001;</pre>
<pre class="alt"><span class="lnum">  19:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_AUTOVSCROLL = 0x00000040;</pre>
<pre><span class="lnum">  20:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_AUTOHSCROLL = 0x00000080;</pre>
<pre class="alt"><span class="lnum">  21:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_NOHIDESEL = 0x00000100;</pre>
<pre><span class="lnum">  22:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_READONLY = 0x00000800;</pre>
<pre class="alt"><span class="lnum">  23:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_WANTRETURN = 0x00001000;</pre>
<pre><span class="lnum">  24:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_SAVESEL = 0x00008000;</pre>
<pre class="alt"><span class="lnum">  25:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_SELECTIONBAR = 0x01000000;</pre>
<pre><span class="lnum">  26:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECO_VERTICAL = 0x00400000;</pre>
<pre class="alt"><span class="lnum">  27:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECOOP_SET = 0x0001;</pre>
<pre><span class="lnum">  28:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECOOP_OR = 0x0002;</pre>
<pre class="alt"><span class="lnum">  29:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECOOP_AND = 0x0003;</pre>
<pre><span class="lnum">  30:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> ECOOP_XOR = 0x0004;</pre>
<pre class="alt"><span class="lnum">  31:  </span></pre>
<pre><span class="lnum">  32:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_SETOPTIONS = (WM_USER + 77);</pre>
<pre class="alt"><span class="lnum">  33:  </span>        <span class="kwrd">private</span> <span class="kwrd">const</span> <span class="kwrd">int</span> EM_GETOPTIONS = (WM_USER + 78);</pre>
<pre><span class="lnum">  34:  </span> </pre>
<pre class="alt"><span class="lnum">  35:  </span> </pre>
<pre><span class="lnum">  36:  </span>        <span class="kwrd">delegate</span> IntPtr EditStreamCallback(IntPtr dwCookie, IntPtr pbBuff, IntPtr</pre>
<pre class="alt"><span class="lnum">  37:  </span>            cb, <span class="kwrd">out</span> IntPtr pcb);</pre>
<pre><span class="lnum">  38:  </span> </pre>
<pre class="alt"><span class="lnum">  39:  </span></pre>
<pre><span class="lnum">  40:  </span>        <span class="kwrd">struct</span> EDITSTREAM</pre>
<pre class="alt"><span class="lnum">  41:  </span>        {</pre>
<pre><span class="lnum">  42:  </span>            <span class="kwrd">public</span> IntPtr dwCookie;</pre>
<pre class="alt"><span class="lnum">  43:  </span>            <span class="kwrd">public</span> IntPtr dwError;</pre>
<pre><span class="lnum">  44:  </span>            <span class="kwrd">public</span> EditStreamCallback pfnCallback;</pre>
<pre class="alt"><span class="lnum">  45:  </span>        }</pre>
<pre><span class="lnum">  46:  </span> </pre>
<pre class="alt"><span class="lnum">  47:  </span></pre>
<pre><span class="lnum">  48:  </span> </pre>
<pre class="alt"><span class="lnum">  49:  </span>        [DllImport(<span class="str">"user32.dll"</span>, CharSet = CharSet.Auto, SetLastError = <span class="kwrd">false</span>)]</pre>
<pre><span class="lnum">  50:  </span>        <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr SendMessage(HandleRef hWnd, Int32 Msg,</pre>
<pre class="alt"><span class="lnum">  51:  </span>                                        IntPtr wParam, IntPtr lParam);</pre>
<pre><span class="lnum">  52:  </span></pre>
<pre class="alt"><span class="lnum">  53:  </span>        [DllImport(<span class="str">"user32.dll"</span>, CharSet = CharSet.Auto, SetLastError = <span class="kwrd">false</span>)]</pre>
<pre><span class="lnum">  54:  </span>        <span class="kwrd">static</span> <span class="kwrd">extern</span> IntPtr SendMessage(HandleRef hwnd, Int32 msg, IntPtr</pre>
<pre class="alt"><span class="lnum">  55:  </span>            wParam,    <span class="kwrd">ref</span> EDITSTREAM lParam);</pre>
<p>In the declarations, you will see that two forms of SendMessage have been defined.  One where the lParam references the EDITSTREAM structure and on where it references an IntPtr structure.  The former is used when streaming data into the RichText window, the latter is used when sending regular messages between controls.  It should be noted, the later could be removed in .NET 2.0 by making use of the System.Windows.Forms.Message class, which essentially allows you to send messages to controls so long as all arguments can be sent as IntPtrs.</p>
<p>After the declarations, the remainder of the code is setting up the actual streaming, and creating the function that the delegate prototypes.  In this example, I&#8217;ve called the streaming function, ReadRichTextStream and the actual streaming function, StreamIn.  These functions would look like the following:</p>
<p><em>ReadRichTextStream: Accepts a RichTextBox Object and the filename of the file to load.</em></p>
<style type="text/css">  .csharpcode, .csharpcode pre  {  	font-size: small;  	color: black;  	font-family: consolas, "Courier New", courier, monospace;  	background-color: #ffffff;  	/*white-space: pre;*/  }  .csharpcode pre { margin: 0em; }  .csharpcode .rem { color: #008000; }  .csharpcode .kwrd { color: #0000ff; }  .csharpcode .str { color: #006080; }  .csharpcode .op { color: #0000c0; }  .csharpcode .preproc { color: #cc6633; }  .csharpcode .asp { background-color: #ffff00; }  .csharpcode .html { color: #800000; }  .csharpcode .attr { color: #ff0000; }  .csharpcode .alt   {  	background-color: #f4f4f4;  	width: 100%;  	margin: 0em;  }  .csharpcode .lnum { color: #606060; }</style>
<p class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span>        <span class="kwrd">private</span> <span class="kwrd">void</span> ReadRichTextStream(System.Windows.Forms.RichTextBox objRich,</pre>
<pre><span class="lnum">   2:  </span>            <span class="kwrd">string</span> sfilename)</pre>
<pre class="alt"><span class="lnum">   3:  </span>        {</pre>
<pre><span class="lnum">   4:  </span></pre>
<pre class="alt"><span class="lnum">   5:  </span>            <span class="kwrd">string</span> filename = sfilename.ToLower();</pre>
<pre><span class="lnum">   6:  </span>            objRich.Text = <span class="str">""</span>;</pre>
<pre class="alt"><span class="lnum">   7:  </span>            <span class="kwrd">int</span> eType = SF_TEXT;</pre>
<pre><span class="lnum">   8:  </span>            <span class="kwrd">if</span> (filename.EndsWith(<span class="str">".mrk"</span>)|filename.EndsWith(<span class="str">".mrk8"</span>)|filename.EndsWith(<span class="str">".tmp"</span>)|filename.EndsWith(<span class="str">".xml"</span>))</pre>
<pre class="alt"><span class="lnum">   9:  </span>            {</pre>
<pre><span class="lnum">  10:  </span>                eType = (((CP_UTF8)&lt;&lt;16)|SF_USECODEPAGE|SF_TEXT);</pre>
<pre class="alt"><span class="lnum">  11:  </span>            }</pre>
<pre><span class="lnum">  12:  </span>            <span class="kwrd">else</span> <span class="kwrd">if</span> (filename.EndsWith(<span class="str">".bmrk"</span>))</pre>
<pre class="alt"><span class="lnum">  13:  </span>            {</pre>
<pre><span class="lnum">  14:  </span>                eType = SF_TEXT;</pre>
<pre class="alt"><span class="lnum">  15:  </span>            }</pre>
<pre><span class="lnum">  16:  </span>            <span class="kwrd">else</span> <span class="kwrd">if</span> (filename.EndsWith(<span class="str">".rtf"</span>))</pre>
<pre class="alt"><span class="lnum">  17:  </span>            {</pre>
<pre><span class="lnum">  18:  </span>                eType = SF_RTF;</pre>
<pre class="alt"><span class="lnum">  19:  </span>            }</pre>
<pre><span class="lnum">  20:  </span>            <span class="kwrd">else</span> <span class="kwrd">if</span> (filename.EndsWith(<span class="str">".txt"</span>))</pre>
<pre class="alt"><span class="lnum">  21:  </span>            {</pre>
<pre><span class="lnum">  22:  </span>                eType = SF_TEXT;</pre>
<pre class="alt"><span class="lnum">  23:  </span>            }</pre>
<pre><span class="lnum">  24:  </span>            <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  25:  </span>            {</pre>
<pre><span class="lnum">  26:  </span>                eType = (((CP_UTF8)&lt;&lt;16)|SF_USECODEPAGE|SF_TEXT);</pre>
<pre class="alt"><span class="lnum">  27:  </span>            }</pre>
<pre><span class="lnum">  28:  </span> </pre>
<pre class="alt"><span class="lnum">  29:  </span>            <span class="rem">//this.Redraw = false;</span></pre>
<pre><span class="lnum">  30:  </span>            <span class="kwrd">long</span> b_length = 0;</pre>
<pre class="alt"><span class="lnum">  31:  </span>            System.IO.FileStream fs = <span class="kwrd">new</span> System.IO.FileStream(sfilename, System.IO.FileMode.Open, System.IO.FileAccess.Read, System.IO.FileShare.Read);</pre>
<pre><span class="lnum">  32:  </span>            b_length = fs.Length;</pre>
<pre class="alt"><span class="lnum">  33:  </span>            Application.DoEvents();</pre>
<pre><span class="lnum">  34:  </span>            System.Runtime.InteropServices.GCHandle gch = System.Runtime.InteropServices.GCHandle.Alloc(fs, System.Runtime.InteropServices.GCHandleType.Normal);</pre>
<pre class="alt"><span class="lnum">  35:  </span>            EDITSTREAM es = <span class="kwrd">new</span> EDITSTREAM();</pre>
<pre><span class="lnum">  36:  </span>            es.dwCookie = (IntPtr)gch;</pre>
<pre class="alt"><span class="lnum">  37:  </span>            EditStreamCallback callback = <span class="kwrd">new</span> EditStreamCallback(StreamIn);</pre>
<pre><span class="lnum">  38:  </span>            es.pfnCallback = callback</pre>
<pre class="alt"><span class="lnum">  39:  </span></pre>
<pre><span class="lnum">  40:  </span>            SendMessage(<span class="kwrd">new</span> HandleRef(objRich, objRich.Handle), (Int32)EM_STREAMIN, (IntPtr)eType, <span class="kwrd">ref</span> es);</pre>
<pre class="alt"><span class="lnum">  41:  </span></pre>
<pre><span class="lnum">  42:  </span>            <span class="rem">//Remember to free allocated memory to avoid leaks.</span></pre>
<pre class="alt"><span class="lnum">  43:  </span>            gch.Free();</pre>
<pre><span class="lnum">  44:  </span>            fs.Close();</pre>
<pre class="alt"><span class="lnum">  45:  </span></pre>
<pre><span class="lnum">  46:  </span></pre>
<pre class="alt"><span class="lnum">  47:  </span>        }</pre>
<style type="text/css">  .csharpcode, .csharpcode pre  {  	font-size: small;  	color: black;  	font-family: consolas, "Courier New", courier, monospace;  	background-color: #ffffff;  	/*white-space: pre;*/  }  .csharpcode pre { margin: 0em; }  .csharpcode .rem { color: #008000; }  .csharpcode .kwrd { color: #0000ff; }  .csharpcode .str { color: #006080; }  .csharpcode .op { color: #0000c0; }  .csharpcode .preproc { color: #cc6633; }  .csharpcode .asp { background-color: #ffff00; }  .csharpcode .html { color: #800000; }  .csharpcode .attr { color: #ff0000; }  .csharpcode .alt   {  	background-color: #f4f4f4;  	width: 100%;  	margin: 0em;  }  .csharpcode .lnum { color: #606060; }</style>
<p><em>StreamIn: StreamIn is the function that actually reads the data from the file and pushs the data into the RichTextBox callback to print into the control.</em></p>
<p class="csharpcode">
<pre class="alt"><span class="lnum">   1:  </span>        <span class="kwrd">public</span> IntPtr StreamIn(IntPtr dwCookie, IntPtr pbBuff, IntPtr</pre>
<pre><span class="lnum">   2:  </span>            cb, <span class="kwrd">out</span> IntPtr pcb)</pre>
<pre class="alt"><span class="lnum">   3:  </span>        {</pre>
<pre><span class="lnum">   4:  </span>            <span class="kwrd">byte</span>[] buffer = <span class="kwrd">new</span> <span class="kwrd">byte</span>[cb.ToInt32()];</pre>
<pre class="alt"><span class="lnum">   5:  </span>            <span class="kwrd">uint</span> result = 0;</pre>
<pre><span class="lnum">   6:  </span> </pre>
<pre class="alt"><span class="lnum">   7:  </span></pre>
<pre><span class="lnum">   8:  </span></pre>
<pre class="alt"><span class="lnum">   9:  </span></pre>
<pre><span class="lnum">  10:  </span>            System.IO.FileStream fs = (System.IO.FileStream)((GCHandle)dwCookie).Target;</pre>
<pre class="alt"><span class="lnum">  11:  </span>            <span class="rem">//pcb = cb;</span></pre>
<pre><span class="lnum">  12:  </span>            <span class="kwrd">try</span></pre>
<pre class="alt"><span class="lnum">  13:  </span>            {</pre>
<pre><span class="lnum">  14:  </span>                pcb = (IntPtr)fs.Read(buffer, 0, cb.ToInt32());</pre>
<pre class="alt"><span class="lnum">  15:  </span></pre>
<pre><span class="lnum">  16:  </span>                <span class="kwrd">if</span> (pcb.ToInt32()&lt;=0)</pre>
<pre class="alt"><span class="lnum">  17:  </span>                {</pre>
<pre><span class="lnum">  18:  </span>                    pcb = IntPtr.Zero;</pre>
<pre class="alt"><span class="lnum">  19:  </span>                    result = 1;</pre>
<pre><span class="lnum">  20:  </span>                    <span class="kwrd">return</span> (IntPtr)result;</pre>
<pre class="alt"><span class="lnum">  21:  </span>                }</pre>
<pre><span class="lnum">  22:  </span>                <span class="kwrd">else</span></pre>
<pre class="alt"><span class="lnum">  23:  </span>                {</pre>
<pre><span class="lnum">  24:  </span></pre>
<pre class="alt"><span class="lnum">  25:  </span>                    System.Runtime.InteropServices.Marshal.Copy(buffer, 0, pbBuff, pcb.ToInt32());</pre>
<pre><span class="lnum">  26:  </span>                }</pre>
<pre class="alt"><span class="lnum">  27:  </span>            }</pre>
<pre><span class="lnum">  28:  </span>            <span class="kwrd">catch</span></pre>
<pre class="alt"><span class="lnum">  29:  </span>            {</pre>
<pre><span class="lnum">  30:  </span>                pcb = IntPtr.Zero;</pre>
<pre class="alt"><span class="lnum">  31:  </span>                result = 1;</pre>
<pre><span class="lnum">  32:  </span>                <span class="kwrd">return</span> (IntPtr)result;</pre>
<pre class="alt"><span class="lnum">  33:  </span>            }</pre>
<pre><span class="lnum">  34:  </span>            fs.Close();</pre>
<pre class="alt"><span class="lnum">  35:  </span>            <span class="kwrd">return</span> (IntPtr)result;</pre>
<pre><span class="lnum">  36:  </span>        }</pre>
<style type="text/css">  .csharpcode, .csharpcode pre  {  	font-size: small;  	color: black;  	font-family: consolas, "Courier New", courier, monospace;  	background-color: #ffffff;  	/*white-space: pre;*/  }  .csharpcode pre { margin: 0em; }  .csharpcode .rem { color: #008000; }  .csharpcode .kwrd { color: #0000ff; }  .csharpcode .str { color: #006080; }  .csharpcode .op { color: #0000c0; }  .csharpcode .preproc { color: #cc6633; }  .csharpcode .asp { background-color: #ffff00; }  .csharpcode .html { color: #800000; }  .csharpcode .attr { color: #ff0000; }  .csharpcode .alt   {  	background-color: #f4f4f4;  	width: 100%;  	margin: 0em;  }  .csharpcode .lnum { color: #606060; }</style>
<p>Anyway, the gist of all this, is that by setting the compile option to target 32-bit processors in the MarcEdit gui, I&#8217;ve been able to solve this issue.  I&#8217;m having the user that found the problem verify that I&#8217;ve indeed hunted this bug down and squashed it &#8212; so as soon as that&#8217;s confirmed, I&#8217;ll be pushing this fix out with MarcEdit.</p>
<p>&#8211;TR</p>
]]></content:encoded>
			<wfw:commentRss>http://people.oregonstate.edu/~reeset/blog/archives/444/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>
