2008-02-28

ClickOnce, SharePoint and Anonymous access

I have been laborating with a ClickOnce deployed application in SharePoint and all seems to work well until I tried to connect to SharePoint (wss3) from a workstation where I used another locally logged in user than the one I used to authenticate myself at the SharePoint server.

When I then tried to access the ClickOnce application the bootstrap downloader (ApplicationActivator) prompts a "Cannot Start Application" error that says "Cannot retrieve application. Authentication error".

The details of the error indicates a 401 response from the webserver.
System.Deployment.Application.DeploymentDownloadException (Unknown subtype)
- Downloading http://wm20031/_layouts/MyApp/MyApp.application did not succeed.
- Source: System.Deployment
- Stack trace:
at System.Deployment.Application.SystemNetDownloader.DownloadSingleFile(DownloadQueueItem next)
at System.Deployment.Application.SystemNetDownloader.DownloadAllFiles()
at System.Deployment.Application.FileDownloader.Download(SubscriptionState subState)
at System.Deployment.Application.DownloadManager.DownloadManifestAsRawFile(Uri& sourceUri, String targetPath, IDownloadNotification notification, DownloadOptions options, ServerInformation& serverInformation)
at System.Deployment.Application.DownloadManager.DownloadDeploymentManifestDirectBypass(SubscriptionStore subStore, Uri& sourceUri, TempFile& tempFile, SubscriptionState& subState, IDownloadNotification notification, DownloadOptions options, ServerInformation& serverInformation)
at System.Deployment.Application.DownloadManager.DownloadDeploymentManifestBypass(SubscriptionStore subStore, Uri& sourceUri, TempFile& tempFile, SubscriptionState& subState, IDownloadNotification notification, DownloadOptions options)
at System.Deployment.Application.ApplicationActivator.PerformDeploymentActivation(Uri activationUri, Boolean isShortcut, String textualSubId, String deploymentProviderUrlFromExtension)
at System.Deployment.Application.ApplicationActivator.ActivateDeploymentWorker(Object state)

--- Inner Exception ---
System.Net.WebException
- The remote server returned an error: (401) Unauthorized.
- Source: System
- Stack trace:
at System.Net.HttpWebRequest.GetResponse()
at System.Deployment.Application.SystemNetDownloader.DownloadSingleFile(DownloadQueueItem next)

If I check the weblog we can se the following two entries

2008-02-28 12:05:29 W3SVC1265274740 192.168.1.199 GET /_layouts/MyApp/MyApp.application 80 domain\administrator 192.168.1.2 Mozilla/4.0+(...) 206 0 0
2008-02-28 12:05:29 W3SVC1265274740 192.168.1.199 GET /_layouts/MyApp/MyApp.application 80 - 192.168.1.2 - 401 5 0
The first is the webbrowser access where I authenticate using the domain\administrator account and the application manifest is successfully returned to the browser. Then the ApplicationActivator tries the same thing as anonymous but fails utterly. Ok, so perhaps this is only anonymous user access that is denied, but I had already checked the "Enable Anonymous access" in the IIS manager for the _layouts/MyApp folder.

Testing with firefox and anonymous access proved that is not the access rights that is incorrectly set.
2008-02-28 12:16:56 W3SVC1265274740 192.168.1.199 GET /_layouts/MyApp/MyApp.application 80 - 192.168.1.2 Mozilla/5.0+... 200 0 0
So the IIS is not blocking access, then it has to be SharePoint? (_layouts is a SharePoint managed folder)

To test I checked the code for the System.Deployment.Application.SystemNetDownloader.DownloadSingleFile(DownloadQueueItem next) method and reproduced the code that was processed there.

WebRequest request = WebRequest.Create("http://wm20031/_layouts/MyApp/MyApp.application");
request.Credentials = CredentialCache.DefaultCredentials;
RequestCachePolicy policy = new RequestCachePolicy(RequestCacheLevel.BypassCache);
request.CachePolicy = policy;
HttpWebRequest request2 = request as HttpWebRequest;
if (request2 != null) {
request2.UnsafeAuthenticatedConnectionSharing = true;
request2.AutomaticDecompression = DecompressionMethods.GZip;
request2.CookieContainer = GetUriCookieContainer(request2.RequestUri);
WebRequest.DefaultWebProxy.Credentials = CredentialCache.DefaultCredentials;
}
WebResponse response = null;
response = request.GetResponse();
using (StreamReader reader = new StreamReader(response.GetResponseStream())) {
Console.WriteLine(reader.ReadToEnd());
}
response.Close();
This code fails with the same exception as the Application Activator and after some debugging I noticed that if I didn't copy the cookies to the request, then it worked?!
Checking further in the cookie container, it only added one cookie MSOWebPartPage_AnonymousAccessCookie and with the value of the webapplication port. (80)

