Clickonce部署初体验

简介:
我们经常要面对的是对开发模式的选择,比如C/S模式和b/s模式。现在,很多人都似乎比较喜欢选择B/S模式进行web的开发,这其中的原因是很多的。但其中一点很重要的原因,那就是因为B/S开发的话,部署非常之容易,因为这样很容易实现"瘦客户端",客户端只需要使用浏览器就可以运行应用了。但B/S模式下开发的WEB应用,也有其不足之处,主要是由于功能实现起来,是没办法和传统的C/S模式下的winform应用相比的,很多winform下要实现的优秀功能,在Web上都很难实现,或者说有的根本没办法实现。但传统的winform,在部署上也有自己的困难之处,如果客户端多的话,每次部署和版本升级都十分麻烦。

  在.net 2.0里,微软新推出了一项叫clickonce(一次点击)的应用程序部署技术,可以很好的解决上面的这个矛盾。在VS2005 中已经整合了clickonce的技术,使到用户可以很方便地部署winform开发的程序,很容易地管理其升级部署。
 
clickonce能带给我们什么

  首先,通过clickonce技术,我们可以实现如下的部署方式:

  1) 在设计完winform程序后,可以选择将程序发布到如下的存贮位置:文件系统,本地的Web服务器,FTP站点,远程Web站点。
 
2) 当应用程序部署到相应的位置后,用户可以通过浏览器浏览一个叫publish.htm的文件,点击下载的链接,将应用程序下载到本机安装。这个publish.htm是部署应用程序的一个入口文件。
 
3) 当用户安装完程序后,会自动产生快捷方式到桌面,并且在控制面版的增加删除中会找到该程序。
 
4) 当用户启动程序时,系统可以首先去检查服务端是否有新的程序版本,如果有的话,则会自动连接服务端,查看是否有新的版本,如果有新的版本的话,则自动下载新的版本到本机并安装,这对于C/S软件的升级维护来说是个“福音”。

ClickOnce 应用程序具有如下优势: 

1)更新是事务处理(即,要么完全执行,要么根本不执行)。
2)该应用程序不但可以脱机工作,而且还可以对其进行某种程度的控制;有一些 API 可使应用程序发现它是联机或脱机;它还可以控制其自身的更新过程;
3)它可以与 Visual Studio .NET 进行良好的集成,包括能够生成合适的额外文件和工具,帮助您找到运行应用程序所需的安全权限。
4)它具有一个可下载必需组件(甚至 .NET Framework 自身)的 Win32“bootstraper”可执行文件。
5)可以按需要或以批处理方式下载应用程序文件;
6)它可在 Start 菜单中添加快捷方式;
 
一个简单的clickonce程序部署的例子
声明:
例子代码来自嘻哈呵嘿的C#版的端口扫描器(PortScanner)一文,在此感谢他允许我使用他的成果.
 
//扫描类
  class Scanner
    {
        string m_host;
        int m_port;

        public Scanner(string host, int port)
        {
            m_host = host; m_port = port;
        }

        public void Scan()
        {
            //我们直接使用比较高级的TcpClient类
            TcpClient tc = new TcpClient();
            //设置超时时间
            tc.SendTimeout = tc.ReceiveTimeout = 2000;
            try
            {
                //Console.Write("Checking port: {0}", m_port);
                //尝试连接
                tc.Connect(m_host, m_port);
                if (tc.Connected)
                {
                    //如果连接上,证明此商品为开放状态
                    Console.WriteLine("Port {0} is Open", m_port.ToString().PadRight(6));
                    Form1.openedPorts.Add(m_port);
                }
            }
            catch (System.Net.Sockets.SocketException e)
            {
                //容错处理
                Console.WriteLine(e.Message.ToString());
              
            }
            finally
            {
                tc.Close();
                tc = null;
                Form1.scannedCount++;
                Form1.runningThreadCount--;

               
            }
        }
    }
    public partial class Form1 : Form
    {
        //已扫描端口数目
        internal static int scannedCount = 0;
        //正在运行的线程数目
        internal static int runningThreadCount = 0;
        //打开的端口数目
        internal static List<int> openedPorts = new List<int>();
        //起始扫描端口
        static int startPort = 1;
        //结束端口号
        static int endPort = 500;
        //最大工作线程数
        static int maxThread = 100;


        public Form1()
        {
            InitializeComponent();
        }

        private void btnScan_Click(object sender, EventArgs e)
        {
           
          
          
            //接收传入参数一作为要扫描的主机
            string host = this.txtHost.Text.Trim();
            //接收传入参数二作为端口扫描范围,如-4000
            string portRange = this.txtStart.Text+"-"+this.txtEnd.Text;
            try
            {
                startPort = int.Parse(portRange.Split('-')[0].Trim());
                endPort = int.Parse(portRange.Split('-')[1].Trim());
            }
            catch(System.Exception ex)
            {
                MessageBox.Show(ex.Message.ToString());

            }

            for (int port = startPort; port < endPort; port++)
            {
                //创建扫描类
                Scanner scanner = new Scanner(host, port);
                Thread thread = new Thread(new ThreadStart(scanner.Scan));
                thread.Name = port.ToString();
                thread.IsBackground = true;
                //启动扫描线程
                thread.Start();

                runningThreadCount++;

                Thread.Sleep(10);
                //循环,直到某个线程工作完毕才启动另一新线程,也可以叫做推拉窗技术
                while (runningThreadCount >= maxThread) ;
            }
            //空循环,直到所有端口扫描完毕
            while (scannedCount + 1 < (endPort - startPort)) ;
            this.lbInfo.Text = "扫描结束!!";
            //输出结果
            String result="";
            result += "总共有" + openedPorts.Count.ToString() + "个端口打开着!\n";
            foreach (int port in openedPorts)
                result +="端口"+ port.ToString().PadLeft(6) + "\n";
            if (MessageBox.Show(result, "扫描信息", MessageBoxButtons.OK, MessageBoxIcon.Information) == DialogResult.OK)
            {
                this.lbInfo.Text = "";
            }
        }
    }


