How can I get all (physical) wwwroot directories (home directories) of an IIS with C# from the IIS metabase?
If you're using IIS6:
You need to add a reference to System.DirectoryServices in Visual Studio in the Add References .NET assemblies tab:
using System;
using System.DirectoryServices;
namespace ListRootAppPathsIIS6
{
class Program
{
static void Main(string[] args)
{
using (DirectoryEntry de = new DirectoryEntry("IIS://Localhost/W3SVC"))
{
foreach (DirectoryEntry w3svc in de.Children)
{
if (w3svc.SchemaClassName == "IIsWebServer")
{
string rootPath =
String.Format("IIS://Localhost/W3SVC/{0}/root", w3svc.Name);
using (DirectoryEntry root = new DirectoryEntry(rootPath))
{
string info = String.Format("{0} - {1} - {2}",
w3svc.Name,
w3svc.Properties["ServerComment"].Value,
root.Properties["Path"].Value);
Console.WriteLine(info);
}
}
}
}
Console.ReadLine();
}
}
}
If you're using IIS7:
Add a reference to C:\Windows\System32\inetsrv\Microsoft.Web.Administration.dll
using System;
using System.Linq;
using Microsoft.Web.Administration;
namespace ListRootAppPathsIIS7
{
class Program
{
static void Main(string[] args)
{
using(ServerManager serverManager = new ServerManager())
{
foreach (var site in serverManager.Sites)
{
var app = site.Applications.Where(a => a.Path == "/").First();
var vdir = app.VirtualDirectories.Where(v => v.Path == "/").First();
string info = String.Format("{0} - {1} - {2}",
site.Id,
site.Name,
Environment.ExpandEnvironmentVariables(vdir.PhysicalPath));
Console.WriteLine(info);
}
}
Console.ReadLine();
}
}
}
The first method (using System.Directoryservices) will work with IIS7 provided you've installed the IIS6 management compatibilities bits.
In both cases you need to be running as an Administrator.
You could call out to
C:\Windows\system32\inetsrv\appcmd.exe list vdir
(using the API to get the right folder of course). And filter for "site\" (for the default site "Default Web Site/". I assume there is some API to do this (but, certainly for older IIS versions, this was very script orientated, so would require dealing with IDispatch to invoke methods and property-gets).
This does require an elevated process on IIS7 and 7.5 (unless sufficient rights to IIS have been delegated).
Related
I'm trying to Create an installer for my CAD plugin, and need to get the AutoCAD install location. but the return values of RegistryKey.GetSubKeyNames() is different from what I see in Registry Editor.
string registry_key = #"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall";
using (Microsoft.Win32.RegistryKey key = Registry.LocalMachine.OpenSubKey(registry_key))
{
foreach (string subkey_name in key.GetSubKeyNames())
{
Console.WriteLine(subkey_name);
}
}
output:
AddressBook
Autodesk Application Manager
Autodesk Content Service
Autodesk Material Library 2015
Autodesk Material Library Base Resolution Image Library 2015
Connection Manager
DirectDrawEx
DXM_Runtime
f528b707
Fontcore
...
In Registry Editor:
animizvideocn_is1
AutoCAD 2015
Autodesk 360
Connection Manager
...
AutoCAD 2015 is what i need
Your installer seems to be a 32 bit application, or at least runs as a 32 bit process.
Therefore, Windows redirects
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall
to
HKEY_LOCAL_MACHINE\SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall
To access the non redirected node, follow the instructions here.
This might be not a direct answer to your question, but i had to do the same thing. I was not looking at the registry, but the Program Files directory. It will then add the netload command to the autoload lisp file. It will install a list of Plugin dlls to all installed autocad versions. This can easily be changed... Hopefully it helps.
using System;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace AMU.AutoCAD.Update
{
public class AutoCadPluginInstaller
{
private static readonly Regex AutoloadFilenameRegex = new Regex("acad([\\d])*.lsp");
public void Install(IEnumerable<string> pluginFiles)
{
var acadDirs = this.GetAcadInstallationPaths();
var autoloadFiles = acadDirs.Select(this.GetAutoloadFile);
foreach (var autoloadFile in autoloadFiles)
this.InstallIntoAutoloadFile(autoloadFile, pluginFiles);
}
private void InstallIntoAutoloadFile(string autoloadFile, IEnumerable<string> pluginFiles)
{
try
{
var content = File.ReadAllLines(autoloadFile).ToList();
foreach (var pluginFile in pluginFiles)
{
var loadLine = this.BuildLoadLine(pluginFile);
if(!content.Contains(loadLine))
content.Add(loadLine);
}
File.WriteAllLines(autoloadFile, content);
}
catch (Exception ex)
{
//log.Log();
}
}
private string BuildLoadLine(string pluginFile)
{
pluginFile = pluginFile.Replace(#"\", "/");
return $"(command \"_netload\" \"{pluginFile}\")";
}
private IEnumerable<string> GetAcadInstallationPaths()
{
var programDirs =
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var autoDeskDir = Path.Combine(programDirs, "Autodesk");
if (!Directory.Exists(autoDeskDir))
return null;
return Directory.EnumerateDirectories(autoDeskDir)
.Where(d => d.Contains("AutoCAD"));
}
private string GetAutoloadFile(string acadDir)
{
var supportDir = Path.Combine(acadDir, "Support");
var supportFiles = Directory.EnumerateFiles(supportDir);
return supportFiles.FirstOrDefault(this.IsSupportFile);
}
private bool IsSupportFile(string path)
=> AutoloadFilenameRegex.IsMatch(Path.GetFileName(path));
}
}
(see here: https://gist.github.com/felixalmesberger/4ff8ed27f66f872face4368a13123fff)
You can use it like this:
var installer = new AutoCadPluginInstaller();
installer.Install(new [] {"Path to dll"});
Have fun.
I have been trying to figure out how is possible to create a query folder via VSO api, but I always the "Method not allowed" message.
I'm using Microsoft.TeamFoundationServer.Client package to connect VSO. This page says that this library is needed for me. I can query data, but it seems something is missing to create data. This library is fit for me because I have a WebApi whihch manages the communication to VSO API.
Here is my code:
public QueryHierarchyItem CreateFolderAsync(string folderName)
{
QueryHierarchyItem newFolder = new QueryHierarchyItem()
{
Name = folderName,
IsFolder = true,
//Path = "Queries/Shared Queries/" + folderName,
IsPublic = true
};
QueryHierarchyItem item = witClient.CreateQueryAsync(newFolder, _projectName, null).Result;
return item;
}
I have tried to play with the Path property but it did not help.
I have checked the user rights. My user is member of "Project Administrators", and
rights are also set up to manage query folders (Click the chevron next to the "Shared Queries" folder -> select "Security") as group and as single user. It did not help.
I use a free account. The strange is that I have logged in with the same user from Visual Studio and I can manage the folders. Is this functionality available for free accounts?
You can refer to this blog from MSDN for details: http://blogs.msdn.com/b/team_foundation/archive/2010/06/16/work-item-tracking-queries-object-model-in-2010.aspx
Quote the code here:
using System;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
namespace QueryAPI
{
class Program
{
private static Project myproject = null;
public static QueryFolder GetMyQueriesFolder()
{
foreach (QueryFolder folder in myproject.QueryHierarchy)
{
if (folder.IsPersonal == true)
return folder;
}
throw new Exception("Cannot find the My Queries folder");
}
public static QueryFolder AddNewFolder(string folderName)
{
QueryFolder folder = new QueryFolder(folderName, GetMyQueriesFolder());
myproject.QueryHierarchy.Save();
return folder;
}
static void Main(string[] args)
{
TfsTeamProjectCollection coll = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri("Your TFS Server URI"));
WorkItemStore store = new WorkItemStore(coll);
myproject = store.Projects["Your project name"];
QueryFolder myNewfolder = AddNewFolder("Your folder name");
}
}
}
In a TFS C# program to connect to TFS server we use two namespace as listed below for the same class Client.
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Client;
My question here is Why are the same class Client used from two different namespace?
For the program listed below ( from Here )
using System;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Client;
namespace TfsApplication
{
class Program
{
static void Main(String[] args)
{
// Connect to Team Foundation Server
// Server is the name of the server that is running the application tier for Team Foundation.
// Port is the port that Team Foundation uses. The default port is 8080.
// VDir is the virtual path to the Team Foundation application. The default path is tfs.
Uri tfsUri = (args.Length < 1) ?
new Uri("http://Server:Port/VDir") : new Uri(args[0]);
TfsConfigurationServer configurationServer =
TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
// Get the catalog of team project collections
ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false, CatalogQueryOptions.None);
// List the team project collections
foreach (CatalogNode collectionNode in collectionNodes)
{
// Use the InstanceId property to get the team project collection
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);
// Print the name of the team project collection
Console.WriteLine("Collection: " + teamProjectCollection.Name);
// Get a catalog of team projects for the collection
ReadOnlyCollection<CatalogNode> projectNodes = collectionNode.QueryChildren(
new[] { CatalogResourceTypes.TeamProject },
false, CatalogQueryOptions.None);
// List the team projects in the collection
foreach (CatalogNode projectNode in projectNodes)
{
Console.WriteLine(" Team Project: " + projectNode.Resource.DisplayName);
}
}
}
}
}
Microsoft.TeamFoundation.Framework.Client namespace is used for CatalogNode class.
Also, TfsConfigurationServer,TfsTeamProjectCollection,TfsConfigurationServerFactory etc are present in Microsoft.TeamFoundation.Client namespace.
Is it possible to connect Visual Studio to TFS Team Project from code? I found article how to connect to TFS: http://msdn.microsoft.com/en-us/library/vstudio/bb286958.aspx however this allows me to perform basic actions on TFS from code but not connecting Visual Studio.
As I understand your question, you can't... you have 3 options:
1-Making an extension for VS Team Explore and this extension will depend on you are already connected using VS.
Extending Team Explorer in Visual Studio 2012
2- Making a separate exe so you will use the the TeamProjectPicker so
you can choose which TFS and which Team Project you want to connect to.
using System.Windows.Forms;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Server;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
Application.EnableVisualStyles(); // Makes it look nicer from a console app.
//"using" pattern is recommended as the picker needs to be disposed of
using (TeamProjectPicker tpp = new TeamProjectPicker(TeamProjectPickerMode.MultiProject, false))
{
DialogResult result = tpp.ShowDialog();
if (result == DialogResult.OK)
{
System.Console.WriteLine("Selected Team Project Collection Uri: " + tpp.SelectedTeamProjectCollection.Uri);
System.Console.WriteLine("Selected Projects:");
foreach (ProjectInfo projectInfo in tpp.SelectedProjects)
{
System.Console.WriteLine(projectInfo.Name);
}
}
}
}
}
}
3- Use API for TFS and hardcode path or put it in a config file like the following:
using System;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.Framework.Client;
namespace TfsApplication
{
class Program
{
static void Main(String[] args)
{
// Connect to Team Foundation Server
// Server is the name of the server that is running the application tier for Team Foundation.
// Port is the port that Team Foundation uses. The default port is 8080.
// VDir is the virtual path to the Team Foundation application. The default path is tfs.
Uri tfsUri = (args.Length < 1) ?
new Uri("http://Server:Port/VDir") : new Uri(args[0]);
TfsConfigurationServer configurationServer =
TfsConfigurationServerFactory.GetConfigurationServer(tfsUri);
// Get the catalog of team project collections
ReadOnlyCollection<CatalogNode> collectionNodes = configurationServer.CatalogNode.QueryChildren(
new[] { CatalogResourceTypes.ProjectCollection },
false, CatalogQueryOptions.None);
// List the team project collections
foreach (CatalogNode collectionNode in collectionNodes)
{
// Use the InstanceId property to get the team project collection
Guid collectionId = new Guid(collectionNode.Resource.Properties["InstanceId"]);
TfsTeamProjectCollection teamProjectCollection = configurationServer.GetTeamProjectCollection(collectionId);
// Print the name of the team project collection
Console.WriteLine("Collection: " + teamProjectCollection.Name);
// Get a catalog of team projects for the collection
ReadOnlyCollection<CatalogNode> projectNodes = collectionNode.QueryChildren(
new[] { CatalogResourceTypes.TeamProject },
false, CatalogQueryOptions.None);
// List the team projects in the collection
foreach (CatalogNode projectNode in projectNodes)
{
Console.WriteLine(" Team Project: " + projectNode.Resource.DisplayName);
}
}
}
}
}
Here you can find step by step guide to Connect Visual Studio to TFS
http://tfs.visualstudio.com/en-us/learn/code/connect-vs/
How do I find out the .NET framework of an IIS virtual directory is using in C#. I need to display it to the user.
using System.DirectoryServices;
using System.IO;
private enum IISVersion
{
IIS5,
IIS6
}
private void ReadVirtualDirectory(string server, string directory, IISVersion version)
{
string siteID = string.Empty;
string path = string.Empty;
switch(verison)
{
case IISVersion.IIS5:
path = string.Format("IIS://{0}/W3SVC/1/Root", server);
if(!string.IsNullOrEmpty(directory))
{
path = string.Concat(path, "/", directory);
}
break;
case IISVersion.IIS6:
path = string.Format("IIS://{0}/W3SVC", server);
if(!string.IsNullOrEmpty(directory))
{
DirectoryEntry de = new DirectoryEntry(path);
foreach(DirectoryEntry child in de.Children)
{
if(child.Properties["ServerComment"].Value.ToString().ToLower() == directory)
{
siteID = child.Name;
break;
}
}
path = string.Concat(path, "/", siteID);
de.Close()
de = null;
}
break;
}
DirectoryEntry iis = new DirectoryEntry(path);
//display iis properties here...
//need to display if the virtual directory is running under .NET 1.1 or 2.0
iis.Close();
iis = null;
}
In IIS there's no hard and fast way to find out which ASP.NET version is used by a website or 'virtual' directory (website application folder - the one that has cogs as an icon).
The reason for this is that IIS and the metabase data only know about scriptmaps and not ASP.NET versions (after all ASP.NET is just another ISAPI application). One way to determine the version of ASP.NET is to use something like the following:
using System;
using System.DirectoryServices;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string path = #"IIS://Localhost/W3SVC/1/root/MyApp";
Console.WriteLine(GetAspNetVersion(path));
}
private static string GetAspNetVersion(string path)
{
using (DirectoryEntry app = new DirectoryEntry(path))
{
PropertyValueCollection pvc = app.Properties["ScriptMaps"];
foreach (string scriptMap in pvc)
{
if (scriptMap.StartsWith(".aspx"))
{
string[] mapping = scriptMap.Split(',');
string scriptProcessor = mapping[1];
// The version numbers come from the path
// C:\Windows\Microsoft.NET\Framework\
// which will be present in the script processor
// DLL path
if (scriptProcessor.Contains("v1.1.4322"))
{
return "1.1";
}
if (scriptProcessor.Contains("v2.0.50727"))
{
return "2.0";
}
}
}
throw new Exception("Unknown version ASP.NET version.");
}
}
}
}
It's not ideal but hasn't failed our needs as a hoster for our provisioning applications/services. I suspect the IIS MMC plug-in performs a similar check behind the scenes. My own detailed examination of the metabase (Windows 2000 and Windows 2003 file based XML) reveals that there isn't a conspicuous property/attribute that stores a specific ASP.NET version number.
It might not be the prettiest method, but if you can grab and parse the output from aspnet_regiis.exe -lk, you'll get all the information you need. An example of the output from a SharePoint VHD:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727>aspnet_Regiis -lk
W3SVC/ 1.1.4322.2407
W3SVC/1/ROOT/Reports/ 2.0.50727.0
W3SVC/1/ROOT/ReportServer/ 2.0.50727.0
W3SVC/1619303638/Root/ 2.0.50727.0
W3SVC/1619303638/Root/_layouts/images/ 1.1.4322.2407
W3SVC/1619303638/Root/_layouts/inc/ 1.1.4322.2407
W3SVC/1720207907/root/ 2.0.50727.0
W3SVC/1720207907/root/SharedServices1/ 2.0.50727.0
W3SVC/1848312571/Root/ 2.0.50727.0
W3SVC/1848312571/Root/_layouts/images/ 1.1.4322.2407
W3SVC/1848312571/Root/_layouts/inc/ 1.1.4322.2407
W3SVC/784543535/Root/ 2.0.50727.0
W3SVC/784543535/Root/_layouts/images/ 1.1.4322.2407
W3SVC/784543535/Root/_layouts/inc/ 1.1.4322.2407
W3SVC/98413328/Root/ 2.0.50727.0
W3SVC/98413328/Root/_layouts/images/ 1.1.4322.2407
W3SVC/98413328/Root/_layouts/inc/ 1.1.4322.2407