Automatically stop/restart ASP.NET Development Server on Build - asp.net

Is there a way to automatically stop the ASP.NET Development Server (Cassini) whenever I do a build/rebuild in VS2008 (and then obviously have it start again when required)? Maybe there's some hidden configuration setting somewhere? Or at least some way to do it as a post-build event maybe?
For some background, the issue is that I'm using Spring.NET for dependency injection, etc, but it loads its singletons on Application Start, meaning that if I change any spring related code/configuration I have to stop the Development Server, so that it starts again next debug/run ensuring the Application Start event is triggered again. In other words, even if you change a bunch of code/config & then start debugging again, it doesn't actually start again, since its already running, so your new code isn't being used.

Workaround: Debugging Global.aspx.cs Application_Start() with ASP.Net Web Server within Visual Studio
Enabling "Edit & Continue" on the web server project worked for me. It doesnt shutdown cassini when you stop debugging, but it does restart cassini when you start debugging.

So I ended up with a workaround based off Magnus' answer, but using the following relatively simple macro (why do they force you to use VB for macros? I feel all dirty):
Imports System
Imports System.Diagnostics
Public Module KillCassini
Sub RestartDebug()
If (DTE.Debugger.DebuggedProcesses.Count > 0) Then
DTE.Debugger.Stop(True)
End If
KillCassini()
DTE.Debugger.Go(False)
End Sub
Sub KillCassini()
Dim name As String = "WebDev.WebServer"
Dim proc As Process
For Each proc In Process.GetProcesses
If (proc.ProcessName.StartsWith(name)) Then
proc.Kill()
End If
Next
End Sub
End Module
Basically if the debugger is currently running, it will stop it & then kill any processes named "WebDev.WebServer" which should be all the Cassini instances and then starts the debugger again (which will implicitly start Cassini again). I'm using proc.Kill() because neither proc.CloseMainWindow() or proc.WaitForExit(1000) seemed to work...
Anyway, once you've got your macro you can assign it to keyboard shortcuts, or create custom toolbar buttons to run it.

I just open a command line (runas admin)
run the following. It should kill all of them
Taskkill /IM WebDev.WebServer40.EXE /F

The only way that I know of is to do a custom Cassini startup on the post.build event. This custom made process kills all instances of Cassini, and startup a new one.
In order to get this to work, you will need to build a small custom command line utility. I have called it SpawnProcess here.
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Diagnostics;
namespace SpawnProc
{
class Program
{
public static void Main(string[] args)
{
if (args.Length > 0)
{
// Kill all current instances
FileInfo fi = new FileInfo(args[0]);
string name = Path.GetFileNameWithoutExtension(fi.FullName);
foreach (Process proc in Process.GetProcessesByName(name))
{
proc.Kill();
}
ProcessStartInfo startInfo = new ProcessStartInfo(args[0]);
if (args.Length > 1)
{
startInfo.Arguments += "/port:" + args[1];
}
if (args.Length > 2)
{
startInfo.Arguments += " /path:\"" + args[2].Trim(new char[]{'"'}) + "\"";
}
if (args.Length > 3)
{
startInfo.Arguments += " /vpath:\"" + args[3].Trim(new char[]{'"'}) + "\"";
}
try
{
Process.Start(startInfo);
}
catch (Exception ex)
{
Debug.WriteLine("Error: " + ex.Message);
for (int i = 0; i < args.Length; i++)
{
Debug.WriteLine("args[" + i + "]: " + args[i].ToString());
}
}
}
}
}
}
Then you will have instruct Visual Studio to not use Cassini. Got to properties for your web application -> Web and select "Use Custom Web Server", enter something like:http://localhost:1685/ (Or whatever port number you would like to use).
Then, enter this command in the post-build event:
"$(ProjectDir)..\SpawnProc\bin\debug\SpawnProc" "C:\Program Files (x86)\Common Files\microsoft shared\DevServer\9.0\WebDev.WebServer.exe" 1685 "$(ProjectDir)" /
Make sure your paths is correct, for instance, since I'm running a 64bit OS, my Program files path is different from a 32bit OS. Also, my SpawnProc.exe is in a sub project.

