Deploying Assemblies to the GAC

Posted 15 May 2013, 14:50 | by | | Perma-link

Pulling together a couple of helpful posts into one place so that I can find it later...

I wanted to deploy an assembly to the Global Assembly Cache (GAC) on a Windows 2008 server - GacUtil isn't neccessary installed, and I don't really want to install the entire SDK on to the server just to get it.

PowerShell to the rescue!

The first thing I needed to do was enable PowerShell to load .Net 4 assemblies, this was done by adding a config file into the PowerShell home directory (run $pshome from a PowerShell console), with the following contents:

<configuration>
  <startup uselegacyv2runtimeactivationpolicy="true">
    <supportedruntime version="v4.0.30319" />
    <supportedruntime version="v2.0.50727" />
  </startup>
</configuration>

You can then run the following commands to load the 4.0 instance of EnterpriseServices, which will install your libraries into the correct GAC depending on it's target runtime:

[System.Reflection.Assembly]::LoadWithPartialName("System.EnterpriseServices")
$publish = New-Object System.EnterpriseServices.Internal.Publish
$publish.GacInstall("C:\PathTo\Your.Assembly.dll")

Filed under: .Net, Fixes

SharePoint Database Moves - Unknown SQL Exception 53

Posted 05 October 2011, 16:21 | by | | Perma-link

This is one of those jobs that looks so simple on the outside, but can lead you down a massive rabbit hole if you're not too careful:

We're in the process of changing an instance of SharePoint from a true "Single Server" setup to having the databases on a separate SQL Server, and there's plenty of documentation about that, starting with: Move all databases

We'd also followed the recommendations in Harden SQL Server for SharePoint Environments but after we'd moved the Content Database to the new server and attached it in SQL, all attempts to "Add a content database" in Central Admin resulted in errors such as:

Cannot connect to database master at SQL server at SqlServer2. The database might not exist, or the current user does not have permission to connect to it.

Digging into the ULS logs we found the following Critical errors:

Unknown SQL Exception 53 occurred. Additional error information from SQL Server is included below.  A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: Named Pipes Provider, error: 40 - Could not open a connection to SQL Server)

It turns out that sometimes the SQL Configuration Manager needs a little bit of a helping hand, and you need start the Old School "SQL Server Client Network Utility" with the command (note the 8.3 format of the name):

cliconfg.exe

On the Alias tab of this app, add the Aliases you added in the SQL Configuration Manager, and you should be good to go.

Filed under: Fixes, SharePoint

LinqPad and Entity Framework

Posted 31 May 2011, 16:36 | by | | Perma-link

I'm a massive fan of LINQPad - it's much more lightweight than SQL Management Studio if you want to muck around with your data, and allows me to work against SQL with C#, rather than having to remember how to use cursors and the like when I've got some otherwise tedious data re-mapping to do.

That said, I'd never really pointed it at an Entity Framework EDM before, but I'd been wondering about the best way to tidy up the code for the tag clouds in the albums section of this site, so thought that I should see what I could do with the entity model as it stood, without resorting to stored procs.

Firing up the "Add Connection" wizard, I selected "Entity Framework" from the "Use typed data context from your own assembly", selected the website library, selected the (only) EDM from the library, and confirmed the provider.

LINQPad then created the data context correctly, so I pulled up a query to start working against it, only to get the following error message:

An assembly with the same identity 'System.Data.Entity, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089' has already been imported. Try removing one of the duplicate references.

This was slightly confusing - obviously both my project and LINQPad are referencing the System.Data.Entity namespace, and if I remove the reference from my project, I won't be able to build it. How do I remove it from LINQPad then?

It turns out that I don't have to do either. The clue (for me) lay in the notes section of the "Using LINQPad with Entity Framework" page:

If your assembly references other assemblies, LINQPad will pick up these, too, providing they live in the same folder.

Note the bit in bold from the original page - it would appear that my reference to the System.Data.Entity library was set to "Copy Local". Setting that to false and restarting LINQPad removed the error message, allowing me to clean up the tag code somewhat.

Filed under: Entity Framework, Fixes, LINQ, Tools