The GetUriCookieContainer parsed the cookies retrieved in IE for the url. If I removed the cookie for the server in the temporary internet files folder, the code above worked even with the cookie row (no cookies added).

To solve the problem one workaround is to create a virtual folder in the root of the SharePoint site (MyApp) (that is not managed by SharePoint), map this to the same folder as _layouts/MyApp, allow anonymous access there and navigate to that url instead (/MyApp/MyApp.application). This works since the cookie is not present for the application.

But what I really like to know is the purpose of the MSOWebPartPage_AnonymousAccessCookie, especially why SharePoint sets this cookie when I navigate to the site and why it throws an access denied when I try to access with the cookie set?

2007-11-26

Task failed because "sgen.exe" was not found

I installed Visual Studio 2008 (final) and started to create a WinForms (2.0) application that calls a webservice and is deployed with clickonce. When I try to compile it (after adding the webreference) I get the following build error

C:\WINDOWS\Microsoft.NET\Framework\v3.5\Microsoft.Common.targets(1993,9):
error MSB3091:
Task failed because "sgen.exe" was not found, or the correct Microsoft Windows SDK is not installed. The task is looking for "sgen.exe" in the "bin" subdirectory beneath the location specified in the InstallationFolder value of the registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A. You may be able to solve the problem by doing one of the following:
1) Install the Microsoft Windows SDK for Windows Server 2008 and .NET Framework 3.5.
2) Install Visual Studio 2008.
3) Manually set the above registry key to the correct location.
4) Pass the correct location into the "ToolPath" parameter of the task.


I thought that the SDK was to be installed with VisualStudio 2008, but when looking into the SDKs folder (C:\Program Files\Microsoft Visual Studio 9.0\SDK) it contains almost nothing, only a few files in the v3.5 folder.

When I searched for the SDK for framework 3.5 it seems that is included in the windows server 2008 platform sdk and that is only avaliable for beta2 so far...

Regarding the registry settings, I have the SDK for v2.0 installed and since I build vs the 2.0 framework, shouldn't it look in the KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v2.0 key?

How do I set the ToolPath?

Anyway, I came around the issue by setting the
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Microsoft SDKs\Windows\v6.0A InstallationFolder key to the same path as the 2.0 Sdk path and compilation was successful...

Is the VisualStudio 2008 release not final since it seems to miss the SDK or have I been sloppy installing the product?

Signing a ClickOnce manifest file using a spc/pvk certificate

To sign a ClickOnce manifest file/assembly you need a pfx file without chaining information.

First we need to convert the spc/pvk file to a pfx file. As Stuart found out you use the pvk2pfx tool to accomplish this.

If we try to use this certificate and it contains chaining information we will get an error stating

"Cannot find the certificate and private key for decryption"

Then we need to make sure that the pfx don't include the chaining information as described in the case @ commodo (importing and exporting the pfx).

When these steps has been completed, you can build and sign your application.

2007-10-27

Media center automatically starts the computer from standby

I've had a problem that I have finally found time to solve. I have a windows media center machine at home connected to my tv set. At night I put the machine in standby and every morning it start by itself at around 7. This is rather annoying since I don't have any scheduled jobs or recordings at that time.

I checked the event log and one of the first logs after startup in the application log was an 'Event Info: Guide Successfully Downloaded'.
Perhaps it's the EPG download that forces the machine to start? Can this be configured to another time in the day?

I checked the settings in mce but no entry states when to download the epg. So after some googling I found a post in one of the The Green Button forums that took up the issue.

To cut it short, the user Cowboy found out that there are two registry keys controlling this behavior

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\EPG\dlLastTime

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Media Center\Service\EPG\dlRegTime


These keys contain the date when the guide was downloaded the last time and when it is registered to run the next time. The data format is stored in NT Time Epoch format but backwards. (see Cowboys forum post for detailed information)

To fix this you can set these values to another time and date by updating these registry values and restart the computer. For ease of use riesm had posted an application that provides a nice GUI for setting the download time. After using this and restarting the computer is not autostarted every morning at 7.

Thanks to Cowboy and riesm for providing the great community support.

2007-09-19

