I try to start my own Windows service on C# based.
I try to run with sc.exe create Service.exe but when I want to run this service I have bugs #1026 (Description: The process was terminated due to an unhandled exception.) and #1000. (Faulting application name: Timesync.exe, version: 1.0.0.0, time stamp: 0xf1683f8e
Faulting module name: KERNELBASE.dll, version: 10.0.22621.674, time stamp: 0x160a2aa8) Now I try to this service with InstallUtil.exe but we I can't. Because I have this error: Exception occurred while initializing the installation:
System.BadImageFormatException: Could not load file or assembly 'file:Service.exe' or one of its dependencies. The module was expected to contain an assembly manifest..
Here is my code:
Timer Schedular;
public Service1()
{
InitializeComponent();
if (!EventLog.SourceExists("Timesync"))
EventLog.CreateEventSource("Timesync", "TimesyncLog");
eventLog1.Source = "Timesync";
eventLog1.Log = "TimesyncLog";
}
protected override async void OnStart(string[] args)
{
System.Diagnostics.Debugger.Launch();
eventLog1.WriteEntry("Timesync was started", EventLogEntryType.Information);
await this.ScheduleService();
}
public void onDebug()
{
OnStart(null);
}
private async void SchedularCallback(object e)
{
await this.ScheduleService();
}
private async Task ScheduleService()
{
try
{
}
catch (Exception ex)
{
eventLog1.WriteEntry("Timesync was be here on catch state", EventLogEntryType.Information);
//Stop the Windows Service.
using (ServiceController serviceController = new ServiceController("Timesync"))
{
serviceController.Stop();
}
}
}
Program.cs
internal class Program
{
static void Main(string[] args)
{
//In Release this section is used. This is the "normal" way.
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
Console.WriteLine("The application was be here");
}
}
I can't understand how to resolve my bug and how to run this service.
If it possible, please help. :)
Any chance you are trying to use 32bit library in x64 solution or vice versa. I usually get badimageformat when I don't set Platform target in project build settings.
So if left on Any CPU and the system is x64, and if I use some dependent library which is 32bit. Service will try to run as x64 but fails because of this 32 library. So in our case solution is to set Platform target to x86.
Related
I have a basic service that will be used to run a ClickOnce application every x minutes, however when i run Process.Start() i am receiving an exception that the file cannot be found.
Code
private void OnElapsedTime(object source, ElapsedEventArgs e)
{
WriteToFile("Timer ticked");
CheckProcess(GetProcessName());
}
public void CheckProcess(string ProcessName)
{
WriteToFile(ProcessName);
try
{
Process.Start(ProcessName);
WriteToFile("It ran");
}
catch (Exception ex)
{
WriteToFile(ex.ToString());
}
}
public string GetProcessName()
{
string ProcessName = string.Concat("%AppData%\\Microsoft\\Windows\\Start Menu\\Programs\\", PublisherName, "\\", ProductName, ".appref-ms");
return ProcessName;
}
The error i receive is:
%AppData%\Microsoft\Windows\Start Menu\Programs\PubName\ProdName.appref-ms
System.ComponentModel.Win32Exception (0x80004005): The system cannot find the file specified
at System.Diagnostics.Process.StartWithShellExecuteEx(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start()
at System.Diagnostics.Process.Start(ProcessStartInfo startInfo)
at System.Diagnostics.Process.Start(String fileName)
If i run the ProcessName retrieved in explorer then the application launches successfully. Value of ProcessName is :
C:\Users\xxx\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\PubName\ProdName.appref-ms
Is there something i am missing in order to start the file?
Windows Services are the programs which will runs even before a user logged into it's Account. This is Windows Service purpose, and by this definition you haven't access to specific User Environment Variables (Like %AppData%) because you aren't in the User Session so your address will be translated to something Odd if you write it into a .txt you will see the result.
Windows Services (By your definitions) will run by LocalSystem, LocalService or NetworkService. Go to TaskManager->Services->Open Services and watch Log On As Column.
So you must use a general path which be access-able through your service.
Most terrifying solution is to force your Service to wait for a user login and impersonate his token.
I will Prefer to choose a better place.
There is a way to debug and see your Service bugs (In UserSession) in VisualStudio.
Change your Program.cs to something like:
static void Main()
{
#if DEBUG
var MainService = new MainService();
MainService.OnDebug();
#else
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MainService()
};
ServiceBase.Run(ServicesToRun);
#endif
}
and Add OnDebug function to your Service:
public void OnDebug()
{
OnStart(null);
}
if you debug your project in this way you will see that your service is working As Expected !!!
The application exits with:
The program '[12868] AppName.vshost.exe' has exited with code 1073741855 (0x4000001f).
Below Code:
Call Export() twice after each other: crash with above logging
Call the contents of Export() inside Export() twice (the inner scope), and it doesn't crash.
This is reproducible, I have no idea where to start.
private void btnExport_Click(object sender, RoutedEventArgs e)
{
Enable(false);
statusbar.Message = "Exporting...";
Task t = new Task(Export);
t.ContinueWith(ExportEnd);
t.Start();
}
private void Export()
{
{
PBNSectionDictionary source = ctrlSectionSelection.SectionSelection.SelectSections;
PBNSectionDictionary dict = new PBNSectionDictionary();
foreach (string sectionType in source.Keys)
{
if (source[sectionType] != null)
{
dict[sectionType] = collector.ReadFullSection(source[sectionType]);
}
}
PBNFMV.Export.PBNExport export = new PBNFMV.Export.PBNExport(new Lms.Custom.Files.AdvancedFileLocator(Constants.NAME), dict, manager);
export.Export();
dict.Dispose();
}
}
private void ExportEnd(Task t)
{
Enable(true);
statusbar.Message = "Export done";
}
Event log:
Faulting application name: PBNFMV.exe, version: 16.2.0.0, time stamp: 0x58aeadf2
Faulting module name: ntdll.dll, version: 6.1.7601.23569, time stamp: 0x57f7bb79
Exception code: 0xc0000374
Fault offset: 0x000ce8fb
Faulting process id: 0xbd4
Faulting application start time: 0x01d28db92a6d6c1e
Faulting application path: C:\APPPATH\source\PBNFMV\bin\Debug\PBNFMV.exe
Faulting module path: C:\windows\SysWOW64\ntdll.dll
Report Id: 72f988f9-f9ac-11e6-8d91-000acd1f71fd
Exception settings completely enabled:
C++ exceptions
common language runtime exceptions
gpu memory access exceptions
managed debugging assitants
win32 exceptions
The issue is solved.
Hence: very strange.
It was due to construction of an object further (!) in code execution, which made things crash (because of a bad implementation in a library).
The strange part is why that object was already instantiated, i believe some optimalisation in the .net runtime.
Apologies
When running locally in the emulator the web worker works fine. However whenever I update my web worker running on an Azure VM I get the following exceptions exceptions in the event viewer and the role won't start:
Application: WaWorkerHost.exe
Framework Version: v4.0.30319
Description: The process was terminated due to an unhandled exception.
Exception Info: System.AggregateException
Stack:
at System.Threading.Tasks.Task.Wait(Int32, System.Threading.CancellationToken)
at System.Threading.Tasks.Task.Wait()
at Foo.PushProcess.WorkerRole.Run()
at Microsoft.WindowsAzure.ServiceRuntime.RoleEnvironment.StartRoleInternal()
at Microsoft.WindowsAzure.ServiceRuntime.Implementation.Loader.RoleRuntimeBridge.b__2()
at System.Threading.ExecutionContext.RunInternal(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object, Boolean)
at System.Threading.ExecutionContext.Run(System.Threading.ExecutionContext, System.Threading.ContextCallback, System.Object)
at System.Threading.ThreadHelper.ThreadStart()
Inner Exception: A task was canceled.
Faulting application name: WaWorkerHost.exe, version: 2.6.1198.712, time stamp: 0x54eba731
Faulting module name: KERNELBASE.dll, version: 6.3.9600.17415, time stamp: 0x54505737
Exception code: 0xe0434352
Fault offset: 0x0000000000008b9c
Faulting process id: 0xfb8
Faulting application start time: 0x01d11e3128981a5d
Faulting application path: E:\base\x64\WaWorkerHost.exe
Faulting module path: D:\Windows\system32\KERNELBASE.dll
Report Id: 30631c5c-8a25-11e5-80c6-000d3a22f3ec
Faulting package full name:
Faulting package-relative application ID:
Session "MA_ETWSESSION_WAD_415df88f8a0447178dbd4c18f1349f0e_Foo.PushProcess_Foo.PushProcess_IN_0" failed to start with the following error: 0xC0000035
This is the relevant code:
public override void Run()
{
Trace.TraceInformation("Foo.PushProcess is running");
try
{
RunAsync(_cancellationTokenSource.Token).Wait(); // This is where the exceptions point to
}
catch (Exception ex)
{
Trace.TraceError("[WORKER] Run error: " + ex);
}
finally
{
_runCompleteEvent.Set();
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
bool result = base.OnStart();
_storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
var queueClient = _storageAccount.CreateCloudQueueClient();
_pushQueue = queueClient.GetQueueReference("pushes");
_pushQueue.CreateIfNotExists();
CreatePushBroker();
Trace.TraceInformation("Foo.PushProcess has been started");
return result;
}
private async Task RunAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Trace.TraceInformation("Working");
CloudQueueMessage message = null;
try
{
message = _pushQueue.GetMessage();
if (message != null)
{
ProcessItem(message);
}
}
catch (Exception ex)
{
if (message != null && message.DequeueCount > 5)
_pushQueue.DeleteMessage(message);
Trace.TraceError("[WORKER] Retrieval Failure: " + ex);
}
await Task.Delay(1000, cancellationToken);
}
}
Note some code has been omitted, however that is all run after the initialisation and in theory isn't reached by this exception.
I am completely at a loss as to what could cause this issue. Any help would be appreciated - even if only to aid me getting a helpful exception.
UPDATE
I have now reduced my code to the below - it is as simple as a web worker can possibly be - and I am still getting the exceptions. I believe that either the old worker is being cached, or there is an issue in the deployment procedure.
public override void Run()
{
Trace.TraceInformation("Foo.PushProcess is running");
try
{
RunAsync(_cancellationTokenSource.Token).Wait(); // This is where the exceptions point to
}
catch (Exception ex)
{
Trace.TraceError("[WORKER] Run error: " + ex);
}
finally
{
_runCompleteEvent.Set();
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
bool result = base.OnStart();
return result;
}
private async Task RunAsync(CancellationToken cancellationToken)
{
while (!cancellationToken.IsCancellationRequested)
{
Trace.TraceInformation("Working");
// code removed for testing - no work is being done.
await Task.Delay(1000, cancellationToken);
}
}
I gave this a whirl and wasn't able to get this to repro on my end. I have VS 2015 Enterprise (14.0.23107.0 D14REL) from a MSDN Azure image I deployed running with .Net Fx version 4.6. I have Azure Tools and SDK 2.8 installed. I created a new Azure Cloud Service using .NET Fx 4.5.2 and I add a single worker role.
I just ran some sparse code template from yours as follows:
public class WorkerRole : RoleEntryPoint
{
private readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
private readonly ManualResetEvent runCompleteEvent = new ManualResetEvent(false);
private CloudQueue _pushQueue;
private CloudStorageAccount _storageAccount;
public override void Run()
{
Trace.TraceInformation("WorkerRole1 is running");
try
{
this.RunAsync(this.cancellationTokenSource.Token).Wait();
}
catch (Exception ex)
{
Trace.TraceError("[WORKER] Run error: " + ex);
}
finally
{
this.runCompleteEvent.Set();
}
}
public override bool OnStart()
{
// Set the maximum number of concurrent connections
ServicePointManager.DefaultConnectionLimit = 12;
// For information on handling configuration changes
// see the MSDN topic at http://go.microsoft.com/fwlink/?LinkId=166357.
bool result = base.OnStart();
_storageAccount = CloudStorageAccount.Parse(RoleEnvironment.GetConfigurationSettingValue("StorageConnectionString"));
var queueClient = _storageAccount.CreateCloudQueueClient();
_pushQueue = queueClient.GetQueueReference("pushes");
_pushQueue.CreateIfNotExists();
CreatePushBroker();
Trace.TraceInformation("Foo.PushProcess has been started");
return result;
}
private void CreatePushBroker()
{
return;
}
public override void OnStop()
{
Trace.TraceInformation("WorkerRole1 is stopping");
this.cancellationTokenSource.Cancel();
this.runCompleteEvent.WaitOne();
base.OnStop();
Trace.TraceInformation("WorkerRole1 has stopped");
}
private async Task RunAsync(CancellationToken cancellationToken)
{
// TODO: Replace the following with your own logic.
while (!cancellationToken.IsCancellationRequested)
{
Trace.TraceInformation("Working");
CloudQueueMessage message = null;
try
{
message = _pushQueue.GetMessage();
if (message != null)
{
ProcessItem(message);
}
}
catch (Exception ex)
{
if (message != null && message.DequeueCount > 5)
_pushQueue.DeleteMessage(message);
Trace.TraceError("[WORKER] Retrieval Failure: " + ex);
}
await Task.Delay(1000, cancellationToken);
}
}
private void ProcessItem(CloudQueueMessage message)
{
return;
}
}
}
That runs without issue in the local emulator, and I went ahead and deployed it to West US with IntelliTrace enabled, on a small instance VM, and had n deployment issues. It is running on a WA-GUEST-OS-4.26_201511-0 guest worker role image, and I was able to RDP into the machine, and I didn't see any issues related to the code or the machine. DO you have any other binaries you might not be including in your packages, or perhaps there are some dependencies not defined properly, or storage account naming issues?
Here was the deployment log for me. As you can see, it took about 7 minutes as I had it pull storage from East US just for fun:
1:11:25 AM - Warning: There are package validation warnings.
1:11:26 AM - Checking for Remote Desktop certificate...
1:11:26 AM - Uploading Certificates...
1:11:42 AM - Applying Diagnostics extension.
1:12:24 AM - Preparing deployment for AzureCloudService1 - 11/24/2015 1:11:19 AM with Subscription ID '9a4715f5-acb8-4a18-8259-1c28b92XXXXX' using Service Management URL 'https://management.core.windows.net/'...
1:12:24 AM - Connecting...
1:12:24 AM - Verifying storage account 'ericgoleastus'...
1:12:24 AM - Uploading Package...
1:12:28 AM - Creating...
1:13:15 AM - Created Deployment ID: c5f26568707b46a3bd42466dd0bf7509.
1:13:15 AM - Instance 0 of role WorkerRole1 is creating the virtual machine
1:13:15 AM - Starting...
1:13:32 AM - Initializing...
1:14:36 AM - Instance 0 of role WorkerRole1 is starting the virtual machine
1:16:11 AM - Instance 0 of role WorkerRole1 is in an unknown state
1:16:43 AM - Instance 0 of role WorkerRole1 is busy
Details: Starting role... System is initializing. [2015-11-24T01:16:08Z]
1:19:50 AM - Instance 0 of role WorkerRole1 is ready
1:19:50 AM - Created web app URL: http://quequetest.cloudapp.net/
1:19:50 AM - Complete.
Let us know if you can get some more details possibly with IntelliTrace enabled.
Regards,
Eric
To fix this issue I simply deleted the original Cloud VM instance which held the worker role, recreated it and re-published the role. From that point it has worked absolutely fine.
I am still unable to determine what caused the error, and have had no further issues like this with any other worker role. My assumption here was that there was a configuration issue with the VM which could not be amended through code or the Azure portal.
I have developed a custom library that I use in some projects.
Nowadays I'm implementing the error capture in my application. One of them considers the possibility that the machine where I try to execute my application doesn't have my libraries.
So what I made to check if the library was installed or not, was try to use it surrounded with a try-catch clause like this:
try
{
MyLibrary library = new MyLibrary();
}
catch (Exception e)
{
MessageBox.Show("Your library is not installed");
Close();
}
This code should show a message when the library is not found, and then close my application. But the message is never shown.
Any idea on how to check if my library is not located in my machine?
With your current try-catch you can not catch that kind of exception because there are not related to your code. The Runtime will try to load the assembly, if it cannot be found, the AssemblyResolve event is raised.
class Test
{
public static void Main()
{
AppDomain currentDomain = AppDomain.CurrentDomain;
currentDomain.AssemblyResolve += MyResolveEventHandler;
}
private static Assembly MyResolveEventHandler(object sender, ResolveEventArgs args)
{
Console.WriteLine("Try resolving: " + args.Name);
return null;
}
}
I am making a Windows Service and I want to debug it.
This is the error I get when I try to debug it:
Cannot start service from the command line or a debugger. A Windows service must be first installed and then started with the Server Explorer, Windows Services Administrative TOll or the NET start command.
I have already installed my service using InstallUtil, but I am still facing problems.
Also, when I try to attach a process, my service goes into the running mode, it never starts debugging.
EDIT: DO we have to reinstall the Windows Service everytime we make a change or just building it would suffice?
In your OnStart use something like this:
#if DEBUG
if(!System.Diagnostics.Debugger.IsAttached)
System.Diagnostics.Debugger.Launch();
#endif
For the most use cases it's good enough to run the service as console application. To do this, I usually have the following startup code:
private static void Main(string[] args) {
if (Environment.UserInteractive) {
Console.WriteLine("My Service");
Console.WriteLine();
switch (args.FirstOrDefault()) {
case "/install":
ManagedInstallerClass.InstallHelper(new[] {Assembly.GetExecutingAssembly().Location});
break;
case "/uninstall":
ManagedInstallerClass.InstallHelper(new[] {"/u", Assembly.GetExecutingAssembly().Location});
break;
case "/interactive":
using (MyService service = new MyService(new ConsoleLogger())) {
service.Start(args.Skip(1));
Console.ReadLine();
service.Stop();
}
break;
default:
Console.WriteLine("Supported arguments:");
Console.WriteLine(" /install Install the service");
Console.WriteLine(" /uninstall Uninstall the service");
Console.WriteLine(" /interactive Run the service interactively (on the console)");
break;
}
} else {
ServiceBase.Run(new MyService());
}
}
This makes it easy not only to run and debug the service, but it can then also install and uninstall without needing the InstallUtil program.
This question has an excellent answer in making the service a console/service hybrid. See the answer from user marc_s. I don't want to duplicate the answer here.
I, personally for me, found the easiest solution is not change the code, by adding more mess and #if #else directives, but simply:
Compile your service binaries in DEBUG mode
Point installed service to DEBUG binaries
Run service
Use connect to process dialog of VS to connect to your running process
Enjoy.
The good thing on this that you don't change the code so it's exactly the same as your production binaries, which, I think, is kind of important.
Good luck.
One way that I've done it before was to insert a Debugger.Break() in the service on start method. Compile and install the service. When it starts it break and open the debug with dialog, from there you should be able to attach and debug.
The Debugger.Launch method is a good way but I prefer to create a class that does the processing and call it from the service, This can then also be called from a win forms app.
eg:
class ProcessingManager
{
public void Start()
{
//do processing
}
public void Stop()
{
//stop
}
}
then in your service / win forms app just create an instance of the processing class as a member variable and call the method on start and stop. It can be used in the service, or a win forms app with a start and stop button, which I find a lot quicker than attaching the debugger each time because you can set the windows application to start as default and add any breakpoints into the processing manager.
extract from service code:
namespace Service
{
public partial class Service : ServiceBase
{
#region Members
private ProcessingManager m_ProcessingManager = null;
#endregion Members
#region Constructor
/// <summary>
/// Constructor
/// </summary>
public Service()
{
InitializeComponent();
try
{
//Instantiate the processing manager
m_ProcessingManager = new ProcessingManager();
}
catch (Exception ex)
{
ErrorHandler.LogError(ex);
}
}
#endregion Constructor
#region Events
/// <summary>
/// Starts the processing
/// </summary>
/// <param name="args">Parameters</param>
protected override void OnStart(string[] args)
{
try
{
//Start the Processing
m_ProcessingManager.Start();
}
catch (Exception ex)
{
ErrorHandler.LogError(ex);
}
}
/// <summary>
/// Service Stopped
/// </summary>
protected override void OnStop()
{
try
{
//Stop Processing
m_ProcessingManager.Stop();
}
catch (Exception ex)
{
ErrorHandler.LogError(ex);
}
}
#endregion Events
}
}
Try following this guide
EDIT: Personally, I have a console application in the same project that does all the work. I then just have the service run the Main of the console application. It makes debugging easy especially when just developing.
For debugging or testing your service without installing it, make changes in Program.cs like this.
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
}
}
Change it to:
static class Program
{
static void Main()
{
#if(!DEBUG)
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new MyService()
};
ServiceBase.Run(ServicesToRun);
#else
MyService myServ = new MyService();
myServ.Process();
// here Process is my Service function
// that will run when my service onstart is call
// you need to call your own method or function name here instead of Process();
#endif
}
}
What i always do is put a:
#if DEBUG
Thread.Sleep(20000)
#endif
in the OnStart. That gives me 20s to attach.
Quick and easy, just remember to wrap it in an #if DEBUG #endif :)