HTTP could not register URL (remote debugging) - wcf

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

Related

VSTO-specific web request not working (System.Net.WebException)

I wrote a 2013/2016 VSTO app for Microsoft Word using C#. My app creates a new toolbar with buttons. One such button runs my app, which launches a basic Windows Form.
Before the user can work with my app, they need to enter information like their license code and email address. My code in turns sends a basic request to my licensing server and awaits a response.
All my code has been running just fine and now it no longer is. Now, when I run the code, I receive the following two error messages:
System.Net.WebException: 'The underlying connection was closed: An
unexpected error occurred on a send.' Inner Exception: IOException:
Unable to read data from the transport connection: An existing
connection was forcibly closed by the remote host.
and
System.Net.WebException: 'The underlying connection was closed: An
unexpected error occurred on a send.' Inner Exception:
SocketException: An existing connection was forcibly closed by the
remote host
I decided to run the code using a standard console app to see if I received the same error message, and sure enough, it worked great! Now I am wondering if Word or the Microsoft VSTO technology is blocking my app from accessing my server.
Here is the code in VSTO that does not work
Note 1: Created a basic 2013/2016 C# VSTO add-in, added a toolbar, and added
Note 2: Added a reference to System.Web.
Note 3: Modified the website link and the query strings as I did not want to publish them on this public forum.
using System;
using Microsoft.Office.Tools.Ribbon;
using System.Web;
using System.Net;
namespace WordAddIn3
{
public partial class Ribbon1
{
private void Ribbon1_Load(object sender, RibbonUIEventArgs e)
{
}
private void button1_Click(object sender, RibbonControlEventArgs e)
{
// Attempt to activate the product using the licensing server on the website.
Console.WriteLine("** ActivateLicense");
//build the url to call the website's software licensing component.
var builder = new UriBuilder("https://validwebsite.com");
builder.Port = -1;
//build the query string.
var query = HttpUtility.ParseQueryString(builder.Query);
query["license_key"] = "validactivationcdode";
query["product_id"] = "validproductid";
query["email"] = "validemailaddress";
builder.Query = query.ToString();
string url = builder.ToString();
Console.WriteLine("activation request:");
Console.WriteLine(url); //display the REST endpoint.
//make the synchronous call to the web service.
var syncClient = new WebClient();
var responseStream = syncClient.DownloadString(url);
Console.WriteLine("Response stream:");
Console.WriteLine(responseStream); //display the server json response.
}
}
}
Here is what is pretty much the same exact code in a console app that does work
Note 1: Created a basic C# console app.
Note 2: Added a reference to System.Web.
Note 3: Modified the website link and the query strings as I did not want to publish them on this public forum. You will receive an error, but that is due to the sample website not having a licensing server.
using System;
using System.Net;
using System.Web;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
// Attempt to activate the product using the licensing server on the website.
Console.WriteLine("** ActivateLicense");
//build the url to call the website's software licensing component.
var builder = new UriBuilder("https://validwebsite.com");
builder.Port = -1;
//build the query string.
var query = HttpUtility.ParseQueryString(builder.Query);
query["license_key"] = "validactivationcdode";
query["product_id"] = "validproductid";
query["email"] = "validemailaddress";
builder.Query = query.ToString();
string url = builder.ToString();
Console.WriteLine("activation request:");
Console.WriteLine(url); //display the REST endpoint.
//make the synchronous call to the web service.
var syncClient = new WebClient();
var responseStream = syncClient.DownloadString(url);
Console.WriteLine("Response stream:");
Console.WriteLine(responseStream); //display the server json response.
Console.ReadKey();
}
}
}
Can you help me determine why the code is no longer working in the add-in where it did before (with no code changes)?
I read a lot online and there seem to be too many reasons why this might happen. As an FYI, the website with the licensing server is running. It is (and always has been) a little slow, but when running the code with VSTO, the response is immediate (suggesting no timeout). The Console code runs and there is never a timeout.. I always get a response from the licensing server.
On another thread for a similar problem, someone recommended running WireShark. I am not really familiar with the product, but during my working console run, I received no error messages and instead I got messages like these:
Standard query 0x626a AAAA mywebsite.com
and
Standard query response 0x626a AAAA mywebsite.com
However, if I run the same code in VSTO, I get additional messages that are errors (this one shows up twice):
TCP 60 443 → 50308 [RST, ACK] Seq=1 Ack=125 Win=32768 Len=0