当运行上面的程序,如下图所示:
200692501.JPG

接下来,我们可以对其进行发布了。鼠标右击PortScanDemo工程,选其中的属性"菜单,如下图所示:
200692502.JPG

上图是项目的属性页,其中有许多选项。主要关注下其中的"发布"选项卡的配置。在最上面的"发布位置"选项框中,允许你指定将项目发布的位置。可以点旁边的"…"按钮,进一步浏览确定发布的位置,如下图:
200662513.JPG

这里,我们可以设定项目要发布的位置,比如文件系统,本地服务器,FTP站点,远程站点等。
 
接着,我们在"安装模式和设置"选项组中,可以点选"系统必备"按钮,这里可以设置要运行该应用程序时,需要额外安装的库文件或其他必须的文件,如下图所示。默认必须安装的是.net framework 2.0。

200692510.JPG

同时,可以选择"安装模式和设置"选项卡中的“更新”选项,这个选项卡如下图所示:
 
200692509.JPG


其中,默认是采用启动应用程序时检查更新的选项的。当然,你也可以选择,是在应用程序连接上网时自动检查是否有更新的版本,或者是选择当应用程序启动后,以后台进程的方式,自动检查是否有新的版本。
最后,选择"选项"选项卡,如下图,填入一些关于应用程序的信息。
200692503.JPG


 最后,我们已经设置完毕,可以开始进行部署了。我们使用其中的"发布向导"进行发布。首先选定要发布的位置,如下图所示:
200692504.JPG


   点"下一步"后,出现如下图,这里,可以选择你的应用是在离线或是可以同时运行在离线和在线状下的。
200692508.JPG


  当应用是可以在在线或者离线状态下都可以运行时,发布成功后,应用程序可以在桌面出现快捷方式。当应用程序只能在在线状态下运行时,应用程序只能通过发布页面通过浏览器执行。

  最后再选“下一步”后,就成功完成了发布了,系统并自动打开IE浏览器,转到publish的页面。我们先来看下,在该应用程序发布到的目的目录下,我们会发现有如下图的文件。

200692505.JPG

现在我们可以看到我们已经成功将PortScanDemo应用程序发布到当前IIS的根目录下了(c\inetpub\wwwroot\PortScanDemo),版本是1.0.0.0。而通过浏览器,可以看到如下的安装部署窗口:

200692506.JPG

此时,按“安装”,就可以进行安装了,IE会打开如下窗口以提示你,目前正在下载一个应用程序安装。

200692507.JPG

此外,你也可以在“开始”菜单中发现,新添加了你刚安装的程序的快捷方式,而且在控制面板中“添加和删除程序”中也可以轻易地卸载掉软件。

200662514.JPG

从以上可以看出,在vs.net 2005中,对winform应用程序的安装部署更加方便了,是采用了所谓的smartclient的方式实现的,使的winform的应用程序也可以通过IE进行部署,并且可以很容易的获得应用程序最新的版本。但是,也不得不提一句我对这个技术的担心之处,安全性应该还是最让人关注的地方,它真的安全吗?这样的安装方式会不会给用户带来更大的麻烦呢??



