Introducing Client Application Deployment with "Clickonce" - Duncan Mackenzie

xiaoxiao2021-03-06  61

Introduction

Web applications are limited in many ways, yet a large number of Web applications have been built over the last few years and more will continue to be developed going forward. Why do companies choose a Web-based solution over a rich client experience? There are A Few Good Reasons, But The Number One Reason I Hear is Deployment.

When a company decides to create a new application for their employees, regardless of the type of system being designed, the discussion eventually moves to the issue of deployment. The system will need to be rolled out to the target users, and there needs to be a plan in place to handle ongoing updates (bug fixes, new feature releases, and so on). Years of experience with rolling out desktop applications have left most developers and IT staff with a good idea of ​​the pain involved in client deployments, and a Web application ends up being the easier path. of course, there are some tradeoffs in going with a browser-based Web application versus a rich-client application, but the fear of deployment usually makes those compromises acceptable. What we really need is a model For Deploying Client Applications That Is As Easy and As Safe As Deploying A Web Application, Removing The Need To Complomise On The FunctionAlity of Our Applications. That is what "clickonce" BRINGS to the table.

"ClickOnce" is a code name for a set of functionality in the next version of Microsoft® Visual Studio® .NET and the Microsoft® .NET Framework. It will allow us to create desktop applications that are deployed with a safe, system-controlled installation, and are automatically updated as needed from a central location. Before I get into the features of ClickOnce and walk you through building a sample, I am going to go through some of the issues that currently exist with client deployment and the drawbacks to going WITH A WEB-BASED SOLUTION.WHY IS Client Deployment SO HARD?

ClickOnce exists to simplify client deployment, but what does that mean? What problems is ClickOnce going to enable us to avoid? Client deployment is hard because it happens on each of many clients, potentially at many locations, and your code and all of the associated Components have to work on all of the target machineines.

Consider a medium-sized application deployment of 10,000 seats (not all that unusual for a business application within a corporation). For a desktop application, that is 10,000 different machines that could each contain a slightly different mix of software configurations. In the case of . a Web application, there may be anywhere from 1 server to a small "Web garden '"' of machines-an extreme difference in scope for your deployment So, in each case, you will need to ensure that your code will:

NOT BREAK Any Existing Software by Being Installed. NOT BE BROKEN BY The Installation of Any Future Software.

Quite a daunting task if you are dealing with 10,000 machines. What impact will it have on your testing to include all of the possible software combinations? The last two items on my list are affectionately known as "DLL Hell," where the installation or removal of a DLL for one application can break another. While there are many ways to reduce the likelihood of a conflict between applications, it is still a possibility when deploying onto client machines. All of these issues can make a Web application look very appealing. After all, when was the last time a Web application broke your desktop? The act of installing your software the first time, or of installing any future updates, is also a challenge. For the Web server case, you could just handle the installation manually, assigning someone to go to each machine and run the setup program-a process that is not feasible for 10,000 clients. When dealing with a large number of clients, you will likely need to rely on the user to take some ac tion to run the initial installation, and to run a new install program for each update over the life of the application. While this approach has already been used successfully on countless occasions, it adds complexity to the release and to each update of the application.

Security is an ossu for application installation on the policies of the company in qustion, a regular user may not have since incer agent installation.

Note Microsoft® System Management Server and other similar systems help ease the pain of deploying applications across a company, but they do not remove the issues of unwanted client install side effects. Such systems also tend to work best in very highly managed environments where desktops Are Created to a Precise Specification and Updates Go Through A Strict Release Procedure.limitations Of Browser-Based Applications

I use the Web everyday, and it is wonderful for many things, but Web-based applications have their limits. There are some obvious issues with browser-based systems. The lack of offline support alone means that a Web-version of Microsoft® Outlook ® ISN'T Enough for Me, And Many Issues With Web Applications Can Be Seen In Even The Most Popular of Sites.

Consider the act of clicking "checkout" or "submit" on an online shopping site once you've entered your credit card info. Right at that exact point on many occasions I've received a browser error of "page not found" or " server is not responding. "What does that mean for my order? Did it go through or not? This type of confusion is hard to avoid in a Web application-although it can be mitigated with e-mail confirmations and other methods-because it IS NOT A Mistake on The Part of The Developer. Rather, IT IS A Side Effect of The Thin-Client Architecture of The Web.

