This question is not about how to restart an application. I am already achieving that by using a Mutex and a secondary starter application. I had to resort to that after facing some problems using Application.Restart.
In any case, not being fluent with IL, I was wondering if someone could explain how Application.Restart works in the first place. It is a call to the runtime but what exactly does the runtime do? How does it close the existing instance and how does it know when to launch a new one?
... not being fluent with IL, ...
Have you considered using a decompiler (Reflector, dotPeek) or, even better, the reference source code of the .NET framework?
Anyway.
At a casual look it does the following:
In all below cases, the current instance is terminated using Application.ExitInternal(). That is the gist of the public Application.Exit() method, eliding some security checks/asserts.
See if it can determine the Assembly.GetEntryAssembly(). If that is null the call the Application.Restart() was most likely done from unmanaged code and the operation throws a NotSupportedException to the caller.
See if the current process is ieexec.exe, if so use it to restart the application (for more information about ieexec.exe see here). Actually that is pretty much also a Process.Start() call to ieexec.exe, but the command line arguments are not gathered by Environment.GetCommandLineArgs() (see below), but by reading the APP_LAUNCH_URL application domain data.
See if the application is a click-once application (ApplicationDeployment.IsNetworkDeployed), if so call an CLR internal native code to (re)launch that: CorLauncApplication. The only publicly available source code that somewhat resembles the native parts of the CLR is the shared source CLI (sscli), which is based on the .NET 2.0 framework and also is partly incomplete. It contains a definition for that function (clr\src\vm\hosting.cpp), but it is only a stub. In the end it will use some means to restart the process (e.g. Win32's CreateProcess API).
Else: the application is a "regular" .NET application. Environment.GetCommandLineArgs() is used to recreate the original command line and Process.Start(Application.ExecutablePath) is used to restart the application.
The use of the Application.Exit-mechanism to try to end the current instance is probably the reason why you find it unreliable. Forms that cancel the send closing event can interrupt it. Also see this SO question.
Related
EDIT: (Resolved by number 6)
What causes a System.AccessViolationException or System.ExecutionEngineException crash in SQLitePCLRaw.provider.e_sqlite3.dll when multiple threads access my FooDbContext simultaneously?
I have a Xamarin Forms app (3.5.0.169047) supporting UWP, Android, and iOS, using NETstandard 2.0.3, Microsoft.EntityFrameworkCore 2.2.4, Microsoft.EntityFrameworkCore.Sqlite 2.2.4, and I have a reproducible crash situation (it happens for sure on UWP) that I'm have trouble resolving that arises during simultaneous access to a sqlite database on device from two different threads at once. I have a sync process (pushes local data to an API and pulls online data from an API) that can take up to a minute or so that I need to execute in a separate thread to keep the UI responsive during its operation. I also need to allow querying of local data during sync to allow navigation during sync or other read-only data operations within the app during sync. The long-running sync works fine if I don't do any data access operation during the sync, but crashes right after the completion of any interrupting shorter data access operation.
The two crash exceptions that I've seen occur (possibly timing related for which causes the crash on identical reproductions) are the following, as seen from the Debug output from Visual Studio 2017 (v15.9.5):
An unhandled exception of type 'System.AccessViolationException' occurred in SQLitePCLRaw.provider.e_sqlite3.dll
Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
An unhandled exception of type 'System.ExecutionEngineException' occurred in SQLitePCLRaw.provider.e_sqlite3.dll
While debugging, there is no additional detail about the exception; it happens during different long-running lines of the sync code, depending on the timing of doing the interrupting action; and the long-running code where the debugger shows the exception occurring is all contained within a
Try { ... } Catch(Exception) { ... } try block in my code.
What might be causing this and how can I resolve it?
I've gone through all of the following:
Is the SQLite usage compatible with multiple threads?
Yes; it is in "Serialized" mode by default according to https://www.sqlite.org/threadsafe.html and that supports multi-thread usage without restriction. The underlying version of SQLite being used is 3.26.0, which I determined while investigating my Microsoft.Data.Sqlite.SQLiteConnection information while debugging.
Is it because I can't have more than one connection open with write capabilities simultaneously?
No; I even modified my connection strings using Microsoft.Data.Sqlite.SqliteConnectionStringBuilder to have the appropriate Mode (SqliteOpenMode.ReadOnly or SqliteOpenMode.ReadWriteCreate) depending on the needs of each data access.
Is it because the interrupting thread's FooDbContext's Dispose() gets rid of resources that the long-running thread's FooDbContext relied upon?
No; I investigated this a lot since that was the last breakpoint I could hit prior to the crash. Even when I overrode the Dispose method in FooDbContext to do nothing, not even call the base class's Dispose (not recommended, but I tried it temporarily), the crash still occurred.
Is there a setting I can set using Microsoft.Data.Sqlite.SqliteConnectionStringBuilder or Microsoft.Data.Sqlite.SQLiteConnection or Microsoft.EntityFrameworkCore.DbContextOptionsBuilder's UseSqlite function to ensure that Serialized mode is used (I wasn't 100% sure it was at this point)?
No; I looked extensively, and that option must be hidden away in the internals of the SQLite library chosen.
I did a fair amount of reading and research, which still gave me little else I could try.
https://www.sqlite.org/sharedcache.html
https://www.sqlite.org/lockingv3.html
https://www.sqlite.org/atomiccommit.html#sect_9_0
https://www.sqlite.org/uri.html
https://learn.microsoft.com/en-us/ef/core/get-started/uwp/getting-started
https://learn.microsoft.com/en-us/ef/core/get-started/netcore/new-db-sqlite
https://github.com/aspnet/EntityFrameworkCore/issues/5466
https://learn.microsoft.com/en-us/windows/uwp/data-access/sqlite-databases
https://www.connectionstrings.com/sqlite/
https://csharp.hotexamples.com/examples/-/DbContextOptionsBuilder/UseSqlite/php-dbcontextoptionsbuilder-usesqlite-method-examples.html
https://system.data.sqlite.org/index.html/info/dd30ecb89d423c4c
https://www.sqlite.org/src/info/e8d439c77685eca6
https://forums.asp.net/t/2143077.aspx?EntityFramework+Core+Do+we+have+to+explicitly+dispose+the+DBContext
https://github.com/aspnet/EntityFrameworkCore/issues/9901
https://xamarinhelp.com/entity-framework-core-xamarin-forms/
EDIT: Answer that solved this problem for me:
I noticed that the dll the exception came from was SQLitePCLRaw.provider.e_sqlite3.dll. That led me to looking at what actually sets up the low-level SQLite library, and it is ultimately the call to SQLitePCL.Batteries_V2.Init(); that selects the platform-specific low-level SQLite provider to be used. Could that be wrong?
Yes; it turns out that after reading through the wiki info at https://github.com/ericsink/SQLitePCL.raw/wiki/SQLitePCL.Batteries.Init#what-does-batteries_v2init-do that the call to SQLitePCL.Batteries_V2.Init was intended to be done only once per platform (either in platform specific code, or in the shared code as long as Microsoft.EntityFrameworkCore.Sqlite is installed in the shared project as well as each platform specific project). My SQLitePCL.Batteries.Init usage was incorrectly inside OnConfiguring in FooDbContext, which made it called once per configuring of a FooDbContext instead of only being done once per app startup. Moving the SQLitePCL.Batteries_V2.Init(); line out of OnConfiguring, and into the App.xaml.cs constructor in my shared project fixed it! The crashes no longer occurred after the interrupting thread's data access. I really hope this saves someone the huge hassle it saved me trying to get to the bottom of this.
Answer that solved this problem for me:
I noticed that the dll the exception came from was SQLitePCLRaw.provider.e_sqlite3.dll. That led me to looking at what actually sets up the low-level SQLite library, and it is ultimately the call to SQLitePCL.Batteries_V2.Init(); that selects the platform-specific low-level SQLite provider to be used. Could that be wrong?
Yes; it turns out that after reading through the wiki info at https://github.com/ericsink/SQLitePCL.raw/wiki/SQLitePCL.Batteries.Init#what-does-batteries_v2init-do that the call to SQLitePCL.Batteries_V2.Init was intended to be done only once per platform (either in platform specific code, or in the shared code as long as Microsoft.EntityFrameworkCore.Sqlite is installed in the shared project as well as each platform specific project). My SQLitePCL.Batteries.Init usage was incorrectly inside OnConfiguring in FooDbContext, which made it called once per configuring of a FooDbContext instead of only being done once per app startup. Moving the SQLitePCL.Batteries_V2.Init(); line out of OnConfiguring, and into the App.xaml.cs constructor in my shared project fixed it! The crashes no longer occurred after the interrupting thread's data access. I really hope this saves someone the huge hassle it saved me trying to get to the bottom of this.
I have the a service, that loads some dlls and starts a function in each dll. Each dll contains some rules, that can be also developed by our clients (something like plugin system). The problem is, that clients can theoretically add forms to be called inside dlls. So the goal is to disallow that, or, at least block such dlls.
The only method I can imagine now is call each dll in a separate thread and kill it after some timeout.
But I think it is not so nice.
Please advice me a better method. Thankx.
The best way to deal with plug-ins is to "sandbox" each one of them in an individual app domain. This way you can safely react to their execution errors, unload them if you need to, and manage them in whatever ways you like. But most importantly for this question, you can monitor their loading of assemblies using this event hook. If you see them loading a DLL that you do not want to allow, you can simply throw an exception. Your code would catch the exception, clean up the app domain, and optionally send the clients a warning for trying to do something that is not allowed.
The only downside to this approach is that it is rather non-trivial to implement.
It is VERY hard problem to protect server from third party code that you need to execute.
I would recommend reading on SharePoint sandbox approach (i.e. http://msdn.microsoft.com/en-us/library/ff798382.aspx) which tries to solve this and related issues.
As SLaks said - you implicitly trust code by simply executing it. Unless you expect code to be outright evil you may be better of by simply logging how long calls take (and maybe time out if possible) and provide your client with this information. Since it seems like client creates the code for themselves it is unlikely that code will be explicitly made non-functional.
Other interesting issues outside showing a Form:
stack overflow exception (easy to create, hard to handle)
while(true); code that never returns control
access to native code if full trust enabled.
You could always use reflection to inspect their code and ensure that certain namespaces and classes (e.g. System.Windows.Forms.*) are not referenced or used.
SQLCLR restricts what is allowed to be used/referenced in assemblies installed as SQLCLR extensions, and that appears to be done that way: http://msdn.microsoft.com/en-us/library/ms403273.aspx
My application (base application is MFC interop with C++/CLI but it also contains a lot of C#, Windows Forms, WPF) has has a handle leak. Shortly after application start I can see the handle count in the task manager grow continuously (at a rate of 10 new handles per second). So I used handles.exe to see what kind of handles they are. I found out that the leaking handles are process handles. And they are process handles to the process of my application.
So I wonder what operations would typically create a handle to the process it runs in. Any idea? Have you ever seen something like this? What else could I do to track down the leak, considering that I can't use debug DLLs and that I can only use tools that can be xcopy deployed.
Update:
I was able to throw windbg and !handle, !htrace at it and found out that the process handles are all created using the following stack traces (ordered by frequency):
0x79f7570b: mscorwks!CorExitProcess+0x00022055
0x79f03edd: mscorwks!GetPrivateContextsPerfCounters+0x0000b6fe
0x79f04b87: mscorwks!GetPrivateContextsPerfCounters+0x0000c3a8
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f
or
0x7c8106f5: kernel32!CreateThread+0x0000001e
0x79f04bb2: mscorwks!GetPrivateContextsPerfCounters+0x0000c3d3
0x79f04b03: mscorwks!GetPrivateContextsPerfCounters+0x0000c324
0x79f919bf: mscorwks!CorExitProcess+0x0003e309
0x79f91b28: mscorwks!CorExitProcess+0x0003e472
0x792d6b4c: mscorlib_ni+0x00216b4c
0x1391a663: +0x1391a663
0x1391a0b1: +0x1391a0b1
0x7a9ea544: System_ni+0x005aa544
0x792a842f: mscorlib_ni+0x001e842f
or
0x08ec2eba: +0x08ec2eba
0x792b8277: mscorlib_ni+0x001f8277
0x792b8190: mscorlib_ni+0x001f8190
0x792b8040: mscorlib_ni+0x001f8040
0x792b7ff2: mscorlib_ni+0x001f7ff2
0x677e48f3: System_Runtime_Remoting_ni+0x000748f3
0x677e44be: System_Runtime_Remoting_ni+0x000744be
0x677e46ec: System_Runtime_Remoting_ni+0x000746ec
0x677e8408: System_Runtime_Remoting_ni+0x00078408
0x7926eb8d: mscorlib_ni+0x001aeb8d
Now what does that tell me?
The call stacks look wrong. Did you setup the symbol server correctly? .symfix should do the trick in Windbg. Afterwards you should get a better stacktrace.
It looks like part of the code that has this problem is managed so it would make sense to break on DuplicateHandle and OpenProcess and dump the managed call stack there. These two methods are the only ones which could produce a real process handle.
You can declare a breakpoint like this and execute commands when the breakpoint is hit.
In this case the managed stack is printed and then the execution does continue.
bp kernel32!OpenProcess "!ClrStack;g"
Had same issues with a webservice calling COM objects through interop.
I solved this by explicitely calling Marshal.ReleaseComObject against the interop objects I created. No issues after that moment for me.
Hope it helps.
So... are you doing performance counters explicitely (if so, try disabling them to narrow down on the source of the leaks).
This may be a long shot but I'm out of ideas.
I've got a VS C# solution with three projects in it. There's a class library project and then two application projects that depend on that class library. The class library in turn depends on a few other DLLs including the avalonedit dll from the sharpdevelop project.
One of the applications is building and running fine, including a use of my own control that wraps the avalonedit control. The other application is failing to run and it seems to be failing at the point when the avalonedit control is initialised via the XAML in my wrapping control.
The problem is that I don't see any errors in the debug output at all, all I see is the dll loaded message and then nothing. If I step into the constructor of my control the step never completes. The debugger says the app is running, but it is apparently spinning somewhere in the avalonedit dll when the underlying edit control is constructed by the XAML side.
I have to assume that there's some issue with difference in environment between the two projects but I'm kind of stumped as to how to proceed in tracking the problem down. Am I going to have to somehow get arrange matters so that I can put a break in the avalonedit source?
Edit: If I pause/break all it just drops back to the line calling my control constructor.
Sounds like a deadlock. Take a close look at all threads, their stack traces and synchronization primitives (locks, semaphores, etc.). Keep in mind: contended resources may not be explicit (for example, when you are inside static constructor waiting on something that tries to get access to a static field of the type being constructed you get a deadlock).
There are many ways to introduce a deadlock but no simple advice to handle it. You could also enable break on all exceptions in Visual Studio (Debug -> Exceptions... and tick CLR Exceptions).
If this does not help you could provide stack traces here and maybe somebody could spot the problem.
How can I snuggle into another process? Like, share another process's name? So if my application is griddemo.exe, and I want to snug into, let's say, explorer.exe, is that possible? Just read something about CreateRemoteThread() from kernel32. Is that in the right direction? Would there be security/UAC issues?
First of all sorry, but my answer will be longer as another answers.
I use DLL injection since years in different version of operation system (from windows NT 4.0 till Windows 7) and I had no time any problem with any virus scanner (inclusive both Norton and McAfee in different versions). So I disagree with Stephen Cleary (see his answer) in this aspect.
Usage of CreateRemoteThread() is really only one of the ways. AppInit_DLLs is another way. Both has its advantage and disadvantage. The main advantage of AppInit_DLLs is a simplicity to inject DLL in any process. The main disadvantages of AppInit_DLLs approach are following:
All GUI application will load the DLL. If you want to load it only in one process like explorer.exe you can't do this. So the working space of all GUI processes will be increased by your DLL. An error in your DLL (especially inside of DllMain or in any dependency DLL of your DLL) can crash many processes which you don't currently know.
You can not inject your DLL with respect of AppInit_DLLs approach in a console application or in any EXE which have no dependency to User32.dll.
You should be very careful inside of your DllMain, because it will be called before User32.dll will be full initialized. So a safe DLL which you can use inside of DllMain of your DLL is Kernel32.dll.
With respect of CreateRemoteThread() one can start an additional thread in a process. The main problem of CreateRemoteThread() is that its lpStartAddress parameter must be an address from the remote process. So one have to use functions OpenProcess, VirtualAllocEx and WriteProcessMemory to write some information into the memory of the destination process. To be able to open a process one have to have debug privilege enabled. If you want to do only 2 + 2 inside of the destination process you can copy the corresponding binary code directly into destination process. All real interesting work can be done with usage of some Windows API. So mostly one don't copy a code. Instead of that one call LoadLibrary("MyPath\\MyDll.dll") inside of destination process. Because the prototype of LoadLibrary is the same as prototype of ThreadProc of CreateThread you can call LoadLibrary as a ThreadProc of CreateRemoteThread(). This way has the name DLL Injection.
I recommend you to use this DLL Injection only if it really required. If your destination application has some other way like plug-ins to load you DLL inside the process your should use this way instead of DLL Injection.
Some general problems you will have to solve after you have a working example of DLL Injection. This problems you can don't see at the first time, but after a long usage of your application you will see its importance:
You should find the moment when the destination process are already running before you can use CreateRemoteThread().
The destination application must be already initialized before you call CreateRemoteThread(). So you should not use CreateRemoteThread() too early. In case of explorer.exe you can use a start of your small trigger program from Run registry key. At the moment is explorer.exe fully prepared for DLL injection.
You should take in consideration 64-bit version of Windows.
Don't forget about DLL relocation inside of destination process. Be careful, that you DLL can be loaded in the destination process at the other address as in your process. Mostly it is a good idea to choose a good base address (linker option) for you DLL which you will inject. The Kernel32.dll can be sometime (very seldom) loaded at the other address as in your source process. You can create a DLL Injection code which are free of this problem.
Terminal Services isolates each terminal session by design. Therefore, CreateRemoteThread fails if the target process is in a different session than the calling process. The problem you can see on XP (which is not connected to domain) or especially on Vista or Windows 7 if you try make DLL injection from a windows service. To fix the problem you should make DLL Injection either from the process running on the same terminal session as destination process or you have to switch current session before using of CreateRemoteThread. Your process must have SE_TCB_NAME privilege enabled and use SetTokenInformation with TokenSessionId parameter. To get session id of the destination process you can use different methods. Functions with the prefix WTS (like WTSGetActiveConsoleSessionId) can be very useful.
So everything is not very easy, but it is really interesting subject where you can study a lot of things about operating system. You should only spend a little time to analyse your problem and different ways to solve it before you choose one way which corresponds your project requirements and start programming.
DLL injection is the traditional method of doing this. It's quite tricky, especially since virus scanners look askance at the practice. So even if you get it working, Norton/McAfee would be likely to block you - or block you in the future.
One easy way of DLL injection is the AppInit_DLLs registry value. Note that Microsoft has reserved the right to simply remove this functionality (and likely will do so in the future).
The Microsoft-approved way to achieve DLL injection is licensing Microsoft Detours.
Note that your DLL must be built against the CLR version 4.0 or higher to perform DLL injection safely, because this is the first version to support in-proc side-by-side.
If you mean injecting your code into another process, then dll injection is one technique:
http://en.wikipedia.org/wiki/DLL_injection
Haven't done this for years, so not sure how happy modern MS Windows operating systems (i.e. post XP) are going to be with this.
I've not tried this lately, but another way to do this would be to create a Hook DLL:
Create a DLL that contains a Hook Procedure like MessageProc.
Install this DLL into Windows\System32.
Use FindWindows(Ex) to locate your victim process' window.
Use GetWindowThreadProcessId() to find the owning thread of that window. This is necessary to avoid injecting your DLL into every single process on the system.
Use SetWindowsHookEx to hook that thread.
PostMessage a WM_USER message to the window - activating your Hook DLL if it isn't already active.
This would likely invoke the new Windows Vista/7 UIPI/UAC if you're not a sufficiently privileged user but this depends on many factors - your mileage may vary.