## UnconstrainedMelody with .Net 4

November 14, 2013

We wanted to include Unconstrained Melody in our .Net project because it provides strongly typed versions of Enum.Parse and Enum.TryParse. (see here and here for more information)

To achieve this, it uses a tool (included in the package) called ConstraintChanger, which performs a bit of MSIL magic on the compiled assembly.

Since our project is on .Net 4.x, but the library was written in the times of .Net 2, some adjustments needed to be made.

First, the Visual Studio (2010, 2012) solution upgrade kicks in and converts solution and projects to the current VS version. Next, we need to change the projects to compile to the .Net 4 Framework.

Hitting Build caused the build to fail for two reasons:

• ConstraintChanger did not find the generated UnconstrainedMelody assembly, *or* the required target directory did not exist
• The UnconstrainedMelody.Test test project refers to the “rewritten” UnconstrainedMelody assembly which does not yet exist.

Since the ConstraintChanger source code references the assemblies with relative paths, and I did not want to figure out where it executes etc., I modified Program.cs to use absolute paths:

private const string InputAssembly =
@"C:\path\to\UnconstrainedMelody\UnconstrainedMelody\bin\Debug\UnconstrainedMelody.dll";
const string OutputAssembly =
@"C:\path\to\UnconstrainedMelody\UnconstrainedMelody\Rewritten\UnconstrainedMelody.dll";

Next, the MS SDK path needs to be updated to refer to ProgramFilesX86 and V7.0A:

string programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86);
string sdkDirectory = Path.Combine(programFiles, @"Microsoft SDKs\Windows\v7.0A\bin");

and the path to the .Net 4 framework as well

string framework2Directory = Path.Combine(windows, @"..\Microsoft.NET\Framework\v4.0.30319");

After building the library and creating the directory C:\path\to\UnconstrainedMelody\UnconstrainedMelody\Rewritten the program can be executed.

Next, I updated the UnconstrainedMelody reference in the test project, and the tests succeeded.

I noticed that the library does not contain case-insensitive versions of Enum.Parse and Enum.TryParse, so I added to EnumInternals.cs:

internal static readonly IList<string> NamesLC;
NamesLC = new ReadOnlyCollection<string>(Names.Select(n => n.ToLower()).ToList());

and to Enums.cs:

public static T ParseName<T>(string name, bool ignoreCase)
where T : struct, IEnumConstraint
{
T value;
if (!TryParseName(name, ignoreCase, out value))
{
throw new ArgumentException("Unknown name", "name");
}
return value;
}
public static bool TryParseName<T>(string name, bool ignoreCase, out T value)
where T : struct, IEnumConstraint
{
if (string.IsNullOrEmpty(name))
{
value = default(T);
return false;
}
int index = ignoreCase
? EnumInternals<T>.NamesLC.IndexOf(name.ToLower())
: EnumInternals<T>.Names.IndexOf(name);
if (index == -1)
{
value = default(T);
return false;
}
value = EnumInternals<T>.Values[index];
return true;
}

Note that every change in the UM library needs both compilation and patching (by ConstraintChanger) for the library to work correctly.

## Working around SSRS error “is ambiguous in the namespace”

October 15, 2013

I am developing a couple of SSRS reports which need to translate UTC dates into timezone-based date values based on a timezone parameter (tzid).

After I found this answer on SO I added System.Core 3.5 to the reports’ References, and added custom Code:

Public Function FromUTC(ByVal d As Date, ByVal tz As String) As Date
Return (TimeZoneInfo.ConvertTimeBySystemTimeZoneId(d, tz))
End Function

and changed the Expression of each datetime field to

= Code.FromUTC(Fields!MyDateTimeField.Value, Parameters!tzid.Value)

Worked fine.

Then a production system was upgraded to SSRS 2012 (and thus VS SSDT 2010), and report deployment did not work anymore, as VS displayed the error messages when hitting Deploy

The definition of the report ‘/myreport’ is invalid

and opening the report