Notes on upgrading to Office 2010

Posted 04 June 2010, 17:22 | by | | Perma-link

This is one of those "20/20 hindsight is a wonderful thing" posts.

The basic issue is that Visio and Project aren't really part of Office, and should probably be uninstalled before you upgrade the main Office Suite - don't rely on their installers to properly clean them out.

I didn't do this, and had the following symptoms floating around:

Visio 2007 and Project 2007 were both still listed in my All Programs menu, with a tool tip "Installs on first use".

I imagine that at somepoint after upgrading Visio 2007 to 2010, I typed Visio<enter> into my start menu, and Visio 2007 reinstalled itself. I then opened Visio 2010, and that reconfigured itself through an installer. I uninstalled Visio 2007 again from the "Programs and Features" control panel, deleted the links, and the files in C:\Windows\Installers\ that they were pointing at.

I thought I was happy - turns out I was wrong. I was working in SharePoint, and getting these odd javascript library not registered errors:

Message: Library not registered.
Line: 1935
Char: 4
Code: 0
URI: http://server/_layouts/1033/init.js?rev=ck%2BHdHQ8ABQHif7kr%2Bj7iQ%3D%3D

Running the Repair tool (Programs and Features, Office 2010, Change and select "Repair") and restarting my machine seems to have fixed the issue nicely.

I hope this helps somebody else, and saves them the hour or so of confusion it's caused me.

Filed under: Fixes

Microsoft Office Live Connector makes Internet Explorer 7 "Downlevel"

Posted 19 February 2009, 14:22 | by | | Perma-link

ASP.NET 1.1 Browser Capabilities are evil. We've already updated the out of the box BrowserCaps in our Machine.configs for our ASP.NET 1.1 sites as per SlingFive's recommended updates, and our clients were happy - Safari, Opera and Firefox all saw the site as they should do.

I was happy too - until I installed Microsoft's latest Live offering - Office Live Connector  - this updated my Internet Explorer user agent string to:

User-Agent: Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30; .NET CLR 3.0.04506.590; .NET CLR 3.0.04506.648; .NET CLR 3.5.21022; .NET CLR 3.0.4506.2152; .NET CLR 3.5.30729; WWTClient2; OfficeLiveConnector.1.3; OfficeLivePatch.0.0)

(additions in bold)

I will go back and fix the BrowserCaps shortly, and when I do, I'll update this post, but in the mean time, I've removed the offending keys from IE's user agent string via the registry*

HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Internet Settings\5.0\User Agent\Post Platform

Now, I may have just broken my Office Live integration, who knows, but that's a price I can live with until I've fixed the browser caps correctly.

Update: 24 March 2009

Looks like it's deeper than that - I've just upgraded my machine to Internet Explorer 8 and the downleveling has happened again - I'm seriously going to have to take a look at what's in my UserAgent, and understand the BrowserCaps section properly - no one else in the office seems to be having this issue however, so it's clearly me.

Update: 30 March 2009

Hmm, removing the World Wide Telescope (WWTClient2) seems to have also resolved the issue, which is odd, as I've had that installed for some time.

Belated Update: 23 June 2009

Thanks to this answer on StackOverflow, I was able to find an actively updated Browser Caps by Owen Brady. Not only that, but Owen's quite knowledgable on this issue, and a quick email exchange led me to discover that ASP.NET 1.1 gets upset when your User Agent string is greater than 128 characters - which is why removing the Office Live stuff worked I guess, but installing IE8 took me back over the limit Angry. Anyway, the other thing Owen pointed out was to set the default tagwriter to the HTML 4.0 tagwriter, rather than the 3.2 one:

<!-- 08-06-06 Think its safe to force the newer tagwriter -->
<!-- tagwriter=System.Web.UI.Html32TextWriter-->
tagwriter=System.Web.UI.HtmlTextWriter

*Use with caution, don't edit the registry unless you know what you're doing, I'm not responsible if you break your machine, etc., etc.

Filed under: Fixes

Visual Studio 2008 SP1 Deletes LINQ to SQL designer files

Posted 09 February 2009, 11:30 | by | | Perma-link

