We have a main application (Winforms) with several dll's referenced containing Logic and UI Layers. After some research on how to perform auto-update in a winforms application, I found a solution using AppDomain and the ShadowCopies feature.
Another executable look for updates and makes the exchange of files.
Okay, but now, I got the following situation:
I start the main application (loaded through the new AppDomain).
I open a form that is in a referenced dll ("ReferenceA"). This dll is copied and instantiated from the copy. (Great!)
At this time the system receives an update with new versions of "ReferenceA" and "ReferenceB", and makes the exchange of files.
I open another form that is in "ReferenceB". This dll is copied and instantiated from the copy, but this dll also references "ReferenceA" that is not updated by ShadowCopy because it is already in the directory.
Now the system is running a newer version of "ReferenceB" with an older version of "ReferenceA". In my test I created a new method in "ReferenceA" then I obviously got the message: "Method not found".
Any suggestions on how I can solve this?
Related
I have a com dll developed in VB.net that provides an interface to eBay api's. Been working for many years. Recently eBay change certificate authority and moved to TLS 1.2. Sorted through that but now the dll seems to quit in mid transaction when called from Access. The functionality does listings from local inventory to eBay. The first part loads pictures of the listing item to eBay. That works fine. I can see the calls and responses using Fiddler. It then moves on to actually listing the item which seems to stop when called from Access. What I get back in Access is "Can't find x.dll at file location". I know the call is going to the dll because it uploads the pictures.
I have a test project developed in VB.net to test the dll and when run from that everything works. I can see the listing call and response in fiddler. When run from Access there is no listing call. I can verify that the endpoints for the calls are the same from test project or Access.
My question is how to debug the dll in the Visual Studio IDE when it is called from Access. Any thoughts?
Yes, the way you do this is open up the vs class you have for the .dll.
Then in debug of the project, setup this:
Now, when you hit f5, then access will launch and run.
If at this point, say you close access (exit), then you note the debugging process stops.
However, go though the forms and whatever in Access, and get to the point where you hit that button or whatever.
You find now that you can say set a break point and even step and debug your .net code like any other code. So say in my example (a custom sage 300 .net interface to access), I want to debug "find customer" routine from VBA.
Well, in vb.net I have this code:
so, when any routine - even those in the class instances is called, you can set break-points etc.
And to stop? Just exit access.
So, you can make a change to your code, and even hit f5.
It not clear how you are registering your .dll (or do you use some VBA to side-load the .net - that's what I do, since it is a pain to have to register my .net com objects on each PC.
But, do give the above a try. It should let you debug your .dll code. The trick is to have VS launch ms-access as a attached debug session - and that is exactly what the above setting in your class project above allows you to do.
do note in above, I used the path to access 2010 (access 14), so replace the path name to the access.exe with your version of access you are using.
And keep in mind, that if have some installer, or some custom "thing" that registers your .net .dll for you?
Well, during this process, if your VBA assumes a registered com object, then ensure you have this check box enabled:
On compile for the project settings, you thus want this option checked:
NOTE very careful, checking the above option does not change the code or anything at all - it ONLY does a regasum automatic for you, and this would of course re-register your existing .dll - which is what we want for debugging. After you done, do run your re-register of your .dll to switch back from the debug .dll that going to be in your current project bin folder to whatever you "regular" use on your PC.
FYI:
In MOST cases, I find this whole idea does NOT work unless you launch VS as administraor. So, make sure VS is being run as administraor for this to work.
I tend to just tap windows key, or even right click on your vs shortcut, and of course choose run as administraor.
This is so often required, you note that VS will EASY and quite CLEAR show you running in admin mode, and I quite much now always run VS this way.
You should see this:
How to update DLL in automation anywhere using metabot. When i am replacing old DLL with updated one its not working. metabot still using old DLL.
i have tried to replace old dll with new one but not working.
You have to delete the old DLL from the metabot and then add the new one.
Double check that the new DLL is actually a new version, for example if you have a C# project go to that project, rebuild it and then go to bin -> Debug | Release -> select the new DLL from here
I never had issues with that doing these steps.
You don't have to delete the DLL as the currently accepted answer states.
All I did was:
Open the MetaBot Designer
Click Add DLL
Choose the updated DLL
You are prompted to replace the existing DLL, "A .NET API DLL with the same name already exists in this metabot. Do you want to replace it?". Choose Yes.
At this point the DLL is updated and the existing logic and variables are intact. If you changed one of the existing APIs, you will need to update the corresponding logic, etc.
I have a problem trying to register DLL. My OS is Windows 7 (x64).
I do it in two different ways:
1) Using regsvr32. I get message "DllRegisterServer ... succeedeed", nevertheless I can't find my CLSID in registry. (And I get "Class not registered" error trying to create an instace of component with this CLSID).In this case, I know that DllRegisterServer is never called (because I create a text file in the beginning of this function and it is not created).
2) Explicitly load my DLL and call DllRegisterServer. In this case, DllRegisterServer returns S_OK, but still I can't find my CLSID in registry and get "Class not registered" error.
I'm sure the code is correct (for it doesn't work only on my OS), so it seems that the problem is in OS. Did anyone face such a problem?
http://msdn.microsoft.com/en-us/library/aa384232(v=vs.85).aspx should explain it
Depending on whether your dll is 32bit or 64bit the registry keys are created at separate locations
Just solved an identical problem. I've manually added to the existing 32-bit COM new interface, implementation (MyNewClass) and rgs file. But when I've successfully registered my COM using SysWow64\regsvr32.exe I've noticed that my ProgId/CLSID didn't appear under HKCR\CLSID or HKCR\Wow6432Node\CLSID
So, actually I missed few thing:
I had to add OBJECT_ENTRY under BEGIN_OBJECT_MAP in MyApp.cpp file
and add DECLARE_REGISTRY_RESOURCEID(IDR_xxx) to MyNewClass.h file
resource.h
define IDR_xxx 105
ExistingCom.rc
IDR_xxx REGISTRY DISCARDABLE "MyNewClass.rgs"
Run command line tool as administrator and then run the register command regsvr32
I have a .NET customer framework that functions much like a Workflow. It uses reflection to get a listing of all of the processes it is capable of from a specific folder, and starts them via reflection with a known start point (all of them have a method called "Process"). Since these files are only called to do the processing and not part of the compile... is there a way for me to be able to drop in a new reference library (DLL) for one of the processes that is being updated without restarting the whole process?
Here is my flow...
START
Load list of references
Load work, assign to references
After X Time, refresh references (or
on WCF refresh command being sent)
Is it possible to do this, or do I do I need to actually stop and restart the assembly base to be able to recognized the new reference file?
Yes you can with Assembly.Load but I think you need to look at MEF first.
I'm creating a self updating app where I have the majority of the code in a seperate DLL. It's command line and will eventually be run on Mono. I'm just trying to get this code to work in C# on windows at the command line.
How can I create a c# application that I can delete a supporting dll while its running?
AppDomain domain = AppDomain.CreateDomain("MyDomain");
ObjectHandle instance = domain.CreateInstance( "VersionUpdater.Core", "VersionUpdater.Core.VersionInfo");
object unwrap = instance.Unwrap();
Console.WriteLine(((ICommand)unwrap).Run());
AppDomain.Unload(domain);
Console.ReadLine();
at the ReadLine the VersionUpdater.Core.dll is still locked from deletion
The ICommand interface is in VersionUpdater.Common.dll which is referenced by both the Commandline app and VersionUpdater.Core.dll
The only way I've ever managed something similar is to have the DLL in a separate AppDomain to the assembly that is trying to delete it. I unload the other AppDomain and then delete the DLL from disk.
If you're looking for a way to perform the update, off the top of my head I would go for a stub exe that spawns the real AppDomain. Then, when that stub exe detects an update is to be applied, it quits the other AppDomain and then does the update magic.
EDIT: The updater cannot share DLLs with the thing it is updating, otherwise it will lock those DLLs and therefore prevent them from being deleted. I suspect this is why you still get an exception. The updater has to be standalone and not reliant on anything that the other AppDomain uses, and vice versa.
Unwrap will load the assembly of the object's type into the appdomain that calls it. One way around this is to create a type in your "base" assembly that calls command.run, then load that into your new appdomain. This way you never have to call unwrap on an object from a type in a different assembly, and you can delete the assembly on disk.
When I built a self-updating app, I used the stub idea, but the stub was the app itself.
The app would start, look for updates. If it found an update, it would download a copy of the new app to temp storage, and then start it up (System.Diagnostics.Process.Start()) using a command-line option that said "you are being updated". Then the original exe exits.
The spawned exe starts up, sees that it is an update, and copies itself to the original app directory. It then starts the app from that new location. Then the spawned exe ends.
The newly started exe from the original app install location starts up - sees the temp file and deletes it. Then resumes normal execution.
You can always use MOVEFILE_DELAY_UNTIL_REBOOT to delete on reboot. This is most likely the least hackey way todo this sort of thing, by hackey I ususally see things like; loading up new DLL's or injecting to explorer.exe even patching a system dll to get loaded into another process, etc...
MoveFileEx From MSDN;
lpNewFileName [in, optional] The new
name of the file or directory on the
local computer.
When moving a file, the destination
can be on a different file system or
volume. If the destination is on
another drive, you must set the
MOVEFILE_COPY_ALLOWED flag in dwFlags.
When moving a directory, the
destination must be on the same drive.
If dwFlags specifies
MOVEFILE_DELAY_UNTIL_REBOOT and
lpNewFileName is NULL, MoveFileEx
registers the lpExistingFileName file
to be deleted when the system
restarts. If lpExistingFileName refers
to a directory, the system removes the
directory at restart only if the
directory is empty.