Inspired by this post and another one about code clean up
I added the macro as PostDebug-event. So every time the debugger returns, it will remove all WebDev.WebServer-s. (And I relaxed the ProcessName-constraint.)
Note: this will probably kill all the WebServers, so also WebServers of other debug-sessions (which is fine with me, at this moment, I usually don't have any). So you may want to only look for child-processes or something like that (and post that code here ;-) ).
So my code looks like this:
Private Sub DebuggerEvents_OnEnterDesignMode(ByVal Reason As EnvDTE.dbgEventReason) _
Handles DebuggerEvents.OnEnterDesignMode
If (Reason = dbgEventReason.dbgEventReasonStopDebugging) Then
Dim name As String = "WebDev.WebServer"
Dim proc As System.Diagnostics.Process
For Each proc In System.Diagnostics.Process.GetProcesses()
If (proc.ProcessName.StartsWith(name)) Then
proc.Kill()
End If
Next
End If
End Sub

Another way is using Powershell:
as pre-build-event: powershell Stop-Process -name webdev.webserver
as Powershell-command-shortcut: powershell.exe Stop-Process -Name #('WebDev.WebServer*', 'Microsoft.Expression.Web*')
PS: I don't know if anybody is still in need, but I just accidentally ran into this solution, while looking for something completely different.

Related

How can you add :// to your file? [duplicate]

How do I register a custom protocol with Windows so that when clicking a link in an email or on a web page my application is opened and the parameters from the URL are passed to it?
Go to Start then in Find type regedit -> it should open Registry editor
Click Right Mouse on HKEY_CLASSES_ROOT then New -> Key
In the Key give the lowercase name by which you want urls to be called (in my case it will be testus://sdfsdfsdf) then Click Right Mouse on testus -> then New -> String Value and add URL Protocol without value.
Then add more entries like you did with protocol ( Right Mouse New -> Key ) and create hierarchy like testus -> shell -> open -> command and inside command change (Default) to the path where .exe you want to launch is, if you want to pass parameters to your exe then wrap path to exe in "" and add "%1" to look like: "c:\testing\test.exe" "%1"
To test if it works go to Internet Explorer (not Chrome or Firefox) and enter testus:have_you_seen_this_man this should fire your .exe (give you some prompts that you want to do this - say Yes) and pass into args testus://have_you_seen_this_man.
Here's sample console app to test:
using System;
namespace Testing
{
class Program
{
static void Main(string[] args)
{
if (args!= null && args.Length > 0)
Console.WriteLine(args[0]);
Console.ReadKey();
}
}
}
Hope this saves you some time.
The MSDN link is nice, but the security information there isn't complete. The handler registration should contain "%1", not %1. This is a security measure, because some URL sources incorrectly decode %20 before invoking your custom protocol handler.
PS. You'll get the entire URL, not just the URL parameters. But the URL might be subject to some mistreatment, besides the already mentioned %20->space conversion. It helps to be conservative in your URL syntax design. Don't throw in random // or you'll get into the mess that file:// is.
If anyone wants a .reg file for creating the association, see below:
Windows Registry Editor Version 5.00
[HKEY_CLASSES_ROOT\duck]
"URL Protocol"=""
[HKEY_CLASSES_ROOT\duck\shell]
[HKEY_CLASSES_ROOT\duck\shell\open]
[HKEY_CLASSES_ROOT\duck\shell\open\command]
#="\"C:\\Users\\duck\\source\\repos\\ConsoleApp1\\ConsoleApp1\\bin\\Debug\\net6.0\\ConsoleApp1.exe\" \"%1\""
Pasted that into notepad, the file -> save as -> duck.reg, and then run it. After running it, when you type duck://arg-here into chrome, ConsoleApp1.exe will run with "arg-here" as an argument. Double slashes are required for the path to the exe and double quotes must be escaped.
Tested and working on Windows 11 with Edge (the chrome version) and Chrome
There is an npm module for this purpose.
link :https://www.npmjs.com/package/protocol-registry
So to do this in nodejs you just need to run the code below:
First Install it
npm i protocol-registry
Then use the code below to register you entry file.
const path = require('path');
const ProtocolRegistry = require('protocol-registry');
console.log('Registering...');
// Registers the Protocol
ProtocolRegistry.register({
protocol: 'testproto', // sets protocol for your command , testproto://**
command: `node ${path.join(__dirname, './index.js')} $_URL_`, // $_URL_ will the replaces by the url used to initiate it
override: true, // Use this with caution as it will destroy all previous Registrations on this protocol
terminal: true, // Use this to run your command inside a terminal
script: false
}).then(async () => {
console.log('Successfully registered');
});
Then suppose someone opens testproto://test
then a new terminal will be launched executing :
node yourapp/index.js testproto://test
It also supports all other operating system.

serilog not creating log files

we are using the following piece of serilog code which writes events to console and file, the file and console logging works fine on my machine, but in the other developers machine console logging works but the file logging does not work and to add to the weirdness the"logs" folder gets created though. Is there any extra setup that needs to be done ?
public static void SetupLogger()
{
//var outputTemplate = "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}";
var outputTemplate = "[{Level:u3}] {Message:lj}{NewLine}{Exception}";
// Logger
//var outputTemplate = "{Timestamp:yyyy-MM-dd HH:mm:ss.fff} [{Level:u4}] | {Message:l}{NewLine}{Exception}";
Log.Logger = new LoggerConfiguration()
.MinimumLevel.Verbose()
.WriteTo.Console(outputTemplate: outputTemplate, theme:SystemConsoleTheme.Literate,restrictedToMinimumLevel:LogEventLevel.Information)
.WriteTo.File($"logs/log-{DateTime.Now:yyyy-MM-dd_HH:mm:ss.fff}.log")
.CreateLogger();
}
The first step when troubleshooting any issue with Serilog is to turn on the SelfLog and see if there are any exceptions being caught. The error messages might give you a clue of what's the problem.
Serilog.Debugging.SelfLog.Enable(s => Console.WriteLine($"Internal Error with Serilog: {s}"));
Alternatively, if you didn't have a Console Window, you could also use a Notepad window to inspect the SelfLog.
Anyway, are the machines where it doesn't work running Windows? I ask because looking at your code, I wouldn't expect it to work on Windows because you're saving the file with : (colon) in the name which is not a valid character for file names in Windows.

Execute of .bat from does not start with expected user

I have the following code:
Dim billy As New System.Diagnostics.ProcessStartInfo("C:\somepath\dumpuser.bat", "")
billy.RedirectStandardOutput = True
billy.WindowStyle = Diagnostics.ProcessWindowStyle.Hidden
billy.UseShellExecute = False
Dim joey As System.Diagnostics.Process
joey = System.Diagnostics.Process.Start(billy)
dumpuser.bat:
echo %username%
net user %username% /domain 2>&1
exit /B 1
I get the following output:
C:\Windows\SysWOW64\inetsrv>echo SERVERXX$
SERVERXX$
C:\Windows\SysWOW64\inetsrv>net user SERVERXX$ /domain 2>&1
The request will be processed at a domain controller for domain xxxxx.com.
There is no such user: SERVERXX$.
More help is available by typing NET HELPMSG 3755.
C:\Windows\SysWOW64\inetsrv>exit /B 1
I would expect the output of %username% to be xxxx\IUSR_SERVERXX because the application pool is set to identity = "xxxxx\IUSR_SERVERXX"
We are using this script to debug the permissions problem, the real .bat file prints to a printer. We are debugging it because the printer "broke" after we changed the identity for the application pool. We have narrowed it down to a permissions problems.
We had other permissions problems on reading and writing files after the change to the application pool identity. Those were solved very simply by changing the permissions on the file. This is different because the script is being executed by a user that is not even defined on the local machine or in active directory on the domain controller.
The question:
How can I get this script to execute as xxxx\IUSER_SERVERXX?
This was a false alarm.
The problem is that .bat is not a reliable way to get the username.
We wrote this c# code and called it in the .bat file as well.
using System;
class Sample
{
public static void Main()
{
Console.WriteLine();
Console.WriteLine("UserName: {0}", Environment.UserName);
}
}
That code output the username we would expect.
We then realized that the problem was not a bad user id, but permissions on the printers.

How to get return Code from Host program triggered from Java Code

My Aim is to trigger a shell script from java program. Here Shell Script is going to move files from one server to another.
So I used the following Code to trigger the shell script from java program.
try {
Process proc = Runtime.getRuntime().exec("/home/destino/workspace/JavaProject/move.sh /"); //Whatever you want to execute
proc.waitFor();
} catch (IOException e) {
System.out.println(e.getMessage());
}
In host scripts I am trying to copy a file from one Host to other using scp command.
So is it possible to get the return code from the shell script.
Thanks,
Abhinav
Simply use exitValue():
proc.exitValue();
If you need to get output of script use proc.getInputStream()

How to capture IIS Express output when run from Visual Studio 2010 SP1?

If you run IIS Express from the command line, anything you write Console.Out in your web app is displayed in the command line output. This is very handy for trouble shooting LINQ to SQL translation issues if you set DataContext.Log = Console.Out. However, if you check "Use IIS Express" in the web project properties in VS 2010 SP1 you never see the command line.
Can you redirect IIS Express Console.Out to a log file or something?
I found a way to write directly to the Debug Console window via damieng's blog:
class DebugTextWriter : System.IO.TextWriter {
public override void Write(char[] buffer, int index, int count) {
System.Diagnostics.Debug.Write(new String(buffer, index, count));
}
public override void Write(string value) {
System.Diagnostics.Debug.Write(value);
}
public override Encoding Encoding {
get { return System.Text.Encoding.Default; }
}
}
You can attach it to a DataContext like you would with Console.Out:
#if DEBUG
db.Log = new DebugTextWriter();
#endif
http://damieng.com/blog/2008/07/30/linq-to-sql-log-to-debug-window-file-memory-or-multiple-writers
You can see console output, if you setup 'image file execution option' for iisexpress.exe. Only issue is, you will see a popup console window when a new iisexpress.exe is started. You can setup this only when you want to see console traces.
Do following to setup image file execution option:
install windbg from http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx
Setup following registry key (This link may help you http://msdn.microsoft.com/en-us/library/a329t4ed(VS.71).aspx)
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\iisexpress.exe]
"Debugger"="c:\\windbg -g -G"
You can disable image file execution option by renaming or deleting above registry key.

Resources