Visual Studio 2012 debugging of remote process not working as expected - c#

I am struggling with a rather difficult debugging challenge and hoping that someone might have some clues how to make this work.
Here's the scenario:
I have a C# Windows service that runs under a user account with admin privileges and launches a separate executable process under a user account that has standard user privileges. The two processes are designed to communicate using WCF.
Unfortunately, when the child process is launched, it crashes immediately, with nothing in the event log that suggests what happened. The parent process continues running without exceptions.
For information: these two applications work reliably together in a configuration whereby the parent process is a desktop application. I have also had success with the parent as a Windows service, but only when both processes run under the same user account with admin privileges.
I now need to reconfigure their relationship to restrict the privileges of the child process, but this is when the crash occurs.
In order to prove that what I am trying to do is feasible, I have created two stub applications and launched them successfully in the desired configuration. So, I can deduce that my real child app contains something that is incompatible with this configuration and which causes a crash even before the code starts executing. Unfortunately, since the child process is a based on some rather complex legacy code, it is not easy to isolate its elements until I eliminate the problem, so I really need a reliable means of stepping through it.
If I modify the code of the child process to launch debugging immediately on startup, it invites me to attach a debugger, but fails to complete the attachment, with a message that indicates that The Just-in-time debugger does not have permission to debug the process.
I have also seen this question and attempted to implement this proposed solution (which looks really promising) but it fails to work in my scenario. Instead of launching debugging prior to launching the application it appears to do nothing - niether the debugger nor the application are launched and the debugging invite dialog is not displayed. However, I have verified that this technique works in my environment (by using it to launch Notepad.exe) so there is clearly something about my application or the way that I am launching it that is causing the problem.
I am happy to experiment and to share more details about my test results, if anyone has any suggestions.
Many thanks for your ideas,
Tim

The fact that the debugger never starts for the child means the error should be occuring in the PARENT server process. If you properly set the Image File Execution Options (which is easiest to do using GFlags program using the free Windows Debugging Tools from Microsoft), then that means you never start creating the child. The simplest way to test this is by adding an Assert to your code, right before the create child process call, build your parent service in debug mode, install/register it as a service, and start it up. When the Assert pops up, attach to the process, and start debugging from there. You should then see the create process error occuring in the parent.
If you want to interactively debug both the parent service and the child process, you can do this using WinDbg and GFlags, but it will be complicated.
You will need WinDbg and GFlags. These tools are included free from Microsoft as part of the Debugging Tools for Windows. You can find that free software package here:
http://msdn.microsoft.com/en-us/windows/hardware/gg463009.aspx
Use GFlag to set the execution option for your PARENT SERVICE with the following debugger options:
"C:\Program Files (x86)\Windows Kits\8.0\Debuggers\x86\WinDbg.exe" -server tcp:port=5000:9000 -o -g
When Windows starts your parent service, it will do so under WinDbg. Because of the -o option, WinDbg will also manage the launched child process, allowing you to interactively DEBUG the child from start up. Because of the -g option, WinDbg will start the ParentService up and let it run, rather than stop it at load up as is normal debugging behavior. This will prevent Windows SCM from shutting it down and starting a new instance.
Because you are running a service, it will not have access to the desktop, so neither will its host WinDbg. You will have to attach ANOTHER debugger to the running instance of the WinDbg running your ParentService. You can do this using another WinDbg instance. To do that, start a second instance of WinDbg, and connect remotely by using the menu item "File|Connect To Remote Session...". At the dialog, put in:
tcp:Port=5000:9000,Server=[machinename]
Once you are connected, you will be able to work with your ParentService.exe, and when it creates the ChildProcess, the executing context will swap to it, and you will be able to debug it as well.
I've used this technique to debug a child process created by a windows service before. It isn't as easy as just debugging something in Visual Studio's built in debugger in its IDE, but it does work.
WinDbg has extensive documentation available for it, both from Microsoft and from other sources online. The URL I provided above includes links to WinDbg documentation.
I recommend using GFlags because it will make all the necessary edits to your Registry for running executables under a debugger of your choice. It also does much more, and is worth the time to learn about.
It is possible to set up breakpoints and set all sorts of options when WinDbg starts. I replace the -g option with the command line option:
-c "$$<c:\MyDebugCommands.txt"
This instructs WinDbg to run a command, and the command is to run a WinDbg script named "MyDebugCommands.txt". I populate MyDebugCommands.txt file with all the set up changes I need (such as load symbol options), as well as setting the breakpoints I am interested in, with the final command in the file being -g
As I said, it isn't as easy as just using the VS IDE and its built in debugger, but it will let you interactively debug your parent service and its launched child process.