We had the following issue: We'd gone back to an old .dbml file, and added a new table on to the design surface. Visual Studio proceeded to check out the project file, and delete the .designer.cs file from the system - which we failed to notice initially, as it's a nested file. What we did notice however was that nothing would compile, especially not our DAL, as the partial class within the data context contained lots of red squiggly lines and complained that most of our data objects no longer existed.

Looks like I'm not the only one seeing this, and MS fixed it last month, but I'm not sure when the fix is coming out.

Thankfully, there is a work around, and it seemed to work quite well for us:

In your partial class, move any using statements inside the namespace:

namespace DataContexts {
  using System.Collections.Generic;
  using System.Linq;
  partial class ConfigDataContext
  {
    [...]
  }
}

Then right-click on the .dbml file in Solution explorer, and select "Run Custom Tool". This will then regenerate the designer files, and your code will now compile.

Filed under: Fixes, LINQ

LINQ to SQL: Changes since Beta 2

Posted 30 November 2007, 10:29 | by | | Perma-link

So, Visual Studio 2008 is now in RTM, which also means that LINQ has moved out of Beta. Yay.

However, I've found some breaking changes between the Beta 2 and RTM bits:

  1. Table<t> no longer has a method Remove() - this has been renamed to DeleteOnSubmit(). This apparently is to "better convey that the updates are deferred until the call to DataContext.SubmitChanges()" (MSDN Forums)
  2. The XML declaration of the .DBML file has changed, in Beta 2 this was:
    <?xml version="1.0" encoding="utf-16"?>
    In the RTM this has changed to:
    <?xml version="1.0" encoding="utf-8"?>
    Curiously, this UTF-16 caused VS to complain about unicode support, and wouldn't open the design surface. Changing it to UTF-8 fixed the issue.

I'll post more as I find them.

Filed under: .Net, Fixes, LINQ

PHP on Windows XP/IIS

Posted 25 January 2007, 10:30 | by | | Perma-link

Ok, for some reason this was a lot harder than it should have been, mainly (i guess) because of some ambiguity around installers and the like.

It is the way the PHP documentation states:

Windows Installer (PHP 5.2 and later)