Client applications can suffer from such issues as well, but in most cases these should be seen as a limitation or a bug;. It can be done better The developer of a client application has the option of saving your order locally and periodically retrying the transaction or querying for the state of the transaction after a loss of network connectivity-choices that are unavailable in a Web application. I'm not going to spend any more time discussing Web applications. I am sure you have your own reasons for wanting to develop And Deploy A Microsoft® Windows® Application, SO i WILL FOCUS ON How Clickonce Makes It Easier for You To Accomplish That Goal.Clickonce Provides The Best of Both Models

There Are Two Main Reasons To Develop for the Web Instead of for the Client Machine:

The first reason is a need to limit your application to the lowest common denominator (the Web browser) in an effort to reach almost any device that can access the network. Web applications aim for "reach" not "rich," supporting the widest number of clients at the cost of some functionality. The second reason is the ease of installation and ongoing updates. The ability to apply a bug fix onto a single machine or a small set of machines, instead of requiring the new code to be applied on every Single Client, IS An Amazing Time Saver In The Maintenance of an Application.

Going for reach is critical when your goal is to ensure availability to almost any device that can connect to the Web, but if you are dealing with a slightly narrower target audience, such as "employees and partners of my company," then reach isn ' t as much of an issue. Once you've reduced your target audience to something a little bit less than everything and everyone, you can constrain the target platform (Windows machines capable of supporting the .NET Framework) and then take advantage of that platform by building a full desktop application ClickOnce allows you to do this by providing the second part of the equation:. easy installation and automatic updates for your applications.Later in this book, I will go into how the three different deployment models (Web, ClickOnce , and full client installs with MSIs) relate, and how you can determine the best choice for your particular application. for now, the table below illustrates the features of each deployment model and shows how ClickOn CE Bridges The Gap Between The Traditional Web and Client Worlds.

FeaturesWebClickOnceMSI / ClientReachY Auto-DeploymentYY Low System ImpactYY Install / Run Per-UserYY Rich / Interactive Experience YYOffline YYWindows Shell Integration YYUnrestricted Install Y

EXISTING Deployment IMPROVEMENTS Under .NET

Although ClickOnce is a new feature in the next version of the CLR and the .NET Framework, it is made possible by many existing aspects of managed code. Even in the initial version 1.0 release of .NET, managed applications were designed for application isolation and ZERO-IMPACT Deployment (offen described as Xcopy Deployment), Making It Easier Than Ever to Install and Update your Applications.

