We have some UI integration tests that can't be run on the build server as launching test GUI app requires running the build agent as an user (instead of a service which is how it's currently setup).
This causes the build pipeline to get stuck. So I'd like to run these tests locally but not on the build server.
Is there a way to achieve this using xUnit or MSTests and Azure DevOps build pipeline?
You sure can.
Setup an Environment variable to indicate if it's running on the build server in your build.yml file.
variables:
- name: IsRunningOnBuildServer
value: true
Answer 1: Using xUnit
Now create a custom fact attribute to use this:
// This is taken from this SO answer: https://stackoverflow.com/a/4421941/8644294
public class IgnoreOnBuildServerFactAttribute : FactAttribute
{
public IgnoreOnBuildServerFactAttribute()
{
if (IsRunningOnBuildServer())
{
Skip = "This integration test is skipped running in the build server as it involves launching an UI which requires build agents to be run as non-service. Run it locally!";
}
}
/// <summary>
/// Determine if the test is running on build server
/// </summary>
/// <returns>True if being executed in Build server, false otherwise.</returns>
public static bool IsRunningOnBuildServer()
{
return bool.TryParse(Environment.GetEnvironmentVariable("IsRunningOnBuildServer"), out var buildServerFlag) ? buildServerFlag : false;
}
}
Now use this FactAttribute on your test methods that you want to skip running on build server. For eg:
[IgnoreOnBuildServerFact]
public async Task Can_Identify_Some_Behavior_Async()
{
// Your test code...
}
Answer 2: Using MSTests
Create a custom test method attribute to override the Execute method:
public class SkipTestOnBuildServerAttribute : TestMethodAttribute
{
public override TestResult[] Execute(ITestMethod testMethod)
{
if (!IsRunningOnBuildServer())
{
return base.Execute(testMethod);
}
else
{
return new TestResult[] { new TestResult { Outcome = UnitTestOutcome.Inconclusive } };
}
}
public static bool IsRunningOnBuildServer()
{
return bool.TryParse(Environment.GetEnvironmentVariable("IsRunningOnBuildServer"), out var buildServerFlag) ? buildServerFlag : false;
}
}
Now use this TestMethodAttribute on your test methods that you want to skip running on build server. For eg:
[SkipTestOnBuildServer]
public async Task Can_Identify_Some_Behavior_Async()
{
// Your test code...
}
You can filter out tests based on namespace etc.
dotnet test --filter FullyQualifiedName!~IntegrationTests
This will run all tests NOT containing "IntetegrationTests" in it's namespace.
You can read more about test filtering here: https://learn.microsoft.com/en-us/dotnet/core/testing/selective-unit-tests
We have a service that needs to kill itself (reason: we use a third party lib, that has unpredictable behavior in shutdown scenarios ...). Sometimes the service is not restarted by the Windows Service Control manager. The service recovery actions, in the SCM, are set to "Restart the Service" (for the first, the second and subsequent failures).
That's the way we kill our service:
public static void TerminateProcess(string message)
{
Log.ErrorFormat("Terminating Process becauses of: {0}", message);
Process.GetCurrentProcess().Kill();
}
Does anybody knows if this Process.GetCurrentProcess().Kill(); is a good way to kill the service?
I also read some threads, where the following combination was suggested:
class MyService : ServiceBase
{
void KillMe()
{
this.ExitCode = 1; // ServiceBase.ExitCode
System.Environment.Exit(1);
}
}
I also found this stackoverflow thread, but it doesn't state anything about service recovery.
What's the preferred/safe way to kill a service, so that the SCM will restart it?
Thx
Make a singleton instance of your service. And then you you can stop your service using stop() method.
public partial class ABCService : ServiceBase
{
public static ABCService ServiceInstance;
private void InitService()
{
ServiceInstance = this;
}
}
public static void StopService()
{
if(ABCService.ServiceInstance != null)
{
ABCService.ServiceInstance.Stop();
}
}
And you don't want the to restart automatically
public static void ChangeServiceMode(bool serviceAutoEnable)
{
RegistryKey key = Registry.LocalMachine.OpenSubKey("SYSTEM\\CurrentControlSet\\Services\\NixService", true);
if (key != null)
{
//Set service to manual / Automatic (Automatic = 2, manual = 3)
int serviceMode = serviceAutoEnable ? 2 : 3;
key.SetValue("Start", serviceMode, RegistryValueKind.DWord);
key.Close();
}
}
}
I think that it is necessary to understand: in what cases it is necessary to disable the service.
The first method you describe allows you to kill a service from a third-party code base. And the second option is in the service itself, but I think that the last option is not realizable, because the question arises: what circumstances should there be for the service to kill itself ???
IMHO the first option is more practical.
Hi what is the best way to deploy database script to my client pc? i have installed the app and have the sql management studio installed at my client pc. Everything went smooth except when i need to update the database. How do i update the database without having me to go to their pc to run the .sql update script. This question applies when my app is used at other country.
For updating code is fine as i am using the ClickOnce.
This is a window based app.
Please help
I would ship the SQL file with your application, and have application startup logic that always checks a certain location for scripts that need to be run. It could be as simple as checking a [application path]\MigrationScripts folder for all .sql files. If files are found, read in the contents and execute against the database.
Once the check (and potential database updates) are complete, continue loading the application.
Sample Code (untested), and a very basic implementation:
public class Migration
{
private string _migrationPath = #"C:\temp\MigrationSteps"; //change
private string[] _sqlFiles = null;
public Migration()
{
Initialize();
}
public Migration(string path)
{
_migrationPath = path;
Initialize();
}
private void Initialize()
{
_sqlFiles = Directory.GetFiles(_migrationPath, "*.sql");
}
public bool Run()
{
bool success = true;
foreach (string sqlFile in _sqlFiles)
{
ExecuteRun(File.ReadAllText(sqlFile));
}
return success; //Do something with this value
}
public bool CleanUp()
{
//Put some logic here to "clean up" files that have already been run.
throw new NotImplementedException();
}
private bool ExecuteRun(string sqlText)
{
//Call your data access library and execute the sqlText
throw new NotImplementedException();
}
}
Usage:
Migration migration = new Migration();
if (migration.Run())
{
migration.CleanUp();
}
else
{
//Do something
}
I'll start by saying I'm not a .NET developer, but have been thrown into a project where I need to use MSMQ so a classic ASP web application can send messages to a C# Windows Service that handles the processing. I have experience integrating other message queues with other languages, but like I mentioned, I don't have much experience with .NET and Windows development so some guidance would be much appreciated.
Here are my questions...
Could someone provide some basic C# code that listens to an existing MSMQ queue and responds to the new message by doing something simple like writing the current timestamp to a log file or sending an email?
How do I package this code up in Visual Studio .NET to create and install a Windows Service? (What type of project should it be, etc. I'm using Visual C# 2010 Express.)
Finally, I'm not sure which version and/or implementation of MSMQ I need to be using for my requirements with classic ASP. I think the COM version is what I need, but I've also read about a new WCF version, as well as differences between 3.0 and 4.0. Could someone please give me direction on which version I should be using?
Many thanks!
You can wait for a message on a given queue using the following code (You want to use the private queue named SomeQueue on your computer, named ComputerName => QueueName = #"ComputerName\private$\SomeQueue")
public void AsyncWatchQueue(object encapsulatedQueueName)
{
Message newMessage;
MessageQueue queue;
string queueName = encapsulatedQueueName as string;
if (queueName == null)
return;
try
{
if (!MessageQueue.Exists(queueName))
MessageQueue.Create(queueName);
else
{
queue = new MessageQueue(queueName);
if (queue.CanRead)
newMessage = queue.Receive();
}
HandleNewMessage(newMessage); // Do something with the message
}
// This exception is raised when the Abort method
// (in the thread's instance) is called
catch (ThreadAbortException e)
{
//Do thread shutdown
}
finally
{
queue.Dispose();
}
}
Note: the Receove method will block untill a message is received at which point it'll remove the message from the queue and return it.
edit: added code for the implementation of the multithreaded portion (and renamed the above method signature)
Thread Creation Code:
public Thread AddWatchingThread(string QueueName)
{
Thread Watcher =
new Thread(new ParameterizedThreadStart(AsyncWatchQueue));
Watcher.Start(QueueName);
// The thread instance is used to manipulate (or shutdown the thread)
return Watcher;
}
I'll just note, that this is untested cod, it's just an quick example
As far as I know, Visual Studio Express does not have a project template for a service. That does not mean you cannot write a windows service with VSE, just that you will not have a template to get you started.
To create a service you can just create a normal Console application. Create the service class which will be responsible for the actual service implementation. It will look something like this
using System.ServiceProcess;
namespace WindowsService1
{
public partial class Service1 : ServiceBase
{
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
}
protected override void OnStop()
{
}
}
}
Then the Service startup code can go into the Main function of your service.
using System.ServiceProcess;
namespace WindowsService1
{
static class Program
{
static void Main()
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[]
{
new Service1()
};
ServiceBase.Run(ServicesToRun);
}
}
}
That should give you the basic framework for your service. The other thing you will need is to add an installer for the service so that it can be installed as a service. The following should get you started, note I have note tested this.
using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;
namespace WindowsService1
{
[RunInstaller(true)]
public class ProjectInstaller : Installer
{
private ServiceProcessInstaller serviceProcessInstaller1;
private ServiceInstaller serviceInstaller1;
public ProjectInstaller()
{
this.serviceProcessInstaller1 = new ServiceProcessInstaller();
this.serviceInstaller1 = new ServiceInstaller();
this.serviceProcessInstaller1.Password = null;
this.serviceProcessInstaller1.Username = null;
this.serviceInstaller1.ServiceName = "Service1";
this.Installers.AddRange(new System.Configuration.Install.Installer[] {
this.serviceProcessInstaller1,
this.serviceInstaller1});
}
}
}
Given the above, you should have enough to search around or ask for more details around the service creation. As for the MSMQ listener, you can use the following MSDN article as a starting point
http://msdn.microsoft.com/en-us/library/ms978425.aspx
I have a windows service written in C# that acts as a proxy for a bunch of network devices to the back end database. For testing and also to add a simulation layer to test the back end I would like to have a GUI for the test operator to be able run the simulation. Also for a striped down version to send out as a demo. The GUI and service do not have to run at the same time. What is the best way to achieve this duel operation?
Edit:
Here is my solution combing stuff from this question , Am I Running as a Service and Install a .NET windows service without InstallUtil.exe using this excellent code by Marc Gravell
It uses the following line to test if to run the gui or run as service.
if (arg_gui || Environment.UserInteractive || Debugger.IsAttached)
Here is the code.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using System.ComponentModel;
using System.ServiceProcess;
using System.Configuration.Install;
using System.Diagnostics;
namespace Form_Service
{
static class Program
{
///
/// The main entry point for the application.
///
[STAThread]
static int Main(string[] args)
{
bool arg_install = false;
bool arg_uninstall = false;
bool arg_gui = false;
bool rethrow = false;
try
{
foreach (string arg in args)
{
switch (arg)
{
case "-i":
case "-install":
arg_install = true; break;
case "-u":
case "-uninstall":
arg_uninstall = true; break;
case "-g":
case "-gui":
arg_gui = true; break;
default:
Console.Error.WriteLine("Argument not expected: " + arg);
break;
}
}
if (arg_uninstall)
{
Install(true, args);
}
if (arg_install)
{
Install(false, args);
}
if (!(arg_install || arg_uninstall))
{
if (arg_gui || Environment.UserInteractive || Debugger.IsAttached)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
else
{
rethrow = true; // so that windows sees error...
ServiceBase[] services = { new Service1() };
ServiceBase.Run(services);
rethrow = false;
}
}
return 0;
}
catch (Exception ex)
{
if (rethrow) throw;
Console.Error.WriteLine(ex.Message);
return -1;
}
}
static void Install(bool undo, string[] args)
{
try
{
Console.WriteLine(undo ? "uninstalling" : "installing");
using (AssemblyInstaller inst = new AssemblyInstaller(typeof(Program).Assembly, args))
{
IDictionary state = new Hashtable();
inst.UseNewContext = true;
try
{
if (undo)
{
inst.Uninstall(state);
}
else
{
inst.Install(state);
inst.Commit(state);
}
}
catch
{
try
{
inst.Rollback(state);
}
catch { }
throw;
}
}
}
catch (Exception ex)
{
Console.Error.WriteLine(ex.Message);
}
}
}
[RunInstaller(true)]
public sealed class MyServiceInstallerProcess : ServiceProcessInstaller
{
public MyServiceInstallerProcess()
{
this.Account = ServiceAccount.NetworkService;
}
}
[RunInstaller(true)]
public sealed class MyServiceInstaller : ServiceInstaller
{
public MyServiceInstaller()
{
this.Description = "My Service";
this.DisplayName = "My Service";
this.ServiceName = "My Service";
this.StartType = System.ServiceProcess.ServiceStartMode.Manual;
}
}
}
You basically have two choices. Either expose an API on the service which you can then call from the UI app OR enable the service to run either as a winforms app or a service.
The first option is pretty easy - use remoting or WCF to expose the API.
The second option can be achieved by moving the "guts" of your app into a separate class then create a service wrapper and a win-forms wrapper that both call into your "guts" class.
static void Main(string[] args)
{
Guts guts = new Guts();
if (runWinForms)
{
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
FormWrapper fw = new FormWrapper(guts);
System.Windows.Forms.Application.Run(fw);
}
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new ServiceWrapper(guts) };
ServiceBase.Run(ServicesToRun);
}
}
If you use the below code:
[DllImport("advapi32.dll", CharSet=CharSet.Unicode)]
static extern bool StartServiceCtrlDispatcher(IntPtr services);
[DllImport("ntdll.dll", EntryPoint="RtlZeroMemory")]
static extern void ZeroMemory(IntPtr destination, int length);
static bool StartService(){
MySvc svc = new MySvc(); // replace "MySvc" with your service name, of course
typeof(ServiceBase).InvokeMember("Initialize", BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod,
null, svc, new object[]{false});
object entry = typeof(ServiceBase).InvokeMember("GetEntry",
BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.InvokeMethod, null, svc, null);
int len = Marshal.SizeOf(entry) * 2;
IntPtr memory = Marshal.AllocHGlobal(len);
ZeroMemory(memory, len);
Marshal.StructureToPtr(entry, memory, false);
return StartServiceCtrlDispatcher(memory);
}
[STAThread]
static void Main(){
if(StartService())
return;
Application.Run(new MainWnd()); // replace "MainWnd" with whatever your main window is called
}
Then your EXE will run as either a service (if launched by the SCM) or as a GUI (if launched by any other process).
Essentially, all I've done here is used Reflector to figure out what the meat of ServiceBase.Run does, and duplicate it here (reflection is required, because it calls private methods). The reason for not calling ServiceBase.Run directly is that it pops up a message box to tell the user that the service cannot be started (if not launched by the SCM) and doesn't return anything to tell the code that the service cannot be started.
Because this uses reflection to call private framework methods, it may not function correctly in future revisions of the framework. Caveat codor.
Create a new winforms app the references the assembly of your service.
There is also FireDaemon. This allows you to run any windows application as a service.
See Am I running as a service for some further useful information.
The most important thing covered is how to reliably determine whether we are running interactively or via a service.
you have to implement a separate process that can communicate with your service. While it is possible on XP and earlier systems to have a service showing an UI, that's no longer possible on Vista and later.
Another possibility is to NOT use a service, but to use an application which resides in the Taskbar (think Roxio Drag-to-Disc, & most likely your Anti-virus software lives down there) which has an icon down by the clock, which launches a menu, when it is right-clicked, and a UI when double-clicked.
If your service is modulated properly, you could host the service either in a executable as a service, or with an executable with gui for the test.
We use this method with our service too, the standalone service-executable hosts the service in productive environment, but we have a console-app for hosting the service, too.
Separate your code into different components: one component to manage the service aspects and one to perform the actual business logic. Create and interact with the business logic from the service component. For testing (of your business logic) you can create a WinForm or console application that uses the business logic component without the service component. Better yet, use a unit testing framework for the bulk of your testing. Many of the methods in the service component will undoubtedly be unit testable as well.
If you encapsulate your business logic in service classes and then use a factory pattern to create those services, you can use the same set of services for a desktop application (desktop factory) and as web services (host in WCF).
Service definition:
[ServiceContract]
public interface IYourBusinessService
{
[OperationContract]
void DoWork();
}
public class YourBusinessService : IYourBusinessService
{
public void DoWork()
{
//do some business logic here
}
}
Factory for desktop WinForms to get at services to do business:
public class ServiceFactory
{
public static IYourBusinessService GetService()
{
//you can set any addition info here
//like connection string for db, etc.
return new YourBusinessService();
}
}
You host this either with the WCF ServiceHost class, or in IIS. Both allow you the ability to specify how to instantiate each instance of the service so that you can do initialization like connection strings, etc.
You can create the service to call another executable with a command line argument so it is run without the form. When that exe is called without the command line argument it shows the form and act as normal.