I am experiencing a weird behaviour from Visual Studio 2013. I've got a C# program which writes to the standard output, let's say
using System;
using System.Threading;
namespace CsSandbox
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello world!");
Thread.Sleep(10000);
}
}
}
In the Debug tab of the project's properties I have redirected the output to a file, like this:
If I open the file within those 10s when my application is still running, the file does contain "Hello world!". However, as soon as the program exits, the file is cleared. This does not happen when I run the program from the command line.
Is there a rationale why Visual Studio does it? Is there a way to bypass this behaviour?
I believe this is due to the way Visual Studio hosts your application, in order to reduce startup time when debugging.
What happens is that your application (Program.exe) will actually be hosted in another process (Program.vshost.exe), which is started with the same command line arguments. When your application ends, this process is immediately restarted. You should be able to see this within Task Manager - look in the details tab so you can see the PID of the processes, and run your app - you'll see one Program.vshost.exe instance which ends when your app finishes, and another one come up immediately. That's then overwriting your output file.
One fix for this is to give your application a command line argument for the file to write to - and open that file within your Main method. You won't get there until you start running the app again.
Another option would be to simply stop using the hosting process - in the Debug part of your project properties, at the bottom you should see a checkbox for "Enable the Visual Studio hosting process". Uncheck this and I think your problem will go away - but it'll take longer to start debugging.
See this blog post for more information about the hosting process.
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.
I got a break point on the first line of Application_Start(), but Visual Studio wont break on it.
Visual Studio have attached itself to the IIS working process:
Auto-attach to process '[2092] w3wp.exe' on machine 'SRD00510' succeeded.
My breakpoint in the home controller do work.
update
I've tried:
iisreset
restarted visual studio
Rebooted.
Tried to reinstall aspnet (aspnet_regiis -i)
Reading your question, I assume you are using IIS for debugging, not Visual Studio Development Server.
In this case, debugging application start is tricky, because it is only called once when the application pool is started or recycled. When Visual Studio attaches to the process, Application_Start has already been running.
The trick is to make the application pool recycle without killing the process you are attached to.
Do the following:
In Visual Studio (must be run as Administrator) set your breakpoint in
global.asax.cs and start debugging as usual (F5). The page opens in
your web browser, but the breakpoint isn't hit.
Now the trick: With a text editor, open web.config from where it is
served by IIS, change it (e.g. enter a blank line somewhere) and
save it. In contrast to recycling the application pool in IIS, this
lets the application pool recycle (and thus running through
Application_Start in global.asax.cs the next time the web site is
called) without killing the process you are attached to.
In your web browser, reload the page. The breakpoint should be hit now!
That works for me (IIS 7.5, VS2015).
Place this line in your Application_Start().
Debugger.Break();
This will present you with a dialog which will allow you to select a debugger. You might need to restart the application pool.
Application_Start() only runs once, when the application starts. A few things that restart the application are:
web.config changes
recycling the worker process - you can do this in IIS Manager or by running iisreset at the command line.
My solution is to switch to using the 'Visual Studio Development Server' to deal with the application class (Global.asax) issues. When done I switch back to IIS.
I assume you're loading the application by clicking the "debug" button in Visual Studio? That's what I'm doing (in VS 2012) and seeing similar problems. Pressing that button the first time starts the application and correctly hits the breakpoint. But it seems like after I stop debugging the application itself keeps going. So, future attempts to debug just attach to the existing process.
There's a "restart" button next to the "stop debugging" button, so I'd assume clicking that at least would change things.
The debugging app does not show up in IIS manager, so I can't stop it there. Likewise, iisreset doesn't catch it either.
Only thing I've figured out so far is to change a line of code, thereby forcing visual studio to trigger a build and then it kills the existing proc and starts over. Kind of annoying if I just want to step through there multiple times.
I don't consider this a suitable "answer", but it might be a helpful workaround for you until somebody does come in with a real answer.
I've got around this problem before by doing this:
Run a clean on my solution (Right click the solution node and click clean)
Close solution
File -> Exit on visual studio
If you have multiple instances of visual studio running then exit out of all instances. Ensure "devenv.exe" is not listed in the processes in task manager
Delete the user options file (.suo), usually in the same directory as your solution (.sln) file
Recycle IIS worker process or if using the development server, kill that process
Now open your solution and give it a shot. (keep your fingers crossed :))
Whenever you run an application for the first time, or say start an application, there is an ASP.Net Development Server - Port [port number] that starts,
Application_Start() runs once in the course of an application.
If you want the break point to be reached , you have to stop the ASP.Net Development Server Port and run your application again.
if [2092] w3wp.exe is a service that you made, try this :
stop service -> rebuild service project -> start rebuilt service -> try to debug
If using IISEXPRESS is not an option, as #David Perlman mentions, I would go for a Logger. Log4Net or NLog are both good. It's good to have a logger in the longrun, for instance in production environments.
namespace DataService
{
using NLog;
public class Global : System.Web.HttpApplication
{
private Logger log;
protected void Application_Start(object sender, EventArgs e)
{
LogManager.LoadConfiguration("nlog.config");
log = LogManager.GetCurrentClassLogger();
log.Error($"Read this line in the log specified in nlog.config");
}
Under my solution I have 2 projects Project A console application , Project B Winforms Window.
How I can From Project B to start new process with console application from Project A ?
I tried to making it via
Process note = new Process();
note.StartInfo.FileName = "note.exe";
note.StartInfo.Arguments = "123";
note.Start();
But in that way i cant debug both processes from one vs instance . Any idea ?
Thanks
If the only reason that you want to start the two projects is that you want to be able to debug both of them you can also configure your solution to have multiple startup projects:
Solution -> Properties -> Set Startup Projects...
If you are going to start the other project as a separate project anyway, you could use
Debug -> Attach to Process
to attach to the newly started process. Then you will also be able to debug both processes in Visual Studio. Attaching the debugger can also be achieved programmatically. In project A you can add the following code to the Main method:
#if DEBUG
System.Diagnostics.Debugger.Launch();
#endif
In the dialog that will then pop up you can select the already running instance of Visual Studio.
Another option is to start the Startup Project via F5 (or Debug > Start Debugging) and the second one by right-clicking the project and going Debug > Start New Instance.
You can start debugger in the application launched by the following statement
System.Diagnostics.Debugger.Break()
then you can choose the visual studio instance and start debugging.
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