Running multiple versions of ASP.NET on the same IIS

When configuring a website to run multiple applications with different versions of ASP.NET there are some issues that needs to be resolved before the applications are running smoothly. The guide below describes the setup for a windows 2003 server.

1. Install the different dotnet framework versions on the server.
When installed you can check the c:\windows\microsoft.net\framework folder and each installed version contains an own folder named vx.x.xxxx. On my server, running
dir c:\WINDOWS\Microsoft.NET\Framework\v*
gives the following output
2007-09-12  08:15    <dir>          v1.1.4322
2007-09-12 08:44 <dir> v2.0.50727
2. Make sure the needed framework is installed in the IIS
Each framework version installs a tool named aspnet_regiis.exe. This tool is used to manipulate the IIS metabase for asp.net registrations and mappings. Depending on which version of the framework the tool is shipped with, there exists different switches that can be used. Run the exe in a command window to see which are supported for your version.
To see which frameworks is installed in the IIS metabase, run the tool with the -lv flags. (Example below)
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_regiis.exe -lv
2.0.50727.0 Valid (Root) C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
If your needed framework isn't listed, go to the version folder and run the aspnet_regiis.exe with the -ir flag. (the -i flag will also install the framework but will also update the scriptmaps, which we don't want to do (not yet anyway))
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis.exe -ir
Start installing ASP.NET (1.1.4322.0) without registering the scriptmap.
Finished installing ASP.NET (1.1.4322.0) without registering the scriptmap.
Running the -lv again we'll se that we now have two frameworks registered in the IIS metabase.
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis.exe -lv
1.1.4322.0 Valid C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\aspnet_isapi.dll
2.0.50727.0 Valid (Root) C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll
3. Install the scriptmaps on the web application
In addition to installing the framework in the IIS metabase we need to configure the web application to use the specific framework version.
To see which mappings that are in effect use the -lk flag
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis.exe -lk
W3SVC/ 2.0.50727.832
W3SVC/1/ROOT/ 2.0.50727.832
W3SVC/1/ROOT/Reports/ 2.0.50727.832
W3SVC/1/ROOT/ReportServer/ 2.0.50727.832
W3SVC/3/Root/ 2.0.50727.832
To set the scriptsmaps for a specific application use the -s flag. (here my application is running on the path W3SVC/258083574/root/MyApplication)
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis.exe -s W3SVC/258083574/root/MyApplication
Start registering ASP.NET scriptmap (1.1.4322.0) recursively at W3SVC/258083574/root/MyApplication.
Finished registering ASP.NET scriptmap (1.1.4322.0) recursively at W3SVC/258083574/root/MyApplication.
When installation is successful use the -lk to see the updated mapping
C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322>aspnet_regiis.exe -lk
W3SVC/ 2.0.50727.832
W3SVC/1/ROOT/ 2.0.50727.832
W3SVC/1/ROOT/Reports/ 2.0.50727.832
W3SVC/1/ROOT/ReportServer/ 2.0.50727.832
W3SVC/258083574/root/MyApplication/ 1.1.4322.0
W3SVC/3/Root/ 2.0.50727.832
4. Make sure each version uses separate Application pools
A common mistake is to use the same application pool for multiple applications running different versions of the framework. This is not recommended and will most certainly break in time.
So... don't.
Changing application pool settings and creating new ones is done in the mmc tool (Internet Information Services). You don't have to configure the pools, just don't mix applications running on different framework versions.

5. Make sure that WebService extensions allows webpages of the specific version
If you now test your new application and tries to view an aspx page but the server only returns a 404 error, then you need to fix the WebService extension settings.
Locate the Web Service Extensions folder in the mmc tool and Allow the ASP.NET version to execute.

Good luck!

2007-09-10

Sandcastle crashes... code and pre tags

Almost done with the current project release. Continuous server(CCNET) is running,
building - OK,
unit tests - OK,
analyzing - OK,
compiling xml documentation -- Err

