PermView is a .NET utility that is a good companion to the ADepends program described in the previous section. Given an assembly, PermView tells you the minimal, optional, and refused permissions requested by the assembly, and it can optionally tell you about the assembly's declarative security.
Well, that's what the documentation says, but what does it actually mean and why is it important? To answer this, I need to take a little side tour into permissions and security. The concept here is that you can (and you often should) tell your assembly to request whatever permissions it needs from the CLR when it starts to execute. To request permissions for your assembly, you first add attributes to your code. The VB .NET language compiler then stores the requested permissions in the program when it's compiled.
When your assembly is loaded by the CLR, these permissions are checked against the security policy rules, and any permission that is not granted is flagged with a security exception. This exception usually doesn't give much helpful information; rather, it says something generic like "System.Security.Policy.PolicyException: Failed to acquire required permissions". This is where PermView is invaluable: Developers and system administrators can use it to check exactly what permissions an assembly is requesting. Once a developer or system administrator knows these permissions, he or she can then examine and change the relevant security policy file to grant the necessary permissions to the assembly.
There are three types of permissions that you can request for your assemblies:
RequestMinimum : The minimum permissions that your assembly needs in order to execute successfully. This might include, for instance, a request for permission to perform file input/output.
RequestOptional : The permissions that your assembly would like to have but are not essential for successful execution. This could, for instance, be a request for permission to write to a specific log file in a specific folder.
RequestRefused : The permissions that your assembly specifically does not want, usually to avoid their misuse by code that calls your assembly. This might be declining permission for any action that involves a write to the registry.
Explicitly requesting these permissions means that an administrator can see your assembly's permission requirements and adjust the assembly's security policy accordingly . It also means that your code is more likely to run properly; if the correct permissions are not specified, your code must deal with every possible permission failure internally if it's to execute without causing an exception.
One interesting "gotcha" is that once you've started adding permission requests , you need to specify all the permissions needed by your assembly. This is because once an assembly has requested a permission, the CLR denies all other permissions that haven't been specifically requested, even if the relevant security policy grants those other permissions. PermView can be useful for spotting this type of situation, which can cause an application to cease working completely for no obvious reason.
The easiest way to invoke PermView on a regular basis is to create a new item on the Tools menu. You can do this by going to Tools ’ External Tools and completing the External Tools dialog box with the following entries:
Title: Permissions (or whatever title you want)
Command: C:\Program Files\Microsoft .Net\FrameworkSDK\bin\ permview.exe
Arguments: $(TargetPath)
Initial directory: $(TargetDir)
You should also check the Use Output window option, as this creates a custom pane in the Output window where PermView can display its information. You should now have a new item on the Tools menu. Selecting this new menu item invokes PermView on the current assembly, allowing you to view the permissions requested for the assembly.
Invoking PermView from the command line is just as easy as invoking it from within Visual Studio. When it's used in this manner, PermView displays its findings directly to the console window. The following command line shows the permissions granted to the assembly MyAssembly.exe:
PERMVIEW MyAssembly.exe
Rather than go into ponderous detail that you can easily find in the documentation, I present in this section some examples of attributing an assembly to request specific permissions and what those permission requests look like when you examine them using PermView .
Imports System.Security.Permissions <Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="FullTrust")>
Running PermView produces the following permission sets:
Microsoft (R) .NET Framework Permission Request Viewer. Version 1.0.3705.0 Copyright (C) Microsoft Corporation 1998-2001. All rights reserved. minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1" Unrestricted="true"/> optional permission set: Not specified refused permission set: Not specified
<Assembly: PermissionSetAttribute(SecurityAction.RequestMinimum, Name:="Internet")>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <Ipermission class="System.Security.Permissions.FileDialogPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Access="Open"/> <IPermission class="System.Security.Permissions.IsolatedStorageFilePermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Allowed="DomainIsolationByUser" UserQuota="10240"/> <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Execution"/> <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Window="SafeTopLevelWindows" Clipboard="OwnClipboard"/> <IPermission class="System.Drawing.Printing.PrintingPermission, System.Drawing, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" version="1" Level="SafePrinting"/> </PermissionSet>
<Assembly: FileIOPermissionAttribute(SecurityAction.RequestMinimum, _ All:="C:\log\logfile.txt")>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="C:\log\logfile.txt" Write="C:\log\logfile.txt" Append="C:\log\logfile.txt" PathDiscovery="C:\log\logfile.txt"/> </PermissionSet>
<Assembly: FileIOPermissionAttribute(SecurityAction.RequestMinimum, Read:="C:\temp")>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.FileIOPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="C:\temp"/> </PermissionSet>
<Assembly: RegistryPermissionAttribute(SecurityAction.RequestMinimum, _ Read:="HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\ CentralProcessor")>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.RegistryPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Read="HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System\CentralProcessor"/> <PermissionSet>
<Assembly: UIPermissionAttribute(SecurityAction.RequestMinimum, _ Clipboard:=UIPermissionClipboard.OwnClipboard)>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Clipboard="OwnClipboard"/> </PermissionSet>
<Assembly: UIPermissionAttribute(SecurityAction.RequestMinimum, _ Window:=UIPermissionWindow.SafeTopLevelWindows)>
Running PermView produces the following:
minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.UIPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Window="SafeTopLevelWindows"/> </PermissionSet>
<Assembly: SecurityPermissionAttribute(SecurityAction.RequestMinimum, _ Assertion:=True)>
Running PermView produces the following:
minimal permission set: minimal permission set: <PermissionSet class="System.Security.PermissionSet" version="1"> <IPermission class="System.Security.Permissions.SecurityPermission, mscorlib, Version=1.0.3300.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" version="1" Flags="Assertion"/> </PermissionSet>