iis Creating new application and enabling Windows Authentication Fails - c#

I can successfully create an Application Pool and an Application plus link them together.
What I am failing to do however is set the applications Windows Authentication to true and Anonymous Authentication to false.
I patched a hodge podge of examples into one to make this work but I keep getting the following error.
This configuration section cannot be used at this path. This happens
when the section is locked at a parent level. Locking is either by
default (overrideModeDefault="Deny"), or set explicitly by a location
tag with overrideMode="Deny" or the legacy allowOverride="false".
Now barring the obvious that overrideMode needs to likely equal Allow. How do I accomplish this?
public static bool CreateApplication(String websiteName, String applicationName, String appDIR,String appPoolName)
{
try
{
ServerManager iisManager = new ServerManager();
if (!applicationName.Contains("/"))
applicationName = "/" + applicationName;
var app = iisManager.Sites[websiteName].Applications.Add(applicationName, appDIR);
app.ApplicationPoolName = appPoolName;
var config = app.GetWebConfiguration();
var anonsection = config.GetSection("system.webServer/security/authentication/anonymousAuthentication", iisManager.Sites[websiteName].Name + applicationName);
//This is where it fails
anonsection["enabled"] = false;
var winsection = config.GetSection("system.webServer/security/authentication/windowsAuthentication", iisManager.Sites[websiteName].Name + applicationName);
winsection["enabled"] = true;
iisManager.CommitChanges();
return true;
}
catch
{
return false;
}
}

Use the following commands from an admin command prompt
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/security/authentication/windowsAuthentication
%windir%\system32\inetsrv\appcmd unlock config -section:system.webServer/security/authentication/anonymousAuthentication
This will unlock those config sections.

Related

Save browser data in CefSharp

I have an Windows Form Application which utilises CefSharp.
A while ago I used a chunk of code that saves the state of the browser such as login details etc so that the user does not have to log in multiple times.
This is the code I used:
private static bool _hasRun;
CefSettings settings = new CefSettings();
if (!_hasRun)
{
Cef.Initialize(new CefSettings { CachePath = "MyCachePath", PersistSessionCookies = true });
}
_hasRun = true;
string cache_dir = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData) + #"\CEF";
settings.CachePath = cache_dir;
settings.CefCommandLineArgs.Add("persist_session_cookies", "1");
string link = Domain;
chrome = new ChromiumWebBrowser(link);
this.tabPage2.Controls.Add(chrome);
chrome.Dock = DockStyle.Fill;
This code runs fine in my old application but when using this on my most recent app I receive this error message:
Any suggestions?
You must provide a full path.
non-absolute: "MyCachepath"
absolute: "C:\users\username\documents\MyCachepath"
why did it work in older projects?
Some project types and versions automaticallly translate an relative path into an absolute path like so:
environment.CurrentDirectory + #"\MyCachepath"

Create an application under default web site IIS

I am trying to create a new application under default web site by using C# code. This is what I tried
public static bool CreateWebSite(Application application)
{
try
{
application.Alias = "Test";
application.PhysicalPath = #"C:\Test";
application.ApplicationPool = "TestAppPool";
using (ServerManager serverManager = new ServerManager())
{
serverManager.Sites["Default Web Site"].Applications.Add("/", application.PhysicalPath);
serverManager.CommitChanges();
}
return true;
}
catch (Exception se)
{
throw se;
}
}
But getting path already exists error can some one help me.
How can we set directory browsing enabled
You could try to use below command to set directory browsing enabled.
ServerManager server = new ServerManager();
Configuration config = server.GetWebConfiguration("TestMVC");
ConfigurationSection directoryBrowseSection = config.GetSection("system.webServer/directoryBrowse");
directoryBrowseSection["enabled"] = true;
directoryBrowseSection["showFlags"] = #"Date, Time, Size, Extension";
server.CommitChanges();
Result:

How to locate the correct Service Endpoint Uri

