Updating Plugin

Updating Plugin

StormyC
Advocate Advocate
2,344 Views
6 Replies
Message 1 of 7

Updating Plugin

StormyC
Advocate
Advocate

Is there a way to update an AutoCAD2014 plugin from our server in a similar way to the Autodesk exchange by using our own "app" server?

 

If so, can anyone point me in the right direction of how to achive it.

 

I would like to create a plugin that, when users attach to our network, checks are made and if updates to the plugin are required an update is executed.

 

Thanks.

0 Likes
Accepted solutions (1)
2,345 Views
6 Replies
Replies (6)
Message 2 of 7

jeff
Collaborator
Collaborator

I use the addin loader to simulate the addinloader

 

Add a  app.bundle that just knows to read a xml file that gives it instructions where to check to look for another file which gives it instruction like copy all files from here, include sub-folders, only include dll's, cui, etc... then does what the addin loader does.

 

When I say mimmick the intial loading and pain in the arse stuff is handled by addin-loader, and without it would not of attempted this approach.

 

  

You can also find your answers @ TheSwamp
Message 3 of 7

StephenPreston
Alumni
Alumni

The way I've done this in the past (quite a long time in the past) is similar to Jeff's suggestion. You keep an XML file on the server where you store the 'stuff' you want to keep up to date on the local machines. The XML documents the latest versions of all the files that need synching. A local app reads the XML and check against a locally stored copy to see if any versions have changed. If they have, it copies the newer file and updates its own XML list. An alternative is just to check last modified dates on files.

 

As Jeff says, using Autoloader will simplify this a little - especially if the components you want to update are addin bundles that use the Autoloader format themselves, because AutoCAD autodetects them when you copy them into place. The only issue I see there is coping with DLLs that are locked because they are currently being used by AutoCAD.

 

 

 

 

Cheers,

Stephen Preston
Autodesk Developer Network
Message 4 of 7

dgorsman
Consultant
Consultant

Almost exactly what I've got working.  I get around the in-use DLL locking by having the updater EXE (just a simple DOS-box routine) hold for any active AutoCAD processes to finish before copying the files.

 

If I had the IT support now that I did when I created it, I'd go even simpler and just use a start-up BAT file with an XCOPY statement and copy-or-refresh arguments.  If programs are already being pushed out automatically through SCCM or other means, then when the DLL is updated it could be distributed through similar means.  If you have a hammer, might as well use it.  🙂

----------------------------------
If you are going to fly by the seat of your pants, expect friction burns.
"I don't know" is the beginning of knowledge, not the end.


Message 5 of 7

jeff
Collaborator
Collaborator
Accepted solution

Well thats make feel better and might be doing something right but here is the main grunt work

 

        private Dictionary<FileSystemInfo, SystemException> CopyFiles(DirectoryInfo sourceDirectory, DirectoryInfo destinationDirectory, ICollection<string> extensionFilters, bool copySubDirectories)
        {
            var exceptions = new Dictionary<FileSystemInfo, SystemException>();

            return CopyFiles(sourceDirectory, destinationDirectory, extensionFilters, copySubDirectories, exceptions);
        }
        private Dictionary<FileSystemInfo, SystemException> CopyFiles(DirectoryInfo sourceDirectory, DirectoryInfo destinationDirectory, ICollection<string> extensionFilters, bool copySubDirectories, Dictionary<FileSystemInfo, SystemException> exceptions)
        {
            
            if (!destinationDirectory.Exists)
            {
                try
                {
                    destinationDirectory.Create();
                }
                catch (IOException ex)
                {
                    exceptions.Add(destinationDirectory, ex);
                }
                catch (SecurityException se)
                {
                    exceptions.Add(destinationDirectory, se);
                }
            }
            //var poop = sourceDirectory.EnumerateFiles().Where(fi => filters.Contains(fi.Extension));
            foreach (var fi in sourceDirectory.GetFilteredFiles(extensionFilters))
            {

                FileInfo newFile = new FileInfo(Path.Combine(destinationDirectory.FullName, fi.Name));


                if (!newFile.Exists)
                {
                    try
                    {
                        fi.CopyTo(newFile.FullName);
                    }
                    catch (IOException ex)
                    {
                        exceptions.Add(newFile, ex);
                    }
                    catch (SecurityException se)
                    {
                        exceptions.Add(newFile, se);
                    }
                }
                else if (fi.LastWriteTimeUtc > newFile.LastWriteTimeUtc)
                {
                    try
                    {
                        fi.CopyTo(newFile.FullName, true);
                    }
                    catch (IOException ex)
                    {
                        exceptions.Add(newFile, ex);
                    }
                    catch (SecurityException se)
                    {
                        exceptions.Add(newFile, se);
                    }
                }


            }

            if (copySubDirectories)
            {
                foreach (var subDi in sourceDirectory.EnumerateDirectories())
                {
                    var tempDI = new DirectoryInfo(Path.Combine(destinationDirectory.FullName, subDi.Name));
                    CopyFiles(subDi, tempDI, extensionFilters, true, exceptions);
                }
            }
            return exceptions;
        }
        private DirectoryInfo ExpandDirectoryPath(string unExpandedPath)
        {
            return new DirectoryInfo(Environment.ExpandEnvironmentVariables(unExpandedPath));
        }

 

  internal static IEnumerable<FileInfo> GetFilteredFiles(this DirectoryInfo sourceDirectory,
            ICollection<string> extensions)
        {
            if (extensions.Count == 0)
            {
                return sourceDirectory.EnumerateFiles();
            }
            return sourceDirectory.EnumerateFiles().Where(fi => extensions.Contains(fi.Extension));
        }

 

            exceps = CopyFiles(updateDirectory, NetLoaderDirectoryPath, extensionFilters, copySubs);
            foreach (var loadFile in xDataDoc.Descendants("LoadFile"))
            {
                var assemblyFI = GetFilePathFromAddinLoaderDirectory(loadFile.Value);
                Assembly.LoadFrom(assemblyFI.FullName);
            }

 

You can also find your answers @ TheSwamp
Message 6 of 7

StormyC
Advocate
Advocate
Many thanks for your replies. I had concluded that an approach would be to store version files on local & server, copy if newer version on server & update version file on local when done.

@jeff Many many thanks for posting that code. Looks comprehensive enough to use if I adopt the file creation time/date to identify updated dlls.
0 Likes
Message 7 of 7

StephenPreston
Alumni
Alumni

Adding my thanks to Jeff. A code snippet is worth a thousand words 🙂

Cheers,

Stephen Preston
Autodesk Developer Network
0 Likes