Computer says:
Info: BuildAssembler: Building topic T:Sdo.Agent.TypeInstance`1

Unhandled Exception: System.Xml.XmlException: Unexpected end tag. Line 2, position 57.
at System.Xml.XmlTextReaderImpl.Throw(Exception e)
at System.Xml.XmlTextReaderImpl.Throw(String res, String arg)
at System.Xml.XmlTextReaderImpl.Throw(Int32 pos, String res)
at System.Xml.XmlTextReaderImpl.ParseDocumentContent()
at System.Xml.XmlTextReaderImpl.Read()
at System.Xml.XmlLoader.ParsePartialContent(XmlNode parentNode, String innerxmltext, XmlNodeType nt)
at System.Xml.XmlElement.set_InnerXml(String value)
at SandcastleBuilder.Components.CodeBlockComponent.Apply(XmlDocument document, String key)
at Microsoft.Ddue.Tools.BuildAssembler.Apply(IEnumerable`1 manifest)
at Microsoft.Ddue.Tools.BuildAssembler.Apply(String manifestFile)
at Microsoft.Ddue.Tools.BuildAssemblerConsole.Main(String[] args)
Last step completed in 01:09:26.3530


Ok, so I checked the xml documentation for the class for mismatching tags, but couldn't find any.
After a bit of searching I found the following post on the Sandcastle forums.
http://www.codeplex.com/SHFB/Thread/View.aspx?ThreadId=12084

A <pre> tag had snuck into the <code> xml documentation and thats not supported.

Well you always learn something. =)

2007-07-04

AccessViolationException using Oracle and MTS

I have been annoyed by a really irritating bug in my test environment for quite some time. I use oracle and enlists the connection in the MTS and when I try to open the connection I get different errors (and sometimes there isn't any errors).
  • Oracle.DataAccess.Client.OracleException Data provider internal error(-3000)
  • Oracle.DataAccess.Client.OracleException : ORA-12514: TNS:listener does not currently know of service requested in connect descriptor
It has also crashed my nunit application and the nunit-console processes that our continuous integration server launches has also crashed.
Searching for these errors have given several pointers where none was appropriate.

Today I finally found the source of the error. I used adplus to get a crash dump of the nunit process.
adplus -crash -pn nunit.exe

The adplus generated some dumps, log and a report. When I read the log I found a new error source. An AccessViolationError was thrown when oracle tried to enlist in the transaction.

Wed Jul 4 08:18:48.229 2007 (GMT+2): (c2c.9ec): Access violation - code c0000005 (first chance)
---
--- 1st chance AccessViolation exception ----
---------------------------------------------------------------

Occurrence happened at:
Debug session time: Wed Jul 4 08:18:48.229 2007 (GMT+2)
System Uptime: 0 days 16:37:08.859
Process Uptime: 0 days 0:01:37.803
Kernel time: 0 days 0:00:02.281
User time: 0 days 0:00:05.093

Faulting stack below ---
*** ERROR: Symbol file could not be found. Defaulted to export symbols for C:\WINDOWS\system32\msvcrt.dll -
# ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
00 04cbdcdc 77bbcfdb 003f0000 00000000 000000e0 ntdll!RtlRestoreLastWin32Error+0x235
01 04cbdcf0 77bba995 000000e0 00000000 0592a2f0 msvcrt!free+0x1a8
02 04cbdd04 04d46612 000000e0 00000000 06e0b228 msvcrt!operator new+0x24
03 04cbdd38 04ccc344 059468a0 0595e340 05918db0 ORAMTS10!kpntenlistctxget+0xe6
04 00000000 00000000 00000000 00000000 00000000 OraOps10w!OpsConEnlist+0x3b4
Here we can see that the ORAMTS10.dll is the source of the error. When I then googled on access violation ORAMTS10 I found the solution in the Microsoft forum where Sahra Parra already had debugged the same issue from another source.

The conclusion of the AccessViolation exception is that the ORAMTS10 contains a method that enlists the connection in the MTS. This method takes a parameter that contains the datasource name and when we pass a datasource longer than 40 characters, this results in that data in the heap is overwritten and resulted in a heap corruption.

Heap corruptions are hard to debug since the error don't show up when the data is written. The error surfaces when the corrupted data is read which explains that the error messages differs (or not surfaces at all).
In this case I got lucky and got an error in the ORAMTS10.dll that gave me a hint to the solution. To actually debug this issue and get error messages that occurs when the data is written, you have to use pageheap/gflag to let the error surface when the data is written.


To work around the bug in ORAMTS10 I only needed to change the Data Souce from the full (more than 40 characters) source name
Data Source=(DESCRIPTION=(ADDRESS_LIST=
(ADDRESS=(PROTOCOL=TCP)(HOST=oracle.internal.com)(PORT=1521)))
(CONNECT_DATA=(SERVER=DEDICATED)(SERVICE_NAME=orcl)))

To the short version (requires a registration in tnsnames.ora)
Data Source=oracle

When changed, the crashes went away and I'm so happy ;)