I am working on an application which is deployed to a TEST and then a LIVE webserver.
I want the class library I am working on to use the correct service endpoint when it is deployed.
Currently the code is as follows;
var data = new SettingsViewModel()
{
ServiceURI = Constants.LIVE_ENDPOINT_SERVICE_ADDRESS,
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
#if DEBUG
data.ServiceURI = Constants.DEV_ENDPOINT_SERVICE_ADDRESS;
#endif
As you can see, this can only pick up the DEV or the LIVE endpoints. This code cannot distinguish whether the webserver is LIVE or TEST
I thought about setting up an App.Config file and get the correct Endpoint from there. But when I create a new item, the Config template is not listed. So how do I do this?
For now I could propose this solution :
public static class Constants
{
public static string GetEndPoint()
{
// Debugging purpose
if (System.Diagnose.Debug.IsAttached)
{
return DEV_ENDPOINT_SERVICE_ADDRESS;
}
else if ( Environment.MachineName == "Test Server" ) // You need to know your test server machine name at hand.
{
return "Return test Server endpoint"
}
else
{
return "Return live server endpoint";
}
}
}
You can used it in your SettingsViewModel like this:
var data = new SettingsViewModel()
{
ServiceURI = Constants.GetEndPoint(),
AutoSync = Constants.DEFAULT_AUTO_SYNC,
AppDataFolder = Path.Combine(ApplicationData.Current.LocalFolder.Path, Constants.ROOT_FOLDER, Constants.DATA_FOLDER),
MapKey = Constants.BASIC_MAP_KEY,
Logging = false
};
The drawback for this solution is, if you change your test server you need to change is manually in your code.
Having done some research I realise I need to clarify something. The application I am working on is a Windows RT application and this does not allow config files. The solution I am meant to use is to use local settings, but these do not reference an external file like an App.Config. If I want to change the location of an EndPoint then I am going to have to specify where that is in the code.

Resolve 'configuration object is read only, because it has been committed by a call to ServerManager.CommitChanges()'?

I've written a custom action for an installer project that does the following:
Checks existing websites to see if any exist with the same name put
in by the user.
Creates the website in IIS if it doesn't exist.
Creates an application pool.
Assigns the application pool to the created website.
When it comes to assigning the application pool I get and error:
The configuration object is read only, because it has been committed
by a call to ServerManager.CommitChanges(). If write access is
required, use ServerManager to get a new reference.
This baffles me as it seems to suggest that I can't assign the newly created application pool with the ServerManager.CommitChanges() call. However, everything else works fine using this, which I wouldn't expect if this was an issue.
Here is my code:
I have a ServerManager instance created like so:
private ServerManager mgr = new ServerManager();
In my Install method I do the following:
Site site = CreateWebsite();
if (site != null)
{
CreateApplicationPool();
AssignAppPool(site);
}
Check existing websites - done in OnBeforeInstall method
private Site CheckWebsites()
{
SiteCollection sites = null;
Site site = null;
try
{
sites = mgr.Sites;
foreach (Site s in sites)
{
if (!string.IsNullOrEmpty(s.Name))
{
if (string.Compare(s.Name, targetSite, true) == 0) site = s;
}
}
}
catch{}
return site;
}
CreateWebSite method:
private Site CreateWebsite()
{
Site site = CheckWebsites();
if (site == null)
{
SiteCollection sites = mgr.Sites;
int port;
Int32.TryParse(targetPort, out port);
site = sites.Add(targetSite, targetDirectory, port);
mgr.CommitChanges();
}
else
{
//TO DO - if website already exists edit settings
}
return site;
}
Create App Pool
//non-relevant code...
ApplicationPool NewPool = mgr.ApplicationPools.Add(ApplicationPool);
NewPool.AutoStart = true;
NewPool.ManagedRuntimeVersion = "4.0";
NewPool.ManagedPipelineMode = ManagedPipelineMode.Classic;
mgr.CommitChanges();
Assign App Pool
private void AssignAppPool(Site site)
{
site.ApplicationDefaults.ApplicationPoolName = ApplicationPool; //ERRORS HERE
mgr.CommitChanges();
}
I can't see why a site could be created, an app pool created but then not assigned. Help.
I finally realised that the 'configuration object' referred to in the error was the 'site'. Seems obvious now, but basically I needed to re-get the site to then assign the app pool to it. I think this is allow the previous changes to take place and then pick them up. So I altered my code by removing the need to pass the Site into private void AssignAppPool() and just getting the site again like this:
Site site = mgr.Sites["TestWebApp"];

"Access to path denied" issue

1) i was trying to create directory programmatically this way
if (!Directory.Exists(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\VoiceRecords"))
{
Directory.CreateDirectory(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) + "\\VoiceRecords");
}
the above code works fine when i run my apps in debug mode but after creating setup and when i installed then when the above line execute and try to create folder in my apps installation location then problem start. what would be the best approach to get rid of this prob because i will distribute this setup to 3rd part and they can install my apps any where which i may not know.
2) when i try to save any value in app.config file then i am getting error.
the error screen shot is here.
now i like to show how i am write data to config at runtime
Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
if (config.AppSettings.Settings["localVoiceRecordsPath"].Value != null || config.AppSettings.Settings["localVoiceRecordsPath"].Value.Trim() != "")
{
config.AppSettings.Settings["localVoiceRecordsPath"].Value = SettingsPopup.txtPath.Text.Replace(",", string.Empty);
config.Save(ConfigurationSaveMode.Modified);
SettingsPopup.txtPath.Text = config.AppSettings.Settings["localVoiceRecordsPath"].Value.Replace(",", string.Empty);
}
else
{
config.AppSettings.Settings.Add("localVoiceRecordsPath", SettingsPopup.txtPath.Text.Replace(",", string.Empty));
config.Save(ConfigurationSaveMode.Modified);
SettingsPopup.txtPath.Text = config.AppSettings.Settings["localVoiceRecordsPath"].Value.Replace(",", string.Empty);
}
everything is working fine when i run my apps in debug mode but problem start when i install the apps from setup and then run. i guess some kind of permission related problem occur. looking for best guidance. thanks
EDIT
Problem solved. i run my apps programmatically in admin mode this way
static bool IsRunAsAdmin()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
return principal.IsInRole(WindowsBuiltInRole.Administrator);
}
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
if (Environment.OSVersion.Version.Major >= 6)
{
if (!IsRunAsAdmin())
{
ProcessStartInfo proc = new ProcessStartInfo();
proc.UseShellExecute = true;
proc.WorkingDirectory = Environment.CurrentDirectory;
proc.FileName = Application.ExecutablePath;
proc.Verb = "runas";
try
{
Process.Start(proc);
}
catch
{
// The user refused the elevation.
// Do nothing and return directly ...
return;
}
Application.Exit(); // Quit itself
}
else
{
Application.Run(new frmMain());
}
}
else
{
Application.Run(new frmMain());
}
}
you need to probably run the app in administrator mode to give it the right permissions.
here is some sample code/explanation how to check to see what mode you are currently in and how to elevate it:
http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3
however be robust! make sure you are running on a Vista system or higher before doing this logic otherwise it will break backward compatibility for earlier OS's if you try to execute the UAC/elevation code.
you may even be able to auto elevate using the app manifest/modifying it:
http://msdn.microsoft.com/en-us/library/aa374191(VS.85).aspx
more information about using the app manifest approach:
http://www.aneef.net/2009/06/29/request-uac-elevation-for-net-application-managed-code/
Security permissions. Let your application request administrator access when it's launched.
You can modify your manifest file and use
<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />

Categories

Resources