Issues with the XmlSerializer in medium trust environments

In my last post I briefly mentioned that CodeHTMLer had issues running in a medium trust environment. The simple web application front end I created kept failing before it ever got started. It keep hitting a SecurityException nested in an InvalidOperationException which looks something like:

[Exception: System.InvalidOperationException: There was an error reflecting type 'CodeHtmler.Languages'. ---> System.Security.SecurityException: Request failed.
   at System.Reflection.CustomAttribute._CreateCaObject(...)
   at System.Reflection.CustomAttribute.CreateCaObject(...)
   at System.Reflection.CustomAttribute.GetCustomAttributes(...)
   at System.Reflection.CustomAttribute.GetCustomAttributes(...)
   at System.Reflection.RuntimePropertyInfo.GetCustomAttributes(...)
   at System.Xml.Serialization.XmlAttributes..ctor(...)
   at System.Xml.Serialization.XmlReflectionImporter.ImportStructLikeMapping(...)
   at System.Xml.Serialization.XmlReflectionImporter.ImportTypeMapping(...)
The action that failed was:
InheritanceDemand
The type of the first permission that failed was:
System.Security.PermissionSet
The Zone of the assembly that failed was:
MyComputer

CodeHTMLer uses the XmlSerializer to read and write the language definitions and it appeared to be what was causing this exceptions to be thrown. I spent a good deal of time trying to figure out why this wasn't working because every thing I read online said the XmlSerializer should actually work in medium trust. After a while of debugging I finally figured out that the problem was caused by some custom attributes.

[XmlAttribute]
[Editor(typeof(HtmlColorEditor), typeof(System.Drawing.Design.UITypeEditor))]
public string Color {...}

Apparently when the XmlSerializer is walking through the custom attributes it runs into the EditorAttribute and then tries to get the type of my custom editor HtmlColorEditor which has UITypeEditor in it's inheritance chain. However UITypeEditor for some reason demands a FullTrust permission set for Inheritance, which is problematic in a medium trust environment. To verify for certain that this was the issue I removed those editor attributes and then the XML serialization worked as expected under medium trust.

Those editor attributes are used by the PropertyGrid, which is my lame way of providing UI to edit the language definitions, so I didn't want to remove them permanently but I also wanted the serialization to work in a medium trust environment. To allow for both the PropertyGrid and the medium trust serialization to work I decided to use the sgen tool to generate the serialization classes statically when I knew I had FullTrust permissions, instead of dynamically at runtime like the generic XmlSerializer class does.

The output of sgen was another assembly, CodeHtmler.XmlSerializers.dll which I then needed to reference and switch the code from using the more general XmlSerializer(typeof(Languages)) to the specific class  LanguagesSerializer(). This was cool because it allowed me to accomplish what I wanted but it in turn forced me to now release two separate assemblies, CodeHtmler.dll and CodeHtmler.XmlSerializers.dll. Wouldn't it be nice if I could get away with just one assembly. It turns out that sgen has this /keep option that will tell it not to delete the temp code files used to build the new assembly. This was great because now I can just take the generated source code for the LanguagesSerializer class and build it as part of my CodeHtmler.dll assembly. Here is the command line I used to do this:

sgen CodeHtmler.dll /keep /force /type:CodeHtmler.Languages

There is a little bit of the chicken and egg problem here because I needed the CodeHtmler.dll to generate the serialization code and I needed serialization code to build CodeHtmler.dll. It really wasn't that big of an issue though because the serialization doesn't actually need to work to run sgen it just needs to be stubbed out so CodeHtmler.dll can be built.

This approach works quite nicely. Now the only issue is that I have to remember to regenerate the serialization code whenever I change any of my serialized classes. Fortunately, I only have a small number of classes I serialize and their serialization interface doesn't change much so I think I can live with this approach.

Added CodeHTMLer project at codeplex

In order to help better manage changes to CodeHTMLer I finally added the project on codeplex at http://codeplex.com/CodeHtmer.

I made a couple of small code updates after I put it up on codeplex:
- Added a new language property DivInlineFont to define the font to use when not using pre tags.
- Added a language definition for F# (thanks to Harry at Blogging in F#)
- Fixed the CodeHTMLer library so it runs in a medium trust environment (needed this because I just moved web hosts and the new one runs in medium trust level, more about the details later).

Thus far codeplex seems pretty cool but I guess I will only be able to realize its full collaboration potential when I actually have more contributors than just myself.

Posted by puzzlehacker | 2 comment(s)
Filed under: ,

Fun with C# functions

Dustin Campbell has an interesting series on C# functions on his Did it with .NET blog.

  1. Fibonacci Numbers, Caching and Closures
  2. What's in a Closure?
  3. Using Automatic Memoization
  4. A Higher Calling
  5. The Art of Currying
  6. Building Functions from Functions, part 1: Partial Application
  7. Building Functions from Functions, part 2: Function Composition

 

Some interesting stuff that ties together a number of C# 2.0 and 3.0 feature sets. Definitely worth a read. Thanks Dustin and keep them coming.

Posted by puzzlehacker | with no comments
Filed under: ,

Failure creating an Outlook application object on Vista

While creating a Outlook application object from another process in C# like:

outlook = new Microsoft.Office.Interop.Outlook.Application();

or powershell

PS> $outlook = new-object -com Outlook.Application

or straight up COM via CoCreateInstance on Vista it's possible to receive the following error:

Retrieving the COM class factory for component with CLSID {0006F03A-0000-0000-C000-000000000046} failed due to the following error: 80080005

Error 0x80080005 (CO_E_SERVER_EXEC_FAILURE) is sort of a generic COM error message that occurs for many reasons while calling CoCreateInstance. One reason someone could receive this error is because the client process and the server process (outlook.exe in this case) are running at different integrity levels. By default it doesn't appear that COM likes talking across two different processes that are running at different integrity levels. There supposedly is a way to implement the COM server in such a way to support it but currently the Outlook COM server doesn't support it.

People who develop their applications on Vista using Visual Studio, which runs at integrity level high by default, will run into this issue often when Outlook is already running. By default Outlook runs at integrity level medium and if the client application is run from Visual Studio it will inherit the high integrity level and thus there will be an integrity level mismatch.

To fix this one needs to make the integrity levels match so either start the client application outside Visual Studio at the normal medium integrity level or run Outlook at the high integrity level (i.e. as Administrator). However it is not recommended to run Outlook at integrity level high all the time. Another way to deal with this is to ensure Outlook is not already running so COM will start the process at the correct integrity level of the client process that created the application object.

I don't know of any way to detect this exact situation programmatically but process explorer works well for manually checking the integrity levels of processes.

Posted by puzzlehacker | 7 comment(s)
Filed under: , ,

Why does my Outlook event seem to stop working?

Imagine we have some code in an Outlook addin that looks similar to code below. Does anyone see anything wrong with it? It simply places a button on the menu bar and shows a message box when the button is clicked. The code works for sometime but then all of a sudden the button mysteriously stops working. What gives? 

using Office = Microsoft.Office.Core;
using Outlook = Microsoft.Office.Interop.Outlook;
...
void SetupCommandBar(Outlook.Application application)
{
    Office.CommandBar menu = application.ActiveExplorer().CommandBars.ActiveMenuBar;

    Office.CommandBarButton button = menu.Controls.Add(Office.MsoControlType.msoControlButton,
        Type.Missing, Type.Missing, Type.Missing, true) as Office.CommandBarButton;

    button.Caption = "Click Me!";
    button.Click += new Office._CommandBarButtonEvents_ClickEventHandler(button_Click);
}
void button_Click(Microsoft.Office.Core.CommandBarButton Ctrl, ref bool CancelDefault)
{
    System.Windows.Forms.MessageBox.Show("Clicked Button!");
}

The button stops working due to the mystical powers of the .Net garbage collector. If we look closely we notice that the button object is locally scoped in the SetupCommandBar function, thus once we execute that function the button object is free to be cleaned up. However, until the button object is actually destroyed by the garbage collector the button click event will fire and the button will work. Due to the non-deterministic nature of the garbage collector we have no idea how long the button will work. In my simple testing it seemed to work for a little while but if you want to speed up the process add a call go GC.Collect in the button_Click callback.

The easiest fix for this problem is to change the scope of the button object to be a member variable of enclosing class. By doing this we ensure that the button object stays alive and works until we are ready for it to stop working.

Posted by puzzlehacker | 6 comment(s)
Filed under: , ,

Powershell script to find strings and highlight them in the output

After reading about Brad's find script I starting thinking about how cool it would be if I could highlight the search pattern in the output. So I wrote my own custom Find-String script to highlight the results.

Find-String.ps1

# Find-String.ps1
#  Wrapper around dir | select-string which will highlight the pattern in the results
param	( [string] $pattern = ""
	, [string] $filter = "*.*"
	, [switch] $recurse = $false
	, [switch] $caseSensitive = $false)

if ($pattern -eq $null -or $pattern -eq "") { Write-Error "Please provide a search pattern!" ; return }

$regexPattern = $pattern
if($caseSensitive -eq $false) { $regexPattern = "(?i)$regexPattern" }
$regex = New-Object System.Text.RegularExpressions.Regex $regexPattern

# Write the line with the pattern highlighted in red
function Write-HostAndHighlightPattern([string]$inputText)
{
	$index = 0
	while($index -lt $inputText.Length)
	{
		$match = $regex.Match($inputText, $index)
		if($match.Success -and $match.Length -gt 0)
		{
			Write-Host $inputText.SubString($index, $match.Index - $index) -nonewline
			Write-Host $match.Value.ToString() -ForegroundColor Red -nonewline
			$index = $match.Index + $match.Length
		}
		else
		{
			Write-Host $inputText.SubString($index) -nonewline
			$index = $inputText.Length
		}
	}
}

# Do the actual find in the files
Get-ChildItem -recurse:$recurse -filter:$filter | 
	Select-String -caseSensitive:$caseSensitive -pattern:$pattern |	
	foreach {
		Write-Host "$($_.FileName)($($_.LineNumber)): " -nonewline
		Write-HostAndHighlightPattern $_.Line
		Write-Host
	}

Sample Output

PS> ./Find-String new-object
Find-String.ps1(13): $regex = New-Object System.Text.RegularExpressions.Regex $regexPattern
Get-ApptsUsingEWS.ps1(55): $responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
Get-ApptsUsingOOM.ps1(6): $outlook = New-Object -ComObject Outlook.Application
getappts.ps1(51): $responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
printAppts.ps1(6): $outlook = New-Object -ComObject Outlook.Application

 

For reference here are some other find scripts around the blogsphere: Brad Wilson, Ian Griffith and Keith Hill.

Posted by puzzlehacker | 3 comment(s)
Filed under: , ,

Retrieving your Outlook appointments for a given date range

Before we dive into the code sample lets take a quick look at what it means for an appointment to fall into a given date range.

When you compare an appointment with a given date range (or any two time intervals) there are the 6 possible outcomes displayed in the diagram above. Usually as a first attempt people write a comparison that looks like:

[Start] >= RangeStart AND [End] <= RangeEnd

If you examine that comparison closely you will notice that it will only retrieve appointments of type 1. This maybe fine for most applications, like getting all appointments for a given week because there usually aren't any appointments spanning over the range edges. However, if you want to be more precise and include any appointments that overlap with a given date range (i.e. type 1, 2, 3, 4) you can use the following comparison:

[End] >= RangeStart AND [Start] <= RangeEnd

This type of restriction will help when you have smaller date/time ranges such as a few hours or a day. In general, unless you specifically only want type 1 appointments, I would recommend using this restriction which finds any appointments that overlap with the given date/time range.

Since Walter has already provided a VBA, WebDAV, and CDO code sample on how to find appointments within a specific time frame, I figured I would provide some Powershell code samples.

Powershell script to retrieve appointments using the Outlook Object Model for a given date range.

Keep in mind in order to get all the appointments, including any instances of recurring appointments, you need to get the items collection on the calendar folder and then Sort by the "[Start]" property and set IncludeRecurrences to true. Once you have done this the Count property on the items collection is bogus because there could potentially be an infinite number of recurring appointments. So to traverse this collection you need to use the enumerator (i.e. foreach) or use the Find/FindNext methods on the collection.

# Get-ApptsUsingOOM.ps1
#    Powershell script to retrieve all appointments for a given date range using the Outlook Object Model
param ( [DateTime] $rangeStart = [DateTime]::Now
      , [DateTime] $rangeEnd   = [DateTime]::Now.AddDays(7))

$outlook = New-Object -ComObject Outlook.Application

# Ensure we are logged into a session
$session = $outlook.Session
$session.Logon()

$olFolderCalendar = 9
$apptItems = $session.GetDefaultFolder($olFolderCalendar).Items
$apptItems.Sort("[Start]")
$apptItems.IncludeRecurrences = $true $restriction = "[End] >= '{0}' AND [Start] <= '{1}'" -f $rangeStart.ToString("g"), $rangeEnd.ToString("g") foreach($appt in $apptItems.Restrict($restriction)) { "{0:MM/dd hh:mm tt} - {1:MM/dd hh:mm tt} : {2}" -f [DateTime]$appt.Start, [DateTime]$appt.End, $appt.Subject } $outlook = $session = $null;

Powershell script to retrieve appointments using Exchange Web Services for a given date range

For simplicity I built the soap message manually and submitted the request, but you could easily generate the web service proxy classes using wsdl.exe like I did in another example if you don't wish to build the soap message yourself.

# GetApptsUsingEWS.ps1
#    Powershell script to retrieve all appointments for a given date range using Exchange Web Services
param ( [DateTime] $rangeStart = [DateTime]::Now
      , [DateTime] $rangeEnd   = [DateTime]::Now.AddDays(7)
      , [System.Net.NetworkCredential] $credentials = (Get-Credential).GetNetworkCredential())

# Remember to set your exchange server address
$exchangeServerAddress = "http<s>://<ExchangeServer>/EWS/Exchange.asmx"

# Soap request derived from http://msdn2.microsoft.com/en-us/library/aa564515.aspx
$soapRequest = @'
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:xsd="http://www.w3.org/2001/XMLSchema"
               xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
  <soap:Body>
    <FindItem Traversal="Shallow" xmlns="http://schemas.microsoft.com/exchange/services/2006/messages">
      <ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="calendar:Start"/>
          <t:FieldURI FieldURI="calendar:End"/>
          <t:FieldURI FieldURI="item:Subject"/>
        </t:AdditionalProperties>
      </ItemShape>
      <CalendarView MaxEntriesReturned="100" StartDate="{0}" EndDate="{1}"/>
      <ParentFolderIds>
        <t:DistinguishedFolderId Id="calendar"/>
      </ParentFolderIds>
    </FindItem>
  </soap:Body>
</soap:Envelope>
'@

# Put the range start and end date in the correct format
$soapRequest = $soapRequest -f $rangeStart.ToString("yyyy-MM-ddTHH:mm:sszzz"), $rangeEnd.ToString("yyyy-MM-ddTHH:mm:sszzz")

# Create the request 
$webRequest = [System.Net.WebRequest]::Create($exchangeServerAddress)
$webRequest.ContentType = "text/xml"
$webRequest.Headers.Add("Translate", "F")
$webRequest.Method = "Post"
$webRequest.Credentials = $credentials

# Setup the soap request to send to the server
$content = [System.Text.Encoding]::UTF8.GetBytes($soapRequest)
$webRequest.ContentLength = $content.Length
$requestStream = $webRequest.GetRequestStream()
$requestStream.Write($content, 0, $content.Length)
$requestStream.Close()

# Get the xml response from the server
$webResponse = $webRequest.GetResponse()
$responseStream = $webResponse.GetResponseStream()
$responseXml = [xml](new-object System.IO.StreamReader $responseStream).ReadToEnd()
$responseStream.Close()
$webResponse.Close()

foreach ($appt in $responseXml.GetElementsByTagName("t:CalendarItem"))
{
    "{0:MM/dd hh:mm tt} - {1:MM/dd hh:mm tt} : {2}" -f [DateTime]$appt.Start, [DateTime]$appt.End, $appt.Subject
}
Posted by puzzlehacker | 9 comment(s)
Filed under: , , ,

Reflector 5 Released

Lutz released Reflector for .NET 5.0

If you do any .NET development and you don't use Reflector for .NET then you are missing out. Scott posted a brief review of the new version. I think I'm most excited about the new analyze feature, it should come in handy.

Reflector for .NET
Reflector for .NET Add-Ins

Posted by puzzlehacker | 1 comment(s)
Filed under: , ,

Image File Execution Options

Every now and than while debugging I need to either determine when a dll/module is loaded or need to attach a debugger to a process at startup that is started outside a debugger. I know there are settings that exist to do this but I always seem to forget exactly what they are. So for future reference here the registry entries.

 

Force a break while debugging when a dll/module is loaded

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<modulename.dll>]
"BreakOnDllLoad"=dword:00000001

Force a process to start under the Visual Studio Debugger

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<processname.exe>]
"Debugger"="vsjitdebugger.exe"

 

Useful links:

Junfeng - Image File Execution Options
Greggm - Breaking when a module loads
Greggm - Inside 'Image File Execution Options' debugging
Oldnewthing - Beware the Image File Execution Options key

Posted by puzzlehacker | with no comments
Filed under: ,

Powershell version of cmd set

If you are like me and are just so used to typing set to list and set environment variables then you might find this script useful.

if (test-path alias:set) { remove-item alias:set > $null }
function set
{
	[string]$var = $args
	if ($var -eq "")
	{
		get-childitem env: | sort-object name
	}
	else
	{
		if ($var -match "^(\S*?)\s*=\s*(.*)$")
		{
			set-item -force -path "env:$($matches[1])" -value $matches[2];		
		}
		else
		{
			write-error "ERROR Usage: VAR=VALUE"
		}
	}	
}

Just add this script to your Powershell profile and you will be all set :)

PS: If anyone is interested I updated the Powershell Language definitions for CodeHTMLer, it now highlights more of the built-in stuff such as cmdlets and variables.

More Posts « Previous page - Next page »