With the first release of .NET, applications could also be run directly from a Web site. (Http: //mysite/myapp.exe) ensuring that they were always up-to-date Nevertheless, the technical limitations of this approach were significant . Href-exes (as applications run from a HTTP address are known) often required security policy changes on the client (which meant that an .MSI had to be run before the application would work). They also ran slower than the same application installed locally, the user experience was lacking (when a new assembly needed loading from the Web server, the UI would freeze for a few moments), and they had no real offline model.The availability of two auto-updating solutions, Jamie Cool's "appUpdater "and the Updater Application Block released on MSDN, provided a better experience for the developer and the end user. With both solutions, applications were installed to the local machine, so they did not have the performance or security issues of href-exes, And It Was Poss ible for an application to support offline us.

Appendix A of this Book Goes Into More Detail on The Deployment Methods Available To You While Still Using Version 1.1 of The .NET Framework. Clickonce Builds On this Layer of Support and Makes It Even Easier

Basic Clickonce Concepts

Now that I have gone through some of the reasons why we need a better deployment model for Windows applications, I will cover how ClickOnce provides an answer. ClickOnce is a combination of a set of features in the .NET runtime (the CLR) and integrated design-time support in Visual Studio .NET. Together, the feature and the IDE tools allow you to create an application that can be automatically installed and updated. you have a great deal of flexibility as to how your application is deployed, launched, and Updated. i Cover Each of Those Topics In More Detail In Future Chapter

ClickOnce applications can be deployed to a client machine from a Web location, a UNC share, or even from a file location such as a CD. When an application is deployed in this fashion from a Web location, the user will click on a link on a Web page, which will cause the application to download and install itself on the client machine (complete with Start Menu shortcuts and a line in the Add / Remove Programs dialog). Once the installation completes, the application will then appear, having been downloaded And installed over the course of a few moments.

Alternatively, ClickOnce applications can be run without deploying them to the client machine;. They can be launched directly from a network location (such as an UNC path or an http URL), with no impact to the client Applications launched in this fashion are cached Locally, But They Are Not Installed in The Traditional Sense. The Various Deployment Options Are Covered in More Detail in Chapter 3 of this book, "'clickonce' scrutarios."

If you need an install that impacts the client machine (to create file associations, install MSDE, or perform other similar actions) then you still have the ability to handle that side of the installation through an .MSI file. Of course, everything you do outside of the regular ClickOnce deployment process can reduce the ClickOnce functionality, but if required then it is certainly possible.For either launched or deployed applications to work, the .NET Framework is required on the target machine. Depending on your particular situation, there are a variety of ways to get the Framework onto a machine in advance of your install or as a part of the install itself. Both the specific topic of deploying the .NET Framework and the general concept of advanced installations are covered in Chapter 4, "advanced Deployment concepts. "

Updating the application

Updates are as flexible as deployment options, allowing you to update at certain times (such as the start of the application), or whenever the application developer chooses to call the appropriate update APIs. It is also possible to specify that a certain update is required , removing the user's ability to ignore an available update. This required update feature is critical for managing ongoing updates and ensuring that the entire user-base can be moved up to a new version in a timely fashion.

Other key features of the update process include the ability to do rollbacks of an application release on either the client or the server. In the case of server rollbacks, this administrative feature allows for the quick removal of a flawed update and the automatic downgrade of your clients to the previous version The client side of the rollback is a critical feature for occasionally connected clients;. if they connect, update, and disconnect, only to find that the new application version fails on their machine, they can rollback to the previous version without having to reconnect. With all of the options that are available, you will be able to achieve whatever specific update functionality you require, but the concepts are complex enough to deserve their own chapter (Chapter 6, "Application Updates"). Manifest Files

The deployment and update activities can be controlled through the use of a pair of XML manifest files that describe the components of the system and the deployment activities that should occur. The application manifest is authored by the developer (with the help of Visual Studio .NET ) and details the files, dependencies, and base security requirements of the application. The deployment manifest is intended to be created by the administrator (although the developer will certainly be creating this manifest during the early phases of development), and it details how the application is supposed to be deployed and updated. These two manifest files are involved in every ClickOnce application, so you will be seeing them and all of their options throughout this book, but they are covered in exacting detail in Chapter 8, "Digging into the Manifest Files. "

Figure 1. The manifest files work together to enable the installation and update of your ClickOnce application.Later in this chapter, as I walkthrough building a simple ClickOnce application, you will see the contents of the basic pair of manifest files created by Visual Studio. Net. Note That The Manifest Files Are Not Signed In The PDC Release of The Next Version of Visual Studio .Net Code Named "Whidbey" But That Feature Will Exist in Future Versions.

Security Concepts

Prior to ClickOnce, security was one of the biggest hurdles in getting an href exe to run correctly on the client's machine, and it is still a critical concept for ClickOnce applications. Thankfully, the security "sandbox" that your application is allowed to play in has been increased in size, and the boundaries of this sandbox are much easier to understand and explore. Due to the auto-install and auto-update functionality of ClickOnce applications, they are intended to support a safe deployment model. Deployed or automatically downloaded code IS LIMITED AS to WHATTION IT CAN Access and what actions it can take. WHETHER An Application IS Lauched from a URL or Deployed from A CD, IT IS NOT ASSUMED TO HAVE FULL TRUST ON The Target Machine.

Although the limitations of the default sandbox for auto-updating applications have been decreased, it has been difficult to troubleshoot a problem that only occurs in a reduced security situation, until now. The Whidbey release of Visual Studio .NET allows you to run your application in a reduced security situation from within the IDE, and with the debugging tools attached. This new feature will allow you to simulate various security settings and restrictions while developing your application, instead of having to deploy your application to a test machine to view any security issues.Chapter 5, "Security in 'ClickOnce' Applications" covers the default security restrictions for the different deployment options and gives you some guidance on how to program within those restrictions. If your application can not run within the default set of restrictions, Chapter 5 Will Also include a Discussion of How security Policy Can Be Adjusted and Rolled Out To Client Machines by Administrators. For t hose situations where making or deploying a security policy change is impractical, there is a new security feature, also covered in Chapter 5, known as Permission Elevation. This allows the user to make trust decisions about a specific application.

Visual Studio Integration

ClickOnce is a key feature of Whidbey, which means that, in addition to being documented and supported, it is tightly integrated into the Whidbey version of Visual Studio .NET. Using the property dialogs, you can specify a variety of ClickOnce information (that will BE Used to create the Two Manifest Files Discussed Earlier, Including the Publishing Details (See Figure 2).

Figure 2. You can specify the location your files should be published to (and accessed from) either in this property dialog or as part of the wizard that runs when you publish your application.The Visual Studio .NET integration extends to more than just configuring your publishing and updating details inside the IDE. You can also publish the application directly from within the IDE by clicking publish from the Project menu, and then walking through a quick wizard of options. I will walk through this process a little later in this chapter , But it is quite simple to use.

Although not only aimed at ClickOnce users, another powerful Visual Studio .NET feature allows you to run your application in the IDE (with a debugger attached) under whatever security context you wish. This feature will really help you to understand the security restrictions your application Will Be Running Under. It Will Also Help You to Properly Debug Security-Related Issues Using The Full Tools of The Visual Studio .NET IDE.

Building a Simple Clickonce Sample

Now that I have gone through the basics behind ClickOnce, it is time for a demonstration. There will be more advanced examples later on in the book, but for now I will focus on a fairly simple application that does not have any real requirements beyond The .NET Framework.

Note Remember that these instructions, screenshots, and other details are based on the PDC 2003 release of Whidbey and the corresponding version of the .NET Framework. User Interface elements and the exact details of steps may change over time.

For The First "Release," I Will Start with An Absolutely Empty Application. (You Can't Really Get Any Simpler That, Right?) THAN, For A Second Release, I'll Add A Few Simple Features SO That You CAN See the auto-updating functionality and the basic process of rolling out an update.requirements

The Only Requirements for this demo area To have:

The PDC version of Visual Studio .NET on the development machine. An available Web server onto which you can put files and create directories. A client machine that has the PDC version of the .NET Framework installed.

If you are using a single machine for everything, then you should have everything you need. If your Web server happens to be Microsoft® Windows Server ™ 2003, then you may need to make one small configuration change. By default, Windows Server 2003 blocks the download of any files that have known file extensions. If you are going to use this server to publish a ClickOnce application, then you should change the settings of Microsoft® Internet Information Services (IIS) to allow .deploy and .manifest extensions to be downloaded. This issue is described in Microsoft Knowledge Base article 327283, and that same article discusses how to add a new file type (and associated extension) to your IIS settings. in the case of the .deploy file type, registering it with a MIME Type of "Application / Deployment" is recommented.

Creating the application

As I mentioned earlier, for the first release, I just built and published an empty application. Create your own empty application by clicking New Project and selecting the Windows Application project type (see Figure 3). The language you choose is not really important at this point, and I'll provide the code for the second release in both C # and Microsoft® Visual Basic® .NET, so just go with whichever language you are more comfortable with.Figure 3. Create a new empty Windows Application project

Now, I Moved ONTO Configuring The Deployment Settings for My New Application.

Configuring Our Deployment Options

The Project Properties dialog has changed quite a bit from Visual Studio .NET 2003, and part of that change was the addition of a property page for the Publishing settings of your application. Open the properties dialog through the Properties menu item on the Project menu, or just right click your project in the Solution Explorer and click the Properties menu item. Click Publish along the left-hand side and you will see the alpha version of a very interesting set of options (shown earlier in Figure 2).

Note Normally, you will not use this properties dialog for the basic ClickOnce settings. Instead, you will set the deployment location and install mode options as part of the Publish Wizard, which is run whenever you choose to publish your application (and is shown a little later in Figure 6). You will need to use this Project Properties dialog to set the advanced options though, so I decided to set all of my properties in this dialog so that I could cover all of the settings at one time.

Specify the deployment location of your application (in the text box under the "Publish my application to ..." prompt), which will default to an http:. // localhost / ... location If your Web server does not support connection through its Web address, you could also specify a file location that corresponds to the same Web folder (// duncanmawhidbey / wwwroot $ / sampleapp) or a FTP address. On a real project, I suggest you give a bit of thought to the server name you want to use in this setting, because it is stored in the project file and will move to different machines along with the project. If you use the real name of your server, even if it happens to also be the same machine as your Visual Studio .NET installation, then you can continue to point at the same Web server, even if you move between different development machines. Alternatively, if you are working on a project with multiple developers, you might not want to use a shared Web Location. Specifying a localhost-based URL Will Allow EA CH Developer to Run Their Own IIS Instance, WITHOUT CHENGING TIME WISH TO PUBLISH An Application Update.

Next, make sure the Install Mode radio button (which reflects the choice between an application that is launched from a network location and one that is installed locally and updates itself from a Web location) is set to "Install the application ..." For this sample application, I wanted to show a system installed in the regular "Windows application" style. Ensure that the option to create a Web page for your published application is checked, and that you have the appropriate name entered into the Web page name textbox . I like to use "default.htm" myself, so that it becomes the default page for the publication folder, but you can enter any file name you wish.Click the Application Updates ... button to set your desired update frequency and options See Figure 4.

Figure 4. The application Updates Dialog Allows You To Indicate When and how offten your application checks the source location for a new version.

The two bottom settings, "Required update" and "Update from ..." are used to configure an application update as mandatory, or with a different update location than previous releases. Match the settings to Figure 4, if they are not set to The Values ​​Already, And Close The Application Updates Dialog.

Clicking on the Prerequisites button allows you to specify the base components necessary for your application to run (see Figure 5). Specifying components as prerequisites will cause them to be compiled into setup programs that can be run on target machines before running your application. For This Sample, Just Leave The .NET Framework SELECTED and Close The Prerequisites Dialog.

Figure 5. Specify The Base Requirements of Your Application In The Prerequisites Dialog.

The Application Files button will allow you to specify which files are required by your application. For this sample the only file listed would be our .exe, so it is not the most interesting of options at this point.Publishing the Application

With all of our settings configured, publishing the application can be initiated from the IDE by clicking Publish from the Project menu. (It is also available on the right-click menu of the project in the Solution Explorer). This will start up a wizard .

Figure 6. The Publish Wizard Allows You To change Some of the Publish Settings from the project Properties Dialog.

There are three steps to this wizard: one for the location, another for the type of deployment (launch versus install), and then a final summary step Since I set up my publishing options back in the Project Properties dialog (see Figure 2). , I just clicked Finish and watched as Visual Studio connected to my Web server, created a new directory, and uploaded a set of files. The deployment manifest was placed at the root of the specified directory, along with my automatically created Web page (publish .htm) and a setup.exe program that can install my application's prerequisites. Below the top level, a directory was created for the current version of my application (/WindowsApplication1_1.0.0.0/, which contained my .exe file and the application .

When the Publish Wizard completes, the auto-generated Web page (see Figure 7) is automatically launched. This page gives me a handy link to the .deploy file, which is what you want an end user to click on to install / launch a ClickOnce application.Figure 7. The auto-generated Web page, which looks similar to the pages created for ASP.NET Web services, provides links to the application's deployment manifest (.deploy file) and the installer for the application's prerequisites.

If you are accessing the Web page from a machine that does not have the .NET Framework installed, you should click the "click here to install prerequisites" link before attempting to install the actual application. Note that without the Framework installed, the client System Wo't Know How To Handle The .deploy File Type and Will Just Ask if you wish to open or save the manifest.

Running the application

To run the application, I clicked on the link to the WindowsApplication1.deploy file. At that point the .NET runtime took over and prompted me (see Figure 8) to confirm the application install that was about to occur.

Figure 8. When An Application NEEDS To Modify Something On your Machine, you are prompted to confirm the installation.

Note This confirmation dialog was only required because in this case the application was being added to the Start Menu, and that action requires user consent. If the application had not needed to be added to the Start Menu, then it would have just run without Any Prompt.

Once I confirmed my desire to install the application, it went through the install process, added a shortcut to the Start Menu (see Figure 9), and then launched the application. The Start Menu shortcut is under the name Microsoft, because I never updated the various properties of my sample application to provide a more appropriate company name, but you are certainly not limited to that install location.Figure 9. When you configure an application to be installed, not just launched, it creates a shortcut on the Start Menu .

Now That The Application Has Been successfully deployed, it is time to make a change and watch the auto-updating feature at work.

Publishing an Application Update

Going back to my sample application, I made a simple change to clearly distinguish between the initial and the updated version. Almost anything noticeable would do, but I decided to add a button that would display a simple message. If you are following along with this Sample, Make A Similarly Obvious Addition To your application, or make the exact same addition using the code snippet Below.

'Visual Basic .NET CODE

Private sub button1_click

Byval sender as system.Object, _

ByVal e as system.eventargs)

Handles button1.click

Messagebox.show (_

"Greetings!", "New Version", _

MessageboxButtons.ok, _

MessageBoxicon.information)

End Sub

// Visual C # CODE

Private vid button1_click

Object sender,

System.Eventargs E)

{

Messagebox.show ("Greetings!",

"New version",

MessageboxButtons.ok,

MessageBoxicon.information)

}

Once I made that addition, I went into the AssemblyInfo file and increased the application version to 1.1.0.0. Then I used the Publish menu item to kick off a new publishing process for this application, once again leaving all of the options the same. When that wizard completes, a new folder will have been created on the Web server to hold the new version (see Figure 10), and the deployment manifest will now indicate that 1.1.0.0 is the version that everyone should be running.Figure 10. New Application Versions Require a change to the .deploy File, and the addition of a new sub folder, but the auto-generated web page does not required Updating.

Once The New Version IS Available on The Server, Client Applications Will Start To Automatical Update Themselves, Based on Their Application Update Settings.

Client Update

Now that the new .deploy file has been made available, if we were to run our original sample, an automatic update would occur. With the settings we have specified for our updates (which is to check for updates when the application starts up), the user will be prompted to confirm that they wish to upgrade to the new version (see Figure 11). Note that the UI around Client Updates is definitely in an alpha state and will be replaced in future builds.

Figure 11. When an update is available, the user is notified and the can choose to accept or ignore the new version.

If the user clicks Yes, then a progress bar will appear (since this is a very small application, the progress bar should appear and disappear so quickly that you barely have time to notice it) and the new version will be downloaded and executed. Of course this update was performed using only the default settings; you will have more control if you consider all of the different options available to you.Note If you run into problems deploying a ClickOnce application, you should take advantage of the log created on the target .

Clickonce in Longhorn

The next release of the Windows Client, code-named "Longhorn," will include many changes to application deployment. However, if you are developing with ClickOnce, you will find most of these changes quite familiar, as Longhorn applications share many of the characteristics And Behavior of Clickonce Applications.

To start with, Longhorn applications will use the same Application and Deployment Manifest model that we have been discussing. They will also support the same two deployment methods (deployed to the local machine or launched from the remote location) as ClickOnce applications. Another key aspect of ClickOnce deployment, the use of a security "sandbox" for deployed or launched applications to run within, is also true in Longhorn in fact, Longhorn extends this concept;. its sandbox is known as the Secure Execution Environment and is used by default for All Applications.

Longhorn will extend the current set of ClickOnce features in several ways, including the ability for installations to perform some of the more traditional actions of an .MSI deployment while still using automatic deployment and update. As an example, a Longhorn application auto-deployed to the user's desktop from a Web site can create file associations (registering itself as the handler for a specific file type) without having to request additional permissions outside of the Secure Execution Environment. Longhorn also adds the concept of privacy information as part of the application manifest , allowing the application creator to describe their privacy policy for information storage, reuse, and more. of course, this far in advance of the release of "Longhorn," details are limited, but it is clear that applications (and developers) using ClickOnce SHOULD BE Well Suited for Transition to Longhorn.figure 12. a Simple ClickOnce Application Running On The PDC Release of Longhorn

The steps for creating a sample ClickOnce application (as shown in Figure 12) are not any different if you wish to target "Longhorn," so you should be able to get a Windows Forms application written and deployed (assuming you have both Longhorn and Whidbey available) by following the same process shown earlier in this chapter. It is important to note that, just as with Windows Server 2003, you will need to add the .deploy and .manifest file types to the set of MIME types for IIS in order For The Download to Work Correctly.

Conclusion

Throughout the rest of this book you will learn about ClickOnce in much greater detail, including coverage of possible update and deployment scenarios, working within the security restrictions of a ClickOnce application, and advanced topics around the development and administration of an auto-updating system. Hopefully, this introductory chapter has provided you with a useful look at the basics of ClickOnce, and has given you some idea of ​​how this technology could help you with your own application deployment issues.About the Author

Duncan Mackenzie is the Microsoft Visual Basic .NET and Microsoft Visual C # Content Strategist for MSDN during the day and a dedicated coder late at night. It has been suggested that he would not be able to do any work at all without his Earl Grey tea But Let's Hope We Never Have to Find Out. for More on Duncan, See His Site.

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

New Post(0)