Call Service Fabric service from console application using WCF HTTPS endpoint

I have a service hosted in a Service Fabric cluster in Azure (not locally) and I'm trying to call a method in it using a console application on my local machine. Using WCF for communication, I have a HTTPS endpoint set up in my application on a specific port, and have configured load balancing rules for the port in the Azure portal. The cluster has 6 nodes and the application is the only one deployed on the cluster.
Have followed the ServiceFabric.WcfCalc on GitHub (link), which works on a local cluster using HTTP endpoints, but can't call a method on the service using HTTPS endpoints once it has been deployed. What do I need to do to get it working? Have tried following the example here but don't know how to configure this for HTTPS with a service on multiple nodes for a console application to access.
Thanks in advance.
EDIT Here's my client code which I am using to call the service method. I pass the fabric:/ URI into the constructor here.
public class Client : ServicePartitionClient<WcfCommunicationClient<IServiceInterface>>, IServiceInterface
{
private static ICommunicationClientFactory<WcfCommunicationClient<IServiceInterface>> communicationClientFactory;
static Client()
{
communicationClientFactory = new WcfCommunicationClientFactory<IServiceInterface>(
clientBinding: new BasicHttpBinding(BasicHttpSecurityMode.Transport));
}
public Client(Uri serviceUri)
: this(serviceUri, ServicePartitionKey.Singleton)
{ }
public Client(
Uri serviceUri,
ServicePartitionKey partitionKey)
: base(
communicationClientFactory,
serviceUri,
partitionKey)
{ }
public Task<bool> ServiceMethod(DataClass data)
{
try
{
//It hangs here
return this.InvokeWithRetry((c) => c.Channel.ServiceMethod(data));
}
catch (Exception)
{
throw;
}
}
}
When debugging my console application on my local machine, the application hangs on the InvokeWithRetry call which calls the method in my service in Service Fabric. The application does not throw any exceptions and does not return to the debugger in Visual Studio.
Make sure you run every service instance /replica with a unique url.
Make sure you call the WebHttpBinding constructor using WebHttpSecurityMode.Transport.
Make sure you register the url using the same port number (443 likely) as in you service manifest endpoint declaration.
Make sure the endpoint is configured as HTTPS.
The warning you see in Service Fabric is telling you that there is already another service registered to listen on port 443 on your nodes. This means that Service Fabric fails to spin up your service (since it throws an exception internally when it is trying to register the URL with http.sys). You can change the port for your service to something else that will not conflict with the existing service, e.g.:
<Resources>
<Endpoint Name="CalculatorEndpoint" Protocol="https" Type="Input" Port="44330" />
</Endpoints>
If you log in to Service Fabric Explorer on https://{cluster_name}.{region}.cloudapp.azure.com:19080 you should be able to see what other applications and services are running there. If you expand services all the way down to node you should be able to see the registered endpoints, including ports, for existing services.
Bonus
You can query the cluster using FabricClient for all registered endpoints
var fabricClient = new FabricClient();
var applicationList = fabricClient.QueryManager.GetApplicationListAsync().GetAwaiter().GetResult();
foreach (var application in applicationList)
{
var serviceList = fabricClient.QueryManager.GetServiceListAsync(application.ApplicationName).GetAwaiter().GetResult();
foreach (var service in serviceList)
{
var partitionListAsync = fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName).GetAwaiter().GetResult();
foreach (var partition in partitionListAsync)
{
var replicas = fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id).GetAwaiter().GetResult();
foreach (var replica in replicas)
{
if (!string.IsNullOrWhiteSpace(replica.ReplicaAddress))
{
var replicaAddress = JObject.Parse(replica.ReplicaAddress);
foreach (var endpoint in replicaAddress["Endpoints"])
{
var endpointAddress = endpoint.First().Value<string>();
Console.WriteLine($"{service.ServiceName} {endpointAddress} {endpointAddress}");
}
}}}}}
Just run that with the proper FabricClient credentials (if it is a secured cluster) and you should see it listing all endpoints for all services there. That should help you find the one that has an endpoint for :443

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/");

Debugging a WCF project

