There is a Windows Service on Windows Server 2003 (Amazon Virtual Machine). Some applications can communicate with it (using pipes, but there is an wrapper to do it). It is tested and it works. Also, there is a Web Service written in C# (ASP.NET) which communicates with mentioned Windows Service. When Web Method is called, it creates an instance of the class and calls a function - the function "connects" to Windows Service and post a job to it. But, if inside Web Method is created a thread and the function which "connects" to Windows Service is called inside a thread - connection fails. Connection to Windows Service uses pipes. Web Service works on IIS7. It is worth to mention that all works on my local machine, either from debugger (local server started by VS 2010) or from IE when I call Web Method on Web Service which works on local IIS7. In local all works - but on Amazon Instance doesn't. I'm not a web programmer, so I think there is some issue with security. Any hint? Thanks.
EDIT: Uwe's comment reminded me - the Web Method at first tries to download some files using http and it saves them to path C:\intetpub\wwwroot\files\". It works if files are downloaded from the web method, but download fails if it is done from another thread created in Web Method. Exception was: Access is denied. So, I changed security settings on mentioned folder and explicitly allowed user created by IIS7 (IIS_IUSRS) to read/write the folder, and now files can be downloaded. It seems that the source of these problems is the same.
EDIT: The solution is moved to an answer on Will's suggestion.
Ok guys, the solution is found and as Will recomends, I'll post it here, as an answer to my own question. So, the solution:
The problem was because the thread created by Web Method has to be impersonated. So, in the caller method I had to something like:
[WebMethod]
public void Fnc()
{
...
...
System.Security.Principal.WindowsIdentity wi = System.Security.Principal.WindowsIdentity.GetCurrent();
System.Threading.Thread postJobThread = new Thread(PostJobThread);
postJobThread.Start(wi);
...
}
...
private void PostJobThread(object ob)
{
System.Security.Principal.WindowsIdentity wi = (System.Security.Principal.WindowsIdentity)ob;
System.Security.Principal.WindowsImpersonationContext ctx = wi.Impersonate();
...
// Do some job which couldn't be done in this thread
...
// OK, job is finished
if(ctx != null)
ctx.Undo();
}
That's all. Thanks to guys who commented my question and I hope it'll be useful for somebody else.
Related
I have a local service running on my computer and trying to get other computers to be able to read the status of my service (whether it's running, stopped, etc.) However, I am unable to as I get an InvalidOperationException error, saying that I am unable to open Service Control Manager. Locally, I am able to, but on another remote computer I am unable to. The ServiceController (cs) object just returns an object with properties that all have the InvalidOperationException error.
I've tried closing down all the firewalls on the other computers, tried running Visual Studio on Administrator privileges, but nothing seems to be working. I've noticed that others suggested hard coding your admin credentials and using WindowsIdentity and Impersonation but that wouldn't work for my project (as it wouldn't be a viable solution at my workplace - wouldn't make sense with the business logic as don't want to give clients any in-house credentials).
Here's my snippet of code:
public bool CheckServiceStatus()
{
try
{
string machineName = pubSubConfig.MachineName;
string serviceName = pubSubConfig.ServiceName;
System.ServiceProcess.ServiceController cs = new System.ServiceProcess.ServiceController(serviceName, machineName);
if (cs != null && cs.ServiceName == serviceName && cs.Status == System.ServiceProcess.ServiceControllerStatus.Running)
{
return true;
}
}
catch(Exception ex)
{
Trace.TraceError("Unable to check service status: /r/n {0}", ex.Message);
}
return false;
}
The error is this:
System.InvalidOperationException: Cannot open Service Control Manager on computer '___'.
This operation might require other privileges. ---> System.ComponentModel.Win32Exception: Access is denied
Does anyone know any workarounds as to how I can get other computers running my C# program to be able to read the ServiceController object?
Thanks!
So as I said in the comments, I was not able to get around the SCM (Service Control Manager) due to admin privileges when accessing another remote computer (makes sense if you think about security). However, I did find another solution that was more or less a workaround. I'll post the solution here in case anyone finds it helpful.
So to check the status of the Windows Service (like if it's running or not), I added an additional WCF service that is hosted in the Windows Service. So now the service can expose a method that literally just returns true.
Essentially the thought-process around it was that if the WCF service is accessible then that means the Window Service is running, and thus will always return true. If the Windows service is down, the WCF service will also be down and thus making that method not available. You wouldn't get anything to return, so you would know that the service is down and not running.
Hope that helps someone! I know it's not really a direct solution to the problem I had originally asked, but it was a workaround, indirect solution.
I have successfully compiled and run Windows Service with WCF. With installutil, the Windows Service is successfully getting installed and started. I think I am at the end of my development and just need to invoke/call the method DoJobs() inside WCF. I don't need any user interaction and so I don't have any Windows forms or anything. I just want to invoke/call my WCF function programmatically just after serviceHost.Open();
The base address in app.config file is
http://localhost:8733/Design_Time_Addresses/WcfServiceLibrary1/Service1/
I am deploying my WCF from Windows service with the following code.
// Create a ServiceHost for the CalculatorService type and provide the base address.
serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
// Open the ServiceHostBase to create listeners and start listening for messages.
serviceHost.Open();
I have also added the service reference and created the below proxy, but not sure of its use.
WcfServiceLibrary1.WCFServiceRef.Service1Client
I have searched tutorials, the examples show how to invoke the WCF function on button_click event of any form after running Windows service. I just want to do that programmatically on start-up of Windows Service.
EDIT: The code inside my DoJobs() fetches the active tab url of firefox with DDE Client, which throws exception when done only in a Windows Service project but runs successfully when done in WCF project. Please see this for reference.
So I made a C#.Net solution with WCF called from a Windows Service and then I called DoJobs() inside Windows Service as shown below.
WcfServiceLibrary1.WCFServiceRef.Service1Client wcfObj = null;
...
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof(WcfServiceLibrary1.Service1));
serviceHost.Open();
if (wcfObj == null)
{
wcfObj = new WcfServiceLibrary1.WCFServiceRef.Service1Client();
wcfObj.DoJobs();
}
}
But, it makes the call happen at the windows service layer, and is throwing the same DdeClient exceptions.
Can the base address url help any way to programmatically invoke DoJobs() in Web-Service? OR there are some other solutions.
Any help is highly appreciated.
Thanks.
This is my aggregated answer from my various comments I made to your post and to Noctis's answer (specifically that we did not know you were using DDE in the OP):
You can't use Dynamic Data Exchange (DDE) in a Windows Service because the latter does not have a message pump. Also DDE requires a Window handle to be passed as a parameter to DDE functions. You can use DDE in programs which do have a message pump does as a WinForms app. See this article for more information
Once your GUI app is running you can either minimize it to a Sys Tray icon or hide the app completely so the user is unaware. Regardless of its visible nature you should have no problem utilising DDE since it will have a message pump.
Now it may be the case you could add a message pump to a Windows Service but I wouldn't recommend it because it falls into the category of because you can do a thing, does not mean you should do a thing. A topic for another time. It's very similar to a recent SO question about how to display a WinForm in a console app - by default you can't and if you managed to you end up with an odd hybrid with much re-inventing of wheels. Not to mention its an ugly hack.
In summary, my best advice is to proceed with a GUI app.
Assuming you have :
// I'm assuming this is your proxy?
var proxy = WcfServiceLibrary1.WCFServiceRef.Service1Client;
// All you need to do is :
proxy.DoJobs() ;
Having seen your update and Micky`s answers, I'm just wondering why you're using DDE. Not sure what your requirements look like, but you can always use your MSMQ to send messages and queue things.
i want to debug my program but i can't host my silverlight project in VS 2010
here is the message that the VS send to me:
"the Silverlight project you are about to debug uses web service. Call to the web service will fail unless the Silverlight is host and launched from the same web project contains the web service"
when I search about it in the web i saw that the problem is that I'm not doing it local
so when I tried to change this line
endpoint address="http://xxx.xx.x.x/WebService/Service1.svc"
to
endpoint address="http://localhost/WebService/Service1.svc"
on this file:
ServiceReferences.ClientConfig
update!!
i tried now to do it like this:
endpoint address="http://localhost:54502/Service1.svc"
and i got and error that says:
the remote server returned an error:NotFound
here:
public int EndAddParticipant(System.IAsyncResult result) {
object[] _args = new object[0];
int _result = ((int)(base.EndInvoke("AddParticipant", _args, result)));
return _result;
what should i do to change it?
i saw that i need to turn on the debug in web.config file but it was already on.
You didn't explain well so here are a bunch of answers:
When you created your solution, you should have told it to host in a web site.
You can do this after the fact but it is a lot of work (for a new guy), you're better off starting over and copying your code from your silverlight project.
If you did but you are trying to connect to another web site as your web service, you will have to implement a Cross Domain configuration file. This opens a big security hole though.
If you have the 2 projects, but your issue is just the "ServiceReferences.ClientConfig" file not pointing the the right server, you need to include the PORT when debugging locally. It should look something like this:
http://localhost:12345/Service1.svc
Where 12345 is the port of your local web service. You can find this out by looking at the "Web" tab of your project properties.
Hope one of these does it. If not, please provide a little more info, like all the important stuff behind the phrase, "it didn't work"!
I have a Windows Service that I am writing in .NET C#. The service is going to act as a file processor. It just watches a directory for File Created events and adds these files to a queue for processing. A separate thread pulls files from the queue and processes them.
My question is whether there is a way to query the windows service to get its "state". I would like to be able to query the service some way and see a list of the files currently waiting in the queue etc.
I know this can be done in Linux via the /proc file system and I was wondering if there is anything similar for Windows. Any tips/pointers would be greatly appreciated.
If you are looking for a non-UI method (eg to write the names to a file or to standard output), it is possible to use the ExecuteCommand Method on the service.
ServiceController sc = new ServiceController("ServiceName");
sc.ExecuteCommand(255);
This simply passes this command to your your service and your service will handle it via the OnCustomCommand
protected override void OnCustomCommand(int command)
{
base.OnCustomCommand(command);
if (command == 255
{
... // Your code here
}
}
You may need to store your queue/service status in a static variable so you can access it from the OnCustomCommand routine.
You could create a hosted WCF service inside of the windows service with whatever methods you need to access the state.
http://msdn.microsoft.com/en-us/library/ms733069.aspx
WCF would be good to do that, especially it can be hosted inside of Windows Service. Might be in your case it makes sense to use XML-RPC with WCF
i did set start my windows service or NT service like everybody says a then
came up this message:
The service myService on local computer started an then stopped.Some services stop automatically if they are not in use by another services or programs
i've started other services and it never hapened...
before i change the value of a parameter that have to find it's value on a web service method
that look on a sql database...
and other change is that got formatted the hard disk...maybe i have to enable somethig
please i need help
It happens most likely because
you have an exception at startup... try to debug your things either by
using a log or by trying to reproduce your behavior in a windows app....
You can even debug your windows service using the following method...
Write the following code in your Service file...
public void OnDebug()
{
OnStart(null);
}
In the program file,
YourService myService = new YourService();
myService.OnDebug();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
This can happen when the logic performed using a windows service exceeds the default timeout.
We cannot overcome the default timeout of a windows service. Usually windows services are used to instantiate a method. So start a child thread within the OnStart event of the windows service and call your method within it.
If this is not solving your issue, put the code in try catch and log the exceptions. This error can happen if there is any exception within OnStart event too.