Code Access Security and User Controls

About a week ago I helped troubleshoot an issue where a customer wrote a WinForms User Control and she was trying to use it on a form she was developing.  When she dragged it from the toolbox, she was getting the following error:

An exception occurred while trying to create an instance of Contoso.XP2.AuthorList.  The exception was "Request for the permission of type System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.5000.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 failed".

No one else in her group experienced this issue.  Right off the bat it smelled like a CAS (code access security) issue, the VS IDE was trying to create an instance of the control to use in the designer and was failing to get some permission (File IO in this case).  In this case, a quick scan of the code for the user control showed that in the contructor it was reading some configuration information from the local HD.

This was a bit confusing to the developer, as she hadn't written any code yet, but the constructor was getting run.  How could this be?

At design time, when a control is put onto the form in the designer, the Visual Studio process (DEVENV.EXE) will create an instance of your control to be able to display it on the design surface.  In doing this, stuff like the constructor gets run. 

The majority CAS issues we see stem from loading an assembly from a network share.  By default, an assembly loaded from the network is not trusted as much, therefore things like File IO get restricted.  But in this case, the developer was working with everything local.  The project and the file being read were on the C: drive.  Time to look under the covers. 

I had her run the (recently aquired) SysInternals FileMon tool and filter on only the DEVENV.EXE process.  After she sent me the trace, the following line looked suspicious (I added the line breaks):

7120 10:01:24 AM devenv.exe:784 QUERY INFORMATION \\chi-fs01\UserAppData\Devlogon\Application Data\Microsoft\VisualStudio\7.1\ProjectAssemblies\ipgr1g-i01\Contoso.XP2.DataAccess.Settings.dll SUCCESS FileFsDeviceInformation

What is with this "ProjectAssemblies" directory?  And why was it on a network share.  The "chi-fs01" naming convention of the server made it sound like a file server in their Chicago office (thanks IT!) and after talking with the developer some more, it turns out her home directory was redirected to a file share for roaming purposes.  After a bit of digging, KB825007 looked like the exact same problem we were seeing, except a different error was occuring.

As I mentioned, Visual Studio will complile a temporary copy of the control so it can run it for display in the designer.  It will compile this temorary copy to a folder in %APPDATA%\Microsoft\VisualStudio\7.1\ProjectAssemblies.  When %APPDATA% is re-directed to a network share, the compiled assemby won't be trusted the same as one on the local hard drive and may fail.  The workaround is to explicity trust this directory in the code access security policy:

  1. Start the Microsoft .NET Framework 1.1 Configuration tool (located in Administrative Tools on the Control Panel). The .NET Configuration 1.1 window opens.
  2. In the left pane of the .NET Configuration 1.1 window, expand Runtime Security Policy, and then expand Machine.
  3. Expand Code Groups, and then expand All_Code.
  4. Right-click LocalIntranet_Zone, and then click New. The Create Code Group dialog box appears.
  5. Click to select the Create a new code group option.
  6. In the Name box, type MyCodeGroup, and then click Next.
  7. In the Choose the condition type for this code group box, click URL.
  8. To fully trust all files that are located in the ProjectAssemblies folder, type the following text in the URL box:
    file:////FolderPath\Microsoft\VisualStudio\7.1\ProjectAssemblies\*
    Note: FolderPath is a placeholder for the path of the folder where the Application Data folder is redirected.
  9. Click Next.
  10. In the Use existing permission set box, click FullTrust, and then click Next.
  11. Click Finish.

After completing these steps, she retried dragging the control from the tool box and it showed up on the form surface this time.