I constructed a little solution containing 4 projects:
Contract: contains my (t4 generated) entities and interface to my service
Service: contains my (t4 generated) context and implementation of my service
Host: contains the bare minimum to host a service
ServiceHost host = new ServiceHost(typeof(InleerAppService));
try
{
host.Open();
Console.WriteLine("The service is ready!");
Console.ReadKey();
host.Close();
}
catch (CommunicationException cex)
{
Console.WriteLine(cex.Message);
}
Client:
var factory = new ChannelFactory("InleerAppService");
IInleerAppService service = factory.CreateChannel();
var result = service.ReturnInput("test string"); // just returns the input string, this works!
Console.WriteLine(result);
var result2 = service.GetAllCompanies(); // this doesn't and crashes the client
foreach (Company c in result2)
{
Console.WriteLine(c.Name);
}
Console.ReadKey();
You understand I would like to figure out what is going. But I don't really understand how I can debug this. First I start the host with ctrl+F5, then the client. But this doesn't allow me to debug. How should I go to that, using this setup? I know there are more ways to work with services, but for this part I'd just want to focus on this setup.
You can setup the solution to start multiple projects and just hit F5. To set this up, right click on the solution and go to properties. Select start up project under common properties. And choose both your service and client projects for startup.
Another way to debug is to select the service project, right click and go to debug -> start new instance. Next, do the same thing for client project. Now you should have both service and client projects running under debug mode.

Connecting via named pipe from windows service (session#0) to desktop app (session #1)

Given:
- the application - desktop GUI (WPF) .NET app
- windows service watching for application (.NET also)
The windows service periodically "pings" application to get sure it's healthy (and if it's not winservice will restart it).
I was going to implement "pinging" via named pipes. To make things simpler I decided to do it with WCF. The application hosts a WCF-service (one operation Ping returning something). The windows service is a client for this WCF-service, invokes it periodically based on a timer.
That's all in Windows 7.
Windows service is running under LocalService (in session#0).
Desktop application is running under currently logged in user (in session#1).
The problem:
Windows service can't see WCF endpoint (with NetNamedPipeBinding) created in and being listened in desktop application. That means that on call via wcf proxy I get this exception: "The pipe endpoint 'net.pipe://localhost/HeartBeat' could not be found on your local machine"
I'm sure code is ok, because another desktop application (in session#1) can see the endpoint.
Obviously here I'm dealing with some security stuff for Win32 system object isolation.
But I believe there should be a way to workaround restrictions I've encountered with.
I can sacrifice WCF approach and go the raw NamedPipe way.
An easier solution might be to use a WCF duplex contract with the Windows service hosting the WCF service. The client App would call an operation on the service to register itself, when it starts up. The Ping would then be an operation invoked periodically by the service on the client's callback contract, to which the App would respond.
Service visibility works this way round, because the Windows service can run with SeCreateGlobalPrivilege, and so the shared memory object via which the pipe name is published by the service can be created in the Global kernel namespace, visible to other sessions. Interactive applications can't easily get that privilege in Windows7, so WCF services in such applications fall back to publishing the pipe in the Local kernel namespace, visible only within their own session.
Finally I've found a solution - using Named Pipes from System.IO.Pipes directly. It's seems that WCF's pipes support implementation doesn't use System.IO.Pipes.
Server:
using (var pipeServer = new NamedPipeServerStream("mypipe", PipeDirection.Out, 1))
{
try
{
while (true)
{
// #1 Connect:
try
{
pipeServer.WaitForConnection();
}
catch (ObjectDisposedException)
{
yield break;
}
if (ae.IsCanceled())
return;
// #2: Sending response:
var response = Encoding.ASCII.GetBytes(DateTime.Now.ToString());
try
{
pipeServer.Write(response, 0, response.Length);
}
catch (ObjectDisposedException)
{
return;
}
// #3: Disconnect:
pipeServer.Disconnect();
}
}
finally
{
if (pipeServer.IsConnected)
pipeServer.Disconnect();
}
}
Client:
using (var pipeClient = new NamedPipeClientStream(".", "mypipe", PipeDirection.In))
{
try
{
try
{
pipeClient.Connect(TIMEOUT);
}
catch(TimeoutException ex)
{
// nobody answers to us
continue;
}
using (var sr = new StreamReader(pipeClient))
{
string temp;
while ((temp = sr.ReadLine()) != null)
{
// got response
}
}
}
catch(Exception ex)
{
// pipe error
throw;
}
}