Automatic updater

xiaoxiao2021-03-06  140

To have .NET Framework Components and Windows have some interesting APIs that create an application that is automatically updated over the network. Write applications as automatic updates like Windows, including convenience of users, to reduce network administrators' maintenance workload. Automatic updates require some factors, such as discover, security, and file replacement. This article uses the characteristics of the BITS API and some .NET framework components, enabling applications to automatically update as Windows.

I like Windows update features. After my computer is turned on, 85% of the time is connected to the Internet, like many people, I don't have so much time using the network. Windows XP uses unused bandwidth to compare the latest service packs and patches that are available on the network. If you find updates, you download them in the background. After the download is complete, it prompts new content to be installed.

If I have a choice, each application of the client should be automatically updated. If you want to automatically update, you must write code to process discovery, download, security, and replacement.

In order to deal with actual downloads, I will use the Background Intelligent Transfer Service (BITS) feature of the Background Intelligent Transfer Service, Bits. I will use the feature of the .NET Framework component to solve the security and update issues of the automatic update application.

Difficult To find updates on the remote server, the application must have a way to query the network, which requires a network programming, a simple application and server communication protocol. This will tell it in the "Discovery" section later. The next step is to download. Download does not need to consider the networking problem, but consider downloading the file requested by the user, and downloading a big file when there is no user agreed. Friendly automatic update applications will use the remaining bandwidth download updates. This sounds simple, but it is a technical problem, and fortunate is already a solution. Safety may be the most critical consideration. Consider the Windows update feature, its main purpose is to get the secure patch, imagine if the Windows update itself cannot verify that secure code is installed. Obviously any application from Internet downloads and executes code must have the highest security level. So I will discuss how to make automatic update applications safer. The final consideration is the process of replacing the original application using the new application. This problem is interesting, because it requires code to delete yourself from the system, there are many ways to implement this feature.

Bits Basics Bits are a new Windows file transfer feature that downloads files from the remote server via HTTP asynchronous. Bits can manage multiple downloads of multiple users using dedicated idle bandwidth. Although BITS is not limited to automatic update applications, it is a low-level API for Windows update. Since it is available for any application, it is used to do many actual work, including the establishment of an automatic update application. The following is a basic idea. The application requests the download of the BITS management file. BITS adds the work to its queue and associates it with the user environment running in the application. Once the user logs in, BITS uses the idle bandwidth to download the file through the network. In fact, the code name of BITS technology is Drizzle, which describes what BITS do. How is this implementation? This technology is quite complicated. First, the implementation of BITS is the same as the WINDOWS service of the work set according to the priority (front desk, high, normal, low) queue. Work in the same priority is given five minutes by time. Once there is no work in the queue, check the work of the next priority queue. The work in the front desk queue uses as large network bandwidth, because the front desk priority is only used to respond to the user requested. Other priorities - high, normal and low - are both a background priority, which only uses idle network bandwidth. In order to obtain background features, BITS monitors network packets and does not address your own packages. The remaining package is used to calculate the bandwidth activity load. BITS uses the active load information to determine whether to continue downloading the file, or to increase the traffic of the active user. For this reason, users will not encounter bandwidth problems. For Bits, once it is noticed that the ability to stop work is very important. In many cases, BITS will give up the network after downloading the file, and even the connection is also lost. The part of the file download is saved, but it starts from the breakpoint when BITS uses the network again. The ability to recover is effective. BITS is used to transfer files from the HTTP server. The server must be compatible with HTTP 1.1, or at least support in the GET method contains the RANGE header because BITS needs to request a part of the file. In addition, the downloaded content must be static, such as tag files, code files, bitmaps, or sounds. Requests containing the RANGE header do not do anything when requesting dynamic content such as CGI, Isapi, or ASP.NET. There are two versions of BITS: 1.0 and 1.5. BITS 1.0 is published with Windows XP, with the following features: Interrupt file download, download priority, selectable work completion notifications and error conditions, you can choose to use a dialog or other UI elements for process notification. Bits 1.5 is released with Windows .NET Server, in addition to the characteristics of BITS 1.0, there is an interrupt file upload and use Basic, Digest, NTLM, Negotiate (Kerberos) or Passport authentication, which is compatible with Windows 2000 or later version = =============

Bits, COM, and manageable code BITS API is implemented as a COM object, and there is no .NET Framework component version of the API, fortunately, the BITS API is very straightforward and easy to use. This article is written in C #, if you use C , BITS code begins with the following code:

