Click here to Skip to main content
15,897,371 members
Articles / Web Development / ASP.NET

Project \ Assembly dependencies viewer

Rate me:
Please Sign up or sign in to vote.
4.57/5 (16 votes)
11 Jan 20041 min read 170.1K   2.1K   32  
This simple application gets any VS.NET project or assembly and displays all the assembly / project dependencies. All dependencies are shown in a tree view with images that indicate the assembly location (Bin, GAC or registered as COM+ component).
using System;
using System.Xml.XPath;
using Interop.COMAdmin; 

namespace DevNetInstaller
{
	/// <summary>
	/// Responsible for analyzing project dependencies by their locations (Bin,GAC,COM+)
	/// and return the data as XML.
	/// </summary>
	public class ReadProject
	{
		bool AllLevels = false;
		string m_FilePath = "";
		System.Text.StringBuilder XmlFile = new System.Text.StringBuilder();
		XPathDocument oXmlReader;
		#region CONSTRUCTORs
			public ReadProject()
		{
			
		}		
			public ReadProject(string FilePath,bool bAllLevels)
		{
			// set depth of links
			AllLevels = bAllLevels; 
			//set target file
			m_FilePath = FilePath;
			// if a project file load it as XMLDocument
			if (m_FilePath.IndexOf (".dll") == -1 && m_FilePath.IndexOf (".exe") == -1)
				oXmlReader = new XPathDocument(m_FilePath);
		}
		#endregion
		/// <summary>
		/// Get the Assembly name. if m_FilePath is EXE or DLL simply return it. else
		/// get the assembly name from the project XML file (csproj).
		/// </summary>
		/// <returns>String - Assembly location</returns>
		private string GetAssemblyName()
		{
			XPathNavigator oPath;
			XPathNodeIterator oIter;
			
			if (m_FilePath.IndexOf (".dll") > -1 || m_FilePath.IndexOf (".exe") > -1)
				return m_FilePath;
			string strAssName="",AssPath ;
			try
			{    
				oPath = oXmlReader.CreateNavigator();
				oIter = oPath.Select("//Settings");

				while (oIter.MoveNext())
				{
					strAssName =  oIter.Current.GetAttribute("AssemblyName","");
				}
				AssPath = m_FilePath.Substring (0,m_FilePath.LastIndexOf("\\")+1) + "bin\\" + strAssName + ".DLL";
				return AssPath;
            
			}
        catch ( Exception Err)
			{
				string a = Err.Message;
				return "";
			}
		}
		/// <summary>
		/// get asembly references and place them between "<REFERS></REFERS>"
		/// </summary>
		/// <returns>String - XML holding reference</returns>
		public string GetReferencToFile()
		{			
			XmlFile.Append ("<REFS>");
			AddReferenceToXml(GetAssemblyName());
			XmlFile.Append ("</REFS>");
			return XmlFile.ToString ();
		}
		/// <summary>
		/// Check if given DLL register as COM+ component. looping through COM+ 
		/// applications and application components. for each component look in
		/// registry for component CLSID InprocServer32 value. if InprocServer32
		/// value match given name return true.
		/// </summary>
		/// <param name="DllName" description="Full assembly name"></param>
		/// <returns>bool</returns>
		private bool IsDllInCom(string DllName)
		{
			bool RV=false;
			COMAdminCatalogClass cat = new COMAdminCatalogClass (); 
			// Get Applications
			ICatalogCollection col = cat.GetCollection("Applications") as ICatalogCollection;  
			col.Populate ();
					
			System.Collections.IEnumerator oEnum =  col.GetEnumerator ();
			while(oEnum.MoveNext ())
			{	string   PackageKey = (string)((ICatalogObject)oEnum.Current).Key;
				string CompKey = "Components";

				ICatalogCollection oComponentsInPackage=null;
				try
				{
					//get components
					oComponentsInPackage  = (ICatalogCollection)col.GetCollection(CompKey,((ICatalogObject)oEnum.Current).Key ) ;
				}
				catch (Exception err)
				{
					string s = err.Message ;
				}
				oComponentsInPackage.Populate ();
				System.Collections.IEnumerator oCompEnum =  oComponentsInPackage.GetEnumerator ();
				while(oCompEnum.MoveNext ())
				{	
					//Get component CLSID
					string CLSID = (string)((ICatalogObject)oCompEnum.Current).get_Value("CLSID");					
					//Search CLSID in registry
					Microsoft.Win32.RegistryKey  RK  = Microsoft.Win32.Registry.ClassesRoot;
					string RegSearch = "CLSID\\" + CLSID + "\\InprocServer32";
					RK = RK.OpenSubKey(RegSearch);
					if (RK != null)
					{
						//check if InprocServer32 Assembly match given assembly
						Object oRegValue  = RK.GetValue("Assembly");
						if (oRegValue != null && oRegValue.ToString() == DllName)
						{
							return true;								
						}
					}
				}				
			}
			return RV;
		}
		/// <summary>
		/// Get project files (ASP.NET pages)
		/// </summary>
		/// <param name="AssemPath" description="Project full path"></param>
		/// <returns>string - Return xml string that holds project files.</returns>
		public string GetFiles(string AssemPath)
		{			
			
			XPathNavigator oPath;
			XPathNodeIterator oIter;
			
			if (m_FilePath.IndexOf (".dll") > -1 || m_FilePath.IndexOf (".exe") > -1)
				return "";

			XPathDocument oDoc = new XPathDocument(AssemPath);
			System.Text.StringBuilder oSB = new System.Text.StringBuilder();
			string FileName;

			string AssPath = m_FilePath.Substring (0,m_FilePath.LastIndexOf("\\")+1);
			
			
			
			oPath = oXmlReader.CreateNavigator();
			oIter = oPath.Select("//File");
			oSB.Append ("<Files>\n");
			while (oIter.MoveNext())
			{
				if (oIter.Current.GetAttribute("DependentUpon","")=="")
				{
					FileName =  m_FilePath.Substring (0,m_FilePath.LastIndexOf("\\")+1) + oIter.Current.GetAttribute("RelPath","");
					// check if file exist to retun corresponding indication.
					if (System.IO.File.Exists (FileName))
					{
						oSB.Append ("<File path=\"" + oIter.Current.GetAttribute("RelPath","") + "\" exist=\"true\"/>\n");
					}
					else
					{
						oSB.Append ("<File path=\"" + oIter.Current.GetAttribute("RelPath","") + "\" exist=\"false\"/>\n");
					}
				}
			}
			oSB.Append ("</Files>\n");
			return oSB.ToString ();

		}
		/// <summary>
		/// Get reference assemblies and check their locations on disk.
		/// </summary>
		/// <param name="AssemPath" description="Full Assembly path"></param>
		private void AddReferenceToXml(string AssemPath)
		{
			System.Reflection.Assembly assem;

			//Load assembly and get it reference assemblies into array
			assem = System.Reflection.Assembly.LoadFrom(AssemPath);
			System.Reflection.AssemblyName[] arrAsem = assem.GetReferencedAssemblies ();

			for(int ienum = 0; ienum < arrAsem.Length ; ienum++)
			{
				string fullName =arrAsem[ienum].FullName;
				string Name =arrAsem[ienum].Name;
				string Path;
				
				// if all levels set to false dont look for Sysytem.* assemblies.
				if ((!AllLevels && (Name.ToLower().IndexOf("system.") == -1))||AllLevels) 
				{
					// if assembly in gac and COM+ = COM+, GAC = GAC, COM+ but not in GAC = BIN (enforce assembly in COM+)
					// to be in GAC!!!
					if(AssemblyInGac(fullName,Name,out Path))
					{
						if(IsDllInCom(fullName))
						{
							XmlFile.Append ("<REF fullname=\"" + fullName + "\" path=\"" + Path + "\" exist=\"true\" loc=\"COM\">\n");
						}
						else
						{
							XmlFile.Append ("<REF fullname=\"" + fullName + "\" path=\"" + Path + "\" exist=\"true\" loc=\"GAC\">\n");
						}
					}
					else if (AssemblyInBin(fullName,Name,out Path))
					{
						XmlFile.Append ("<REF fullname=\"" + fullName + "\" path=\"" + Path + "\" exist=\"true\" loc=\"BIN\">\n");
					}
					else if(AssemblyIsMSCore(fullName,Name,out Path))
					{
						XmlFile.Append ("<REF fullname=\"" + fullName + "\" path=\"" + Path + "\" exist=\"true\" loc=\"COR\">\n");
					}
					else
					{
						XmlFile.Append ("<REF fullname=\"" + fullName + "\" path=\"none\" exist=\"false\" loc=\"NON\">\n");
					}
					if (Path.IndexOf ("framework") == -1 && Path.IndexOf ("system.") == -1)
						if (Path != "")
							AddReferenceToXml(Path);
					XmlFile.Append ("</REF>\n");
				}
			}
		}
		/// <summary>
		///	Check if assembly in BIN directory
		/// </summary>
		/// <param name="inFullName"></param>
		/// <param name="asmName"></param>
		/// <param name="Path"></param>
		/// <returns></returns>
		private bool AssemblyInBin(string inFullName, string asmName,out string Path)
		{
			bool RV=false;
			string AssPath;
			// get assembly path
			if (m_FilePath.IndexOf (".dll") > -1 || m_FilePath.IndexOf (".exe") > -1)
			{
				 AssPath = m_FilePath.Substring (0,m_FilePath.LastIndexOf("\\")+1) +  asmName + ".DLL";			
			}
			else
			{
				 AssPath = m_FilePath.Substring (0,m_FilePath.LastIndexOf("\\")+1) + "bin\\" + asmName + ".DLL";			
			}
			// check if assembly exist
			if (System.IO.File.Exists(AssPath))
			{				
				//load assembky and check if it full name match the given inFullName
				System.Reflection.Assembly assem = System.Reflection.Assembly.LoadFrom (AssPath);
				
				if (assem.FullName == inFullName)
				{
					RV = true;
				}				
			} 			  		
			Path = AssPath;
			return RV;
		}
		/// <summary>
		/// check if Assembly in GAC
		/// </summary>
		/// <param name="inFullName"></param>
		/// <param name="asmName"></param>
		/// <param name="Path"></param>
		/// <returns></returns>
		private bool AssemblyInGac(string inFullName,string asmName,out string Path)
		{
			bool RV=false;
			Path="";
			//load assembly
			System.Reflection.Assembly assem = System.Reflection.Assembly.LoadWithPartialName (inFullName);
			if (assem != null)
			{			
				//check if assembly in GAC
				if (System.Runtime.InteropServices.RuntimeEnvironment.FromGlobalAccessCache (assem))
				{					
					if (assem.FullName == inFullName)
					{
						RV = true;
						Path = assem.CodeBase;
					}
					
				}				
			}
			
			return RV;
		}
		/// <summary>
		/// Well this function get DLLs that are MScore and not exist in GAC or BIN.
		/// basically it the same as AssemblyInGac.
		/// </summary>
		/// <param name="inFullName"></param>
		/// <param name="asmName"></param>
		/// <param name="Path"></param>
		/// <returns></returns>
		private bool AssemblyIsMSCore(string inFullName,string asmName,out string Path)
		{
			bool RV=false;
			Path="";
			System.Reflection.Assembly assem = System.Reflection.Assembly.LoadWithPartialName (inFullName);
			if (assem != null)
			{				
				if (!System.Runtime.InteropServices.RuntimeEnvironment.FromGlobalAccessCache (assem))
				{					
					if (assem.FullName == inFullName)
					{
						RV = true;
						Path = assem.CodeBase;
					}
					
				}				
			}
			
			return RV;
		}

	}
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here


Written By
Web Developer
Israel Israel
Read my blog




Natty Gur is the founder and CTO of “The enterprise architects group” an international enterprise architecture consulting group based in Vestal, NY. Natty has 13 years of experience in the IT field, 7 of them focused on running enterprise architecture in companies and governmental bodies. Natty has written many articles and is a well known speaker on EA topics. You can reach natty at: natty@theeagroup.net


Comments and Discussions