When #if SERVICE does work and when it does not? - c#

I often used to use (and as far as I can remember it was working just fine)
public static void Main() {
#if SERVICE
ServiceBase.Run(new MyService());
#else
....
#endif
in services code so I can run it as console or register with installutil and run as service.
But... since some updates or with switch to 4.5.1 ( or even maybe in release build ) it just doesn't work anymore. Whenever I use installutil or just run as console it's using code for console, e.g. not for SERVICE and it fails because I used Console.ReadKey there and sure service can't deal with it.
Maybe I am doing something wrong and there is alternative ways of doing it?

... so I can run it as console or register with installutil and run as service
That can't have been enough. The #if SERVICE is a compile time condititon, it cannot produce different behaviours depending on how you run it. It needs a different Build configuration.
My guess is that you lost a piece of tooling or forgot a certain habit after that upgrade.

Related

How to stop installing app every time when tests run in xamarine.uitest

I am new to mobile testing and working to test a native app using Xamarine.UITest on an android in which I am executing multiple BDD scenarios . Every time I run tests it installs the app again and I lose the data created by previous scenarios. How can I stop installation of app when app is already installed and check if installed skip installation and just launch the app. Below is the piece of code which I am using to install the app and return IApp. Thanks for looking into it.
public static IApp StartApp(Platform platform)
{
if (platform == Settings.Platform)
{
return ConfigureApp
.Android
.InstalledApp(Settings.AUTPackageName)
.StartApp();
}
return ConfigureApp
.iOS
.StartApp();
}
So I've run into the other side of this -- I have some different run behavior on first load, so I want to force it to install clean sometimes.
What I've found is that Android and iOS devices have different behavior on this. With Android, using the InstalledApp will always rebuild the application, it will check against the installed version and install the new build if different. Loss or caching of data is effected by the AppDataMode.
So, if the issue is the building of the application, because it can be slow on a slow machine, I'd suggest looking at using a pre-built APK file to run the tests, using .ApkFile("") instead of .InstalledApp.
If the concern is the loss of data (which is more what your question sounds like), then you should do something like:
{
_app = ConfigureApp
.Android
.InstalledApp(Settings.AUTPackageName)
.StartApp(AppDataMode.DoNotClear);
}
iOS is a different beast, but I think you're looking at Android specifically here.

Generate a CIL executable not EXE then execute it

I have a c# project that generates an EXE file. Now, I'm in a "secure" corporate environment, where I can compile my project, but I cannot execute the EXE file.
As a Java programmer, I'm wondering if there is not a way to compile the c# project into something that would not be an EXE file, but a CIL file and then execute the CIL file by something that corresponds to java.exe in the dotnet world.
EDIT in response to comments:
I can run exe files that have been installed by a package manager
Yes, I know the corporate policy is stupid.
Well, this should be pretty easy.
.NET executables are simply DLLs like any other - the main difference being the executable format itself, and the fact that EXE files have an entry point, while DLLs don't.
It also means that you can load the EXE into memory exactly the same way as you would with a DLL:
Assembly.LoadFrom("SomeExe.exe");
You're already half way there - now we just need to find and execute the entry point. And unsurprisingly, this is also pretty trivial:
var assembly = Assembly.LoadFrom("SomeExe.exe");
assembly.EntryPoint.Invoke(null, null);
For most applications, this should work perfectly fine; for some, you'll have to make sure the thread you're using to invoke the entry point has STAThread or MTAThread respectively (Thread.TrySetThreadApartment if you're starting a new thread).
It might need tweaking for some applications, but it shouldn't be too hard to fix.
So you can just make some bootstrap application ("interpreter") that only really contains these two lines of code. If you can't get even that approved, and you really need something as an "official package", try some .NET application that allows you to execute arbitrary code - for example, LINQPad, or PowerShell.
EDIT:
This does have limitations, of course, and it does introduce some extra setup work:
The bootstrapper has to target the same or higher version of .NET Framework. .NET Portable might be particularly tricky, but I assume you have that well under control. It also has to have the same bitness (if specified explicitly).
You need to run the debugging through the bootstrapper. That actually isn't all too hard - just go to project properties, debug and select "Start external program".
The bootstrapper has to run under full trust conditions - it's necessary for reflection to work. On most systems, this simply means you have to have the exe as a local file (e.g. not from a network share). Tools like LINQPad will run under full trust by default.
The application must not depend on Assembly.GetEntryAssembly. This isn't used all that often, so it shouldn't be a problem. Quite a few similar issues should also be fine since you build the application you're trying to run yourself.

Base class not finding app settings

This is somewhat of a general question but I haven't found much by googling it. I have a test framework that sets up an environment for testing purposes. My application consumes this framework through a reference path and runs manual tests just fine. However, once I ask the build server to run my test the framework complains it cannot find any of my app settings. The app.config file sits in my testing project for my application and I am sure it exists in the correct bin folder on my build server. I'm doing this in a C# .NET environment.
EDIT:
I'm not sure what to be more specific about. I would imagine it's something with the build server since it seems to work running tests locally but I have no clue what to look at. Nothing else about the build server is failing, just getting the app settings.
The framework is .NET 4.0 while the main project is 4.5. I'm using nunit to run the tests and running them outside the build process but using the Nunit gui fails at the same point.
The code that grabs the app settings is pretty basic:
string databaseName = ConfigurationManager.AppSettings["databaseName"];
EDIT
Snippet of my test:
public class UserServiceTests : DeployDBEveryFixtureBase
{
public UserServiceTests()
{
DBSetup("Core");
DBSetup("Postal");
DBSetup("Common");
}
private UserService userService = new UserService(string.Format("Data Source={0};Initial Catalog={1};User ID={2};Password={3};",
ConfigurationManager.AppSettings["targetServer"],
ConfigurationManager.AppSettings["databaseName"],
ConfigurationManager.AppSettings["userID"],
ConfigurationManager.AppSettings["password"]));
[Test]
public void UserService_Get()
{
// Act
User user = userService.GetUser(Guid.Empty, "*****", string.Empty);
// Assert
Assert.IsTrue(user.FirstName == "System");
}
}
The environment deployment is in the base class of DeployDBEveryFixtureBase. The DBSetup calls ensure that each database is deployed in the proper order. All of those seem to run fine and my tests complete but I still get the described error. If I look at the database I can all the datbases being properly deployed and then removed (the base class includes a TestFixtureTearDown) but it seems like the build process is trying to run it again.
Note: I am only building the solution file during this process. I do not currently have a .proj file in the build.
Without knowing much about your build server or how exactly you run your tests there is only one issue which comes to mind, that is Shadow Copying. Can you check if your unit tested DLLs are not shadow copied to some location where the app.config file doesn't exist?
Apparently my testing framework had an empty constructor that wasn't so empty. It looks like the app.config was being properly queried but was returning an empty result set since the empty constructor did not have the proper arguments. After removing the contents of the empty constructor my test ran fine. Thank you all for the help.

How To Run And Test a Windows Services In VS

I created a windows service in VS:File->New Project->C#->Windows Services
But I don't know how to run and test it.VS says I have to install my windows services to run it.but I Just want to test it and I don't want to install it.Can anybody Help me???
To debug your Windows service, add the following in your Main():
if (!Environment.UserInteractive) {
// We are not in debug mode, startup as service
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MyServer() };
ServiceBase.Run(ServicesToRun);
} else {
// We are in debug mode, startup as application
MyServer service = new MyServer();
service.StartService();
System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
}
And the following method in your class MyServer:
public void StartService() {
this.OnStart(new string[0]);
}
Now hit F5 to debug, as any winform or console application.
When creating a Windows Service I usually put all functionality into a separate class library... for testing I create a "normal app" which makes use of the class library...
AFTER the functionality is tested and the bugs are gone I do build/install the Windows Service... there can be problems specific to Windows Service like permissions etc. - these need to be addressed accordingly (some logging is usually very helpful).
Debugging a Windows Service with VS is a bit different from debugging an application - for details see http://msdn.microsoft.com/en-us/library/7a50syb3.aspx
A windows service is not really a normal executable, it builds as exe but has to be installed and started with Services icon from Control Panel.
Once you got it installed and started you can use Visual Studio Debug menu, Attach to process and attach to the service to debug it, not the simplest and fastest way to debug because if you need to change anything you have to build it again and install it again, start and attach again.
Usually a nice approach is to anyway split and isolate the logic of the service in a class library (probably the service business logic) which can be used also from let's say a console application.
At this point you create a test console application which calls some methods and behaves kind of like the service from the Main method and you test and debug this one.
Once everything has been tested and verified and you are satisfied with the results you copy the code you have put in the Main method of the test console application in the Service class, probably in the OnStart method or similar, details depend on your specific design.
we do this also to debug and test WCF services which are hosted in a test console app during development and in a Windows Service in production.
you should use visual studio command prompt with the following command:
installutil "the path of the exe"
and the go to Services (start-> run-> services.msc) you will find the service. click on start and you're done.
P.S: to debug your service in vs: tools-> attach to process and find your service in the list)
You cannot debug service directly from VS. Need to attach the debugger to Windows Service.
To do it, in VS do following:
From the Debug menu, select Attach To Process…
Near the bottom of the window, select Show processes in all sessions.
Left-click the compiled EXE to be run as the Windows Service in the list. Press Attach.
Result: you can place breakpoints at places in your functions, and you'll be able to debug the service execution.

