Windows Service: Specified eventSource exists already - c#

I'm writing a Windows Service in C# (.NET 4).
Here is the code for the installer:
[RunInstaller(true)]
public partial class JobManagerInstaller : Installer
{
public JobManagerInstaller()
{
InitializeComponent();
this.Installers.Clear();
ServiceProcessInstaller serviceProcessInstaller = new ServiceProcessInstaller();
ServiceInstaller serviceInstaller = new ServiceInstaller();
EventLogInstaller eventLogInstaller = new EventLogInstaller();
// Service Account Information
serviceProcessInstaller.Account = ServiceAccount.LocalSystem;
serviceProcessInstaller.Username = null;
serviceProcessInstaller.Password = null;
// Service Information
// The installer's ServiceName must be identical to the JobManager.ServiceName set in the constructor of JobManager.cs
serviceInstaller.ServiceName = "VIAVista";
serviceInstaller.DisplayName = "VIAVista";
serviceInstaller.StartType = ServiceStartMode.Automatic;
// EventLog
eventLogInstaller.Source = "VIAVista";
eventLogInstaller.Log = "VIAVista";
// Dependency SQL Server service (i.e.SQL Server must run)
serviceInstaller.ServicesDependedOn = new string[] { "MSSQL$SQLEXPRESS" };
this.Installers.Add(serviceProcessInstaller);
this.Installers.Add(serviceInstaller);
this.Installers.Add(eventLogInstaller);
}
}
As you can see I want my event's source and log to be named "VIAVista".
When I try to install the service on my server (Windows Web Server 2008 R2 64bit) I'm told that the event source already exists in log "Application". That's weird since I thought this.Installers.Clear() would prevent creating a default source/log.
Info: I used regedit to make sure that there is no "VIAVista" key before installing the service.
Any ideas? Did I miss anything?

Try
serviceInstaller.Installers.Clear();

Do this:
if (!EventLog.SourceExists(source))
EventLog.CreateEventSource(source, log);
EventLog.WriteEntry(source, message, type, eventid);
If the source exists it will be used, otherwise it will be created.

Related

Quartz.net as service can't configure the quartz_job.xml