According to my tests based on your scenario above (parent process is service with admin rights, child is console without admin rights), I see the same debugging error as you when I artificially force the child process to throw a permission exception as soon as it starts. The error message in this instance might be misleading, as it's not clear that this is actually a debugger permission problem
It would be useful to know what type of application your child process is, because that will affect the debugging options that you have.
The first way I've tried to debug this is to intercept all unhandled exceptions in my child process (a console app). You can do this by adding the following code in the start-up procedure of your child app:
AppDomain.CurrentDomain.UnhandledException += new
UnhandledExceptionEventHandler(App_UnhandledException);
Then I added code to my App_UnhandledException procedure to log the exception. This worked for me, and I could see the reason for the permission error. The only caveat is that this won't intercept an exception where your app won't even load because of the permission problem. But this approach should at least reduce your search space in understanding the permission problem.
If the exceptioon is generated before your exception handler is reached, another possiblity is to use the assembly binding log viewer. This is a very useful tool.
FWIW you can step through your service code (but unfortunately not into your child process) by starting your service within Visual Studio. The code shown below in the switch case called DEBUG will let you start/debug your service within VS.
// This is the entry point
static void Main(string[] args)
{
// If parameter passed, act on it
if ( args.Length > 0 )
{
switch (args[0] )
{
// Debug the service as a normal app from within Visual Studio
case DEBUG:
MyService DebugService = new MyService();
DebugService.OnStart(null);
break;
// Install the service programatically
case INSTALL:
ManagedInstallerClass.InstallHelper(new string[] _
{ Assembly.GetExecutingAssembly().Location });
break;
// Un-install the service programatically
case UNINSTALL:
ManagedInstallerClass.InstallHelper(new string[] +
{ UNINSTALL, Assembly.GetExecutingAssembly().Location });
break;
// We don't understand this parameter!
default:
message = string.Concat(DEBUG, " to run service manually.", Environment.NewLine);
message += string.Concat(INSTALL, " to install service.", Environment.NewLine);
message += string.Concat(UNINSTALL, " to un-install service.", Environment.NewLine);
message += string.Concat("Do not understand the command-line parameter ", args[0]);
throw new System.NotImplementedException(message);
}
}
// If no parameter passed, just start the service normally
else
{
ServiceBase[] ServicesToRun;
ServicesToRun = new ServiceBase[] { new MyService() };
ServiceBase.Run(ServicesToRun);
}
}

Have you tried running Visual Studio as Administrator and calling the Process.EnterDebugMode() method?

If I modify the code of the child process to launch debugging immediately on startup, it invites me to attach a debugger, but fails to complete the attachment, with a message that indicates that The Just-in-time debugger does not have permission to debug the process
Run secpol.msc as administrator and under 'Local Policies | User Rights Management' select 'Debug Programs'. Then add the 'Users' group to that. See if that fixes the permissions issue.
HTH

Related

Service Broker / External Application Activation and Visual Studio Debugging

