How to update dll-file without program being restart?
I want to create my "Updater" class. It's main idea is to
check local(connected to executive file) and server dll-files,
and when newer version is available, copying server file to local.
Code:
Updater updater = new Updater(LOCAL_PATH, SERVER_PATH);
if (updater.IsAvailableNewerVersion)
updater.Update();
Updater's ctor take two paths - to server dll and to local dll and calculate their Versions.
Then I call a property IsAvailableNewerVersion - if it's true (available version is newer then a local), I call Update method.
Main Idea of Update method is to copying server dll-file to local with overwrite, and say to user to restart program.
Code:
public class Updater
{
private readonly string _localPath;
private readonly string _serverPath;
private readonly Version _currentVersion;
private readonly Version _availableVersion;
public Updater(string localPath, string serverPath)
{
_localPath = localPath;
_serverPath = serverPath;
_currentVersion = AssemblyName.GetAssemblyName(_localPath).Version;
_availableVersion = AssemblyName.GetAssemblyName(_serverPath).Version;
}
public bool IsAvailableNewerVersion => _availableVersion.Major > _currentVersion.Major ||
_availableVersion.MajorRevision > _currentVersion.MajorRevision ||
_availableVersion.Minor > _currentVersion.Minor ||
_availableVersion.MinorRevision > _currentVersion.MinorRevision ||
_availableVersion.Build > _currentVersion.Build ||
_availableVersion.Revision > _currentVersion.Revision;
public void Update()
{
try
{
File.Copy(_serverPath, _localPath, true);
}
catch (Exception e)
{
MessageBox.Show("Unable to copying file - " + e);
return;
}
MessageBox.Show("File was successfully updated. Please restart program.");
}
}
Is there a way to check dll-files before they being used?
How to update dll-file without program being restart?
P.S.
I think to use server dll-files, but my program becomes dependent on the server that is not good.
You can't really unload / change the assemblies in a running app-domain; so basically you have two options here:
use a launcher exe that does this work and invokes an inner exe to do the real work, shutting it down when complete (launching a new one either before or after the shutdown)
use multiple app-domains in a single exe, isolating where each loads from
The second approach is more useful for server applications, since you can handle the network IO in the outer exe and funnel requests through to the inner app-domain, just changing a single reference to swap between the two systems. However, app-domains aren't in .NET Core, so you should be aware that it limits your flexibility.
1. Is there a way to check dll-files before they being used?
If you are using a single EXE, it depends on how you use the DLLs. If they are hard coupled to your app, I do not know any way on how to do so.
But if the DLLs are just implemeting interfaces of your core DLLs, you could load them using:
Assembly assembly = Assembly.LoadFrom("path\orbital.dll"));
Type type = assembly.GetType("FullClassName");
object instanceOfMyType = Activator.CreateInstance(type);
This requires you to follow some design patterns, what would be good for your app. But if you already have several DLLs strongly coupled (that means, you added them as reference in your Visual Studio project and are creating objects as var object = new YourOtherDLLNamespace.YorObjectInTheOtherDLL()) then you will probably take a lot of time to change to this approach.
The good about this approach is that you could check the DLL version before loading it, copy a new version from a server (or any other method you find appropriate) and then load it.
2. How to update dll-file without program being restart?
Ok, lets suppose you made just like my suggestion on item 1. Once you loaded the DLL, you wont be able to Unload it. You could destroy all the objects using the garbage collector, but that won't change the way windows is loading it.
So the basic answer for a single EXE is no.
Other solutions
You could wrap your solution in other EXE that keeps constantly checking if the DLL is updated, send a custom event (so that your app EXE would now what is going on an take appropriate action before shutting it down), notify the user and, if the user wants to do so, then you could close the app. Then your other app wrapper would update it and launch the EXE again.
Related
I am using filehelpers ExcelStorage somewhat like this:
ExcelStorage provider = new ExcelStorage(typeof(Img));
provider.StartRow = 2;
provider.StartColumn = 1;
provider.FileName = "Customers.xls";
provider.HeaderRows = 6;
provider.InsertRecords(imgs.ToArray()); // imgs was a list before
And when I am done inserting records, I would like to open the Excelfile I created (with my software still running). But it seems that Excel is somehow locked. I.e. there is an Excel instance running in process manager. When I kill all Excel instances I can open the file. Do I have to dispose the ExcelStorage in some sort of way?
I've used FileHelpers, but not ExcelStorage. The link here suggests that you should probably be using FileHelpers.ExcelNPOIStorage instead.
Looking at the source code for ExcelStorage, there is no public dispose method. There is a private CloseAndCleanup method which is called at the end of InsertRecords. Therefore I don't think there's anything you are doing wrong.
The usage of ExcelNPOIStorage looks very much the same, there is a call to GC.Collect() within the private cleanup method here, so I'd guess that there was a known issue with the cleanup of the prior version of the component.
Your best bet is to grab a copy of HANDLE.EXE which you can use with an elevated command prompt to see what has a handle to the file in question. This may be your code, anti virus or excel (if open). Excel does keep a full lock on a file when open preventing ordinary notepad access etc.
If the process owning the handle to the file is your own code, then see if the handle exists once you have exited back to the development environment. If that clears the handle, then you are not releasing the lock properly and that can be slightly trickier as it will depend on exactly what you have coded.
The CloseAndCleanup function mentioned by #timbo is only called from a few places, the Sheets property and the ExtractRecords / InsertRecords functions. The only other thing to wonder is whether you are seeing any exceptions when it attempts to perform the CloseAndCleanup or the reference count the Excel application hasn't been properly released by the COM system.
If you can replicate this with a small sample app, I will be more than willing to give it a quick test and see what happens.
Note 1, if you are running your code from within Visual Studio, it may be a process called <APPNAME>.VSHOST.EXE which is visual studio's development process, or if you've turned off Visual Studio hosting, just your <APP>.EXE. If running within IIS for a web page or web service, you will more than likely have a w3p process.
Note 2, if you run handle without being elevated, it may or may not find the handle to the file in question. Therefore, it is always recommended to run elevated to ensure results are accurate.
Note 3, the difference between ExcelStorage and ExcelNPOIStorage is that the former deals with .xls and the latter deals with .xlsx if I remember rightly.
I would like to use a temporary directory which would be automatically deleted once the application is stopped.
Does such a mechanism exist in the framework, or should I program it myself ?
Thanks !
There's nothing built-in that will do that. You can create the folder on startup and lock a file in it to prevent it's deletion by another process, but I'm pretty sure that's it.
If it's important that this folder not exists at all if the app isn't running then you'll want a service that monitors both the state of the app and folder. This way, should the app crash or the computer restarts, you'll be (reasonably) certain that the folder isn't accessible past either of these scenarios. Of course you will want to make your service start automatically on boot.
No built-in method for Directories exists as far as I know, but you can do easily mimic that behaviour by creating a disposable class and the using construct, which ensures that the folder will be deleted even if the app terminates unexpectedly:
public class TempFolder : IDisposable
{
public string RootPath { get; private set; }
public TempFolder()
{
RootPath = Path.GetTempPath();
}
public void Dispose()
{
Directory.Delete(RootPath, true);
}
}
Then, in your application:
public static class MyApp
{
public static void Main(string[] args)
{
using(var tempFolder = new TempFolder())
{
// Do my stuff using tempFolder.RootPath as base path to create new files
}
// temporal directory will be deleted when we reach here
// even if an exception is thrown! :)
}
}
Note that this is a simplistic approach; beware of locked files inside the temporally directory that may cause the Directory.Delete operation to fail
Also, some in some cases the Dispose method could not be called:
Some uncatchable exceptions like StackOverflowException and OutOfMemoryException
An uncatched exception is thrown in a different thread spawned by your application
The process is killed
BTW I'm using a similar approach to handle some NUnit tests that must operate over files, and it is working fine so far.
You should also keep in mind the application may be quit in a unusual way. Maybe even power down the computer. So the folder may already exists when you restart the program.
Windows API has support for files to be created such that when the last handle to the file is closed, the file is deleted. However, I'm not sure such exists for a directory. Look into System.IO.File.CreateFile(); and FileOptions.DeleteOnClose for description. Also look into underlying Win32 API - perhaps you can adapt it to your needs.
I'm trying out LabView, experimenting with how to use it in conjunction with .NET. I've managed to create a small app that reads a gauge, converts the value in .NET, and displays the result on another gauge.
The trouble is that when I try to add to the .NET project and rebuild, the DLL is locked and I can't overwrite it. NI claims that LabView uses Shadow Copying. But if that's true, my DLL shouldn't be locked.
Is there some way I can get LabView to stop locking the DLL? Other than exiting LabView every time I want to rebuild, which seems like a tedious fix.
What I believe is happening in your application is the following:
When Labview launches, it pulls in the dll of your application, tightly locking it into memory. As such, the file is locked and Visual Studio won't be able to overwrite this file (I have directly seen this behavior in other applications). Since the dll never gets freed until Labview exits, you need to find a way to "trick" Labview into loading a fresh dll every time you re-compile.
Here is what I recommend:
In LabView, instead of loading your dll directly, as suggested by Chris Sterling you'll want to create a "wrapper" dll that will load your specific LabView dll through an interface
By utilizing an interface stored in your wrapper dll you fully decouple the two dlls, which will prevent the wrapper dll from knowing about/locking your primary dll. Later, when you are finished with the debugging, you can directly link the dll to LabView.
Here is roughly how the code should look:
public class LabViewWrapper : IYourCustomClass
{
private IYourCustomClass _labViewClass;
private string labviewPath = "Full Path to labview dll";
public LabViewWrapper()
{
Assembly assembly;
try
{
using (FileStream fs = File.OpenRead(labviewPath))
{
using (MemoryStream ms = new MemoryStream())
{
byte[] buffer = new byte[1024];
int read = 0;
while ((read = fs.Read(buffer, 0, 1024)) > 0)
ms.Write(buffer, 0, read);
assembly = Assembly.Load(ms.ToArray());
ms.Close();
}
fs.Close();
}
Type t = assembly.GetType(IYourCustomClass);
_labViewClass= (IYourCustomClass)Activator.CreateInstance(t);
}
catch
{
// Unable to load dll dynamically
}
}
// Implement all the methods in your interface with something like the following:
/// <summary>
/// Your Custom Method
/// </summary>
public void CustomLabViewMethod()
{
_labViewClass.CustomLabViewMethod();
}
}
By doing it this way, you are loading the dll from memory, and therefore labview never locks your original dll that you compiled. The only real downside with this is that it does make debugging harder, if you want to insert breakpoints, you'll likely need to directly reference the source dll.
Note: One thing I am not sure about, but I believe will "work out" is whether Labview is smart enough to re-construct the object every time it executes your code, or whether it just keeps the same object throughout the session. If it does end up doing the later, you'll need to add code to "reload" the dll from the file system every time you launch your custom widget.
You could create a light DLL wrapper that itself has explicit runtime loading and unloading of your main DLL. That way the wrapper stays locked, but you can update your frequently changing code DLL quickly.
I'm doing a test in LV2012 with a C# class with a new custom class in a separate folder from the Labview VI. I'm able to recompile the C# code in VS2010 without having to close out Labview, but Labview doesn't see the changes to the DLL (if any are made). For Labview to see the changes in my test case, it needs to be fully closed and reopened.
For Labview C++ DLLs, you for sure have to close down the calling VIs, as the reference to the DLL is left open. You only need to close down to the Labview Start-up pane though.
You can have VS automatically spawn Labview.exe in a C# project by going to Project->Properties->Debug->Start External Program. When you hit F5 in VS, the DLL compiles and spawns Labview. However, VS doesn't automatically attach the DLL to process, which is really, really obnoxious. Dunno if that helps or not.
Personally, I like the way C# methods integrate with Labview, but find C++ more powerful. Working with C++, you can also spawn Labview in a similar way as above, but it automatically attaches the DLL to the Labview.exe process, making debugging a one step process of just hitting F5. You can still use classes and such in C++, you just have to wrap C functions to call them in Labview. Given the one step debugging and power of C++, I find it superior to C# when using external code in Labview.
The terminology there is a little unclear, because it's talking about LV "calling" an assembly, and I don't know if that refers to accessing the assembly at edit time or actually calling it at run-time. If it's the second, that would probably explain why it's locked.
I'm not a .NET programmer, so I have no idea what the actual solution is, but I'm guessing that you don't actually need to fully close LV to release the lock. It's possible that closing the project is enough, although I know that's not necessarily any better and it probably won't help if the lock happens at the process level.
get http://www.emptyloop.com/unlocker/
unlocker -h for its comand line options
run in prebuild. with unlock command on relevante dlls.
if only unlock doesn't help use unlock+delete.
simple as
Unlocker mydllpath.dll /s /d
You'll find that this behavior changes depending on how the dll is distributed.
If Labview is calling the assembly by a static location on disc (specified by a path input), you'll find that you cannot rebuild the dll while the Labview application is open.
However, if the dll is registered and Labview accesses it by name, you can rebuild and reinstall to your heart's content, and Labview will update its reference to the DLL once it is closed and reopened.
I accidentally stumbled across this when sharing a .Net assembly through COM Interop, as well as installing it to the GAC.
There used to be KnowledgeBase articles on this topic as recently as 2017, but they appear to be missing now.
I've included the official Labview help guide on loading assemblies here.
I'm writing a small utility to update our application.
In order to update the update utility, I would like it to rename itself while running and copy the new version from a remote source. So the next time you start the updater, you have a new version.
Do you know of any possible problems which could occur, using that mechanismn?
Actually I was surprised it is at all possible to rename a running program (lost a cake there...), while deleting is not allowed.
Kind regards for any hints
using Win XP, .NET 3.5
You can rename - because it alters metadata only, but the actual file allocation chain is unmodified, which means they can stay memory-mapped in the process(es) that use it.
This is an ubiquitous trick in installers, when they have to upgrade 'live' running binaries.
It can cause trouble if the application tries to later reopen from the original filespecification. This is not something that regularly happens with executables or dlls, though you should be aware of embedded resources and programs that may do some self-certification (license checks). It's usually best to restart the corresponding application sooner than rather later, much like windows will urge you to reboot on system updates
Renaming an .exe is usually possible without any problems - renaming .dll's is quite another story.
I'd suggest using subdirectories instead (labeled with the date or version number) and creating a small launcher application (with the same name and icon as your "real" application) that reads the current version from a text file and launches it.
i.e.
updater.exe (the launcher)
updater.config (containing /updater_v_02/updater.exe)
/updater_v_01/updater.exe (the real app, v 01)
/updater_v_02/updater.exe (the real app, v 02)
This way, you can
keep several versions of your application around
test a new version (by directly launching it from the subdir) while your users continue using the old version
switch DLLs etc. without any hassle
I currently have a multithreaded application which runs in following order:
Start up and change XML file
Do work
Change XML to default values
The step 3 is very important and I have to insure that it always happens. But if the application crashes, I might end up with the wrong XML.
The scenario where I am using it is:
My application is a small utility which connects to a remote device, but on the same machine there is a running service which is connected to the same remote device, which I want to connect to. Service exposes restartService method and during startup depending on the XML data it will connect to the remote device or will not. So in the end I have to ensure that whatever happened to my application, XML is set to the default state.
I thought having a thread running as a separate process and checking every n seconds if the main process is alive and responding would solve this issue. But I have found very few examples of multiprocess applications in C#. So if someone could show an example of how you to create a thread which runs as a separate process, that would be great.
What if I create a separate project - console application. It is compiled into separate executable and is launched from within main application. Then use IpcChannel for the communication between 2 processes. Or Create a WCF application. Will one of these approach work?
A Thread belongs to a Process, so if the process dies then so do all it's threads. Each application is expected to be a single process and while you can launch additional processes it sounds like a complex solution to what might be a simple problem.
Rather than changing and reverting the file could you just read it into memory and leave the filesystem alone?
You can subscribe to an event called DispatcherUnhandledException so when ever an Unhandled exception is thrown , you can safely revert your XML settings.
public partial class App : Application
{
public App()
{
this.DispatcherUnhandledException += new System.Windows.Threading.DispatcherUnhandledExceptionEventHandler(App_DispatcherUnhandledException);
}
void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
//When ever an Unhandeled exception is thrown
// You can change your XML files to default values.
}
}
// If you killed process through Task Manager
AppDomain.CurrentDomain.ProcessExit += new EventHandler(CurrentDomain_ProcessExit);
void CurrentDomain_ProcessExit(object sender, EventArgs e)
{
// Change your Settings Here.
}
// If you initiated Windows ShutDown
this.SessionEnding += new SessionEndingCancelEventHandler(App_SessionEnding);
void App_SessionEnding(object sender, SessionEndingCancelEventArgs e)
{
// XML Changes
}
What you are talking about is usually called "supervision" in mainframe computing and other large-ish computing infrastructures. A supervised process is a process that runs under the scrutiny of a supervisor process, which restarts it or otherwise "fixes" the problem if the former crashes or is unable to finish its job.
You can see a glimpse of this in the way that Windows restarts services automatically if they stop working; that is a very simplistic version of a supervision subsystem.
As far as I understand, this is a complex area of computer engineering, and I don't think that Windows or .NET provide a programmatic interface to it. Depending on your specific needs, you might be able to develop a simple approach to it.
Consider setting a "dirty" flag in your config file and storing a backup of the default XML in another file. When your application starts it changes the XML and sets the flag. If it successfully completes then it resets the flag and restores the XML. Your service checks the flag to see if it needs to use the last XML written by your app or switch to the backup file.
I think that whether the application is multithreaded or multiprocess or whatever is not actually the problem you need to solve. The real problem is: how do I make this operation atomic?
When you say that you have to insure that step 3 always happens, what you're really saying is your program needs to perform an atomic transaction: either all of it happens, or none of it happens.
To accomplish this, your process should be designed the way that database transactions are designed. It should begin the transaction, do the work, and then either commit the transaction or roll it back. The process should be designed so that if, when it starts up, it detects that a transaction was begun and not committed or rolled back by an earlier run, it should start by rolling back that transaction.
Crucially, the commit method should have as little instability as possible. For instance, a typical way to design a transactional process is to use the file system: create a temporary file to indicate that the transaction has begun, write the output to temporary files, and then have the commit method rename the temporary files to their final names and delete the transaction-flag file. There's still a risk that the file system will go down in between the time you've renamed the files and the time you've deleted the flag file (and there are ways to mitigate that risk too), but it's a much smaller risk than the kind you've been describing.
If you design the process so that it implements the transactional model, whether it uses multiprocessing or multithreading or single-threading is just an implementation detail.