What's the best way to deploy an executable process on a web server?

The original question:
The title of this question might be a bit clumsily phrased, but here's the situation:
I have a .NET web project deployed on my server. It's still in beta, so there's a lot of releasing and re-releasing happening.
I have also written a C# executable in the same VS solution (call it "admin.exe") that runs in the background on the server, periodically performing certain business rule integrity checks and making appropriate insertions to a warning table in the DB.
Question is: what's the best way to deploy this app so that it gets updated whenever I make a new release? It should be running all the time in between releases, so ideally I'd like some sort of setup whereby the shutdown-deploy-startup process involves the minimum possible number of steps.
Thanks!
Edit - Bounty started
The answers given thus far have been helpful and interesting, but haven't provided me with a clear, concise and elegant solution. Please do not assume I have extensive knowledge of deployment projects, because I don't. Bounty goes to the person who can provide a solution that does the following:
Publish the latest version of the web site;
Shut down any instances of admin.exe that are running on the server;
Update admin.exe;
Launch admin.exe;
All of the above should be done preferably in one step, or as few steps as possible, seeing as it will be done repeatedly throughout the life of the product; and
All of the above should be done preferably without requiring installation of any 3rd party software.
Thank you for your help!
Minor edit - clarification
I think a lot of the solutions offered thus far have overestimated the complexity of the problem, so let me clarify: everything that is to be deployed, only has to be deployed on one computer, which also happily has Visual Studio available with all source code. I only need to (1) publish the web site to the web folder, and (2) shut down, reinstall and restart admin.exe on the same server. Isn't there a simple way of doing this in one step? Can it be done with a VS Deployment project?
The "correct" way is probably to set up deployment scripts and installers, but being able to just click publish in Visual Studio and skip going in with remote desktop is a lot more convenient during development.
I have an admin web app that acts as a front end to a command line app - slightly different from what you are doing, but the same solution should work.
Simply add a reference to the console project in the admin web app. Even though you don't call any methods in the console project, the reference will cause the console app to be rebuilt and uploaded when you publish the admin website.
A simple start/stop page added to the web app takes care of steps 2 & 4 - Mine calls Process.Start()/Process.Kill(), though you obviously have the option of a cleaner shutdown depending on the setup of admin.exe.
Below is the code from my start/stop page - I have them set up as web service methods (to facilitate some monitoring stuff you probably won't need), but they should work just as well called from a simple button click method. Note that the service account will need permission to run/stop the process - on a dev box the simplest option is to set up iis to run as an admin user rather than the default service account.
private void KillProcess(string name)
{
var binpath = Server.MapPath("~/bin");
var pp2 = Process.GetProcesses();
var pp = from p in pp2 where p.ProcessName.Contains(name) && !p.ProcessName.Contains("vshost") select p;
foreach (var p in pp)
{
p.Kill();
}
}
[WebMethod]
public void StartQueueRunner()
{
var binpath = Server.MapPath("~/bin");
System.Diagnostics.Process.Start(Path.Combine(binpath, "TwoNeeds.QueueRunner.exe"));
}
[WebMethod]
public void StartQueueRunner()
{
var binpath = Server.MapPath("~/bin");
System.Diagnostics.Process.Start(Path.Combine(binpath, "TwoNeeds.QueueRunner.exe"));
}
It sounds like you need to take a look at a custom MSBuild script for deployment.
MSBuild does much more than just build solutions. You can also use it to copy files and update them, too. A good resource for tasks to do this is the MSBuild Community Tasks here.
You can then include the deployment of your background process alongside the deployment of the Web site deployment.
An alternative approach might be to use Windows Powershell with something like PSExec to remotely execute copy and update commands.
Both these kinds of approach can be automated very well with continuous integration servers such as Hudson. I have a build process that automatically monitors my source code repository, builds the program, deploys to a staging server, runs acceptance tests, then deploys to a preview box. I have another (manual) job that with one click deploys this preview version to live, minimising downtime and (usually) reducing errors from mistiped commands.
There is probably a much cleaner way but maybe install it as a windows service then script the install / uninstall commands using installutil.exe. Then just update the folder where the service sits and re-run the script for each update?
Great service tutorial here
Hope this helps
I would recommend writing a script that you could run on your PC, that would do the deployment over the network (so that you don't have to log in to the target machine every time). I have done it using msbuild, but you can really just go for a batch file.
I assume your admin process is running a windows service (anyway, it makes sense to run it as a service), so you would deploy it like this (this is part of the msbuild script - you can delete the bits with username and password if you don't need it):
<ItemGroup>
<ReleaseFiles Include="localPath\bin\*.dll"/>
<ReleaseFiles Include="localPath\bin\*.exe"/>
<ReleaseFiles Include="localPath\bin\*.pdb"/>
<ReleaseFiles Include="localPath\bin\*.config"/>
</ItemGroup>
<Target Name="Release">
<Message Text="Installing Admin on $(DeploymentMachine) as user $(User)"/>
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) stop "Admin"" />
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) delete "Admin"" />
<Delete ContinueOnError="true" Files="\\$(DeploymentMachine)\C$\path-to-admin\*.*"/>
<MakeDir Directories="\\$(DeploymentMachine)\C$\path-to-admin"/>
<Copy SourceFiles="#(ReleaseFiles)" DestinationFiles="#(ReleaseFiles->'\\$(DeploymentMachine)\C$\path-to-admin\%(RecursiveDir)%(Filename)%(Extension)')" />
<Exec Command="sc.exe \\$(DeploymentMachine) create "Admin" binpath= "C:\path-to-admin\admin.exe" start= auto obj= $(User) password= $(Password)" />
<Exec ContinueOnError="true" Command="sc.exe \\$(DeploymentMachine) start "Admin"" />
</Target>
Deploying IIS web sites is usually a bit more pain, but if you have everything set up on the target machine then possibly it would work to just copy the files over the network (again using the \DeploymentMachine\share or \DeploymentMachine\C$\path addressing).
Unfortunately deployment is never nice nor elegant :(
Please let me know if you need clarification on anything
Here's a nasty thought. If you're admin.exe isn't doing anything too hard core, why not throw into IIS? To write a C# Web Service, you probably won't need to change much.
To ensure it gets called repeatedly, you could use any variety of methods, like Windows Scheduler to run wget once a minute. Keep concurrent copies from running with a file lock, should it ever take MORE than one minute to complete.
This would make your deployment as simple as a file copy (FTP). I don't even think you need to reboot IIS when pushing a C# DLL. If you do, you can script that up over SSH.
To me, your problem sounds a lot like the deployment problem SharePoint solves through their Timer service running in each WFE, stsadm enqueuing admin tasks, that service dequeuing and running them etc.
What I would do is to
write a service running in each WFE
write a small custom "stsadm" tool so you can enqueue tasks, specify when they need to run, etc.
Another approach: what about using the plain vanilla Windows Task Scheduler? Look here, you can easily enqueue tasks remotely for ex.
I would write a command-line application that would do all of that.
Here is a rough example:
Site.api.publish();
admin.api.shutdown();
while(shell.status("admin.exe") == true) {}; //still running
file.replace("admin.exe", "path-to-compile\admin.exe");
shell.run("admin.exe");
You probably get the point. If you want it to do it automatically just use the Task Schedular to call it every day, or however often you want it.
Store on the server/web the most recent version of the project that is online. eg: in a version.txt the value "2.1.0", or query the database if you have access too.
Your application running on clients, will periodically read the contents of the version.txt file, then compared against the inbuilt(self) version number.
If a patch or minor release is detected eg 2.1.123, spins out a second app(updater.exe) that will quietly
do the upgrade,
it shall download the updated(preferred zipped) project from server/web.
Stop any running instances.
Unzipping the content.
Backup existing files(rename)
copy/install the new version of the project,
Start the application (when the app is restarted successfully it will delete its own backup file).
if a major release is detected eg: 3.0.0
notifies the user there is a major upgrade
if user accepts, download the installer
runs a full installer update
Does this help?
VS Deployment project for a web app is not that easy to master and somewhat not reliable. What I'd suggest:
Modify your Admin.exe into a .NET Windows service. Seebelow why would you need to do it.
Use sc.exe, InstallUtil.exe or installer-building services like installer.codeeffects.com to reinstall your service fast on every deployment. Btw, if I remember correctly, at installer.codeeffects.com you can download a VS example code of how to build a .NET Windows service if you're new to services.
Deployment could be done like this (assuming that your needs in automation is minimal and you're fine deploying almost manually):
Run either of the above mentioned tools to reinstall your service first. The sc.exe and InstalUtil.exe tools support command line. Therefore, if your web app, VS and the service is running on the same machine (your development computer, I assume?), you can right-click the web project in VS, select Properties and set pre- or post-build commands in the Build Events tab there. This way your VS can automatically rebuild and reinstall your service before you publish your web app. This is the main reason why the exe program is not good in your case, a Windows service would serve you better.
Then deploy your web app (assuming it's been build as discussed above). No biggies here, just use the Publish command from your VS or move all files of your web app except for the .cs files, /Properties/ and /obj/ folders. Or, if running from the project's folder, just right click the main page and select "View in Browser" - this will start the run time through VS without starting the debugger.
Sorry for such a lengthy post. Did I understand your question and clarifications correctly? :)
What about making admin.exe a click once deployment. Then in your admin.exe, before you check the integrity of business rules, check if an update is available. If it is, update and then continue on with your checks.
In order to make things simple and make sure I would be able to roll back everything, I would create a PowerShell Script that performed the following actions:
Stop the Application Pool.
Copy the current web app to the
"history folder" so you can rollback
to that version if required
Deploy the new web app
Stop the current admin.exe from
services
Uninstall the admin.exe, by
executing the Uninstall.bat (this is
quite common for Windows Services)
Copy the current admin.exe app to
the history folder (see 2)
Copy the new admin.exe to the
correct location and run install.bat
Start the new service
Start the application Pool
You can automate all of that in a Powershell script (the only thing I'm not sure is about the app pool, but I'm pretty sure that you can do this).
More info on PowerShell can be found here: http://arstechnica.com/business/news/2005/10/msh.ars/2

Categories

Resources