The Windows PHP installer for later versions of PHP is built using MSI technology using the Wix Toolkit (http://wix.sourceforge.net/). It will install and configure PHP and all the built-in and PECL extensions, as well as configure many of the popular web servers such as IIS, Apache, and Xitami.

First, install your selected HTTP (web) server on your system, and make sure that it works. Then proceed with one of the following install types.

Normal Install

Run the MSI installer and follow the instructions provided by the installation wizard. You will be prompted to select the Web Server you wish to configure first, along with any configuration details needed.

This is a lie.

The key to this lie is almost every other page, which directs you to the Manual Installation Steps:

Manual Installation Steps

This install guide will help you manually install and configure PHP with a web server on Microsoft Windows. To get started you'll need to download the zip binary distribution from the downloads page at /downloads.php.

Although there are many all-in-one installation kits, and we also distribute a PHP installer for Microsoft Windows, we recommend you take the time to setup PHP yourself as this will provide you with a better understanding of the system, and enables you to install PHP extensions easily when needed.

Which should be followed.

Basically, the installer will, without asking, install everything by default in C:\Program Files\PHP\. Fine, you think, as it should be. However, it then fails to configure anything in IIS (as I requested in the installer), sets up an environment key %PHPRC% to C:\Program Files\PHP\ - no quotes though, so nothing can use it, and adds the following as entries in the php.ini file:

upload_tmp_dir="C:\DOCUME~1\BENJAM~1\LOCALS~1\Temp\php\session"
session.save_path="C:\DOCUME~1\BENJAM~1\LOCALS~1\Temp\php\upload"

Ignoring the fact that these look to be the wrong way round (Upload to session, sessions saved in Upload?), when I finally got a PHP file to load, I received errors stating that these two lines were badly formed.

This leads me on to the final point:

Initially I was getting a message in the browser:

The specified module could not be found.

That was it, nothing else.

So I gave up, and moved everything to C:\PHP\, changed the Path environment variable, changed the PHPRC variable, repointed the PHP ISAPI handler, and updated the relevant lines in php.ini  - creating a folder structure of Temp\Uploads and Temp\Session under the PHP folder.

Restarted IIS, and Robert's your Mother's Brother, as they say, PHP pages loading in the browser, and executing script.

Filed under: Fixes

Getting AjaxPro to behave in the Global Assembly Cache (GAC)

Posted 08 November 2006, 23:52 | by | | Perma-link

Getting AjaxPro (CodePlex Start Kit) to behave in the Global Assembly Cache (GAC). While the means to do this are available in the Starter Kit, the "Quick Guide" doesn't really cover the main points here.

If you need to deploy AjaxPro to a web server via the GAC here are the key points to remember:

Modify your web.config as follows (this is for the .Net 1.1 version, for the .Net 2.0, just change "AjaxPro" to "AjaxPro.2"):

In configSections block add the following:

<sectionGroup name="ajaxNet">
    <section name="ajaxSettings"
             type="AjaxPro.AjaxSettingsSectionHandler,
                   AjaxPro,
                   Version=6.10.6.2,
                   Culture=neutral,
                   PublicKeyToken=4735ae9824c7d3ec" />
</sectionGroup>

Remember to update the version number to the version you are using - Michael Schwarz is quite prolific with his releases.

Then add the following as a direct child of configuration:

<ajaxNet>
    <ajaxSettings>
        <urlNamespaceMappings useAssemblyQualifiedName="true" allowListOnly="false" />
        <debug enabled="false" />
    </ajaxSettings>
</ajaxNet>

The key element here is the useAssemblyQualifiedName="true" attribute. This tells the AjaxPro library to output the calls to your AjaxMethods as fully qualified paths - with the version number, culture and public key information.

Finally, add the following block as a child of the system.web element:

<httpHandlers>
    <add verb="GET,POST"
         path="AjaxPro/*.ashx"
         type="AjaxPro.AjaxHandlerFactory,
               AjaxPro,
               Version=6.10.6.2,
               Culture=neutral,
               PublicKeyToken=4735ae9824c7d3ec"/>
</httpHandlers>

Again, updating the version number as required.

You can then follow the rest of the quick start guide to set up your first AjaxPro page.

I'm going to write up a note on error reporting tomorrow hopefully, but the key point here is you'll notice that I left in the Debug element in the ajaxNet section, set the value to true and you will be able to retrieve the stack, trace and lines from the exception as well as just the message.

Filed under: AJAX, ASP.NET, Fixes

Setting up ASP.Net 2 Stuff&#8230;

Posted 30 June 2006, 15:25 | by | | Perma-link

Couple of notes to self mostly:

I had a couple of problems with an ASP.Net 2.0 site on Windows XP Pro, namely I first received errors like:

Failed to execute the request because the ASP.NET process identity does not have read permissions to the global assembly cache. Error: 0x80070005 Access is denied.

As you'll probably have found out, you need to ensure that the local user ASPNET has access to the GAC, and for that you need the command line tool cacls:

cacls c:\windows\assembly /E /T /G ASPNET:R

/E - Edit the ACL instead of replacing it
/T - Change files in this directory and all sub-directories
/G user:perm - Grant the user a permision.

The recommendation I'd seen used /P instead of /G, I found that /G was more reliable.

On top of that, I then had to ensure that both the user ASPNET and the user IUSR_MachineName had read access to the website's files - so run the cacls command with those directories, and you should be away (you need to do it for IUSR_ as that's the account that non .Net pages are called under - .css, .js, .html, etc).

The other problem I had was with ATLAS (ajax to non-softies):
I was setting up some admin pages that shared a master page, and wanted the pages to asynchronously call the server every now and then to keep the session alive during prolonged edits. I initially tryed to add a public method on the page decorated with a [WebMethod] attribute, but to no avail, the PageMethods JavaScript class wasn't being generated. Turns out if you want to call an ATLAS server side method from a master page, you need to call it through a webservice. Enjoy...

Filed under: ASP.NET, Fixes