WCF selfhosted service, installer class and netsh - wcf

I have a selfhosted WCF service application which I want to deploy by a msi installer package. The endpoint uses http port 8888. In order to startup the project under windows 2008 after installation I have to either run the program as administrator or have to edit the http settings with netsh:
"netsh http add urlacl url=http://+:8888/ user=\Everyone"
I want to edit the http settings from my installer class. Therefore I call the following method from the Install() method:
public void ModifyHttpSettings()
{
string parameter = #"http add urlacl url=http://+:8888/ user=\Everyone";
System.Diagnostics.ProcessStartInfo psi =
new System.Diagnostics.ProcessStartInfo("netsh", parameter);
psi.Verb = "runas";
psi.RedirectStandardOutput = false;
psi.CreateNoWindow = true;
psi.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
System.Diagnostics.Process.Start(psi);
}
This method will work for english versions of windows, but not for localized versions (The group Everyone has different names in localized versions). I have also tried to use Environment.UserName to allow access at least for the current logged on user. But this does also not work, because the installer class is run by the msi service which runs under the user SYSTEM. Hence Enviroment.UserName returns SYSTEM and that is not what I want. Is there a way to grant access to all (or at least for the current logged on) user to my selfhosted WCF service from a msi installer class?

My aproach to a solution:
public void ModifyHttpSettings()
{
string everyone = new System.Security.Principal.SecurityIdentifier(
"S-1-1-0").Translate(typeof(System.Security.Principal.NTAccount)).ToString();
string parameter = #"http add urlacl url=http://+:8888/ user=\" + everyone;
ProcessStartInfo psi = new ProcessStartInfo("netsh", parameter);
psi.Verb = "runas";
psi.RedirectStandardOutput = false;
psi.CreateNoWindow = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = false;
Process.Start(psi);
}
The SID "S-1-1-0" is a wellknown SID and stands for the "Everyone" account. The SID is the same for all localizations of windows. The method Translate of SecurityIdentifier class returns the localized name of the Everyone account.

Related

Get AD Users Visual Studio Web App versus Console

I have the following code below.
When I run Debug in Visual Studio with this code in an ASP.NET Core App (so running as IIS Express) this works
When I run Debug in Visual Studio with this code in a ASP.NET hosted process in a Windows Service this return nothing, but also no error messages
I connect from my home laptop via RDP to another laptop where VPN is running, so I think that is probably it. I tried running visual studio as admin, running the compiled exe as admin, /runas with the domain specified, etc but the commandline app will show nothing while the asp.net core app shows the list. So it must be the user it runs under.
But when i run WindowsIdentity.GetCurrent().Name in both cases it gives the same domain and name (me). In task manager the devenv and iis process is me.
public List<AdSecurityGroupDTO> GetAllDomainSecurityGroups(string domain)
{
List<AdSecurityGroupDTO> result = new List<AdSecurityGroupDTO>();
using (var ctx = new PrincipalContext(ContextType.Domain, domain))
{
GroupPrincipal findAllGroups = new GroupPrincipal(ctx, " * ");
PrincipalSearcher ps = new PrincipalSearcher(findAllGroups);
foreach (Principal group in ps.FindAll())
{
AdSecurityGroupDTO adSecurityGroupDTO = new();
adSecurityGroupDTO.Name = group.Name;
adSecurityGroupDTO.Description = group.Description;
adSecurityGroupDTO.DisplayName = group.DisplayName;
adSecurityGroupDTO.DistinguishedName = group.DistinguishedName;
adSecurityGroupDTO.SamAccountName = group.SamAccountName;
result.Add(adSecurityGroupDTO);
}
return result;
}
}

Servicestack, Xamarin and authentication

I've got an ServiceStack service running with custom authentication, this runs fine from the browser and through a Windows console program.
I'm now trying to get a simple Xamarin Android program to authenticate but whatever I try it crashes with an Exception without any further explanation. The code I am using stops at the line with 'var authResponse', I'm using the 4.0.44 ServiceStack packages and the lastest stable Xamarin from inside VS2015.
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
// Set our view from the "main" layout resource
SetContentView (Resource.Layout.Main);
// servicestack
var client = new JsonServiceClient("http://10.0.2.2:8080");
var authResponse = client.Get<AuthenticateResponse>( new Authenticate
{
UserName = "Willem",
Password = "secret",
RememberMe = true
});
Any pointers to what/where I should look?
tia
If this is a self-hosted Service you would need to register the HttpListener AppHost to accept requests from different hosts by listening on a host wildcard, e.g:
appHost.Start("http://*:8080/");

HTTP could not register URL (remote debugging)