IBackgroundCopyManager * pBCM = NULL; hr = CoCreateInstance (__ uuidof (BackgroundCopyManager), NULL, CLSCTX_LOCAL_SERVER, __uuidof (IBackgroundCopyManager), (void **) & pBCM); if (SUCCEEDED (hr)) {// use Pbcm interface pointer} C # using the new Keywords are equivalent to establishing the BackgroundCopyManager object, followed by calculating a reference to the IBACKGROUNDCOPYMANAGER interface without using methods such as calling CocreateInstance or QueryInterface. The following code acquires the IBACKGROUNDCOPYMANAGER interface:

IBACKGROUNDCOPYMANAGER BCM = NULL; // Establish bits object BCM = (ipackgroundcopymanager) New BackgroundCopyManager ();

This code is simple and may make people misunderstand because it is necessary to do a lot of work to do, to connect manageable BackgroundCopyManager and IBACKGROPYMANAGER Types correspond to the lower COM objects and interfaces. The .NET frame assembly interacts with the COM object via RCW. To use RCW to associate a manageable type, you must use properties. The code in Figure 1 shows how to declare the BackgroundCopyManager class and the IBackgroundCopyManager interface so they describe the BITS COM object.

[GuidAttribute ( "4991D34B-80A1-4291-83B6-3328366B9097")] [ClassInterfaceAttribute (ClassInterfaceType.None)] [ComImportAttribute ()] class BackgroundCopyManager {} [InterfaceTypeAttribute (ComInterfaceType.InterfaceIsIUnknown)] [GuidAttribute ( "5CE34C0D-0DC9-4C1F -897C-DAA1B78CEE7C ")] [ComImportAttribute ()] interface IBackgroundCopyManager {void createJob ([MarshalAs (UnmanagedType.LPWStr)] string DisplayName, BG_JOB_TYPE Type, out Guid pJobId, [MarshalAs (UnmanagedType.Interface)] out IBackgroundCopyJob ppJob); void GetJob (ref Guid jobID, [MarshalAs (UnmanagedType.Interface)] out IBackgroundCopyJob ppJob); void EnumJobs (uint dwFlags, [MarshalAs (UnmanagedType.Interface)] out IEnumBackgroundCopyJobs ppenum); void GetErrorDescription ([MarshalAs (UnmanagedType.Error)] int HRESULT, UINT LANGUAGEID, [MARSHALAS (UnmanagedType.lpwstr)] Out String Perrtescription;}

Figure 1. Defines the code attribute (Comimportattribute, Guidattribute, Marshalasattribute, etc.) in Figure 1, so that the actual code does not look clear. In fact, this is not a real code. The interface and class definitions are only some arranged neat placeholders in the metadata form (CLR) called in the General Language Runtime (CLR). The interopbits.cs file in the code example provides C # provides interactive operation code with the BITS API using all interfaces, enumeration types, and structures. Although the routine only uses a few ways, I also contain a complete implementation because if you decide that the more features of the API will find that this is useful. The code in the interopbits.cs file is not managed (managed) API, so it doesn't have the value, but it has implemented interactive operations with the API through the COM API. Finally, it is expected that Microsoft will issue an API that exposes the BITS function to the .NET framework component code, so that it can be consistent with the class library of other .NET framework components. Figure 1 The code file interopbits.cs is hand-established. The .NET Framework Component SDK released a tool called Tlbimp.exe, which establishes and compile similar code to become a manageable component, if you have a TLB file describing the target COM API. The BITS API does not release with the TLB file, but the platform SDK includes a file called bits.idl, a file description of the interface. I use the MIDL.EXE tool (released with the platform SDK) to create a TLB file from bits.idl. Then I use TLBIMP.EXE to create a manageable component describing the TLB file. I use ildasm.exe to break down the components generated by TLBIMP.exe into intermediate languages, and finally I use the intermediate language to establish C # code for the wizard, adjust its location to make it more useful, and correct. This way to interact with COM is in place, but it provides an exceptional control of the last output.

================================= In the automatic update application, use the BITS BITS service to manage file downloads during the work. An application establishes a transfer work, then adds one or more files to this work. Once the list of files work is determined, the task continues (because the status of the work is suspended). Work is used to manage some details, such as priority, authentication, and error management. It can be terminated by the application at any time. Once Bits completed the transfer of all files in a job, the application calls a method to end the work. Complete method Copy all files to their last destination. Although BITS document guidance uses "Copying" file end tasks, it is a destination to establish a temporary hidden file, and the Complete method simply changes the name of the hidden file and makes them visible. Even if you minimize BITS API (only using the IBackgroundCopyManager and IBACKGROPYMANAGER and IBACKGROPYJOB interface), each file you need to automatically update the application can be obtained. If other features are required, such as an enumeration or completion, you must use additional interfaces. Randics AutoupDater.exe uses BITS to complete the update discovery and download. For this purpose, the application defines a continuous name mode for updating: update1.dll, update2.dll, and more. Although this is not the only way to discover updates, it has made BITS functionality very well. The routine maintained an XML file for saving the update state. Two related parts of the file are the next update quantity and describe the GUID of the current BITS download work (if there is currently no work). Every time the application runs, it opens an XML file and checks if it looks down if the update has been downloaded. If not, there is no GUID in the XML file, the application initializes the BITS work to download the next update online. The following code demonstrates the necessary way to initialize the download work: ipackgroundcopyjob job = null; // Established a job Download Next update bcm.createJob ("Application Update", BG_JOB_TYPE.BG_JOB_TYPE_DOWNLOAD, OUT JOBID, OUT JOB; // Work Add to Document Job.Addfile (UpdateURL, LocAllocation); Job.Resume (); // Startup Work

Call job.addfile passed the location of the file to download, the completed local path and the last saved file name. Note The task begins to start a suspend state, and must start again before the BITS service is working. If there is GUID in the XML file, the BITS task has been initialized. Therefore, the GUID is passed to the ibackgroundcopymanager.getjob method to see if the previously scheduled download tasks have a result. Next, dependent on the status of work. In the following code (Figure 2) If the work is in an error, the application ends the work (it clears the failed work from the queue) and then establishes a new job for the same download file. The most probable cause of the wrong state is simple, that is, the update does not exist. This implements the discovery update section in the routine. The advantage of using the BITS query update is BITS working in the background. Therefore, although the query is not a special elegant, non-mandatory BITS download is a possible method of discovering updates. If it is in a translated state, the application is connected to the ipackgroundcopyjob.complete to end the task. This causes the file to write to the target directory, making it ready to update. The application will then return, and the downloaded file table will be combined. BCM.GetJob (REF JOBID, OUT JOB); // Get bits work object Job.getState (outstate); // Check Status Switch (State) {Case BG_JOB_STATE.BG_JOB_STATE_ERROR: // If there is an error Job.comPlete (); XML.BitsJob = Guid.empty; Marshal.ReleaseComObject (job); Job = null; break; // Continue to create new work Case BG_JOB_STATE.BG_JOB_STATE_TRANSFERRED: // If the file job.complete (); // end work XML. BitsJob = guid.empty; return; // All completion, return to default: return;} ... // to initialize a new job for update downloads

Figure 2. Checking the working status and ending work, in the default, the routines of Figure 2 simply return and ignore the work. There are two states that there may be two states: is being transferred (this means work in progress) or instantaneous error status. Both states are considered to be potentially successful, so the application separates enough space separately. If the BITS task enters the instantaneous error status, the BITS service considers that the error can be restored, so it tries again. Finally, the instantaneous error is either successful either BITS to set it in an error. Error recovery logic overwrites the entire discovery and download autOUpDater.exe application components. In view of the deeper function of the download process, the implementation method does not seem like network communication and is similar to the usual file replication. In the product application you will find the use of a large number of other features that will use the BITS API, such as auto-transport notifications, task priority maintenance, and upload tasks.

================================================== BITS BITS is designed to never initialize the network connection. This is best because you don't want the application that does not need to connect to an ISP to check the update. But BITS 1.0 and 1.5 are received by the Internet connection sharing limit. If the system A shared system B's Internet connection, the application of the initialization bits working on system A may cause system B initialization dialing because the current BITS service does not consider sharing connection issues. This is a problem that is difficult to solve, but there may be a patch in the future version of BITS. Windows update features also have this problem, using BITS applications, the dialing of the shared connection is nothing difference with Windows. The last issue of BITS is the consistency of work files. If your download work contains multiple files, BITS does not think that the work is completed, nor does it think that the file reaches their last destination until all files are available. However, BITS can't know that a file on the server changes after other files have been downloaded. For this reason, the update on the server may affect the consistency of client downloads. There are two ways to solve this problem. The first is to limit BITS to work for a single file, which is the method I use in routines. The second method is to save all files to all files to the same directory of the server. When there is an update to these files, set a new directory for the new file collection on the server. Using this method, the client in the original work will not be affected by the collection of new files. The problem with this solution is that the server's file positioning changes, the client requires a way to get the location of the new file. . If you need to find bits code, BitSadmin.exe is the best helper. The tool is distributed with Windows XP CDs in the Support / Tools subdirectory. In order to save time, I didn't install the tool, but directly decompressed from the support.cab file from the Support.cab file. When you first familiar with BITS download, BitsAdmin.exe tool is very useful. Almost all features of the API expose this option to this command line tool. You can enumerate your work, check your work status, check out detailed work and error message; you can initialize, hang, continue and end download work; Finally, you can change your work and cancel your work from Bitsadmin.exe. The Windows API can be accessed like this through related tools. In fact, scripts (for example, batch files) can use BITS with BITSADMIN.EXE tools. Bits is a powerful solution for discovering and downloading updates, which is very small for most applications. Now let's take a look at the security problem ================== NET Framework component and security .NET Framework components are used in the code to introduce a lot of interesting security structures. Code Access Security is an example. Another part of the security structure is the enhanced name binding of the manageable components. In order to secure the code update from the server to the client, I use this feature. The problem is that the automatic update application is associated with a server with a server with the server and download files (including code to the client). These new files cannot be controlled by the network between the client and the server. One of this problem solution is that the entire data exchange is connected via HTTPS.

The BITS service is able to locate the target resource via HTTPS protocol. HTTPS is merely HTTP communication using an encrypted SSL / TLS channel. But the program has several disadvantages. The first is to reduce performance. The web server is superior to send static content (eg HTML documents or EXE files). When the Microsoft Internet Information Service (IIS) receives a request for a static file, it makes a call to the TransmitFile Win32 API. TransmitFile provides excellent performance from the file system from the file system from the file system one by one. When you encrypt through HTTPS, the performance is greatly reduced, because each bit of the file is encrypted, which will increase the cost of updating the relevant server. Another problem using HTTPS it makes the web server a node that is easy to damage in the security structure. If the web server is corrupted, the client will blindly download and install malicious content on the server. With a fairly simple feature of the .NET Framework component, you can get higher security for updated file delivery without these disadvantages. First, the encrypted SSL / TLS channel is unnecessary (such a way to use this solution, the big security threat from the corrupted server will be rejected by the server and client, the server will be banned Run malicious code on the client. This feature of the .NET Framework component is to enhance the name binding, which is part of the component loader. ============================ Enhance the name and secure binding. NET Framework component Difficulty long-term trouble DLL is using a file The name is not easy to use the reusable code. This leads to all types of applications to enter "DLL Hell". It is the way to enhance the name. Enhanced name consists of several parts: file name, version number, cultural information, and public key. The .NET Framework component uses an enhanced name to implement a stricter binding between the components. The framework assembly uses a public / private key pair to verify the reinforce naming component before loading. In the case of strengthening naming components, .NET Framework Component Language Compiler (C # or Visual Basic .NET) builds the public key into the DLL file. As a supplement to the public key, the compiler also uses the private key (saved by the established organization) to make the file content and encrypt. The messy signal is also a digital signature. In order to check the digital signature, you need to extract the public key from the component file and decrypt the mess. The content of the file will then be confused again and compare the results with the digital signature. If any changes have occurred, the signature verification will fail because the messy signal does not match. If you think that the public key in the component is used to confirm the same components, you are wrong. However, if you perform a verification code, you can confirm that the public key is a known or expected key, then you need a more complete security scheme. The .NET framework assembly uses a messy signal we know, called public key token or the originator (ORIGINATOR). When the component is loaded into the application, you can specify a public keyboard. If a component is enhanced and the public key of the enhanced name is matched to the public key token passed to the Assembly.Load method, the .NET Framework component only loads the component. Below I will demonstrate the process of renovating a component and use the initiator to load it. The following C # code can be used to create a reinforcing naming component.

This component does not do anything, only for demo to enhance the name binding: use system.reflection; [assembly: assemblykeyKeyFile (@ "keys.snk")] Before the code is compiled, you must establish a private / private key pair Keys.snk. You can implement the Sn.exe tool implementation issued with the .NET Framework component SDK:> Sn -k keys.snk Now you can use the C # compiler to compile the enhanced naming component into one .NET Framework component DLL . > csc -t: library strongname.cs result assembly called strongName.dll. You can use the sn.exe's / t parameter to view the public keyboard of the enhanced name, as shown in Figure 3: Figure 1. Example of the public key token of one component is extracted shows a public key. The Token is a D586E46FD39D13B5 (hexadecimal) DLL. In order to verify the name using tempered loading the component, using the following code: // Loading Update String name = Path.GetFileNameWithoutExtension (patchName); name = "StrongName.dll, PublicKeyToken = d586e46fd39d13b5"); Assembly update = Assembly.Load ( Name);

These code either verify the signature and returns a reference to the component object, either verify the failure and the assembly.load method is wrong. In addition, using Assembly.Load, the code can verify that the component is not modified after being established. Automatic Update Applications You can use BITS to download update files without involving server-side security issues. Next, you can use Assembly.Load to verify the component using Assembly.Load before updating and use. The only prerequisite is to install the public / private key pair of public keywords that already exist with the original application. Before installation and use, only the update created by the matching key can be verified by the client. During this time, the key pair for establishing an updated can be stored on a computer that is never connected to the network. This safety mechanism is very powerful, but there are some problems. For example, can you update a code file (such as bitmap and data files)? To use this mechanism you have to build all DLL and EXE files with enhanced naming? The answers to these issues are all yet. ======================= Update package and replacement If the automatic upgrade application does not work without code file, or it requires all EXE and DLL files to manage And do name enhancement, I will not be interested in it. So I need a way to use the .NET Framework component to enhance the name binding without forcing the update file is the .NET Framework component file. The answer is to embed an update file as a resource of the component into a component file. This not only enables all file types to be enhanced naming, but also simplifies BITS work, from multiple works to a single file download, a big file is actually a plurality of small file packages. In fact, the package can include a CAB file or a MSI script - these are not limited. All .NET Framework Components Language compilers allow for any file to be embedded to a component file. I will demonstrate how to use the C # compiler to implement this function, but the concept is the same as Visual Basic .NET or Manage C . The following code compiles CODE.DLL, Bitmap.gif and Data.xml into an Update2.dll file, which contains each file as an embedded resource: csc /res:code.dll /res: bitmap.gif / res: Data.xml / T: Library Note that the C # compiler has sufficient flexibility, and can establish a DLL component when there is no .cs code file. The DLL only contains embedded resources. However, if you want the DLL to include a strengthening name, you need to include a short .cs file, its code is similar to strongName.cs. Assembly.Load (...); // Load component // Get resource name string [] resources = update.getmanifestResourceNames (); // enumerate resource foreach (String s in resources) {using (//////// Get resource stream stream res = update.getManifestResourceStream (s), file = new filestream (s, filemode.createNew) // created file) {INT32 pseudobyte; while ((pseudobyte = res. radyte ())! = - 1) { // Copy byte file.writebyte ((byte) pseudobyte;}}} Extract component resource code

The necessary code to be embedded in embedded resources and copy them to the file system is shown in Figure 4. The code uses Assembly.getManifestResourceName and Assembly.getManifestResourceStream methods to find resources and copy them as file systems. The original file data of the file system is not saved in the code, but it can simply modify this function. Note that the extraction process is only validated after Assembly.Load has verified the signature of the container component.

Document replacement and extraction Even if there is an enhanced name and component resource, extracting files in the application update process is also a not easy problem. The problem of this problem is that the application is running to replicate their files. More complicated is that you run the app may like Notepad, this application, while multiple instances are running. If there are similar applications, we are universal solutions. Instead, a solution is not as good as viewing the features available to manage replacement issues. First, a simple possibility is to run automatic upgrade characteristics in the process separated from the main program. This is a very good way when the app is unmanaged or wants to expand it. The update process can handle all BITS logic and file extraction, which is waiting until the file is taken until the primary application is terminated. There are three main disadvantages to run extraction code during separate processes. First, it is difficult to make your own batch automatic update code. Second, there is nothing benefit to this method in the server side, because the server is unlikely to close. Third, if the primary application is managed by Windows Job object, the automatic update process will be automatically terminated by Windows when the main process exists. AutoPdateApp.exe routines run automatic upgrade logic during the main application logic. If you decide to do it, you may encounter a problem that delete and replaces the DLL and EXE files used by the process. Deleting a public tip of the DLL or EXE file in use is to rename the file as a temporary file, and copy the new file to the file name. Then you can use the MoveFileEx Win32 API to record the deletion of the file using the MoveFileEx Win32 API when restarting the system next time, or contains logic that looks for temporary files and deletes. Even if you use a renamed trick, you have to consider the update is in progress, the user runs another instance of the application, which will load some old files and some new files. There are a variety of ways to solve the problem, one of which is the use of the application domain's video (Shadow) replication feature in the CLR. The CLR runs to manage the management code in the logical application vessel (called application domain or appdomain). Multiple Appdomain can run in a Windows process. When establishing an appdomain, you can identify a new domain to image copy files. It means that when the application loads the component, the component file is copied to a hidden folder and load from the image location. This feature is used by the ASP.NET class in the ASP.NET framework, which is used to export the application file so that it can be updated by the ASP.NET code generator. AppDomain also has useful execution of the application. Ideally, when there is an update presence, the application will prompt the user to be interested in updating. After answering "Yes", the application runs using new features. For some applications, reloading applications in new processes is acceptable, in other applications, better ways are new code running during execution updates. Re-runs Manage EXE using Appdomain is easy. The Relaunchexe method in this article is an example of an implementation. The RELAUNCHEXE method creates a new AppDomain and re-executes the execution file to pass the same command line parameters. ================ AutoupdateApp.exe sample application This code example not only includes automatic upgrade logic, but also two upgraded version of the application so that you can see Operation scheme. Although Visual Studio .NET is a powerful programming environment, there are some time you just need to create batch establishment (Build).

My project is an example, a multi-version constructed, it is difficult to generate as a Visual Studio project. Therefore, in the publishing, an example is a series of resource files and a batch file for executing the creation from the command line. In order to test the app, please download this application file and code (http://download/9/4/C/94cd450c-e7ae-46a3-ad1e-d19f2b80fa0c/bits.exe), and will They decompressed to an empty directory. Then run build.bat from the command line. In order to run the batch file, the CSC.EXE (C # command line compiler) and sn.exe (enhanced Name Tool) are required in the path to the environment variable. You will find that CSC.exe in the .NET Framework component is installed in the C: /Windows / Microsoft.Net/framework/ directory, the .EXE of the .NET Framework component is generally installed in C: / Program Files / Microsoft.net or C. : / Program Files / Microsoft Visual Studio .NET location. Once the project has been built with build.bat, two important directories are created: App and Updates. Note that a SLN file will appear so you can use Visual Studio .NET to simply edit the code file (but you need to use Build.bat to establish the project). The first directory (APP) contains the application installation. Turn the current directory to the app directory and run AutouPdateApp.exe to test. The actual functionality of the application is to display it first bitmap in the load directory (see Figure 2). Figure 2. Automated Update Simple Application To view the update feature, create a IIS virtual root directory called Updates and assign anonymous download access. Its purpose is http: // localhost / updates as a posting position that publishes all updates. Then copy the contents of the second directory (Updates) to the virtual directory. Suppose all all settings are correct, your application will be able to find update1.dll and update2.dll on http: // localhost / updates. Execute and turn off from the command line several times, the application will prompt the first update to be available for a second and third load. The first update adds a new GIF file to the directory. The second update actually installs the new copy of AutouPdateApp.exe, which now has the characteristics of all GIF files that run the slide display loaded in the directory. The application creates a data file called UpdateState.xml when you load autOUpdateApp.exe. This file contains information that controls the AutouPdateApp.exe feature, including the application finds an updated network location. If you don't want to use the http: // localhost / location, you can change the URL in the updateState.xml to specify different update servers. The future of automatic update applications currently have many features to write automatic update applications can be used. That is, Microsoft developers are currently working hard to make automatic updates more simple and become natural parts developed by applications. The 1.0 version of the .NET Framework component has now provided some basic functions. In the end, your application is easier to install and update, the more successful applications. In the future versions of Windows, you will have a plan to update the Built-in service for updating discovery and replacement. The BITS service will continue to be the lower download mechanism, but the additional API will simplify download and security. As a supplement, BITS will expand into an easy-to-use user interface that manages the application update.

转载请注明原文地址:https://www.9cbs.com/read-99165.html

New Post(0)