I've used a simple windows service to make a method work in specific time and it works fine. Following that I've already tried:
protected override void OnStart(string[] args)
{
this.WriteToFile("Simple Service started {0}");
this.ScheduleService();
}
protected override void OnStop()
{
this.WriteToFile("Simple Service stopped {0}");
this.Schedular.Dispose();
}
private Timer Schedular;
public void ScheduleService()
{
try
{
Schedular = new Timer(new TimerCallback(SchedularCallback));
string mode = ConfigurationManager.AppSettings["Mode"].ToUpper();
this.WriteToFile("Simple Service Mode: " + mode + " {0}");
//Rest of the code here
}
catch(Exception ex)
{
WriteToFile("Simple Service Error on: {0} " + ex.Message + ex.StackTrace);
//Stop the Windows Service.
using (System.ServiceProcess.ServiceController serviceController = new System.ServiceProcess.ServiceController("SimpleService"))
{
serviceController.Stop();
}
}
}
This is done in a simple windows application. So what I am trying to do is to call a web service (A specific method to operate in a specific time) in a windows service. The application I am building is web-based and am little bit confused how would I integrate the windows service into it? Do I need any alternatives or any suggestions would be appreciated.
Note: What I would like to know is it required to create another project for windows service in the web application or any other way to implement?
To call a web service from a Windows Service application, you would first generate a DLL from that web service, then instantiate its namespace. Assuming you have the code for that web service and/or know its namespace, you can perform these commands to do this:
Perform these lines on a command line:
cd C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools
wsdl /l:CS /protocol:SOAP %svc%?WSDL
where %svc% is the URL for your web service, i.e. http://localhost:777/MyWebService.asmx
If the code is in VB instead of C#, change /l:CS to /l:VB.
This will output a proxy class file that can be converted to a DLL.
Move the MyWebService.cs file from C:\Program Files (x86)\Microsoft SDKs\Windows\v8.1A\bin\NETFX 4.5.1 Tools to the C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\ directory.
Run these two commands on the command line:
cd C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727
csc /t:library %name%.cs /reference:System.Web.Services.dll /optimize
where %name% is the name of the class (without the .cs, since the command will append this). In our case, we'd use MyWebService. (Change .cs to .vb for a VB class.)
Navigate to C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727 via Windows Explorer. You should see a DLL created in that folder with the name of the class (MyWebService.dll). Copy this file to the bin folder of your Service project. You will need to set the bin folder to be included in your project, and right-click the folder to Add > Existing Item. Select the DLL. Once imported, select the DLL and change its properties to:
Build Action: Content
Copy to Output Directory: Copy if newer (or Copy always, as you prefer)
Right-click References > Add References. Navigate to the DLL in the bin folder for your web service.
Right-click References > Add Service References. Assuming your web service is running, take its full URL (i.e. http://localhost:777/MyWebService.asmx) and put that on the Address line. In the Namespace textbox, give it something more meaningful than ServiceReference1, but it should not be the same as MyWebService (the name/namespace of the ASMX file). Perhaps MWS.
Instantiate your web service in your Windows Service:
MWS.MyWebServiceSoapClient webService = new MWS.MyWebServiceSoapClient();
webService.Open();
string someDataYouWant = webService.SomeMethodToGetData();
webService.Close();
Or you can probably do:
MyWebService webService = new MyWebService();
string someDataYouWant = webService.SomeMethodToGetData();
webService.Dispose();
In answer to your query on my comment;
Another approach is to use an IIS Auto-Start website contaning your Windows Service logic. The IIS Auto-start is supierior to using a Windows Service as it contains all the IIS application hosting logic including auto-restart, and aggressive resource management. A poorly written Windows Service can take down a Server but it takes a lot for an ASP.net IIS hosted application to take down its host (its almost impossible).
Your Auto-Start website need not be visibile to the outside world - it just needs to have an internal timer that keeps it alive when it starts up. Note that the web application might be started and stopped by IIS for various reasons; but the outcome is that it will be running whenever your other web service application is running. The internal timer can wait for a specific time to execute the logic you need to call your second web service.
The key thing to remember is that a Windows Service is designed to be an application that is hosted by Windows and is continually running. An IIS application is designed to be run by Windows but runs only when called. The IIS Auto-Start website concept allows you to provide a "continually running" website but hosted by the robust IIS application hosting components, instead of it running directly as an OS process.
Generally people dont do this because either they dont know about it, or want to avoid needing the IIS infrastructure to run "Windows Service" type applications, but in your case you have already paid the cost of using IIS to host your second web service, so you may as well make full use of IIS (and avoid the second technology stack and deployment headaches of Windows Service deployment).
So I suggest using an IIS Auto Start in preference to a Windows Service in your situation because;
You only need to use on tech stack in your solution, which was what your OP was asking about
IIS carries out active resource management on all its applications, terminating, restarting as neccessary if they become non-functional. Windows Services do not have that capability.
Your IIS based service code is XCOPY deployable with no administrator access credentials on the target machine.
Your IIS service is hot upgradeable without needing OS level administrator rights - IIS handles the stopping and restarting on upgrade without you needing to do anything.
Related
I am trying to use an already existing ASP.net web application to host a WCF service, so I tried the following steps,
1- In Visual Studio 2010, I created web application through the Web > ASP.net Web Application template, named WebApp.
2- Added new WCF Service through Add > New Item ... > WCF Service , named MyServ.
3- Modified the DoWork() method in MyServ.svc as follows,
From
public void DoWork()
{
}
To
public string DoWork()
{
return "hello";
}
and consequently I modified IMyServ.cs to match the new signature.
4- When I run the application on development server and visit http://localhost:1399/MyServ.svc , the service runs fine.
5- So I create a publish for this application, to prepare it to be hosted on the IIS.
6- In the IIS, I create a new website named WebAppSite and is given the port 111, so now when I visit http://localhost:111/ , I am directed for the published WebApp site default page, which is fine and shows that the aspx part of the application is working fine on the IIS.
7- So I try to visit http://localhost:111/MyServ.svc to check if the service is successfully deployed, but I get this message,
HTTP Error 404.3 - Not Found
The page you are requesting cannot be served because of the extension configuration. If the page is a script, add a handler. If the file should be downloaded, add a MIME map.
Any idea where the problem is?
you need to register the .svc mime type in your IIS
run "\%windir%\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe -i"
Here is a full guide, please apply all steps:
Add “.svc” extension and MIME Type as “application/octet-stream” to IIS Mime Type in Features View.
Register Asp.net by running aspnet_regiis.exe -i command from VS 2010 command prompt (Run as admin).
Right click cmd, run as admin, go to “C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation” folder and run : ServiceModelReg.exe -i
If you did some changes in your IIS, you may need to go to handler mappings, right click on the static file and select "Revert to Parent".
I have a Azure WebRole which I'm trying to configure logging for using the DiagnosticMonitor.
According to the documentation at windowsazure.com the logging should be implemented in OnStart:
Note: The code in the following steps is typically added to the OnStart method of the role.
https://www.windowsazure.com/en-us/develop/net/common-tasks/diagnostics/
In order to access the OnStart method I have to define a RoleEntryPoint. But once it is defined I can't access the RoleEnvironment in web applications Application_Start.
How can I make the RoleEnvironment available to the application while still being able to use the DiagnosticMonitor?
I store the applications connection-strings in the service configuration.
public class WebRole : RoleEntryPoint
{
public override bool OnStart()
{
// config
var config = DiagnosticMonitor.GetDefaultInitialConfiguration();
LocalResource localResource = RoleEnvironment.GetLocalResource("MyCustomLogs");
DirectoryConfiguration dirConfig = new DirectoryConfiguration();
dirConfig.Container = "wad-mycustomlogs-container";
dirConfig.DirectoryQuotaInMB = localResource.MaximumSizeInMegabytes;
dirConfig.Path = localResource.RootPath;
DiagnosticMonitorConfiguration diagMonitorConfig = DiagnosticMonitor.GetDefaultInitialConfiguration();
diagMonitorConfig.Directories.ScheduledTransferPeriod = TimeSpan.FromMinutes(1.0);
diagMonitorConfig.Directories.DataSources.Add(dirConfig);
DiagnosticMonitor.Start("Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString", config);
return base.OnStart();
}
I've solved it.
After cleaning my solution, rebuilding, restarting IIS, shutting down the azure emulators and restarting Visual Studio it suddenly started working.
I changed no code at all.
(I even did all of those things before posting as well but it only worked when I did it all at the same time)
This is defintely the right example set of code. You need to set all of this in the Role though NOT in your web application.
NOTE: since Azure now has full IIS the context is different between the RoleEntryPoint On_start and the Web application, which is running in it's own worker pool within IIS.
Just a quick sanity checklist:
The code you're writing is in your class that inherits from RoleEntryPoint (typically WebRole.cs NOT in the Global.asax)?
You're running the project in the Azure Emulator (not inadvertently starting a web project directly?)
If you're running the application in the Azure emulator or deployed to Azure itself RoleEnvironment is available from within your IIS application as long as you have the relevant DLLs reference. If you can build with RoleEnvironment.IsAvailable in your code, then the libraries are included. The only thing I can think is that you're running the web site directly, not within the Azure emulator.
Set the Cloud project to be your startup in Visual Studio and you should be golden.
I am using visual studio 2010, my application has a multiu layer architect,
MainUI, WCFService, BLL and DAL
My MainUI communicated to WCF and WCF further communicates to BLL and DAL, whenever i need to debug BLL and DAL, i first need to attach WCF as a process in Visual studio(everytime). How could i can save myself from this hassle.
How could i set up visual studio in a way that i automatically attach to the service automatically and i could debug my application easily.
Thanks
Configure your solution for multi project start up. I do this for a similar application. VS launches the WCF and client automatically and I can set break points in either.
The start-up order is the order in which you select the projects.
Right mouse click on your solution and select 'choose startup projects'. Then select multiple startup projects and select the projects.
Sample howto start a process and attach it to Visual Studio 2010 with EnvDTE(Version is relevant).
//c:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\PublicAssemblies\EnvDTE.dll
using Process = EnvDTE.Process;
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.FileName = System.AppDomain.CurrentDomain.BaseDirectory + #"\YourProcess.exe";
//Start the process
p.Start();
//Wait for process init
System.Threading.Thread.Sleep(1000);
bool attached = false;
//did not find a better solution for this(since it's not super reliable)
for (int i = 0; i < 5; i++)
{
if (attached)
{
break;
}
try
{
EnvDTE.DTE dte2 = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.10.0");
EnvDTE.Debugger debugger = dte2.Debugger;
foreach (Process program in debugger.LocalProcesses)
{
if (program.Name.Contains("YouProcess.exe"))
{
program.Attach();
attached = true;
}
}
}
catch (Exception ex)
{
//handle execption...
}
}
Try using System.Diagnostics.Debugger.Break() in the code. If a debugger is not attached, then running that code will ask to attach a debugger and you can choose the existing instance.
Have you tried System.Diagnostics.Debugger.Launch() in your service you would like the debugger to attach to?
http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.launch.aspx
In the properties page for the wcf service project, select the Web tab.
Select 'Start External Program' for the start action, and choose MainUI.exe.
Set the working directory as the folder that MainUI.exe is in (probably a bin folder).
Set a break point and press f5 to start debugging.
If I understand correctly, Macro may be answer:
in Vs:
Tools->Macros->record TemporarilyMacro (Ctrl+shift+r)
Attach VS to process as usual (ctrl+alt+p)
Stop recording macro (ctrl+shift+r)
Go to View->Other Windows->Macro Explorer (CTRL+F8)
find your Temporarily Macro (somewhere in MyMacros->RecordingModule) and rename it
Now, go to Tools->Options->Keyboard and find your macro (in "Show Command containing write name of you macro)
in "Press Shortcut keys" bind it to some key shortcut (i have my macro in CTRL+SHIFT+K ;))
Push OK
Be Happy
Have you tried using the WCFSvcHost.EXE that comes with Visual Studio to launch the BLL and DAL service? There is a help file with it. The help file states it best, "Windows Communication Foundation (WCF) Service Host (wcfSvcHost.exe) allows you to launch the Visual Studio debugger (F5) to automatically host and test a service you have implemented. You can then test the service using WCF Test Client (wcfTestClient.exe), or your own client, to find and fix any potential errors." The default installation is C:\Program Files\Microsoft Visual Studio 10.0\Common7\IDE. You can configure it to use your MainUI app as the client. The help file WcfSvcHost.chm in the same directory has a section for using a custom client under the Scenarios for using ECF Service Host. If you rather here is the link to help on MS web site: Using WCF Service Host (wcfSvcHost.exe).
If this is for a self-hosted WCF windows service, you need to make your WCF service host configurable to either run in console or as a windows service. When you have run in console turned on, you can start debugging from visual studio.
Create an app setting called "RunInConsole." In your service host startup method, have the following code:
public class MyWindowsService : ServiceBase
{
public static void Main(string[] args)
{
// if configuration says to run in the console, run the service in a console app. otherwise, use windows
// service to host application
if (ConfigurationManager.AppSettings["RunInConsole"] == "true")
{
using (ServiceHost host = new ServiceHost(typeof(MyService)))
{
host.Open();
Console.WriteLine("Press <Enter> to terminate the Host application.");
Console.ReadLine();
}
}
else
ServiceBase.Run(new MyWindowsService ());
}
}
On all environments you deploy to, you'd always have this config setting set to false or else the service will fail to start, but when debugging locally you'd set it to true.
Here is a detained article that explains how to do this...You can customize this macro.
http://sivablogz.wordpress.com/2013/04/08/running-an-application-and-attaching-to-the-process-with-a-macro-in-visual-studio/
Personally I prefer to use Debugger.Launch() as suggested here
in this thread, because it doesn't need for references to the DTE (that's IDE-specific and must be explicitly referenced into the project to be used)
I have written a service in C#. I kept the DLLs of my service in c:\windows\system32\myservice.dll. I have done the necessary registry changes for hosting in svchost.exe, but my service is not being executed. It gets a 1053 error code.
The following is the registry entry for myservice. I created a key and have given the path of the myservice.dll file.
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\svcsvc2]
"Type"=dword:00000010
"Start"=dword:00000002
"ErrorControl"=dword:00000001
"ImagePath"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,00,\
74,00,25,00,5c,00,73,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,73,\
00,76,00,63,00,68,00,6f,00,73,00,74,00,2e,00,65,00,78,00,65,00,20,00,2d,00,\
6b,00,20,00,4c,00,6f,00,63,00,61,00,6c,00,53,00,65,00,72,00,76,00,69,00,63,\
00,65,00,00,00
"DisplayName"="#%SystemRoot%\\system32\\svcsvc.dll,-200"
"ObjectName"="NT AUTHORITY\\LocalService"
"ServiceSidType"=dword:00000001
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\svcsvc2\Parameter]
"ServiceDll"=hex(2):25,00,53,00,79,00,73,00,74,00,65,00,6d,00,52,00,6f,00,6f,\
00,74,00,25,00,5c,00,53,00,79,00,73,00,74,00,65,00,6d,00,33,00,32,00,5c,00,\
73,00,76,00,63,00,73,00,76,00,63,00,2e,00,64,00,6c,00,6c,00,00,00
"ServiceMain"="Main"
1053 is ERROR_SERVICE_REQUEST_TIMEOUT
The service did not respond to the start or control request in a
timely fashion.
StartServiceCtrlDispatcher was not called?
You also have type set to SERVICE_WIN32_OWN_PROCESS, not SERVICE_WIN32_SHARE_PROCESS.
And please respect this note from MSDN:
Note that Svchost.exe is reserved for use by the operating system and
should not be used by non-Windows services. Instead, developers should
implement their own service hosting programs.
svchost doesn't host the .NET framework, so is not able to execute your .NET assembly.
.NET services run with their own applications (.exe).
Why not creating a Setup Project in VS that installs your service?
Unless you want to install a service programatically, I would advise you to read this article.
I have a web service application in C#. When I run the Debug in Visual Studio, it starts the service at http://localhost:###### and shows the Default.htm page with links to test the different calls that can be made to the web service.
Is there a way to call this locally running version to test it from another computer? I tried making a call that the links on the test page make, but replaced localhost with the IP address of the machine running it, but it said that it could not connect to the server.
The embedded Visual Studio web server (Cassini) is only accessible from the local machine. If you want to use the web service from a different computer, you will need to deploy the service to IIS and then you'll be able to get to it at http://xxx.xxx.xxx.xxx/MyWebService/MyWebService.asmx (replace xxx with your IP Address and MyWebService with the appropriate IIS web site path).
Then to create a test application, you can create either an ASP.NET website or WinForms/Console application and import a Web Service reference in Visual Studio. That will build the proxy classes for you automatically and make calling the service very easy.
Just wrap your service in a console application so it can be accessed.
Create a new console application project in your solution, naming it something that makes sense (If your service is named MyService maybe MysServiceConsoleHost or some facsimile).
Include a reference to the service project in this project.
In your new project (program.cs) have something like the following:
using System;
using System.ServiceModel;
class Program
{
static String TITLE_TEXT = "MyService -- Console Host ({0})" + (System.Diagnostics.Debugger.IsAttached?" [DEBUG]":"");
static void Main(string[] args)
{
Console.Title = String.Format(TITLE_TEXT, "Not Running");
try
{
ServiceHost host = new ServiceHost(typeof(MyService));
Console.Title = String.Format(TITLE_TEXT, "Starting");
host.open();
Console.Title = String.Format(TITLE_TEXT, "Running");
Console.WriteLine("Service is started, press any key to exit.");
Console.ReadKey();
Console.Title = String.Format(TITLE_TEXT, "Closing");
host.close();
host = null;
Console.Title = String.Format(TITLE_TEXT, "Closed");
}
catch (Exception ex)
{
Console.Title = String.Format(TITLE_TEXT, "Exception");
Console.WriteLine("An error occured while running the host:");
Console.WriteLine(ex.Message);
Console.WriteLine();
Console.WriteLine(ex.StackTrace);
Console.ReadLine();
}
}
}
Replace the instances of MyService as necessary, then run it. Make sure you have a .config file that specifies the endpoints of your service, port to run on, etc. Then anyone can access your service and, if necessary, you can debug through the service during live calls.
A really simple solution to this is to use localtunnel:
http://progrium.com/localtunnel/
It will set up a proxy that will point to your localmachine and can be accessed outside of your machine.
If you are using Visual Studio's built in web server (Cassini) then this can only be called locally. If you want to connect remotely you will have to install IIS and configure your project to use it.
Yes and no. If you are using the built in ASP.NET dev server (most likely, since you have :####), I don't believe that can be contacted externally.
But, you can "deploy" to the local IIS instance and it then can be hit from other computers. Web Service Studio is a good test tool for web services. There are also some really good open source tools out there. I like SoapUI myself.
I can test the webservice on localhost. I have a windows CE Motorola terminal, connected to my computer. I have VS2008 on the computer.
My computer address is xxx.xxx.x.xxx and webserver is localhost:62209, so at the terminal i use webservice address: http://xxx.xxx.x.xxx/62209/MyWebservice.asmx and it works.
Maybe because the terminal is connected directly to the computer wher the webserver runs?
Anyway, it works.