本文转自Phinecos(洞庭散人)博客园博客,原文链接:http://www.cnblogs.com/phinecos/archive/2006/09/26/514728.html,如需转载请自行联系原作者
目录
相关文章
|
SQL 存储 druid
Minerva -- Airbnb 的大规模数据指标系统 Part 3
Minerva -- Airbnb 的大规模数据指标系统 Part 3
707 0
Minerva -- Airbnb 的大规模数据指标系统 Part 3
|
消息中间件 存储 负载均衡
Kafka面试题及答案
Kafka面试题及答案
|
9月前
|
存储 运维 资源调度
阿里云服务器经济型e实例解析:性能、稳定性与兼顾成本
阿里云经济型e云服务器以其高性价比、稳定可靠的性能以及灵活多样的配置选项,成为了众多企业在搭建官网时的首选。那么,阿里云经济型e云服务器究竟怎么样?它是否能够满足企业官网的搭建需求?本文将从性能表现、稳定性与可靠性、成本考虑等多个方面对阿里云经济型e云服务器进行深入剖析,以供大家参考选择。
543 37
|
9月前
|
存储 弹性计算 数据挖掘
阿里云服务器ECS通用算力型u1和ECS经济型e实例性能特点、使用及常见问题解答FAQ
阿里云ECS云服务器的经济型e实例和通用算力型u1实例深受开发者和中小企业青睐。e实例适合中小型网站、开发测试等轻量级应用,采用共享CPU调度模式,性价比高;u1实例则适用于中小型企业级应用,提供更高的性能保障和稳定性,支持固定CPU调度模式,计算性能更稳定。同等配置下,u1实例在网络带宽、IOPS等方面表现更优,价格也相对较高。个人用户可选择e实例,中小企业建议选择u1实例以确保业务稳定性。
315 5
|
Java 编译器 Serverless
Java 原生化的未来 Graal AOT 编译器
使用 Graal 编译器对 Java 程序进行 AOT 编译使其适合 Serverless 场景。
237 0
Java 原生化的未来 Graal AOT 编译器
|
Web App开发 数据采集 Python
让ChromeDriver 125顺利运行:解决找不到chromedriver.exe的技巧
本文介绍了如何解决Selenium使用ChromeDriver时遇到的版本不匹配问题,以及如何设置环境变量。同时,文章提供了示例代码,展示如何在Python中配置Selenium使用代理IP、设定User-Agent和Cookie进行网页抓取,以提高爬虫的效率和成功率。确保ChromeDriver与Chrome浏览器版本一致,将`chromedriver.exe`添加到环境变量,然后使用`Options`和`Proxy`类配置代理和浏览器选项,最后通过`webdriver.Chrome()`启动浏览器并执行抓取任务。
1041 0
让ChromeDriver 125顺利运行:解决找不到chromedriver.exe的技巧
|
移动开发 前端开发 JavaScript
解决浏览器兼容性问题的方法
解决浏览器兼容性问题的方法
|
机器学习/深度学习 人工智能 自动驾驶
人工智能的伦理困境:机器的自主性与人类的责任
【8月更文挑战第8天】在人工智能技术飞速发展的今天,一个日益凸显的问题是关于AI的伦理困境。随着机器学习和深度学习技术的进步,AI系统展现出越来越高的自主性,这引发了关于人类责任和控制的哲学讨论。本文将探讨AI自主性的提升如何影响人类的伦理责任,以及我们应如何平衡技术进步与道德考量。
|
自然语言处理 并行计算 Python
千问大模型对话
该段Python代码演示了如何使用`modelscope`库加载预训练的因果语言模型`Qwen2-1___5B-Instruct`到CUDA设备,并进行文本生成。首先,它定义了设备为`cuda`,然后加载模型和分词器。接着,设置了一个聊天情境并准备输入文本。通过调用`tokenizer.apply_chat_template`处理输入,然后将处理后的文本转化为模型输入张量并传入设备。使用`model.generate`方法生成新的文本,截取生成的输出并解码为人类可读的字符串。最后,打印出生成的响应。
371 6
|
Python
mplfinance设置K线图中红涨绿跌的样式
要设置K线图中红涨绿跌的样式,您可以使用mplfinance库中的marketcolors参数来自定义K线图的颜色。默认情况下,mplfinance会使用红色表示上涨和绿色表示下跌,但您可以根据自己的需求进行修改。
1528 1