I just got moved to a code-base that uses a lot of Service Broker functionality.
My EAService.config is setup as below
<ApplicationService name="NotificationTest" enabled="true">
<OnNotification>
<ServerName>MyServer\MyInstance</ServerName>
<DatabaseName>MyDatabase</DatabaseName>
<SchemaName>dbo</SchemaName>
<QueueName>MyQueueName</QueueName>
</OnNotification>
<LaunchInfo>
<ImagePath>C:\SomeFolder\SomeConsoleApp.exe</ImagePath>
<CmdLineArgs>myCommandLineArg1</CmdLineArgs>
<WorkDir>C:\SomeFolder\</WorkDir>
</LaunchInfo>
<Concurrency min="1" max="1" />
</ApplicationService>
My issue comes when I try to debug the above code.
Since the Service Broker External Activator (C:\Program Files\Service Broker\External Activator\Bin\ssbeas.exe) is instantiating the code....this is not something (to my best knowledge) that I can run in "Debug Mode" to wait for the call to come in and have a breakpoint set.
For example, with a WEBAPI project, I can do the traditional Start/Debug, and put a breakpoint on the ApiController/Method, and when a request comes in, it will break on the breakpoint, and I can pick up the debugging from there.
With Service Broker, it is instantiating some .exe....and the .exe may open and close so quickly, and I cannot "search and find" to attach a debugger to it.
I also thought, "Maybe I'll have Service Broker send messages to a WCF service", but that looks like it is not possible or very cumbersome to implement, based on what I read at this SOF post:
Service Broker and WCF interoperability
Is there anyway for me to do the above setup in EAService.config AND get the debugger to break as seen in the image below?
Or has anyone figured out a non hacky way to debug the C# code that is "activated" by Service Broker?
You have several options:
A. Modify the EAConfig to launch the program under debugger:
<ImagePath>C:\PathToDebugger\YourDebuggerOfChoice.exe</ImagePath>
<CmdLineArgs>C:\SomeFolder\SomeConsoleApp.exe myCommandLineArg1</CmdLineArgs>
B. Use GFlags image execution options to add a debugger to your app
C. Launch debugger from the app itself with Debugger.Launch()
D. Disable EA and run the application directly from VS (F5), for debugging purposes, then enable EA back.
So this is what I ended up with...as the most consistent method I could find.
static void Main(string[] args)
{
try
{
#if DEBUG
int index = Array.FindIndex(args, x => x.Equals("LAUNCHDEBUGGER", StringComparison.OrdinalIgnoreCase));
if (index > -1)
{
System.Diagnostics.Debugger.Launch();
}
#endif
<LaunchInfo>
<ImagePath>C:\SomeFolder\SomeConsoleApp.exe</ImagePath>
<CmdLineArgs>myCommandLineArg1 LAUNCHDEBUGGER</CmdLineArgs>
<WorkDir>C:\SomeFolder\</WorkDir>
</LaunchInfo>

Application_start not working

I have written some code in the application_start() method in my global.asax file. It does not get called when I deploy my application on IIS server. The code is accessible when I run it in the .NET framework.
I've tried to restart the application many times, but it's still not working.
I've also tried the suggestion from the following link.
Application_Start not firing?
There are few things you need to know before you are trying to debug Appplication_Start. There are -
One : When the code executes and why it is almost impossible to debug by attaching to it.
The application start method is executed when the application pool starts and your website is being started up for the first time. If you deploy new deliverables to IIS, then IIS might restart it itself, but there is no guarantee that it will. So, deploying new codes does not guarantee that it will restart the pool and he execution of application start. You should restart your application pool to guarantee execution of application start.
While debugging IIS applications, Visual Studio attaches itself to a process something named w3wp.exe or similart (I forgot the actual executable name), which is the worker process and only available after, remember after, your application pool is up and your site is up. So, in other words, if you are seeing this in service list, then the application start has already been executed and attaching to it will not give you a chance to debug it. It is kind of a tug of war with time.
So, in other words, it is kind of impossible to debug application start unless you are very very quick.
Two, the solution 1 - With Dev Server
Launch your application in visual studio with Asp.net development server or IIS express, then you will be able to debug. But if you really want to debug on IIS, then check the next section
Two, the solution 2 - With IIS
There is a library in the name System.Diagnostics, Debuggerand it has a nice way to call debugger in code. You can read it here - http://msdn.microsoft.com/en-us/library/system.diagnostics.debugger.break(v=vs.110).aspx
Modify you application start with this -
public void Application_Start(){
....... //other codes
Debugger.Break() or Debugger.Launch()
}
When this line executes, IIS will halt execution, and will show you a debugger selector window (similar to the one attached), keep your solution open in vs and select that vs from the list, will be able to debug as usual... :)
In case you are using windows 8 and the debugger does not launch, read this article to enable it -
http://blogs.msdn.com/b/mapo/archive/2013/11/07/debugger-launch-not-displaying-jit-debugger-selection-popup-on-windows-8-8-1.aspx
Three: A very important thing
I noticed that you said, you are adding db entries in Application_Start. You should keep in mind that, Application_Start does not have a HttpContext, ViewContext, So your db access code may fail for so many others reasons.
Make sure that the Global.asax file is actually deployed to the destination folder in the root. If the file is not present then the code behind you have written for Application_Start will never be called.
Also make sure the signature is correct
public class Global : System.Web.HttpApplication {
protected void Application_Start(object sender, EventArgs e) {/*do something here like logging so you know it was called*/}
}
If you are running Server 2008R2 (or earlier) and/or IIS 7.5, you might want to look into the Application Initialization module. This can be downloaded here:
www.iis.net/downloads/microsoft/application-initialization
With IIS versions prior to 8.0, the application start is not called until the first web request arrives. I'm reading your question as you want your application start to be fired before the first web request, yes?
Here is a fantastic guide to configuring this module (if it applies to you):
https://blogs.msdn.microsoft.com/benjaminperkins/2014/01/07/configure-the-iis-application-initialization-module/
The key takeaways is that you need to set your app pool to 'AlwaysRunning' instead of 'OnDemand'. You also need to set a preloadEnabled flag for your website. Once both of these are done, fire off an iisreset and you should see the results of your application start (look in the database since it's writing there).
Other answers are relevant as well, in that this is tough to debug and you're missing all the niceties you're used to such as a httpcontext in app start.
If you are running IIS 8.0 - you should still read the above link to configure preloading.
This did work for me:
Menu -> Build -> Clean Solution
Menu -> Build -> Rebuild Solution
Then, Application_Start() was fired only for the first time.
In my case in production environment App_global.asax.compiled was missing and all content of global.asax not fired.

windows service: failed to debug

I was following the instructions in official msdn to debug my windows service:
http://msdn.microsoft.com/en-us/library/7a50syb3.aspx
however, after I attached the process to debugger and tried to Stop the service in Service Control Manager, the process just disappeared and the debugger thus exit without hitting any break point.
I chose the process name as the executable of my window service application.
Did i do anything wrong?
When the debugger is attached to a process, clicking the blue Stop button usually terminates the process, that's why you saw the service process disappear. Of course at that point, breakpoints won't be hit since all the modules for that process are unloaded. If you want to detach from the service and still let it run, in the Debug menu in Visual Studio click Detach All.
It feels like though you're having issue debugging your service. Debugging Windows services is a little different than debugging other projects in Visual Studio. Just clicking the green "play" button doesn't automatically put the service in debug mode. In many cases, the breakpoint needs to be set in the OnStart() method since that is where the problem occurs. They way I always debug Windows services is by putting a Thread.Sleep() statement on the top of the OnStart() method, before the program attempts to do anything else. You can specify how long you want the main thread to be asleep, and then use this time to attach the VS debugger to the Windows service. For example:
protected override void OnStart(string[] args)
{
Thread.Sleep(10000);
// Rest of the code
}
Will give you 10 seconds to attach to the service. Install the service, start in in the Services window, and then attach to it.
Can you try adding this at the top of your service....
System.Diagnostics.Debugger.Launch();
or if possible, convert your service to use http://topshelf-project.com/. Which supports debugging in visual studio. And has an added benfit of allowing the service to "run as console app" for debugging.

Activator.CreateInstance fails in Windows Service

I have an issue with a Windows Service which throws a NullReference exception whenever I try to use
var myType = Activator.CreateInstance(typeof(MyType))
There is no problem whenever I run the exact same code in a console window - and after debugging the obvious "which user is running this code" I doubt that it is a mere fact of changing the user running the service as I've tried to run the service using the computer's Administrator account as well as LocalSystem. I'm suspecting a Windows Update fiddling with default user rights but that's a bit of a desperate guess I feel.
Remember: The type and assembly exist and works fine - otherwise I wouldn't be able to run the code in a console window. It is only when running in the context of a Windows Service I get an error.
The question is: Can I in any way impersonate i.e. LocalSystem in a unittest by creating a GenericPrincipal (how would that GenericPrincipal look)?
You could always run a visual studio instance as LocalSystem. From the command line, enter the following:
at <time in near future> /interactive <path to devenv.exe>
Then wait for that time to roll around and VS should open up, but will be running under the LocalSystem account.
I'd personally not suspect the user account, and instead suspect that it's something to do with being interactive - does the constructor or class constructor for MyType have some implicit dependency on the desktop?
(Edit - oops, should be time before /interactive, corrected command line).
e.g.
at 11:48 /interactive "c:\Program Files\Microsoft Visual Studio 9.0\Common7\IDE\devenv.exe"
I know its a simple answer but have you tried putting it in a try catch block then writing out the exception to see if it is Permission based or otherwise.

Canceling a programatically started SQL Server Express Install

During my application setup, the user has the option of installing a new SQL Server Express 2005 instance in the local machine if they don't want to use an already existing SQL Server 2005 in their network for whatever reason.
As the SQL Server installation is optional, I don't have it as a prerequisite of my installer. Instead, I just bundle the sqlexpr32.exe setup in my install media and programatically launch it with the appropriate command line arguments in order to perform an automatic install. (Note: I'm using the /qb command line flag so the install is not silent, it shows the user interface, but does not ask for any user input). And in case anyone wants to know, I'm following this Microsoft article on how to launch the SQL Server Express setup.
This is what I'm doing in my custom install action:
// All this runs on a background thread so the user
// can cancel my app's setup at any time
// Launch the installer
Process setupProcess = new Process();
setupProcess.StartInfo.FileName = "sqlexpr32.exe";
setupProcess.StartInfo.Arguments = " a bunch of command line args here";
setupProcess.StartInfo.UseShellExecute = false; // to avoid a shell window
setupProcess.Start();
// At this point the SQL Server installer is running
// Monitor the process on 2-second intervals:
while (!setupProcess.WaitForExit(2000))
{
if(WasCancelled) // flag that is set when the user cancels my app's setup
{
// This following line is my problem. Sending CloseMainWindow does not
// seem to work. The SQL Server installer just keeps running.
setupProcess.CloseMainWindow();
setupProcess.WaitForExit();
break;
}
}
// After this point I build a results report for the user.
// My app's installer does not yet quit even if it was canceled.
So my question is: How could I 'signal' the SQL Server installer process to cancel and exit?
This line does not seem to do anything:
setupProcess.CloseMainWindow();
This also does not work:
setupProcess.Close(); // This closes my handle. Not the target process.
And I obviously wouldn't want to just kill the process as I could be leaving the user's machine in a not-so-desirable state, in the best case with a lot of garbage files or worse, with a corrupt install.
Any ideas? Sending keys or simulating user clicks? Or hopefully something less hacky?
EDIT:
I think I have found out why CloseMainWindow does not work:
The process I start (sqlexpr32.exe) is not really the one that shows the UI for the SQLServer Installer, but a self-extracting exe that in turn launches the sql server real setup.exe as a child process. So this issue gets even harder. =(
What if you wait until the installer finishes, and after that - if the user has cancelled the main process - you uninstall it immediately?
I know it's a more time consuming process but it's clear and easy.

Categories

Resources