When using
var properties = new NameValueCollection();
properties["quartz.plugin.triggHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin";
properties["quartz.plugin.jobInitializer.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin";
properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";
properties["quartz.plugin.jobInitializer.failOnFileNotFound"] = "true";
properties["quartz.plugin.jobInitializer.scanInterval"] = "120";
// First we must get a reference to a scheduler
_schedulerFactory = new StdSchedulerFactory(properties);
_scheduler = _schedulerFactory.GetScheduler();
The windows service / quartz cannot resolve the path of quartz_jobs.xml.
If i run this as console it works fine.
public static void StartJobs()
{
try
{
_logger = LogManager.GetCurrentClassLogger();
var properties = new NameValueCollection();
properties["quartz.plugin.triggHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin";
properties["quartz.plugin.jobInitializer.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin";
properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";
properties["quartz.plugin.jobInitializer.failOnFileNotFound"] = "true";
properties["quartz.plugin.jobInitializer.scanInterval"] = "120";
// First we must get a reference to a scheduler
_schedulerFactory = new StdSchedulerFactory(properties);
_scheduler = _schedulerFactory.GetScheduler();
// start the schedule
_scheduler.Start();
}
catch (Exception ex)
{
_logger.Error(ex);
throw new Exception(ex.Message);
}
}
If it's still not working, include the file as an embedded resource in the project, set the action to Copy always, to be sure. Then provide the full file path to the quartz property:
Path.Combine(Path.GetDirectoryName(Assembly.GetEntryAssembly().Location), "quartz_jobs.xml")
I know this thread is from 2015, but i can't find any information regarding using quartz.net in a windows service. In my case, I am using .Net Core 2.1 Generic Host as a windows service with the quartz_jobs.xml which is referenced in my appsettings.json file. When the windows service starts up an looks for the quartz_job.xml it tries to find it in c:\windows\system32. But my quartz_job.xml is located where my executable is located. I tracked down Method ResolveFile in Quaztz\Util\FileUtil.cs of their repo where is says to put a "~" to for relative file. So I changed my appsettings.json to
"plugin": {
"jobInitializer": {
"type": "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins",
"fileNames": "~\\quartz_jobs.xml"
}
and now the windows service is able to read the quartz_jobs.xml. I would expect the if you change
properties["quartz.plugin.jobInitializer.fileNames"] = "quartz_jobs.xml";
to
properties["quartz.plugin.jobInitializer.fileNames"] = "~\\quartz_jobs.xml";
it should also work.

How could I make my RavenDB application execute properly when UseEmbeddedHttpServer is set to true using 2-tier architecture?

I used RavenDB-Embedded 2.0.2230 in my application interacted with ASP .Net Web API in different assemblies.
When I set UseEmbeddedHttpServer = true on the document store, first time I send a request to RavenDB, it executes properly but when I try for the second time my application displays Raven Studio.
When I remove UseEmbeddedServer setting, my application runs without any problems.
My RavenDB is configured with the following codes in data tier :
this.documentStore = new EmbeddableDocumentStore
{
ConnectionStringName = "RavenDB",
UseEmbeddedHttpServer = true
}.Initialize();
and implementation of Web.config have these settings in the service tier :
<connectionStrings>
<add name="RavenDB" connectionString="DataDir=~\App_Data\RavenDatabase" />
</connectionStrings>
Is there a setting I missed?
Is there any settings I need to apply to point Raven Studio to a different port?
The only way I could reproduce the experience you describe is by intentionally creating a port conflict. By default, RavenDB's web server hosts on port 8080, so if you are not changing raven's port, then you must be hosting your WebApi application on port 8080. If this is not the case, please let me know in comments, but I will assume that it is so.
All you need to do to change the port Raven uses is to modify the port value before calling Initialize method.
Add this RavenConfig.cs file to your App_Startup folder:
using Raven.Client;
using Raven.Client.Embedded;
namespace <YourNamespace>
{
public static class RavenConfig
{
public static IDocumentStore DocumentStore { get; private set; }
public static void Register()
{
var store = new EmbeddableDocumentStore
{
UseEmbeddedHttpServer = true,
DataDirectory = #"~\App_Data\RavenDatabase",
// or from connection string if you wish
};
// set whatever port you want raven to use
store.Configuration.Port = 8079;
store.Initialize();
this.DocumentStore = store;
}
public static void Cleanup()
{
if (DocumentStore == null)
return;
DocumentStore.Dispose();
DocumentStore = null;
}
}
}
Then in your Global.asax.cs file, do the following:
protected void Application_Start()
{
// with your other startup registrations
RavenConfig.Register();
}
protected void Application_End()
{
// for a clean shutdown
RavenConfig.Cleanup();
}
When you enable the HttpServer in an EmbeddableDocumentStore ravenDB "hijacks" the webapplication and starts listening on the same port that the application is running.
Oren Eini:
When you use UseEmbeddedHttpServer from inside IIS, it takes the port
from IIS. You need to set the value again
on https://groups.google.com/forum/?fromgroups=#!topic/ravendb/kYVglEoMncw
The only way to prevent it is either turn-ff the raven http-server or assign it to a different port
int ravenPort = 8181;
NonAdminHttp.EnsureCanListenToWhenInNonAdminContext(ravenPort);
var ds = new EmbeddableDocumentStore {
DataDirectory = [DataFolder],
UseEmbeddedHttpServer = true,
Configuration = {Port = ravenPort}
};

How to make Installer using WCF

I have one console application.The application calls WCF on server.
The application runs perfectly in Visual Studio 2008.
error:
I used an installer project in Visual Studio.
I make an installer give primary output to the Application.
It cannot connect to WCF on server.
What steps are necessary to make an installer which has an console (Application)exe,
which in turn uses WCF.
My Scope Initialization starts from initScopeInfo.
private void initScopeInfo()
{
DBSyncProxy.SqlSyncProviderProxy client = null;
ScopeConfigHandler scopeHandler = null;
try
{
//Providing the Config file name('db_config_new.xml') stored in static variable.
DBSyncXMLUtil.setXPathDocument(DBSyncConstants.DB_SYNC_CONFIG_FILE_NAME);
//DBSyncXMLUtil.setXPathDocument(filepath);
string endpoint = DBSyncXMLUtil.getSystemParameter(DBSyncXMLUtil.getDocumnetRoot(), "ServiceURL");
In setXpathDocument
public static void setXPathDocument(string uri)
{
public static XPathDocument doc = null;
doc = new XPathDocument(uri);
}
public static string getSystemParameter(XPathNavigator docroot, string key)
{
string value = null;
try
{
string xpath = DBSyncConstants.XPATH_SYSTEM_PARAMETER;
xpath += "[#key='" + key + "']";
Console.WriteLine("DBSyncXMLUtil :: getParameter() :: XPATH =="+xpath);
Probably Error on below mentioned line
XPathNavigator node = getDocumnetRoot(doc).SelectSingleNode(xpath);
if (node != null)
value = node.Value;
else
Console.WriteLine("Invalid XPATH");
}
catch (Exception ex)
{
Console.WriteLine("DBSyncXMLUtil :: getSystemParameter() :: Exception ==" + ex.ToString());
}
return value;
}
Actually you cannot directly create an installer project by adding primary output from a WCF service. You should host the WCF service inside a windows service and add the primary output of the windows service to the installer project.
create a WCF.
create a windows service and host the WCF inside it (call the WCF from windows service).
Create a setup project (installer project).
Add the primary output of the windows service to the installer project.
see this link to see the hosting details...
http://msdn.microsoft.com/en-us/library/ms733069.aspx
See this blog. It will help you with the implementation of windows service...
http://joefreeman.co.uk/blog/2010/03/creating-a-setup-project-for-a-windows-wcf-service-with-visual-studio/

Multiple services in one assembly. How installer knows which service to install and start?

I have a project which includes 2 windows services. I create a ProjectInstaller to install these items, which works fine. But I have a question; given the code defined below, how does the project installer know which service to install for serviceInstaller1 and which for serviceInstaller2?
Is it simply based upon the ServiceName?
[RunInstaller(true)]
public partial class ProjectInstaller : System.Configuration.Install.Installer
{
private ServiceProcessInstaller process;
private ServiceInstaller serviceInstaller1;
private ServiceInstaller serviceInstaller2;
public ProjectInstaller()
{
InitializeComponent();
try
{
process = new ServiceProcessInstaller();
process.Account = ServiceAccount.LocalSystem;
serviceInstaller1 = new ServiceInstaller();
serviceInstaller1.ServiceName = "xxx";
serviceInstaller1.Description = "Does Something";
serviceInstaller1.StartType = ServiceStartMode.Automatic;
serviceInstaller2 = new ServiceInstaller();
serviceInstaller2.ServiceName = "yyy";
serviceInstaller2.Description = "Does something else";
serviceInstaller2.StartType = ServiceStartMode.Automatic;
Installers.Add(process);
Installers.Add(serviceInstaller1);
Installers.Add(serviceInstaller2);
}
catch (Exception ex)
{
throw new Exception("Failed", ex);
}
}
}
It is based on ServiceName.
Installer doesn't really care about the name, you can supply pretty much any name and installer will be happy to register a Windows service with this name for you, but when you attempt to start service it will fail, unless it finds service in your assembly that has ServiceName matching to the ServiceName specified in the installer.
Error 1083: The executable program that this service is configured to run in does not implement the service.

When programmatically creating a new IIS web site, how can I add it to an existing application pool?

I have successfully automated the process of creating a new IIS website, however the code I've written doesn't care about application pools, it just gets added to DefaultAppPool. However I'd like to add this newly created site to an existing application pool.
Here is the code I'm using to create the new website.
var w3Svc = new DirectoryEntry(string.Format("IIS://{0}/w3svc", webserver));
var newsite = new object[] { serverComment, new object[] { serverBindings }, homeDirectory };
var websiteId = w3Svc.Invoke("CreateNewSite", newsite);
site.Invoke("Start", null);
site.CommitChanges();
<update>
Although this is not directly related to the question, here are some sample values being used above. This might help someone understand exactly what the code above is doing more easily.
webServer: "localhost"
serverComment: "testing.dev"
serverBindings: ":80:testing.dev"
homeDirectory: "c:\inetpub\wwwroot\testing\"
</update>
If I know the name of the application pool that I'd like this web site to be in, how can I find it and add this site to it?
You have to assign the AppPool on the virtual dir (not the webserver) and set the AppIsolated property to 2 which mean pooled-process ;)
http://msdn.microsoft.com/en-us/library/ms525598%28v=VS.90%29.aspx
Relevant code sample from link:
static void AssignVDirToAppPool(string metabasePath, string appPoolName)
{
// metabasePath is of the form "IIS://<servername>/W3SVC/<siteID>/Root[/<vDir>]"
// for example "IIS://localhost/W3SVC/1/Root/MyVDir"
// appPoolName is of the form "<name>", for example, "MyAppPool"
Console.WriteLine("\nAssigning application {0} to the application pool named {1}:", metabasePath, appPoolName);
try
{
DirectoryEntry vDir = new DirectoryEntry(metabasePath);
string className = vDir.SchemaClassName.ToString();
if (className.EndsWith("VirtualDir"))
{
object[] param = { 0, appPoolName, true };
vDir.Invoke("AppCreate3", param);
vDir.Properties["AppIsolated"][0] = "2";
Console.WriteLine(" Done.");
}
else
Console.WriteLine(" Failed in AssignVDirToAppPool; only virtual directories can be assigned to application pools");
}
catch (Exception ex)
{
Console.WriteLine("Failed in AssignVDirToAppPool with the following exception: \n{0}", ex.Message);
}
}
Note that if you are not explicitly adding a new virtual directory to the application, the metabasePath will simply be "IIS://<servername>/W3SVC/<siteID>/Root"
You need to get the AppPoolfrom IIS://{0}/W3SVC/AppPools, and attach it to the site's AppPoolId. Something like:
var appPool = new DirectoryEntry(
string.Format("IIS://{0}/W3SVC/AppPools/{1}", webServer, appPoolName)
);
site.Properties["AppPoolId"].Value = appPool;
site.Properties["AppPoolId"][0]= "poolname";

Categories