Use WMI to create IIS Application Directory with C# - iis-7

We have a web application that is installed on Windows 2003 and Windows 2008 systems. In the past, our install code used ADSI to create a couple of application directories in IIS, but this requires the IIS 6 management components to be installed in Windows 2008. I have been trying to use WMI to create the application directories so we can support both operating systems.
I have been trying this code
public static void AddVirtualFolder(string serverName, string websiteId, string name, string path)
{
ManagementScope scope = new ManagementScope(string.Format(#"\\{0}\root\MicrosoftIISV2", serverName));
scope.Connect();
string siteName = string.Format("W3SVC/{0}/Root/{1}", websiteId, name);
ManagementClass mc = new ManagementClass(scope, new ManagementPath("IIsWebVirtualDirSetting"), null);
ManagementObject oWebVirtDir = mc.CreateInstance();
oWebVirtDir.Properties["Name"].Value = siteName;
oWebVirtDir.Properties["Path"].Value = path;
oWebVirtDir.Properties["AuthFlags"].Value = 5; // Integrated Windows Auth.
oWebVirtDir.Properties["EnableDefaultDoc"].Value = true;
// date, time, size, extension, longdate ;
oWebVirtDir.Properties["DirBrowseFlags"].Value = 0x4000003E;
oWebVirtDir.Properties["AccessFlags"].Value = 513; // read script
oWebVirtDir.Put();
ManagementObject mo = new ManagementObject(scope, new System.Management.ManagementPath("IIsWebVirtualDir='" + siteName + "'"), null);
ManagementBaseObject inputParameters = mo.GetMethodParameters("AppCreate2");
inputParameters["AppMode"] = 2;
mo.InvokeMethod("AppCreate2", inputParameters, null);
mo = new ManagementObject(scope, new System.Management.ManagementPath("IIsWebVirtualDirSetting='" + siteName + "'"), null);
mo.Properties["AppFriendlyName"].Value = name;
mo.Put();
}
}
However, I get path not found errors on known directories. If anybody has some references I can use, I would greatly appreciate it. Any other suggestions on how to go about this are also welcome.

Using the code above, you will still need the IIS6 compatibility bits on Windows 2008/IIS7. The reason for this is that the calls to set properties such as DirBrowseFlags, AccessFlags and so on are IIS 6 metabase properties that are not supported in IIS7 without the IIS6 management components.
For IIS7 I'd recommend programming directly against the Microsoft.Web.Administration namespace, but if you really need to use WMI then see this article:
Managing Sites with IIS 7.0's WMI Provider (IIS.NET)

Related

Zebra Print issue using asp.net with c#

I am using the PrintDocument for printing directly to the network printer using asp.net with and C#. The application hosted in IIS with Windows authentication. I am not getting the error and also the PrintStatus is Printing. But we can not see the printed document in the printer and also there is no errors in the printer.
System.Drawing.Printing.PrintDocument printdoc = new System.Drawing.Printing.PrintDocument();
printdoc.DefaultPageSettings.PaperSize = new PaperSize("Custom", 4, 3);
printdoc.OriginAtMargins = true;
// Set the printer name
PrinterSettings printer = new PrinterSettings();
printer.PrinterName = SqlDatabaseUtility.GetZebraPrinterName();
string fullName = CheckPrinterConfiguration(printer.PrinterName);
if (!String.IsNullOrEmpty(fullName))
{
printdoc.PrinterSettings.PrinterName = fullName;
// Handle printing
if (printdoc.PrinterSettings.IsValid)
{
printdoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(printdoc_PrintPage);
printdoc.PrinterSettings.Copies = 2;
printdoc.Print();
}
}
Just a theory, but the PrintDocument class is a descendant of Component and so implements IDisposable.
In the same way that you don't leave SqlConnection instances undisposed, you should call Dispose() on your printdoc instance so that any unmanaged resources held by the PrintDocument instance - such as a handle to the printer device, perhaps - get released.
Put a using clause around your printing block as below. It might help with your problem, but even if it does not it is proper practice.
using (System.Drawing.Printing.PrintDocument printdoc = new System.Drawing.Printing.PrintDocument())
{
...
}
The next line of enquiry would be to follow up on the "user permissions" suggestion in the comment. Assuming that your code works if you run it in a test console application, a quick test for this would be to change the user account of your web app's Application Pool to be your own account. If your web app starts printing, then you know that permissions are the problem.

Embedding a readonly SQLite Database in a DLL and conenct via Entity Framework

I have a requirement that my DLL should have a readonly database. I made my database as a embedded resource but i am not able to figure it out to connect to the database via entity framework.
try
{
var dataSet = ConfigurationManager.GetSection("system.data") as System.Data.DataSet;
dataSet.Tables[0].Rows.Add("SQLite Data Provider"
, ".Net Framework Data Provider for SQLite"
, "System.Data.SQLite"
, "System.Data.SQLite.SQLiteFactory, System.Data.SQLite");
}
catch (System.Data.ConstraintException) { }
string providerName = "System.Data.SQLite";
string serverName = "NameSpace.DB.sqlite";
// Initialize the connection string builder for the
// underlying provider.
SqlConnectionStringBuilder sqlBuilder = new SqlConnectionStringBuilder();
// Set the properties for the data source.
sqlBuilder.DataSource = serverName;
sqlBuilder.InitialCatalog = "DB.sqlite";
sqlBuilder.IntegratedSecurity = true;
// Build the SqlConnection connection string.
string providerString = sqlBuilder.ToString();
// Initialize the EntityConnectionStringBuilder.
EntityConnectionStringBuilder entityBuilder =
new EntityConnectionStringBuilder();
//Set the provider name.
entityBuilder.Provider = providerName;
// Set the provider-specific connection string.
entityBuilder.ProviderConnectionString = providerString;
// Set the Metadata location.
entityBuilder.Metadata = #"res://*/DataModel.DB.csdl|
res://*/DataModel.DB.ssdl|
res://*/DataModel.DB.msl";
Console.WriteLine(entityBuilder.ToString());
using (EntityConnection conn =
new EntityConnection(entityBuilder.ToString()))
{
conn.Open();
Console.WriteLine("Just testing the connection.");
_container = new MyEntities(conn);
var usersList = _container.UserTable.ToList();
}
It works only when we are copying the database to the client application. I don't want to provide the database as a separate file. I want to embedded it in the dll and give only the dll to other applications.
Regards,
Vivek
As CL. said SQLite has to be in an independent .sqlite file, It cannot be embedded. Take a look at SQL Server Compact. It is all you need, an embedded SQL Database that you can access using Entity Framework.
Here's a tutorial in how to connect to EF.
SQLite databases are based on files.
The SQLite library has the ability to access files through a virtual file system, which would allow redirecting file accessing to somewhere else. So it would be possible to implement a VFS that accesses a resource.
However, System.Data.SQLite does not appear to allow registering your own VFS.

Angular SPA cannot open remote SSRS report

thanks to all for your time and efforts trying to help me solve this.
Now lets get to it... I have an AngularJS SPA. I would like to provide links on my view page, that when clicked, open a new tab and launch pre-existing SSRS reports in PDF format. Technically what I am trying to do: Render an SSRS report in my Repository, pass that through my WEB API then on to my SPA for display in a new tab.
One important note before I go any further: This setup, method, approach works flawlessly on my local machine within Visual Studio. It's when I move my SPA to a remote Web server (the same server that hosts SSRS) that I have a problem.
My Landscape:
Local Development Machine (Windows 7 Pro, VS2015 Pro)
Server1 (Win Server 2012R2): Hosts IIS (8), SPA, SQL (2014) and SSRS
Server2 (Win Server 2012R2). Hosts SSRS (SQL 2012) source of data (happens to be SSAS cubes, but I don't think that matters).
On My Local Development Machine:
As stated above the solution works fine through Visual Studio. The only part of the solution on my local machine is the SPA. The SSRS and SQL portion are located remotely. I can launch my SPA, click on a link and new tab opens containing the PDF report. I can also make a call directly to the web API and display a PDF report (http://localhost:3040/api/dataservice/ProductivityReportH/)
Problem 1
Browsing to the deployed version of my SPA on Server1, the application displays fine. But, if I click on a report hyperlink I get a the following message:
Do you want to open or save ProductivityReportH/ (3.28KB) from Server1?
No matter what I click (Open, Save, Cancel) nothing happens.
If I try and launch the report directly through the API, I get the same message. There are no errors displayed in the console window. I could find no errors in the Server1 log files.
On Server1: I can display the report via the SSRS report viewer.
Problem 1A
Using a browser on Server1, I can display the application just fine. But, if I click on a report hyperlink I get the same message as Problem 1. If I try to launch the report directly through the web API (http://Server1/projecttracker/api/dataservice/ProductivityReportH/)
on Server1, I get the same message.
Any ideas would be greatly appreciated
My SPA Setup:
View Page:
<div class="view indent">
<div class="container">
<h2>Productivity Reports Method 1</h2>
<a ng-href='#here' ng-click="hproductivityreport()">Launch</a><br>
</div>
My Controller:
(function () {
var ProjectsController = function ($scope, $window) {
$scope.hproductivityreport = function () {
$window.open('api/dataservice/ProductivityReportH/', '_blank');
};
}
ProjectsController.$inject = ['$scope', '$window'];
angular.module('ReportTracker').controller('ProjectsController', ProjectsController)
}());
The WEB API:
using ProjectTracker.Repository;
using System.IO;
using System.Net;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Web;
using System.Web.Http;
namespace ProjectTracker.Model
{
[Authorize]
public class DataServiceController : ApiController
{
IProjectTracker _ProjectTrackerRepository;
public DataServiceController()
: this(null)
{
}
public DataServiceController(IProjectTracker Repo)
{
_ProjectTrackerRepository = Repo ?? new ProjectTrackerRepository ();
}
[HttpGet]
public HttpResponseMessage ProductivityReportH()
{
var result = new HttpResponseMessage(HttpStatusCode.OK);
byte[] bytes = _ProjectTrackerRepository.RenderProductivityReport("Hibble, Norman");
Stream stream = new MemoryStream(bytes);
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/pdf");
return result;
}
}
}
The Respository:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Data;
namespace ProjectTracker.Repository
{
public class ProjectTrackerRepository : RepositoryBase<ProjectTrackerContext>, IProjectTracker
{
ProjectTrackerContext _Context;
public ProjectTrackerRepository()
{
_Context = new ProjectTrackerContext();
}
public Byte[] RenderProductivityReport(string _sManager)
{
Server1.ReportExecutionService rs = new Server1.ReportExecutionService();
rs.Credentials = System.Net.CredentialCache.DefaultCredentials;
rs.Url = "http://Server1/reportserver/ReportExecution2005.asmx";
// Render arguments
byte[] result = null;
string reportPath = "/Staff Client Services/StaffProductivity";
string format = "PDF";
string historyID = null;
string devInfo = #"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
//Create the list of parameters that will be passed to the report
List<Server1.ParameterValue> lstParameterValues = new List<Server1.ParameterValue>();
Server1.ParameterValue aParameter = new Server1.ParameterValue();
aParameter.Name = "SupervisorSupervisorName";
aParameter.Value = "[Supervisor].[Supervisor Name].&[" + _sManager + "]";
lstParameterValues.Add(aParameter);
Server1.ParameterValue bParameter = new Server1.ParameterValue();
bParameter.Name = "PayPeriodPayPeriodYear";
bParameter.Value = "[Pay Period].[Pay Period Year].&[2015]";
lstParameterValues.Add(bParameter);
int index = 0;
Server1.ParameterValue[] parameterValues = new Server1.ParameterValue[lstParameterValues.Count];
foreach (Server1.ParameterValue parameterValue in lstParameterValues)
{
parameterValues[index] = parameterValue;
index++;
}
string encoding;
string mimeType;
string extension;
Server1.Warning[] warnings = null;
string[] streamIDs = null;
Server1.ExecutionInfo execInfo = new Server1.ExecutionInfo();
Server1.ExecutionHeader execHeader = new Server1.ExecutionHeader();
rs.ExecutionHeaderValue = execHeader;
execInfo = rs.LoadReport(reportPath, historyID);
rs.SetExecutionParameters(parameterValues, "en-us");
String SessionId = rs.ExecutionHeaderValue.ExecutionID;
try
{
result = rs.Render(format, devInfo, out extension, out encoding, out mimeType, out warnings, out streamIDs);
execInfo = rs.GetExecutionInfo();
}
catch (Exception e)
{
Exception Errr = e.InnerException;
}
return result;
}
}
}
Finally! For those that are interested...
Found this from nearly two years ago.
AppPool Permission Issue with Accessing Report Server
In particular the comment below:
Almost the same situation here except IIS and Report Server running on Windows Server 2008 R2. I used to have the asp.net application running with it's own application pool and everything worked. When I changed the application to the DefaultAppPool (due to a different problem), I got the permissions problem. I changed the Identity of the DefaultAppPool from ApplicationPoolIdentity to LocalSystem (in IIS, Advanced Settings) and it worked again.
Changed web server default app pool to LocalSystem and wha-la, I am rendering PDF reports from an SSAS cube through my AngularJS SPA.

How to recognize client's computer?

I have a problem recognizing client's computer data. I'm developing an application that requires some king of recongnision of machine client is currently using. I tried
System.Environment.MachineName;
and also
string hostName = Dns.GetHostName();
var add = Dns.GetHostAddresses(hostName);
, but it always returns data of server computer IIS is working on. Also i tried to get processors and basebords id's but with same result as previous examples.
ManagementObjectSearcher mos = new ManagementObjectSearcher("SELECT SerialNumber FROM Win32_BaseBoard");
ManagementObjectCollection moc = mos.Get();
foreach (ManagementObject mo in moc)
{
serial = mo["SerialNumber"].ToString();
}
ManagementObjectSearcher mbs = new ManagementObjectSearcher("Select * From Win32_processor");
ManagementObjectCollection mbsList = mbs.Get();
string id = "";
foreach (ManagementObject mo in mbsList)
{
id = mo["ProcessorID"].ToString();
}t
System will be used inside a private network(not to be used publicly).
Is there any way to somehow recognize any unique client's computer data in ASP.NET web application development, or .NET simply deny any recognision of client's computer data due to safety?
Thanks
Since the code runs on the Server, "System" is the Server. In ASP.NET you can get information about who is requesting (the client) with the Request object. Try this:
Request.UserHostAddress
Or this:
Request.UserHostName

Limitation on using PrincipalContext & DomainContext, to retrive Active directory users

I have added the following code inside my asp.net mvc web application model class, to retrive the current AD users:-
public List<DomainContext> GetADUsers(string term=null)
{
List<DomainContext> results = new List<DomainContext>();
string ADServerName = System.Web.Configuration.WebConfigurationManager.AppSettings["ADServerName"];
using (var context = new PrincipalContext(ContextType.Domain, ADServerName))
using (var searcher = new PrincipalSearcher(new UserPrincipal(context)))
{
var searchResults = searcher.FindAll();
foreach (Principal p in searchResults)
{
if (term == null || p.SamAccountName.ToString().ToUpper().StartsWith(term.ToUpper()))
{
DomainContext dc = new DomainContext();
dc.DisplayName = p.DisplayName;
dc.UserPrincipalName = p.UserPrincipalName;
dc.Name = p.Name;
dc.SamAccountName = p.SamAccountName ;
dc.DistinguishedName = p.DistinguishedName;
results.Add(dc);
}
}
}
return results;
}
I am now on the development machine , where AD is on the same machine as the asp.net mvc web application runs. And there is no need to provide username or password to access the AD. But I have the following questions about using my above approach on production server :-
Will the same approach work well if the AD and the asp.net mvc (deployed on IIS ) are not on the same machine?
Will I be able to provide username and password to access the active directory?
What are the general requirements I should achieve to be able to allow the Domaincontext class to access AD on remote servers ?
Thanks I advance for any help.
Regards
I think you're asking if you're able to use the same code if the web server is not apart of the Active Directory domain. PrincipalContext does have an overload for username and password to allow for credentials to be used to connect, instead of relying on the machine having enough permissions to read from the directory.
As for permissions, grant as few as possible. I would get your system administrator involved to create a the account. You maybe able to use Service Accounts which were introduced in Windows Server 2008 to allow for the authentication to happen.

Resources