[rsCompilerErrorInCode] There in an error on line 1 of custom code: [BC30560] “TimeZoneInfo” is ambiguous in the namespace “System”

or, in German

“TimeZoneInfo” ist im Namespace “System” nicht eindeutig.

So there’s no deployment for you, sorryyyyyyy.

A bit of google-fu brought up this question on Social and this issue on Connect, which means that MS is sitting on this bug for half a year now, and the “workaround” seems to be to create your own SSRS assembly, and/or to use Reflection to access the TimeZoneInfo methods, as sketched here.

I did not want to give in so easily, so I tried and verified that the procedure described in Deploying SSRS Reports with PowerShell still works for SSRS 2012.

And a colleague found that you can still deploy to SSRS 2012 using BIDS 2008 if you set the project’s TargetServerVersion to “SQL Server 2008 R2 or later”.

## CJK Spam

October 15, 2013

There must be a huge online market for golf and fake watches targeting the Japanese.

How do I know?

Well, spam bots from 62.210.202.241 and 62.210.202.243 and 192.99.9.72 tell me so. Permanently! Unfortunately, even if you are interested in 時計 コピー or アルマーニ 腕時計 or カシオ 時計 or ゴルフ ドライバー, you won’t find them here.

Another spam bot from 198.204.241.75 seems to have encoding problems posting Italian junk text, but the accented characters end up as or . Meow.

Do you have a spam issue on this site; I also am a blogger, and I was curious about your situation

Well, Akismet catches most of it

## ABCpdf: “Remote process terminated unexpectedly” Exception

October 10, 2013

Once I got ABCpdf 8 running when invoked from a Windows service, it worked for a long time without any problems:

I split the document, which can become quite large, into its chapters, have each chapter generate the HTML, pass the HTML to ABCpdf, and finally merge the parts using iTextSharp, along with page numbering and header and footer generation.

Until, one day, two chapters consistently raised the exception

System.Exception: Remote process terminated unexpectedly. —> System.Runtime.Serialization.SerializationException:
End of Stream encountered before parsing was completed.
at System.Runtime.Serialization.Formatters.Binary.__BinaryParser.Run()
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream,
HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RpcCaller.Call(MethodBase method, Object[] parameters)
— End of inner exception stack trace —
Server stack trace:
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RpcCaller.Call(MethodBase method, Object[] parameters)
at WebSupergoo.ABCpdf8.Internal.Spawntaneous.RemoteInstance1.Invoke(IMessage msg)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at WebSupergoo.ABCpdf8.Internal.Gecko.IGeckoWorker.AddImageUrl(String url, Double pageWidthMm, Double pageHeightMm, Byte[] serializedOpts)
at WebSupergoo.ABCpdf8.Internal.Gecko.GeckoCallback.MyCallback(IntPtr closure, IntPtr serializedOpts, UInt32 serializedOptsLen, Double widthInMm, Double heightInMm, String url, UInt32& outNumCommands, IntPtr& outSerializedData, UInt32& outSerializedDataLen)
at WebSupergoo.ABCpdf8.Internal.NDoc.N.AddImageUrlGecko_32(IntPtr doc, String url, Int32 width, IntPtr callback, String& outErr)
at WebSupergoo.ABCpdf8.Doc.AddImageHtml(String html, Boolean paged, Int32 width, Boolean disableCache)

Teh internets were of no use, unfortunately, and there was no trace of what had happened in the Event Log, so I poked around a bit, and tried to find the intermediate documents or log files hopefully generated by ABCpdf.

I did not find a clue of what exactly had caused the exception, but after deleting the directory

C:\Users\[service account]\AppData\Local\Temp\ABCpdf

PDF generation worked fine again.

## Shrinking MS SQL Server Tables

September 27, 2013

One of my application logs User Agent identifiers to a database table which, over the years, reached several gigabytes in size.

Trying to reduce the size without losing the information, I created a lookup table for these strings, calculated the foreign keys, and then set the identifiers to NULL.

But, no combination of DBCC SHRINKFILE or DBCC CLEANTABLE would actually cause the .mdf file to reduce its size.