C#, Windows 7.
I write an AutoCAD plugin and use the remote debuging (MS Visual Studio). My plugin must work as a WCF service. AutoCAD is unmanaged application and must to be as a host for my service. I am reading a book about WCF, and I try use it. I can't use acad.exe.config for my service settings: I have not permission. So I do it myself (I will read them from my xml file, but later, after refactoring). Code of my "server" (this code start by AutoCAD):
private static void RunServices() {
Ap.Document doc = cad.DocumentManager.MdiActiveDocument;
try {
Uri address = new Uri("http://localhost:8000/CadService");
BasicHttpBinding binding = new BasicHttpBinding();
binding.Name = "httpBinding";
binding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
binding.Security.Mode = BasicHttpSecurityMode.None;
host = new ServiceHost(typeof(CadService));
host.AddServiceEndpoint(typeof(ICadService), binding, address);
host.Open(); // I get an Exception here...
if (doc != null) {
doc.Editor.WriteMessage("Service launched.\n");
}
}
catch (Exception ex) {
if (doc != null) {
doc.Editor.WriteMessage("Exception: {0}\n", ex.Message);
}
}
}
I get an exception (look the code comment):
Exception: HTTP could not register URL http://+:8000/CadServices/.
Your process does not have access rights to this namespace
(see http://go.microsoft.com/fwlink/?LinkId=70353 for details).
But the http://go.microsoft.com/fwlink/?LinkId=70353 page is not exist. I try launch MS Visual Studio 2013 as admin (I read about this here), but It is not help me (look P.S.2 bellow).
P.S. If I launch AutoCAD as admin - all works fine.
P.S.2 If I launch the remote debugger as admin - all works fine too.
But I need use it as a usual user. Can I start my service (hosted in the AutoCAD) without the admin rights?
This is probably because AutoCad does not have the required rights to register the port in HTTP.SYS. In that case you have two options:
Start Autocad in Admin mode
Register the port / endpoint in HTTP.SYS manually. For this, there are several tools available. This is the one I would use : http://www.codeproject.com/Articles/437733/Demystify-http-sys-with-HttpSysManager
Let me know if this works

Deploying a WCF service on a remote pc

I have a WCF web service, which I have hosted in IIS on my PC. This I have added as Service Reference in a Visual Studio Project and I am able to invoke it successfully in a web service in this VS Project.
Now I am trying to deploy this web services on a remote PC, which doesn't have Visual Studio installed. For this purpose I copied the .svc and web.config files and bin folder of this web services to a folder on the remote PC. Then I hosted the services on IIS pointing to the respective folder. Now when I browse the web service using the .svc link I am able to access the web service from my PC. I added this web service as a service reference in my Visual Studio project and everything looks OK, I am able to see the separate methods and their parameters in the Object browser. The problem appears when I try to invoke methods from this web services.
I am able to invoke one method and then when I invoke the second one I get the following error (The absolutely same web service and all its methods work perfectly if hosted in IIS on my PC.):
Object reference not set to an instance of an object.
Here is a part of the method where I invoke the web service (the web service name is TFSWS):
public void ImportRequirements(string username, string password)
{
TFSWS.TFSWSClient obj = new TFSWS.TFSWSClient();
string projects = obj.GetTFSProjects(username, password, TFS_URI);
string list = obj.GetAllWorkItems(ProjectName2, username, password, TFS_URI, WItypes);
Here is the code of the first method which I am able to invoke successfully from TFSWS:
public string GetTFSProjects(string userName, string password, string Uri)
{
StringWriter MyStringWriter = new StringWriter();
NetworkCredential cred = new NetworkCredential(userName, password);
TfsTeamProjectCollection _tfs = new TfsTeamProjectCollection(new Uri(Uri), cred);
_tfs.Authenticate();
ICommonStructureService tfsProjectService = (ICommonStructureService)_tfs.GetService(typeof(ICommonStructureService));
ProjectInfo[] projects = tfsProjectService.ListAllProjects();
string[] proj = new string[projects.Length];
for (int i = 0; i < projects.Length; i++)
{
proj[i] = projects[i].ToString();
}
DataTable ProjectsDT = GetDataTableFromArray(proj);
...
}
Here is the code of the second method that I invoke from TFSWS and that throws the error message (When I debug I can see that all parameters are assigned correctly):
public string GetAllWorkItems(string projectName, string username, string password, string URI, string[] WItypes)
{
StringWriter MyStringWriter = new StringWriter();
NetworkCredential cred = new NetworkCredential(username, password);
TfsTeamProjectCollection _tfs = new TfsTeamProjectCollection(new Uri(URI), cred);
_tfs.Authenticate();
WorkItemStore _witStore =(WorkItemStore)_tfs.GetService(typeof(WorkItemStore));
DataTable myData = new DataTable();
string project = projectName;
string[] m_columns;
Hashtable context = new Hashtable();
Project proj = _witStore.Projects[project];
}
string myQuery = "SELECT [System.Id], [System.Title], [System.WorkItemType], [System.State] FROM WorkItems WHERE ...";
WorkItemCollection result = _witStore.Query(myQuery, context);
DisplayFieldList fieldList = result.Query.DisplayFieldList;
...
}
You can debug remotely to figure out the issue the code is experiencing on the target machine, without installing all of Visual Studio on it. You just need to deploy debug instead of release mode assemblies, and have the remote debugger service running on it.
Remote Debugging Setup

Running a windows command in a wcf rest service

I have a wcf rest service running the code below:
string command = #"C:\Test.exe";
System.Diagnostics.ProcessStartInfo procStartInfo =
new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);
Logger.Write(string.Format("1"), LogType.Error);
procStartInfo.RedirectStandardOutput = true;
procStartInfo.UseShellExecute = false;
procStartInfo.CreateNoWindow = true;
Logger.Write(string.Format("2"), LogType.Error);
System.Diagnostics.Process proc = new System.Diagnostics.Process();
proc.StartInfo = procStartInfo;
Logger.Write(string.Format("3"), LogType.Error);
proc.Start();
Logger.Write(string.Format("4"), LogType.Error);
string result = proc.StandardOutput.ReadToEnd();
Logger.Write(string.Format("5"), LogType.Error);
// Display the command output.
Logger.Write(string.Format("Plugin : {0} has started", result), LogType.Error);
It works fine in my development machine. When I publish the service to server, the problem occurs. The latest log in my log file is written by:
Logger.Write(string.Format("4"), LogType.Error);
I think it's a security / permission issue. What can I do to run my code without problem in server too.
Thanks in advance,