This being the internets, I finally found the solution that worked for me in these posts

I tried

ALTER INDEX Index_name ON Table_Name REORGANIZE WITH (LOB_COMPACTION=ON)

and it worked. The operation needs to be executed on the CLUSTERED index, which is, unless another index created as clustered, the primary key by default. The alternative

ALTER INDEX ALL ON dbo.Mytable REBUILD

may achieve the same effect (I haven’t tried).

## VS – Side-Effects of Upgrading a Project’s .Net Framework Version

September 16, 2013

The other day I was playing around with two of my applications, checktsql and SMOscript, as I was considering to include the functionality of checktsql into SMOscript.

Now, up to the current versions, both applications have been developed using Visual Studio 2008 targeting .Net 2.0. (I prefer to keep requirements to a minimum). But now I thought it was time to migrated them to VS2010/3.5 (client framework), and came across a couple of unresolved mysteries.

### Missing Exceptions in SqlCommand.Execute*()

The first mystery is that the behavior of the Execute* methods changed such that ExecuteNonQuery() and ExecuteReader() do not reliably raise exceptions any more if an error occurs in T-SQL.

Take the example

CREATE PROCEDURE TestTemp AS
CREATE TABLE #T (id int)
SELECT * FROM #T
GO

which checktsql tries to verify (with the SET FMTONLY ON option) like this

BEGIN TRAN
SET FMTONLY ON; EXECUTE [dbo].TestTemp
ROLLBACK

(Note that the transaction is actually created by SqlConnection.BeginTransaction(), but essentially it’s the same mechanism)

SSMS returns an error:

Msg 208, Level 16, State 0, Procedure TestTemp, Line 6
Invalid object name '#T'.`

What I noticed after migrating the code to VS2010/.Net3.5 is that some (most?) stored procedures cause the error to be raised as an exception in .Net, and some do not. However, the behavior is consistent for each stored procedure.

Fortunately, I noticed the different behavior only when using the SET FMTONLY ON option, but still, there is a difference depending on which VS or framework version is used.

Teh internets did not really help me – I found a couple of discussions, but no documentation of the change, or how to get the original semantics back:

### SMO dependency on System.Core

When I tried to debug (and understand) above issue, and reverted the application back to .Net 2.0, but still build with VS2010, I suddenly got the error message during build:

The primary reference “Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL” could not be resolved because it has an indirect dependency on the framework assembly “System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″ which could not be resolved in the currently targeted framework. “.NETFramework,Version=v2.0″. To resolve this problem, either remove the reference “Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL” or retarget your application to a framework version which contains “System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089″

There was nothing I could do to get VS2010 to the original behavior (i.e.: compile successfully) targeting .Net 2.0, even though the same assemblies were referenced both in the VS2008 and the VS2010 project.

This thread on MS connect shows the “amusing” dependency zigzag that SMO assemblies implement, switch dependencies even between minor releases:

Posted by Chris Dennis on 4/20/2011 at 10:19 AM
Installing SQL Server 2008R2 Cumulative Update 7 upgrades Microsoft.SqlServer.Management.SqlParser to 10.50.1777.0 which again depends on System.Core v3.5.
Posted by Chris Dennis on 3/25/2011 at 12:50 PM
Installing SQL Server 2008R2 Cumulative Update 6 upgrades Microsoft.SqlServer.Management.SqlParser to 10.50.1765.0 which does not depend on System.Core v3.5. Only version 10.50.1750.9 has a dependency on System.Core v3.5.
Posted by Microsoft on 3/25/2011 at 11:08 AM
Your assertion is correct the Microsoft.SqlServer.Management.SqlParser took a dependency on System.Core v3.5. Any projects which reference this assembly directly or indirectly need to be targeted to .NET Framework V3.5.
This is a nightmare!

## Happy Anniversary – 6 years devioblog

September 13, 2013

Happy Anniversary!

You registered on WordPress.com 6 years ago!

Thanks for flying with us. Keep up the good blogging!

Not as active as it used to be, but still alive…