增加程序更新功能
parent
433e03a448
commit
90e07b6f2f
|
|
@ -3,9 +3,23 @@
|
|||
<component name="AutoGeneratedRunConfigurationManager">
|
||||
<projectFile>WinformGeneralDeveloperFrame.Start/Start.csproj</projectFile>
|
||||
<projectFile>WinformGeneralPrimordialForm/PrimordialForm.csproj</projectFile>
|
||||
<projectFile>Update/Update.csproj</projectFile>
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="6ebc9dde-4dcc-424b-9663-06c3bf6f8c79" name="Changes" comment="" />
|
||||
<list default="true" id="6ebc9dde-4dcc-424b-9663-06c3bf6f8c79" name="Changes" comment="">
|
||||
<change beforePath="$PROJECT_DIR$/.idea/.idea.WinformGeneralDeveloperFrame/.idea/workspace.xml" beforeDir="false" afterPath="$PROJECT_DIR$/.idea/.idea.WinformGeneralDeveloperFrame/.idea/workspace.xml" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.vs/WinformGeneralDeveloperFrame/v17/.suo" beforeDir="false" afterPath="$PROJECT_DIR$/.vs/WinformGeneralDeveloperFrame/v17/.suo" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/.vs/WinformGeneralDeveloperFrame/v17/fileList.bin" beforeDir="false" afterPath="$PROJECT_DIR$/.vs/WinformGeneralDeveloperFrame/v17/fileList.bin" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Update/Class1.cs" beforeDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Update/Properties/AssemblyInfo.cs" beforeDir="false" afterPath="$PROJECT_DIR$/Update/Properties/AssemblyInfo.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/Update/Update.csproj" beforeDir="false" afterPath="$PROJECT_DIR$/Update/Update.csproj" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.Commons/GetDataTableUtils.cs" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.Commons/GetDataTableUtils.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.Start/App.config" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.Start/App.config" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.sln" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame.sln" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/DB.cs" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/DB.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/DB/MESDB.cs" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/DB/MESDB.cs" afterDir="false" />
|
||||
<change beforePath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/LoginView.cs" beforeDir="false" afterPath="$PROJECT_DIR$/WinformGeneralDeveloperFrame/LoginView.cs" afterDir="false" />
|
||||
</list>
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
|
|
@ -66,6 +80,24 @@
|
|||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
<configuration name="Update" type="DotNetProject" factoryName=".NET Project">
|
||||
<option name="EXE_PATH" value="" />
|
||||
<option name="PROGRAM_PARAMETERS" value="" />
|
||||
<option name="WORKING_DIRECTORY" value="" />
|
||||
<option name="PASS_PARENT_ENVS" value="1" />
|
||||
<option name="USE_EXTERNAL_CONSOLE" value="0" />
|
||||
<option name="USE_MONO" value="0" />
|
||||
<option name="RUNTIME_ARGUMENTS" value="" />
|
||||
<option name="PROJECT_PATH" value="$PROJECT_DIR$/Update/Update.csproj" />
|
||||
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
|
||||
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
|
||||
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
|
||||
<option name="PROJECT_KIND" value="Console" />
|
||||
<option name="PROJECT_TFM" value="" />
|
||||
<method v="2">
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="SpellCheckerSettings" RuntimeDictionaries="0" Folders="0" CustomDictionaries="0" DefaultDictionary="application-level" UseSingleDictionary="true" transferred="true" />
|
||||
<component name="TaskManager">
|
||||
|
|
@ -77,6 +109,9 @@
|
|||
<updated>1637673594984</updated>
|
||||
<workItem from="1637673603163" duration="178000" />
|
||||
<workItem from="1646484218854" duration="261000" />
|
||||
<workItem from="1652186181534" duration="3660000" />
|
||||
<workItem from="1653834391439" duration="828000" />
|
||||
<workItem from="1654865714910" duration="1917000" />
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,385 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.ComponentModel;
|
||||
using System.Xml.Serialization;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
using System.Collections.Specialized;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 下载错误事件数据
|
||||
/// </summary>
|
||||
public class DownloadErrorEventArgs : EventArgs
|
||||
{
|
||||
public Exception Error { get; set; }
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度事件数据
|
||||
/// </summary>
|
||||
public class DownloadProgressEventArgs : ProgressChangedEventArgs
|
||||
{
|
||||
public DownloadProgressEventArgs(int progressPercentage, object userState)
|
||||
: base(progressPercentage, userState)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// 当前下载的文件名
|
||||
/// </summary>
|
||||
public string FileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 获取收到的字节数。
|
||||
/// </summary>
|
||||
public long BytesReceived { get; set; }
|
||||
/// <summary>
|
||||
/// 获取 System.Net.WebClient 数据下载操作中的字节总数。
|
||||
/// </summary>
|
||||
public long TotalBytesToReceive { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载完成事件数据
|
||||
/// </summary>
|
||||
public class DownloadCompleteEventArgs : AsyncCompletedEventArgs
|
||||
{
|
||||
public DownloadCompleteEventArgs(Exception error, bool cancelled, object userState)
|
||||
: base(error, cancelled, userState)
|
||||
{
|
||||
}
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 服务器文件下载类
|
||||
/// </summary>
|
||||
public class DownloadClass : Component
|
||||
{
|
||||
#region 变量定义
|
||||
private WebClient webClient = new WebClient();
|
||||
private Manifest manifest;
|
||||
private int fileCount = 0;
|
||||
private bool cancel = false;
|
||||
private string tempPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp");
|
||||
|
||||
private HybridDictionary userStateToLifetime = new HybridDictionary();
|
||||
private object defaultTaskId = new object();
|
||||
private delegate void WorkerEventHandler(AsyncOperation asyncOp);
|
||||
private System.ComponentModel.Container components = null;
|
||||
private SendOrPostCallback onProgressReportDelegate;
|
||||
private SendOrPostCallback onCompletedDelegate;
|
||||
private AsyncOperation current;
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadProgressEventArgs> DownloadProgressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 下载完成事件
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadCompleteEventArgs> DownloadCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// 下载错误触发的事件
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadErrorEventArgs> DownloadError;
|
||||
#endregion
|
||||
|
||||
#region 构造及析构
|
||||
public DownloadClass(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
InitializeComponent();
|
||||
InitializeDelegates();
|
||||
}
|
||||
|
||||
public DownloadClass()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeDelegates();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 初始化代理
|
||||
/// </summary>
|
||||
protected virtual void InitializeDelegates()
|
||||
{
|
||||
onProgressReportDelegate = new SendOrPostCallback(ReportProgress);
|
||||
onCompletedDelegate = new SendOrPostCallback(DoDownloadCompleted);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 触发下载进度事件
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnDownloadProgressChanged(DownloadProgressEventArgs e)
|
||||
{
|
||||
if (DownloadProgressChanged != null)
|
||||
{
|
||||
DownloadProgressChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发下载完成事件
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnDownloadCompleted(DownloadCompleteEventArgs e)
|
||||
{
|
||||
if (DownloadCompleted != null)
|
||||
{
|
||||
DownloadCompleted(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 触发下载错误事件
|
||||
/// </summary>
|
||||
/// <param name="e"></param>
|
||||
protected virtual void OnDownloadError(DownloadErrorEventArgs e)
|
||||
{
|
||||
if (DownloadError != null)
|
||||
{
|
||||
DownloadError(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载文字保存的临时目录
|
||||
/// </summary>
|
||||
public string TempPath
|
||||
{
|
||||
get
|
||||
{
|
||||
return tempPath;
|
||||
}
|
||||
set
|
||||
{
|
||||
tempPath = value;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步下载
|
||||
/// </summary>
|
||||
/// <param name="manifest">文件下载清单</param>
|
||||
public void Download(Manifest manifest)
|
||||
{
|
||||
Init(manifest);
|
||||
foreach (var file in manifest.ManifestFiles.Files)
|
||||
{
|
||||
string serverFileName = Path.Combine(manifest.ManifestFiles.BaseUrl, file.Source);
|
||||
string clientFileName = Path.Combine(tempPath, file.Source);
|
||||
Uri uri = new Uri(serverFileName);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(clientFileName)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(clientFileName));
|
||||
}
|
||||
webClient.DownloadFile(uri, clientFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载
|
||||
/// </summary>
|
||||
/// <param name="manifest">文件下载清单</param>
|
||||
public void DownloadAsync(Manifest manifest)
|
||||
{
|
||||
Init(manifest);
|
||||
DownloadAsync(manifest, defaultTaskId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载并指定任务Id
|
||||
/// </summary>
|
||||
/// <param name="manifest">文件下载清单</param>
|
||||
/// <param name="taskId">任务Id</param>
|
||||
public void DownloadAsync(Manifest manifest, object taskId)
|
||||
{
|
||||
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(taskId);
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
if (userStateToLifetime.Contains(taskId))
|
||||
{
|
||||
throw new ArgumentException("参数taskId必须是唯一的", "taskId");
|
||||
}
|
||||
userStateToLifetime[taskId] = asyncOp;
|
||||
}
|
||||
WorkerEventHandler workerDelegate = new WorkerEventHandler(DownloadWorker);
|
||||
workerDelegate.BeginInvoke(asyncOp, null, null);
|
||||
}
|
||||
|
||||
private void Init(Manifest manifest)
|
||||
{
|
||||
this.manifest = manifest;
|
||||
webClient.BaseAddress = manifest.ManifestFiles.BaseUrl;
|
||||
webClient.Credentials = CredentialCache.DefaultCredentials;
|
||||
webClient.Encoding = Encoding.UTF8;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载方法
|
||||
/// </summary>
|
||||
/// <param name="asyncOp"></param>
|
||||
private void DownloadWorker(AsyncOperation asyncOp)
|
||||
{
|
||||
current = asyncOp;
|
||||
if (!TaskCanceled(asyncOp.UserSuppliedState))
|
||||
{
|
||||
try
|
||||
{
|
||||
webClient.DownloadFileCompleted += new AsyncCompletedEventHandler(webClient_DownloadFileCompleted);
|
||||
webClient.DownloadProgressChanged += new DownloadProgressChangedEventHandler(webClient_DownloadProgressChanged);
|
||||
foreach (var file in manifest.ManifestFiles.Files)
|
||||
{
|
||||
string serverFileName = Path.Combine(manifest.ManifestFiles.BaseUrl, file.Source);
|
||||
string clientFileName = Path.Combine(tempPath, file.Source);
|
||||
Uri uri = new Uri(serverFileName);
|
||||
if (!Directory.Exists(Path.GetDirectoryName(clientFileName)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(clientFileName));
|
||||
}
|
||||
while (webClient.IsBusy)
|
||||
{
|
||||
//阻塞异步下载
|
||||
}
|
||||
if (!cancel)
|
||||
{
|
||||
webClient.DownloadFileAsync(uri, clientFileName, file.Source);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
DownloadErrorEventArgs e = new DownloadErrorEventArgs();
|
||||
e.Error = ex;
|
||||
e.Manifest = manifest;
|
||||
OnDownloadError(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步完成方法
|
||||
/// </summary>
|
||||
/// <param name="exception">异常数据</param>
|
||||
/// <param name="canceled">是否取消</param>
|
||||
/// <param name="asyncOp"></param>
|
||||
private void CompletionMethod(Exception exception, bool canceled, AsyncOperation asyncOp)
|
||||
{
|
||||
if (!canceled)
|
||||
{
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
userStateToLifetime.Remove(asyncOp.UserSuppliedState);
|
||||
}
|
||||
}
|
||||
|
||||
DownloadCompleteEventArgs e = new DownloadCompleteEventArgs(exception, canceled, asyncOp.UserSuppliedState);
|
||||
e.Manifest = manifest;
|
||||
asyncOp.PostOperationCompleted(onCompletedDelegate, e);
|
||||
current = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载进度事件(仅对于单个文件)
|
||||
/// </summary>
|
||||
void webClient_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
|
||||
{
|
||||
DownloadProgressEventArgs args = new DownloadProgressEventArgs(e.ProgressPercentage, e.UserState);
|
||||
args.BytesReceived = e.BytesReceived;
|
||||
args.FileName = e.UserState.ToString();
|
||||
args.TotalBytesToReceive = e.TotalBytesToReceive;
|
||||
if (current != null)
|
||||
{
|
||||
current.Post(onProgressReportDelegate, args);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载完成事件(仅对于单个文件)
|
||||
/// </summary>
|
||||
/// <param name="sender"></param>
|
||||
/// <param name="e"></param>
|
||||
void webClient_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
|
||||
{
|
||||
fileCount++;
|
||||
if (fileCount == manifest.ManifestFiles.Files.Length)
|
||||
{
|
||||
this.CompletionMethod(e.Error, TaskCanceled(current.UserSuppliedState), current);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消异步下载
|
||||
/// </summary>
|
||||
public void CancelAsync()
|
||||
{
|
||||
CancelAsync(defaultTaskId);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 取消异步下载
|
||||
/// </summary>
|
||||
public void CancelAsync(object taskId)
|
||||
{
|
||||
webClient.CancelAsync();
|
||||
cancel = true;
|
||||
current = null;
|
||||
AsyncOperation asyncOp = userStateToLifetime[taskId] as AsyncOperation;
|
||||
if (asyncOp != null)
|
||||
{
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
userStateToLifetime.Remove(taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool TaskCanceled(object taskId)
|
||||
{
|
||||
return cancel || (userStateToLifetime[taskId] == null);
|
||||
}
|
||||
|
||||
private void DoDownloadCompleted(object operationState)
|
||||
{
|
||||
DownloadCompleteEventArgs e = operationState as DownloadCompleteEventArgs;
|
||||
OnDownloadCompleted(e);
|
||||
}
|
||||
|
||||
private void ReportProgress(object state)
|
||||
{
|
||||
DownloadProgressEventArgs e = state as DownloadProgressEventArgs;
|
||||
OnDownloadProgressChanged(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,411 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.ComponentModel;
|
||||
using System.Threading;
|
||||
using System.Collections.Specialized;
|
||||
using System.Collections;
|
||||
using System.IO;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件复制进度报告事件参数
|
||||
/// </summary>
|
||||
public class FileCopyProgressChangedEventArgs : ProgressChangedEventArgs
|
||||
{
|
||||
public FileCopyProgressChangedEventArgs(int progressPercentage, object userState)
|
||||
: base(progressPercentage, userState)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 当前复制的字节数
|
||||
/// </summary>
|
||||
public double BytesToCopy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前复制操作中的字节总数
|
||||
/// </summary>
|
||||
public double TotalBytesToCopy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前复制的源文件名
|
||||
/// </summary>
|
||||
public string SourceFileName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 当前复制的目标文件名
|
||||
/// </summary>
|
||||
public string TargetFileName { get; set; }
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制完成事件参数
|
||||
/// </summary>
|
||||
public class FileCopyCompletedEventArgs : AsyncCompletedEventArgs
|
||||
{
|
||||
public FileCopyCompletedEventArgs(Exception error, bool cancelled, object userState)
|
||||
: base(error, cancelled, userState)
|
||||
{
|
||||
}
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制错误事件参数
|
||||
/// </summary>
|
||||
public class FileCopyErrorEventArgs : EventArgs
|
||||
{
|
||||
public Exception Error { get; set; }
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制组件类
|
||||
/// </summary>
|
||||
public class FileCopyClass : Component
|
||||
{
|
||||
#region 变量定义
|
||||
private object defaultTaskId = new object();
|
||||
private int writeFileLength = 1024 * 64;
|
||||
|
||||
private delegate void WorkerEventHandler(Manifest manifest, string sourcePath, AsyncOperation asyncOp);
|
||||
|
||||
private SendOrPostCallback onProgressReportDelegate;
|
||||
private SendOrPostCallback onCompletedDelegate;
|
||||
|
||||
private HybridDictionary userStateToLifetime = new HybridDictionary();
|
||||
|
||||
private System.ComponentModel.Container components = null;
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制进度事件
|
||||
/// </summary>
|
||||
public event EventHandler<FileCopyProgressChangedEventArgs> FileCopyProgressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制完成事件
|
||||
/// </summary>
|
||||
public event EventHandler<FileCopyCompletedEventArgs> FileCopyCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// 文件复制错误事件
|
||||
/// </summary>
|
||||
public event EventHandler<FileCopyErrorEventArgs> FileCopyError;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 构造及析构
|
||||
|
||||
public FileCopyClass(IContainer container)
|
||||
{
|
||||
container.Add(this);
|
||||
InitializeComponent();
|
||||
InitializeDelegates();
|
||||
}
|
||||
|
||||
public FileCopyClass()
|
||||
{
|
||||
InitializeComponent();
|
||||
InitializeDelegates();
|
||||
}
|
||||
|
||||
protected virtual void InitializeDelegates()
|
||||
{
|
||||
onProgressReportDelegate = new SendOrPostCallback(ReportProgress);
|
||||
onCompletedDelegate = new SendOrPostCallback(CopyCompleted);
|
||||
}
|
||||
|
||||
private void InitializeComponent()
|
||||
{
|
||||
components = new System.ComponentModel.Container();
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (components != null)
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 实现
|
||||
|
||||
public int WriteFileLength
|
||||
{
|
||||
set
|
||||
{
|
||||
writeFileLength = value;
|
||||
}
|
||||
}
|
||||
|
||||
public void Copy(Manifest manifest, string sourcePath)
|
||||
{
|
||||
string[] sourceFiles = null;
|
||||
string[] targetFiles = null;
|
||||
GetFiles(manifest, sourcePath, out sourceFiles, out targetFiles);
|
||||
for (int i = 0; i < sourceFiles.Length; i++)
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(targetFiles[i])))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFiles[i]));
|
||||
}
|
||||
File.Copy(sourceFiles[i], targetFiles[i], true);
|
||||
}
|
||||
}
|
||||
|
||||
public void CopyAsync(Manifest manifest, string sourcePath)
|
||||
{
|
||||
CopyAsync(manifest, sourcePath, defaultTaskId);
|
||||
}
|
||||
|
||||
public void CopyAsync(Manifest manifest, string sourcePath, object taskId)
|
||||
{
|
||||
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(taskId);
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
if (userStateToLifetime.Contains(taskId))
|
||||
{
|
||||
throw new ArgumentException("参数taskId必须是唯一的", "taskId");
|
||||
}
|
||||
userStateToLifetime[taskId] = asyncOp;
|
||||
}
|
||||
|
||||
WorkerEventHandler workerDelegate = new WorkerEventHandler(FileCopyWorker);
|
||||
workerDelegate.BeginInvoke(manifest, sourcePath, asyncOp, null, null);
|
||||
}
|
||||
|
||||
private bool TaskCanceled(object taskId)
|
||||
{
|
||||
return (userStateToLifetime[taskId] == null);
|
||||
}
|
||||
|
||||
public void CancelAsync()
|
||||
{
|
||||
CancelAsync(defaultTaskId);
|
||||
}
|
||||
|
||||
public void CancelAsync(object taskId)
|
||||
{
|
||||
AsyncOperation asyncOp = userStateToLifetime[taskId] as AsyncOperation;
|
||||
if (asyncOp != null)
|
||||
{
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
userStateToLifetime.Remove(taskId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FileCopyWorker(Manifest manifest, string sourcePath, AsyncOperation asyncOp)
|
||||
{
|
||||
Exception exception = null;
|
||||
FileCopyProgressChangedEventArgs e = null;
|
||||
Stream rStream = null;
|
||||
Stream wStream = null;
|
||||
double writeBytes = 0;
|
||||
string[] sourceFiles = null;
|
||||
string[] targetFiles = null;
|
||||
GetFiles(manifest, sourcePath, out sourceFiles, out targetFiles);
|
||||
|
||||
if (!TaskCanceled(asyncOp.UserSuppliedState))
|
||||
{
|
||||
try
|
||||
{
|
||||
double totalBytes = GetFileLength(sourceFiles);
|
||||
byte[] buffer = new byte[writeFileLength];
|
||||
int len = 0;
|
||||
int offset = 0;
|
||||
for (int i = 0; i < sourceFiles.Length; i++)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (!Directory.Exists(Path.GetDirectoryName(targetFiles[i])))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(targetFiles[i]));
|
||||
}
|
||||
|
||||
rStream = new FileStream(sourceFiles[i], FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
wStream = new FileStream(targetFiles[i], FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
while ((len = rStream.Read(buffer, offset, writeFileLength)) > 0)
|
||||
{
|
||||
wStream.Write(buffer, offset, len);
|
||||
writeBytes += len;
|
||||
e = new FileCopyProgressChangedEventArgs((int)(writeBytes / totalBytes * 100), asyncOp.UserSuppliedState);
|
||||
e.SourceFileName = sourceFiles[i];
|
||||
e.TargetFileName = targetFiles[i];
|
||||
e.TotalBytesToCopy = totalBytes;
|
||||
e.BytesToCopy = len;
|
||||
e.Manifest = manifest;
|
||||
asyncOp.Post(this.onProgressReportDelegate, e);
|
||||
Thread.Sleep(1);
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
DisposeStream(wStream);
|
||||
DisposeStream(rStream);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
exception = ex;
|
||||
OnFileCopyError(new FileCopyErrorEventArgs() { Error = ex, Manifest = manifest });
|
||||
}
|
||||
}
|
||||
|
||||
this.CompletionMethod(manifest, exception, TaskCanceled(asyncOp.UserSuppliedState), asyncOp);
|
||||
|
||||
//如果文件是压缩文件,则解压这些文件
|
||||
ZipFiles(e.Manifest);
|
||||
}
|
||||
|
||||
private void GetFiles(Manifest manifest, string sourcePath, out string[] sourceFiles, out string[] targetFiles)
|
||||
{
|
||||
sourceFiles = new string[manifest.ManifestFiles.Files.Length];
|
||||
targetFiles = new string[manifest.ManifestFiles.Files.Length];
|
||||
string path = Path.GetFullPath(manifest.MyApplication.Location);
|
||||
for (int i = 0; i < manifest.ManifestFiles.Files.Length; i++)
|
||||
{
|
||||
sourceFiles[i] = Path.Combine(sourcePath, manifest.ManifestFiles.Files[i].Source);
|
||||
targetFiles[i] = Path.Combine(path, manifest.ManifestFiles.Files[i].Source);
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeStream(Stream stream)
|
||||
{
|
||||
if (stream != null)
|
||||
{
|
||||
stream.Flush();
|
||||
stream.Close();
|
||||
stream.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
private double GetFileLength(string[] sourceFiles)
|
||||
{
|
||||
double bytes = 0;
|
||||
foreach (var file in sourceFiles)
|
||||
{
|
||||
FileInfo fileInfo = new FileInfo(file);
|
||||
bytes += fileInfo.Length;
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
private void CopyCompleted(object operationState)
|
||||
{
|
||||
FileCopyCompletedEventArgs e = operationState as FileCopyCompletedEventArgs;
|
||||
|
||||
OnFileCopyCompleted(e);
|
||||
}
|
||||
|
||||
private void ReportProgress(object state)
|
||||
{
|
||||
FileCopyProgressChangedEventArgs e = state as FileCopyProgressChangedEventArgs;
|
||||
|
||||
OnProgressChanged(e);
|
||||
}
|
||||
|
||||
protected void OnFileCopyCompleted(FileCopyCompletedEventArgs e)
|
||||
{
|
||||
if (FileCopyCompleted != null)
|
||||
{
|
||||
FileCopyCompleted(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 如果文件是压缩文件,则解压这些文件
|
||||
/// </summary>
|
||||
/// <param name="manifest"></param>
|
||||
private void ZipFiles(Manifest manifest)
|
||||
{
|
||||
if (manifest != null)
|
||||
{
|
||||
string path = Path.GetFullPath(manifest.MyApplication.Location);
|
||||
foreach (ManifestFile file in manifest.ManifestFiles.Files)
|
||||
{
|
||||
bool unzip = false;
|
||||
bool.TryParse(file.Unzip, out unzip);
|
||||
|
||||
if (file.Source.EndsWith(".zip", StringComparison.OrdinalIgnoreCase) && unzip)
|
||||
{
|
||||
string zipFile = Path.Combine(path, file.Source);
|
||||
try
|
||||
{
|
||||
ZipUtility.UnZipFiles(zipFile, path, null, true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
WriteLine(ex.ToString());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteLine(string message)
|
||||
{
|
||||
string temp = DateTime.Now.ToString("[yyyy-MM-dd HH:mm:ss] ") + message + "\r\n\r\n";
|
||||
string fileName = DateTime.Now.ToString("yyyyMMdd") + ".log";
|
||||
try
|
||||
{
|
||||
File.AppendAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName), temp, Encoding.GetEncoding("GB2312"));
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnProgressChanged(FileCopyProgressChangedEventArgs e)
|
||||
{
|
||||
if (FileCopyProgressChanged != null)
|
||||
{
|
||||
FileCopyProgressChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
protected void OnFileCopyError(FileCopyErrorEventArgs e)
|
||||
{
|
||||
if (FileCopyError != null)
|
||||
{
|
||||
FileCopyError(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void CompletionMethod(Manifest manifest, Exception exception, bool canceled, AsyncOperation asyncOp)
|
||||
{
|
||||
if (!canceled)
|
||||
{
|
||||
lock (userStateToLifetime.SyncRoot)
|
||||
{
|
||||
userStateToLifetime.Remove(asyncOp.UserSuppliedState);
|
||||
}
|
||||
}
|
||||
|
||||
FileCopyCompletedEventArgs e = new FileCopyCompletedEventArgs(exception, canceled, asyncOp.UserSuppliedState);
|
||||
e.Manifest = manifest;
|
||||
asyncOp.PostOperationCompleted(onCompletedDelegate, e);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,655 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
using System.Collections;
|
||||
using System.IO.Compression;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩文件类
|
||||
/// </summary>
|
||||
public class GZip
|
||||
{
|
||||
#region MyRegion
|
||||
/*
|
||||
//Compress三个参数分别是“要压缩的目标目录”,“保存压缩文件的目录”,压缩文件名
|
||||
GZip.Compress(@"E:\much\", @"E:\much\", "ziptest");
|
||||
|
||||
//Decompress三个参数分别是"压缩包所在目录","要解压到的目录",“压缩包名”
|
||||
//如果压缩包所在目录不存在则解压不会成功
|
||||
GZip.Decompress(@"E:\much\zip\", @"E:\much\zip\", "ziptest");
|
||||
*/
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Compress
|
||||
/// </summary>
|
||||
/// <param name="lpSourceFolder">The location of the files to include in the zip file, all files including files in subfolders will be included.</param>
|
||||
/// <param name="lpDestFolder">Folder to write the zip file into</param>
|
||||
/// <param name="zipFileName">Name of the zip file to write</param>
|
||||
public static GZipResult Compress(string lpSourceFolder, string lpDestFolder, string zipFileName)
|
||||
{
|
||||
return Compress(lpSourceFolder, "*.*", SearchOption.AllDirectories, lpDestFolder, zipFileName, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compress
|
||||
/// </summary>
|
||||
/// <param name="lpSourceFolder">The location of the files to include in the zip file</param>
|
||||
/// <param name="searchPattern">Search pattern (ie "*.*" or "*.txt" or "*.gif") to idendify what files in lpSourceFolder to include in the zip file</param>
|
||||
/// <param name="searchOption">Only files in lpSourceFolder or include files in subfolders also</param>
|
||||
/// <param name="lpDestFolder">Folder to write the zip file into</param>
|
||||
/// <param name="zipFileName">Name of the zip file to write</param>
|
||||
/// <param name="deleteTempFile">Boolean, true deleted the intermediate temp file, false leaves the temp file in lpDestFolder (for debugging)</param>
|
||||
public static GZipResult Compress(string lpSourceFolder, string searchPattern, SearchOption searchOption, string lpDestFolder, string zipFileName, bool deleteTempFile)
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(lpSourceFolder);
|
||||
FileInfo[] files = di.GetFiles("*.*", searchOption);
|
||||
return Compress(files, lpSourceFolder, lpDestFolder, zipFileName, deleteTempFile);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compress
|
||||
/// </summary>
|
||||
/// <param name="files">Array of FileInfo objects to be included in the zip file</param>
|
||||
/// <param name="lpBaseFolder">Base folder to use when creating relative paths for the files
|
||||
/// stored in the zip file. For example, if lpBaseFolder is 'C:\zipTest\Files\', and there is a file
|
||||
/// 'C:\zipTest\Files\folder1\sample.txt' in the 'files' array, the relative path for sample.txt
|
||||
/// will be 'folder1/sample.txt'</param>
|
||||
/// <param name="lpDestFolder">Folder to write the zip file into</param>
|
||||
/// <param name="zipFileName">Name of the zip file to write</param>
|
||||
public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, string zipFileName)
|
||||
{
|
||||
return Compress(files, lpBaseFolder, lpDestFolder, zipFileName, true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compress
|
||||
/// </summary>
|
||||
/// <param name="files">Array of FileInfo objects to be included in the zip file</param>
|
||||
/// <param name="lpBaseFolder">Base folder to use when creating relative paths for the files
|
||||
/// stored in the zip file. For example, if lpBaseFolder is 'C:\zipTest\Files\', and there is a file
|
||||
/// 'C:\zipTest\Files\folder1\sample.txt' in the 'files' array, the relative path for sample.txt
|
||||
/// will be 'folder1/sample.txt'</param>
|
||||
/// <param name="lpDestFolder">Folder to write the zip file into</param>
|
||||
/// <param name="zipFileName">Name of the zip file to write</param>
|
||||
/// <param name="deleteTempFile">Boolean, true deleted the intermediate temp file, false leaves the temp file in lpDestFolder (for debugging)</param>
|
||||
public static GZipResult Compress(FileInfo[] files, string lpBaseFolder, string lpDestFolder, string zipFileName, bool deleteTempFile)
|
||||
{
|
||||
GZipResult result = new GZipResult();
|
||||
|
||||
try
|
||||
{
|
||||
if (!lpDestFolder.EndsWith("\\"))
|
||||
{
|
||||
lpDestFolder += "\\";
|
||||
}
|
||||
|
||||
string lpTempFile = lpDestFolder + zipFileName + ".tmp";
|
||||
string lpZipFile = lpDestFolder + zipFileName;
|
||||
|
||||
result.TempFile = lpTempFile;
|
||||
result.ZipFile = lpZipFile;
|
||||
|
||||
if (files != null && files.Length > 0)
|
||||
{
|
||||
CreateTempFile(files, lpBaseFolder, lpTempFile, result);
|
||||
|
||||
if (result.FileCount > 0)
|
||||
{
|
||||
CreateZipFile(lpTempFile, lpZipFile, result);
|
||||
}
|
||||
|
||||
// delete the temp file
|
||||
if (deleteTempFile)
|
||||
{
|
||||
File.Delete(lpTempFile);
|
||||
result.TempFileDeleted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch //(Exception ex4)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void CreateZipFile(string lpSourceFile, string lpZipFile, GZipResult result)
|
||||
{
|
||||
byte[] buffer;
|
||||
int count = 0;
|
||||
FileStream fsOut = null;
|
||||
FileStream fsIn = null;
|
||||
GZipStream gzip = null;
|
||||
|
||||
// compress the file into the zip file
|
||||
try
|
||||
{
|
||||
fsOut = new FileStream(lpZipFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
gzip = new GZipStream(fsOut, CompressionMode.Compress, true);
|
||||
|
||||
fsIn = new FileStream(lpSourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
buffer = new byte[fsIn.Length];
|
||||
count = fsIn.Read(buffer, 0, buffer.Length);
|
||||
fsIn.Close();
|
||||
fsIn = null;
|
||||
|
||||
// compress to the zip file
|
||||
gzip.Write(buffer, 0, buffer.Length);
|
||||
|
||||
result.ZipFileSize = fsOut.Length;
|
||||
result.CompressionPercent = GetCompressionPercent(result.TempFileSize, result.ZipFileSize);
|
||||
}
|
||||
catch //(Exception ex1)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gzip != null)
|
||||
{
|
||||
gzip.Close();
|
||||
gzip = null;
|
||||
}
|
||||
if (fsOut != null)
|
||||
{
|
||||
fsOut.Close();
|
||||
fsOut = null;
|
||||
}
|
||||
if (fsIn != null)
|
||||
{
|
||||
fsIn.Close();
|
||||
fsIn = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void CreateTempFile(FileInfo[] files, string lpBaseFolder, string lpTempFile, GZipResult result)
|
||||
{
|
||||
byte[] buffer;
|
||||
int count = 0;
|
||||
byte[] header;
|
||||
string fileHeader = null;
|
||||
string fileModDate = null;
|
||||
string lpFolder = null;
|
||||
int fileIndex = 0;
|
||||
string lpSourceFile = null;
|
||||
string vpSourceFile = null;
|
||||
GZipFileInfo gzf = null;
|
||||
FileStream fsOut = null;
|
||||
FileStream fsIn = null;
|
||||
|
||||
if (files != null && files.Length > 0)
|
||||
{
|
||||
try
|
||||
{
|
||||
result.Files = new GZipFileInfo[files.Length];
|
||||
|
||||
// open the temp file for writing
|
||||
fsOut = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
|
||||
foreach (FileInfo fi in files)
|
||||
{
|
||||
lpFolder = fi.DirectoryName + "\\";
|
||||
try
|
||||
{
|
||||
gzf = new GZipFileInfo();
|
||||
gzf.Index = fileIndex;
|
||||
|
||||
// read the source file, get its virtual path within the source folder
|
||||
lpSourceFile = fi.FullName;
|
||||
gzf.LocalPath = lpSourceFile;
|
||||
vpSourceFile = lpSourceFile.Replace(lpBaseFolder, string.Empty);
|
||||
vpSourceFile = vpSourceFile.Replace("\\", "/");
|
||||
gzf.RelativePath = vpSourceFile;
|
||||
|
||||
fsIn = new FileStream(lpSourceFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
buffer = new byte[fsIn.Length];
|
||||
count = fsIn.Read(buffer, 0, buffer.Length);
|
||||
fsIn.Close();
|
||||
fsIn = null;
|
||||
|
||||
fileModDate = fi.LastWriteTimeUtc.ToString();
|
||||
gzf.ModifiedDate = fi.LastWriteTimeUtc;
|
||||
gzf.Length = buffer.Length;
|
||||
|
||||
fileHeader = fileIndex.ToString() + "," + vpSourceFile + "," + fileModDate + "," + buffer.Length.ToString() + "\n";
|
||||
header = Encoding.Default.GetBytes(fileHeader);
|
||||
|
||||
fsOut.Write(header, 0, header.Length);
|
||||
fsOut.Write(buffer, 0, buffer.Length);
|
||||
fsOut.WriteByte(10); // linefeed
|
||||
|
||||
gzf.AddedToTempFile = true;
|
||||
|
||||
// update the result object
|
||||
result.Files[fileIndex] = gzf;
|
||||
|
||||
// increment the fileIndex
|
||||
fileIndex++;
|
||||
}
|
||||
catch //(Exception ex1)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fsIn != null)
|
||||
{
|
||||
fsIn.Close();
|
||||
fsIn = null;
|
||||
}
|
||||
}
|
||||
if (fsOut != null)
|
||||
{
|
||||
result.TempFileSize = fsOut.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch //(Exception ex2)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fsOut != null)
|
||||
{
|
||||
fsOut.Close();
|
||||
fsOut = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result.FileCount = fileIndex;
|
||||
}
|
||||
|
||||
public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName)
|
||||
{
|
||||
return Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, true, null, null, 4096);
|
||||
}
|
||||
|
||||
public static GZipResult Decompress(string lpSourceFolder, string lpDestFolder, string zipFileName, bool writeFiles, string addExtension)
|
||||
{
|
||||
return Decompress(lpSourceFolder, lpDestFolder, zipFileName, true, writeFiles, addExtension, null, 4096);
|
||||
}
|
||||
|
||||
public static GZipResult Decompress(string lpSrcFolder, string lpDestFolder, string zipFileName,
|
||||
bool deleteTempFile, bool writeFiles, string addExtension, Hashtable htFiles, int bufferSize)
|
||||
{
|
||||
GZipResult result = new GZipResult();
|
||||
|
||||
if (!lpDestFolder.EndsWith("\\"))
|
||||
{
|
||||
lpDestFolder += "\\";
|
||||
}
|
||||
|
||||
string lpTempFile = lpSrcFolder + zipFileName + ".tmp";
|
||||
string lpZipFile = lpSrcFolder + zipFileName;
|
||||
|
||||
result.TempFile = lpTempFile;
|
||||
result.ZipFile = lpZipFile;
|
||||
|
||||
string line = null;
|
||||
string lpFilePath = null;
|
||||
string lpFolder = null;
|
||||
GZipFileInfo gzf = null;
|
||||
FileStream fsTemp = null;
|
||||
ArrayList gzfs = new ArrayList();
|
||||
bool write = false;
|
||||
|
||||
if (string.IsNullOrEmpty(addExtension))
|
||||
{
|
||||
addExtension = string.Empty;
|
||||
}
|
||||
else if (!addExtension.StartsWith("."))
|
||||
{
|
||||
addExtension = "." + addExtension;
|
||||
}
|
||||
|
||||
// extract the files from the temp file
|
||||
try
|
||||
{
|
||||
fsTemp = UnzipToTempFile(lpZipFile, lpTempFile, result);
|
||||
if (fsTemp != null)
|
||||
{
|
||||
while (fsTemp.Position != fsTemp.Length)
|
||||
{
|
||||
line = null;
|
||||
while (string.IsNullOrEmpty(line) && fsTemp.Position != fsTemp.Length)
|
||||
{
|
||||
line = ReadLine(fsTemp);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(line))
|
||||
{
|
||||
gzf = new GZipFileInfo();
|
||||
if (gzf.ParseFileInfo(line) && gzf.Length > 0)
|
||||
{
|
||||
gzfs.Add(gzf);
|
||||
lpFilePath = lpDestFolder + gzf.RelativePath;
|
||||
lpFolder = GetFolder(lpFilePath);
|
||||
gzf.LocalPath = lpFilePath;
|
||||
|
||||
write = false;
|
||||
if (htFiles == null || htFiles.ContainsKey(gzf.RelativePath))
|
||||
{
|
||||
gzf.RestoreRequested = true;
|
||||
write = writeFiles;
|
||||
}
|
||||
|
||||
if (write)
|
||||
{
|
||||
// make sure the folder exists
|
||||
if (!Directory.Exists(lpFolder))
|
||||
{
|
||||
Directory.CreateDirectory(lpFolder);
|
||||
}
|
||||
|
||||
// read from fsTemp and write out the file
|
||||
gzf.Restored = WriteFile(fsTemp, gzf.Length, lpFilePath + addExtension, bufferSize);
|
||||
}
|
||||
else
|
||||
{
|
||||
// need to advance fsTemp
|
||||
fsTemp.Position += gzf.Length;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch //(Exception ex3)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fsTemp != null)
|
||||
{
|
||||
fsTemp.Close();
|
||||
fsTemp = null;
|
||||
}
|
||||
}
|
||||
|
||||
// delete the temp file
|
||||
try
|
||||
{
|
||||
if (deleteTempFile)
|
||||
{
|
||||
File.Delete(lpTempFile);
|
||||
result.TempFileDeleted = true;
|
||||
}
|
||||
}
|
||||
catch //(Exception ex4)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
|
||||
result.FileCount = gzfs.Count;
|
||||
result.Files = new GZipFileInfo[gzfs.Count];
|
||||
gzfs.CopyTo(result.Files);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static string ReadLine(FileStream fs)
|
||||
{
|
||||
string line = string.Empty;
|
||||
|
||||
const int bufferSize = 4096;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
byte b = 0;
|
||||
byte lf = 10;
|
||||
int i = 0;
|
||||
|
||||
while (b != lf)
|
||||
{
|
||||
b = (byte)fs.ReadByte();
|
||||
buffer[i] = b;
|
||||
i++;
|
||||
}
|
||||
|
||||
line = System.Text.Encoding.Default.GetString(buffer, 0, i - 1);
|
||||
|
||||
return line;
|
||||
}
|
||||
|
||||
private static bool WriteFile(FileStream fs, int fileLength, string lpFile, int bufferSize)
|
||||
{
|
||||
bool success = false;
|
||||
FileStream fsFile = null;
|
||||
|
||||
if (bufferSize == 0 || fileLength < bufferSize)
|
||||
{
|
||||
bufferSize = fileLength;
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int remaining = fileLength;
|
||||
int readSize = 0;
|
||||
|
||||
try
|
||||
{
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
fsFile = new FileStream(lpFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
|
||||
while (remaining > 0)
|
||||
{
|
||||
if (remaining > bufferSize)
|
||||
{
|
||||
readSize = bufferSize;
|
||||
}
|
||||
else
|
||||
{
|
||||
readSize = remaining;
|
||||
}
|
||||
|
||||
count = fs.Read(buffer, 0, readSize);
|
||||
remaining -= count;
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
fsFile.Write(buffer, 0, count);
|
||||
fsFile.Flush();
|
||||
|
||||
}
|
||||
fsFile.Flush();
|
||||
fsFile.Close();
|
||||
fsFile = null;
|
||||
|
||||
success = true;
|
||||
}
|
||||
catch //(Exception ex2)
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (fsFile != null)
|
||||
{
|
||||
fsFile.Flush();
|
||||
fsFile.Close();
|
||||
fsFile = null;
|
||||
}
|
||||
}
|
||||
return success;
|
||||
}
|
||||
|
||||
private static string GetFolder(string lpFilePath)
|
||||
{
|
||||
string lpFolder = lpFilePath;
|
||||
int index = lpFolder.LastIndexOf("\\");
|
||||
if (index != -1)
|
||||
{
|
||||
lpFolder = lpFolder.Substring(0, index + 1);
|
||||
}
|
||||
return lpFolder;
|
||||
}
|
||||
private static FileStream UnzipToTempFile(string lpZipFile, string lpTempFile, GZipResult result)
|
||||
{
|
||||
FileStream fsIn = null;
|
||||
GZipStream gzip = null;
|
||||
FileStream fsOut = null;
|
||||
FileStream fsTemp = null;
|
||||
|
||||
const int bufferSize = 4096;
|
||||
byte[] buffer = new byte[bufferSize];
|
||||
int count = 0;
|
||||
|
||||
try
|
||||
{
|
||||
fsIn = new FileStream(lpZipFile, FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||
result.ZipFileSize = fsIn.Length;
|
||||
|
||||
fsOut = new FileStream(lpTempFile, FileMode.Create, FileAccess.Write, FileShare.None);
|
||||
gzip = new GZipStream(fsIn, CompressionMode.Decompress, true);
|
||||
while (true)
|
||||
{
|
||||
count = gzip.Read(buffer, 0, bufferSize);
|
||||
if (count != 0)
|
||||
{
|
||||
fsOut.Write(buffer, 0, count);
|
||||
}
|
||||
if (count != bufferSize)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex1)
|
||||
{
|
||||
result.Errors = true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (gzip != null)
|
||||
{
|
||||
gzip.Close();
|
||||
gzip = null;
|
||||
}
|
||||
if (fsOut != null)
|
||||
{
|
||||
fsOut.Close();
|
||||
fsOut = null;
|
||||
}
|
||||
if (fsIn != null)
|
||||
{
|
||||
fsIn.Close();
|
||||
fsIn = null;
|
||||
}
|
||||
}
|
||||
|
||||
fsTemp = new FileStream(lpTempFile, FileMode.Open, FileAccess.Read, FileShare.None);
|
||||
if (fsTemp != null)
|
||||
{
|
||||
result.TempFileSize = fsTemp.Length;
|
||||
}
|
||||
return fsTemp;
|
||||
}
|
||||
|
||||
private static int GetCompressionPercent(long tempLen, long zipLen)
|
||||
{
|
||||
double tmp = (double)tempLen;
|
||||
double zip = (double)zipLen;
|
||||
double hundred = 100;
|
||||
|
||||
double ratio = (tmp - zip) / tmp;
|
||||
double pcnt = ratio * hundred;
|
||||
|
||||
return (int)pcnt;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 要压缩的文件信息
|
||||
/// </summary>
|
||||
public class GZipFileInfo
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件索引
|
||||
/// </summary>
|
||||
public int Index = 0;
|
||||
/// <summary>
|
||||
/// 文件相对路径,'/'
|
||||
/// </summary>
|
||||
public string RelativePath = null;
|
||||
public DateTime ModifiedDate;
|
||||
/// <summary>
|
||||
/// 文件内容长度
|
||||
/// </summary>
|
||||
public int Length = 0;
|
||||
public bool AddedToTempFile = false;
|
||||
public bool RestoreRequested = false;
|
||||
public bool Restored = false;
|
||||
/// <summary>
|
||||
/// 文件绝对路径,'\'
|
||||
/// </summary>
|
||||
public string LocalPath = null;
|
||||
public string Folder = null;
|
||||
|
||||
public bool ParseFileInfo(string fileInfo)
|
||||
{
|
||||
bool success = false;
|
||||
try
|
||||
{
|
||||
if (!string.IsNullOrEmpty(fileInfo))
|
||||
{
|
||||
// get the file information
|
||||
string[] info = fileInfo.Split(',');
|
||||
if (info != null && info.Length == 4)
|
||||
{
|
||||
this.Index = Convert.ToInt32(info[0]);
|
||||
this.RelativePath = info[1].Replace("/", "\\");
|
||||
this.ModifiedDate = Convert.ToDateTime(info[2]);
|
||||
this.Length = Convert.ToInt32(info[3]);
|
||||
success = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
success = false;
|
||||
}
|
||||
return success;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件压缩后的压缩包类
|
||||
/// </summary>
|
||||
public class GZipResult
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩包中包含的所有文件,包括子目录下的文件
|
||||
/// </summary>
|
||||
public GZipFileInfo[] Files = null;
|
||||
/// <summary>
|
||||
/// 要压缩的文件数
|
||||
/// </summary>
|
||||
public int FileCount = 0;
|
||||
public long TempFileSize = 0;
|
||||
public long ZipFileSize = 0;
|
||||
/// <summary>
|
||||
/// 压缩百分比
|
||||
/// </summary>
|
||||
public int CompressionPercent = 0;
|
||||
/// <summary>
|
||||
/// 临时文件
|
||||
/// </summary>
|
||||
public string TempFile = null;
|
||||
/// <summary>
|
||||
/// 压缩文件
|
||||
/// </summary>
|
||||
public string ZipFile = null;
|
||||
/// <summary>
|
||||
/// 是否删除临时文件
|
||||
/// </summary>
|
||||
public bool TempFileDeleted = false;
|
||||
public bool Errors = false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Xml;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 文件清单对象
|
||||
/// </summary>
|
||||
[XmlRoot("manifest")]
|
||||
public class Manifest
|
||||
{
|
||||
[XmlElement("version")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[XmlElement("description")]
|
||||
public string Description { get; set; }
|
||||
|
||||
[XmlElement("fileBytes")]
|
||||
public long FileBytes { get; set; }
|
||||
|
||||
[XmlElement("myapplication")]
|
||||
public MyApplication MyApplication { get; set; }
|
||||
|
||||
[XmlElement("files")]
|
||||
public ManifestFiles ManifestFiles { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新的文件列表
|
||||
/// </summary>
|
||||
public class ManifestFiles
|
||||
{
|
||||
[XmlElement("file")]
|
||||
public ManifestFile[] Files { get; set; }
|
||||
|
||||
[XmlAttribute("base")]
|
||||
public string BaseUrl { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新的单个文件对象
|
||||
/// </summary>
|
||||
public class ManifestFile
|
||||
{
|
||||
[XmlAttribute("source")]
|
||||
public string Source
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[XmlAttribute("hash")]
|
||||
public string Hash
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
|
||||
[XmlAttribute("unzip")]
|
||||
public string Unzip
|
||||
{
|
||||
get;
|
||||
set;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 更新的程序对象
|
||||
/// </summary>
|
||||
public class MyApplication
|
||||
{
|
||||
[XmlAttribute("applicationId")]
|
||||
public string ApplicationId { get; set; }
|
||||
|
||||
[XmlElement("location")]
|
||||
public string Location { get; set; }
|
||||
|
||||
[XmlElement("entryPoint")]
|
||||
public EntryPoint EntryPoint { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 程序启动对象
|
||||
/// </summary>
|
||||
public class EntryPoint
|
||||
{
|
||||
[XmlAttribute("file")]
|
||||
public string File { get; set; }
|
||||
|
||||
[XmlAttribute("parameters")]
|
||||
public string Parameters { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 客户端配置文件对象
|
||||
/// </summary>
|
||||
public class UpdaterConfigurationView
|
||||
{
|
||||
private static XmlDocument document = new XmlDocument();
|
||||
private static readonly string xmlFileName = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "updateconfiguration.config");
|
||||
|
||||
static UpdaterConfigurationView()
|
||||
{
|
||||
document.Load(xmlFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 刷新配置文件信息
|
||||
/// </summary>
|
||||
public void Refresh()
|
||||
{
|
||||
document.RemoveAll();
|
||||
document.Load(xmlFileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 程序版本
|
||||
/// </summary>
|
||||
public string Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return document.SelectSingleNode("applicationUpdater").Attributes["version"].Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
document.SelectSingleNode("applicationUpdater").Attributes["version"].Value = value;
|
||||
document.Save(xmlFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 应用程序唯一标识
|
||||
/// </summary>
|
||||
public string ApplicationId
|
||||
{
|
||||
get
|
||||
{
|
||||
return document.SelectSingleNode("applicationUpdater").Attributes["applicationId"].Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
document.SelectSingleNode("applicationUpdater").Attributes["applicationId"].Value = value;
|
||||
document.Save(xmlFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 远程更新文件的清单路径
|
||||
/// </summary>
|
||||
public string ManifestUri
|
||||
{
|
||||
get
|
||||
{
|
||||
return document.SelectSingleNode("applicationUpdater").Attributes["manifestUri"].Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
document.SelectSingleNode("applicationUpdater").Attributes["manifestUri"].Value = value;
|
||||
document.Save(xmlFileName);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 程序名称
|
||||
/// </summary>
|
||||
public string Title
|
||||
{
|
||||
get
|
||||
{
|
||||
return document.SelectSingleNode("applicationUpdater").Attributes["title"].Value;
|
||||
}
|
||||
set
|
||||
{
|
||||
document.SelectSingleNode("applicationUpdater").Attributes["title"].Value = value;
|
||||
document.Save(xmlFileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("Update.Core")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Update.Core")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("4903d5f5-ff01-426d-b5bb-aadf7c4232fa")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
//可以指定所有这些值,也可以使用“生成号”和“修订号”的默认值
|
||||
//通过使用 "*",如下所示:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>Update.Core</RootNamespace>
|
||||
<AssemblyName>Update.Core</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="ICSharpCode.SharpZipLib, Version=1.3.3.11, Culture=neutral, PublicKeyToken=1b03e6acf1164f73, processorArchitecture=MSIL">
|
||||
<HintPath>..\packages\SharpZipLib.1.3.3\lib\net45\ICSharpCode.SharpZipLib.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Downloader.cs" />
|
||||
<Compile Include="FileCopyClass.cs" />
|
||||
<Compile Include="GZip.cs" />
|
||||
<Compile Include="Model.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UpdateClass.cs" />
|
||||
<Compile Include="ZipUtility.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,386 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Net;
|
||||
using System.IO;
|
||||
using System.Xml.Serialization;
|
||||
using System.Xml;
|
||||
using System.ComponentModel;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// 程序更新事件参数
|
||||
/// </summary>
|
||||
public class ManifestEventArgs : EventArgs
|
||||
{
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 激活安装开始事件参数
|
||||
/// </summary>
|
||||
public class ActivationStartedEventArgs : EventArgs
|
||||
{
|
||||
public Manifest Manifest { get; set; }
|
||||
|
||||
public bool Cancel { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 安装完成事件参数
|
||||
/// </summary>
|
||||
public class ActivationCompletedEventArgs : AsyncCompletedEventArgs
|
||||
{
|
||||
public ActivationCompletedEventArgs(Exception error, bool cancelled, object userState)
|
||||
: base(error, cancelled, userState)
|
||||
{
|
||||
}
|
||||
|
||||
public Manifest Manifest { get; set; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 程序自动更新操作类,封装了文件下载、文件复制、文件解压等操作
|
||||
/// </summary>
|
||||
public class UpdateClass
|
||||
{
|
||||
#region 变量属性
|
||||
private DownloadClass downloader = new DownloadClass();
|
||||
private FileCopyClass fileCopyer = new FileCopyClass();
|
||||
private UpdaterConfigurationView updateCfgView = new UpdaterConfigurationView();
|
||||
private string backupFilePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "backup");
|
||||
|
||||
/// <summary>
|
||||
/// 封装的文件下载操作类
|
||||
/// </summary>
|
||||
public DownloadClass Downloader
|
||||
{
|
||||
get
|
||||
{
|
||||
return downloader;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 封装的文件复制操作类
|
||||
/// </summary>
|
||||
public FileCopyClass FileCopyer
|
||||
{
|
||||
get
|
||||
{
|
||||
return fileCopyer;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 事件
|
||||
|
||||
/// <summary>
|
||||
/// 下载进度
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadProgressEventArgs> DownloadProgressChanged;
|
||||
|
||||
/// <summary>
|
||||
/// 下载完成事件
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadCompleteEventArgs> DownloadCompleted;
|
||||
|
||||
/// <summary>
|
||||
/// 下载错误触发的事件
|
||||
/// </summary>
|
||||
public event EventHandler<DownloadErrorEventArgs> DownloadError;
|
||||
|
||||
public event EventHandler<ManifestEventArgs> ActivationInitializing;
|
||||
|
||||
public event EventHandler<ActivationCompletedEventArgs> ActivationCompleted;
|
||||
|
||||
public event EventHandler<ActivationStartedEventArgs> ActivationStarted;
|
||||
|
||||
public event EventHandler<FileCopyProgressChangedEventArgs> ActivationProgressChanged;
|
||||
|
||||
public event EventHandler<FileCopyErrorEventArgs> ActivationError;
|
||||
|
||||
#endregion
|
||||
|
||||
#region 下载更新实现
|
||||
|
||||
public UpdateClass()
|
||||
{
|
||||
downloader.DownloadCompleted += new EventHandler<DownloadCompleteEventArgs>(downloader_DownloadCompleted);
|
||||
downloader.DownloadError += new EventHandler<DownloadErrorEventArgs>(downloader_DownloadError);
|
||||
downloader.DownloadProgressChanged += new EventHandler<DownloadProgressEventArgs>(downloader_DownloadProgressChanged);
|
||||
fileCopyer.FileCopyError += new EventHandler<FileCopyErrorEventArgs>(fileCopyer_FileCopyError);
|
||||
fileCopyer.FileCopyCompleted += new EventHandler<FileCopyCompletedEventArgs>(fileCopyer_FileCopyCompleted);
|
||||
fileCopyer.FileCopyProgressChanged += new EventHandler<FileCopyProgressChangedEventArgs>(fileCopyer_FileCopyProgressChanged);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 是否有最新的版本
|
||||
/// </summary>
|
||||
public bool HasNewVersion
|
||||
{
|
||||
get
|
||||
{
|
||||
var m = CheckForUpdates();
|
||||
return m.Length > 0;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 检查更新,返回更新清单列表
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public Manifest[] CheckForUpdates()
|
||||
{
|
||||
updateCfgView.Refresh();
|
||||
|
||||
Uri uri = new Uri(updateCfgView.ManifestUri);
|
||||
string doc = DownLoadFile(uri);
|
||||
XmlSerializer xser = new XmlSerializer(typeof(Manifest));
|
||||
var manifest = xser.Deserialize(new XmlTextReader(doc, XmlNodeType.Document, null)) as Manifest;
|
||||
if (manifest == null ||
|
||||
manifest.Version == updateCfgView.Version ||
|
||||
manifest.MyApplication.ApplicationId != updateCfgView.ApplicationId)
|
||||
{
|
||||
return new Manifest[0];
|
||||
}
|
||||
return new Manifest[] { manifest };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 用于远程下载文件清单
|
||||
/// </summary>
|
||||
/// <param name="uri">文件清单网络路径</param>
|
||||
/// <returns></returns>
|
||||
private string DownLoadFile(Uri uri)
|
||||
{
|
||||
WebRequest request = WebRequest.Create(uri);
|
||||
request.Credentials = CredentialCache.DefaultCredentials;
|
||||
string response = String.Empty;
|
||||
using (WebResponse res = request.GetResponse())
|
||||
{
|
||||
using (StreamReader reader = new StreamReader(res.GetResponseStream(), true))
|
||||
{
|
||||
response = reader.ReadToEnd();
|
||||
}
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 同步下载文件清单中的文件
|
||||
/// </summary>
|
||||
/// <param name="manifests">下载文件清单</param>
|
||||
public void Download(Manifest[] manifests)
|
||||
{
|
||||
foreach (var m in manifests)
|
||||
{
|
||||
downloader.Download(m);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步下载文件清单中的文件
|
||||
/// </summary>
|
||||
/// <param name="manifests">下载文件清单</param>
|
||||
public void DownloadAsync(Manifest[] manifests)
|
||||
{
|
||||
foreach (var m in manifests)
|
||||
{
|
||||
downloader.DownloadAsync(m);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 下载完毕后执行的启动操作
|
||||
/// </summary>
|
||||
/// <param name="manifests"></param>
|
||||
public void Activate(Manifest[] manifests)
|
||||
{
|
||||
foreach (var m in manifests)
|
||||
{
|
||||
OnActivationInitializing(new ManifestEventArgs() { Manifest = m });
|
||||
Backup(m);
|
||||
ActivationStartedEventArgs e = new ActivationStartedEventArgs() { Manifest = m };
|
||||
OnActivationStarted(e);
|
||||
if (e.Cancel)
|
||||
{
|
||||
Clear();
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
fileCopyer.CopyAsync(m, downloader.TempPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 备份操作
|
||||
/// </summary>
|
||||
/// <param name="manifest">文件清单</param>
|
||||
private void Backup(Manifest manifest)
|
||||
{
|
||||
try
|
||||
{
|
||||
string sourcePath = Path.GetFullPath(manifest.MyApplication.Location);
|
||||
string s_filename = string.Empty;
|
||||
string t_filename = string.Empty;
|
||||
if (!Directory.Exists(backupFilePath))
|
||||
{
|
||||
Directory.CreateDirectory(backupFilePath);
|
||||
}
|
||||
foreach (var file in manifest.ManifestFiles.Files)
|
||||
{
|
||||
t_filename = Path.Combine(backupFilePath, file.Source);
|
||||
s_filename = Path.Combine(sourcePath, file.Source);
|
||||
if (File.Exists(s_filename))
|
||||
{
|
||||
File.Copy(s_filename, t_filename, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 回滚文件下载内容
|
||||
/// </summary>
|
||||
/// <param name="manifest"></param>
|
||||
public void Rollback(Manifest manifest)
|
||||
{
|
||||
try
|
||||
{
|
||||
string filename = string.Empty;
|
||||
foreach (var file in manifest.ManifestFiles.Files)
|
||||
{
|
||||
filename = Path.Combine(backupFilePath, file.Source);
|
||||
File.Copy(filename, Path.Combine(Path.GetFullPath(manifest.MyApplication.Location), file.Source));
|
||||
}
|
||||
Directory.Delete(backupFilePath, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 清除临时文件
|
||||
/// </summary>
|
||||
private void Clear()
|
||||
{
|
||||
try
|
||||
{
|
||||
Directory.Delete(backupFilePath, true);
|
||||
Directory.Delete(downloader.TempPath, true);
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region 事件处理
|
||||
|
||||
private void fileCopyer_FileCopyError(object sender, FileCopyErrorEventArgs e)
|
||||
{
|
||||
OnActivationError(e);
|
||||
}
|
||||
|
||||
private void fileCopyer_FileCopyProgressChanged(object sender, FileCopyProgressChangedEventArgs e)
|
||||
{
|
||||
if (ActivationProgressChanged != null)
|
||||
{
|
||||
ActivationProgressChanged(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void fileCopyer_FileCopyCompleted(object sender, FileCopyCompletedEventArgs e)
|
||||
{
|
||||
Clear();
|
||||
try
|
||||
{
|
||||
updateCfgView.Version = e.Manifest.Version;
|
||||
}
|
||||
catch
|
||||
{ }
|
||||
|
||||
if (ActivationCompleted != null)
|
||||
{
|
||||
ActivationCompletedEventArgs evt = new ActivationCompletedEventArgs(e.Error, e.Cancelled, e.UserState);
|
||||
evt.Manifest = e.Manifest;
|
||||
OnActivationCompleted(evt);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloader_DownloadProgressChanged(object sender, DownloadProgressEventArgs e)
|
||||
{
|
||||
if (DownloadProgressChanged != null)
|
||||
{
|
||||
DownloadProgressChanged(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloader_DownloadError(object sender, DownloadErrorEventArgs e)
|
||||
{
|
||||
if (DownloadError != null)
|
||||
{
|
||||
DownloadError(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void downloader_DownloadCompleted(object sender, DownloadCompleteEventArgs e)
|
||||
{
|
||||
if (DownloadCompleted != null)
|
||||
{
|
||||
DownloadCompleted(sender, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivationInitializing(ManifestEventArgs e)
|
||||
{
|
||||
if (ActivationInitializing != null)
|
||||
{
|
||||
ActivationInitializing(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivationStarted(ActivationStartedEventArgs e)
|
||||
{
|
||||
if (ActivationStarted != null)
|
||||
{
|
||||
ActivationStarted(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivationCompleted(ActivationCompletedEventArgs e)
|
||||
{
|
||||
if (ActivationCompleted != null)
|
||||
{
|
||||
ActivationCompleted(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivationError(FileCopyErrorEventArgs e)
|
||||
{
|
||||
if (ActivationError != null)
|
||||
{
|
||||
ActivationError(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnActivationProgressChanged(FileCopyProgressChangedEventArgs e)
|
||||
{
|
||||
if (ActivationProgressChanged != null)
|
||||
{
|
||||
ActivationProgressChanged(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,153 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Collections;
|
||||
using ICSharpCode.SharpZipLib.Zip;
|
||||
using System.IO;
|
||||
|
||||
namespace Updater.Core
|
||||
{
|
||||
public static class ZipUtility
|
||||
{
|
||||
/// <summary>
|
||||
/// 压缩文件中的文件,可设置密码
|
||||
/// </summary>
|
||||
/// <param name="inputFolderPath">输入的文件夹</param>
|
||||
/// <param name="outputPathAndFile">输出的压缩文件全名</param>
|
||||
/// <param name="password">压缩密码</param>
|
||||
public static void ZipFiles(string inputFolderPath, string outputPathAndFile, string password)
|
||||
{
|
||||
ArrayList ar = GenerateFileList(inputFolderPath);
|
||||
int TrimLength = (Directory.GetParent(inputFolderPath)).ToString().Length;
|
||||
// find number of chars to remove // from orginal file path
|
||||
TrimLength += 1; //remove '\'
|
||||
FileStream ostream;
|
||||
byte[] obuffer;
|
||||
string outPath = inputFolderPath + @"\" + outputPathAndFile;
|
||||
ZipOutputStream oZipStream = new ZipOutputStream(File.Create(outPath));
|
||||
if (!string.IsNullOrEmpty(password))
|
||||
{
|
||||
oZipStream.Password = password;
|
||||
}
|
||||
oZipStream.SetLevel(9); // 设置最大压缩率
|
||||
|
||||
ZipEntry oZipEntry;
|
||||
foreach (string Fil in ar)
|
||||
{
|
||||
oZipEntry = new ZipEntry(Fil.Remove(0, TrimLength));
|
||||
oZipStream.PutNextEntry(oZipEntry);
|
||||
|
||||
if (!Fil.EndsWith(@"/")) // 如果文件以 '/' 结束,则是目录
|
||||
{
|
||||
ostream = File.OpenRead(Fil);
|
||||
obuffer = new byte[ostream.Length];
|
||||
ostream.Read(obuffer, 0, obuffer.Length);
|
||||
oZipStream.Write(obuffer, 0, obuffer.Length);
|
||||
}
|
||||
}
|
||||
oZipStream.Finish();
|
||||
oZipStream.Close();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 根据文件夹生成文件列表
|
||||
/// </summary>
|
||||
/// <param name="Dir"></param>
|
||||
/// <returns></returns>
|
||||
private static ArrayList GenerateFileList(string Dir)
|
||||
{
|
||||
ArrayList fils = new ArrayList();
|
||||
bool Empty = true;
|
||||
foreach (string file in Directory.GetFiles(Dir))
|
||||
{
|
||||
fils.Add(file);
|
||||
Empty = false;
|
||||
}
|
||||
|
||||
if (Empty)
|
||||
{
|
||||
//加入完全为空的目录
|
||||
if (Directory.GetDirectories(Dir).Length == 0)
|
||||
{
|
||||
fils.Add(Dir + @"/");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (string dirs in Directory.GetDirectories(Dir)) // 递归目录
|
||||
{
|
||||
foreach (object obj in GenerateFileList(dirs))
|
||||
{
|
||||
fils.Add(obj);
|
||||
}
|
||||
}
|
||||
return fils;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 解压文件到指定的目录,可设置密码、删除原文件等
|
||||
/// </summary>
|
||||
/// <param name="zipPathAndFile">压缩文件全名</param>
|
||||
/// <param name="outputFolder">解压输出文件目录</param>
|
||||
/// <param name="password">解压密码</param>
|
||||
/// <param name="deleteZipFile">是否删除原文件(压缩文件)</param>
|
||||
public static void UnZipFiles(string zipPathAndFile, string outputFolder, string password, bool deleteZipFile)
|
||||
{
|
||||
using (ZipInputStream s = new ZipInputStream(File.OpenRead(zipPathAndFile)))
|
||||
{
|
||||
if (password != null && password != String.Empty)
|
||||
{
|
||||
s.Password = password;
|
||||
}
|
||||
|
||||
ZipEntry theEntry;
|
||||
string tmpEntry = String.Empty;
|
||||
while ((theEntry = s.GetNextEntry()) != null)
|
||||
{
|
||||
#region 遍历每个Entry对象进行解压处理
|
||||
string directoryName = outputFolder;
|
||||
string fileName = Path.GetFileName(theEntry.Name);
|
||||
if (directoryName != "")
|
||||
{
|
||||
Directory.CreateDirectory(directoryName);
|
||||
}
|
||||
|
||||
if (fileName != String.Empty)
|
||||
{
|
||||
if (theEntry.Name.IndexOf(".ini") < 0)
|
||||
{
|
||||
string fullPath = directoryName + "\\" + theEntry.Name;
|
||||
fullPath = fullPath.Replace("\\ ", "\\");
|
||||
string fullDirPath = Path.GetDirectoryName(fullPath);
|
||||
if (!Directory.Exists(fullDirPath)) Directory.CreateDirectory(fullDirPath);
|
||||
using (FileStream streamWriter = File.Create(fullPath))
|
||||
{
|
||||
#region 写入文件流
|
||||
int size = 2048;
|
||||
byte[] data = new byte[2048];
|
||||
while (true)
|
||||
{
|
||||
size = s.Read(data, 0, data.Length);
|
||||
if (size > 0)
|
||||
{
|
||||
streamWriter.Write(data, 0, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
if (deleteZipFile)
|
||||
{
|
||||
File.Delete(zipPathAndFile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="SharpZipLib" version="1.3.3" targetFramework="net48" />
|
||||
</packages>
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8" ?>
|
||||
<configuration>
|
||||
<startup>
|
||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8" />
|
||||
</startup>
|
||||
</configuration>
|
||||
|
|
@ -1,12 +0,0 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public class Class1
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
namespace Update
|
||||
{
|
||||
partial class Form1
|
||||
{
|
||||
/// <summary>
|
||||
/// Required designer variable.
|
||||
/// </summary>
|
||||
private System.ComponentModel.IContainer components = null;
|
||||
|
||||
/// <summary>
|
||||
/// Clean up any resources being used.
|
||||
/// </summary>
|
||||
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing && (components != null))
|
||||
{
|
||||
components.Dispose();
|
||||
}
|
||||
base.Dispose(disposing);
|
||||
}
|
||||
|
||||
#region Windows Form Designer generated code
|
||||
|
||||
/// <summary>
|
||||
/// Required method for Designer support - do not modify
|
||||
/// the contents of this method with the code editor.
|
||||
/// </summary>
|
||||
private void InitializeComponent()
|
||||
{
|
||||
this.progressBarControl1 = new DevExpress.XtraEditors.ProgressBarControl();
|
||||
this.lab_percent = new DevExpress.XtraEditors.LabelControl();
|
||||
this.lab_filename = new System.Windows.Forms.Label();
|
||||
this.lab_fileinfo = new System.Windows.Forms.Label();
|
||||
this.lblUpdateLog = new System.Windows.Forms.Label();
|
||||
((System.ComponentModel.ISupportInitialize)(this.progressBarControl1.Properties)).BeginInit();
|
||||
this.SuspendLayout();
|
||||
//
|
||||
// progressBarControl1
|
||||
//
|
||||
this.progressBarControl1.Location = new System.Drawing.Point(25, 63);
|
||||
this.progressBarControl1.Name = "progressBarControl1";
|
||||
this.progressBarControl1.Properties.Step = 1;
|
||||
this.progressBarControl1.Size = new System.Drawing.Size(438, 35);
|
||||
this.progressBarControl1.TabIndex = 0;
|
||||
//
|
||||
// lab_percent
|
||||
//
|
||||
this.lab_percent.Location = new System.Drawing.Point(469, 74);
|
||||
this.lab_percent.Name = "lab_percent";
|
||||
this.lab_percent.Size = new System.Drawing.Size(18, 15);
|
||||
this.lab_percent.TabIndex = 1;
|
||||
this.lab_percent.Text = "0%";
|
||||
//
|
||||
// lab_filename
|
||||
//
|
||||
this.lab_filename.BackColor = System.Drawing.Color.Transparent;
|
||||
this.lab_filename.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lab_filename.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
|
||||
this.lab_filename.Location = new System.Drawing.Point(31, 31);
|
||||
this.lab_filename.Name = "lab_filename";
|
||||
this.lab_filename.Size = new System.Drawing.Size(410, 19);
|
||||
this.lab_filename.TabIndex = 3;
|
||||
this.lab_filename.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
|
||||
//
|
||||
// lab_fileinfo
|
||||
//
|
||||
this.lab_fileinfo.BackColor = System.Drawing.Color.Transparent;
|
||||
this.lab_fileinfo.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lab_fileinfo.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
|
||||
this.lab_fileinfo.Location = new System.Drawing.Point(23, 114);
|
||||
this.lab_fileinfo.Name = "lab_fileinfo";
|
||||
this.lab_fileinfo.Size = new System.Drawing.Size(410, 19);
|
||||
this.lab_fileinfo.TabIndex = 4;
|
||||
this.lab_fileinfo.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
|
||||
//
|
||||
// lblUpdateLog
|
||||
//
|
||||
this.lblUpdateLog.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
|
||||
this.lblUpdateLog.ForeColor = System.Drawing.SystemColors.ActiveCaptionText;
|
||||
this.lblUpdateLog.Location = new System.Drawing.Point(23, 133);
|
||||
this.lblUpdateLog.Name = "lblUpdateLog";
|
||||
this.lblUpdateLog.Size = new System.Drawing.Size(440, 85);
|
||||
this.lblUpdateLog.TabIndex = 6;
|
||||
this.lblUpdateLog.Text = "更新说明:(无)";
|
||||
//
|
||||
// Form1
|
||||
//
|
||||
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
|
||||
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
|
||||
this.ClientSize = new System.Drawing.Size(515, 233);
|
||||
this.Controls.Add(this.lblUpdateLog);
|
||||
this.Controls.Add(this.lab_fileinfo);
|
||||
this.Controls.Add(this.lab_filename);
|
||||
this.Controls.Add(this.lab_percent);
|
||||
this.Controls.Add(this.progressBarControl1);
|
||||
this.MaximizeBox = false;
|
||||
this.MinimizeBox = false;
|
||||
this.Name = "Form1";
|
||||
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
|
||||
this.Text = "版本更新";
|
||||
this.Load += new System.EventHandler(this.Form1_Load);
|
||||
((System.ComponentModel.ISupportInitialize)(this.progressBarControl1.Properties)).EndInit();
|
||||
this.ResumeLayout(false);
|
||||
this.PerformLayout();
|
||||
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private DevExpress.XtraEditors.ProgressBarControl progressBarControl1;
|
||||
private DevExpress.XtraEditors.LabelControl lab_percent;
|
||||
private System.Windows.Forms.Label lab_filename;
|
||||
private System.Windows.Forms.Label lab_fileinfo;
|
||||
private System.Windows.Forms.Label lblUpdateLog;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,336 @@
|
|||
using DevExpress.XtraEditors;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Data;
|
||||
using System.Diagnostics;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Windows.Forms;
|
||||
using Updater.Core;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
public partial class Form1 : DevExpress.XtraEditors.XtraForm
|
||||
{
|
||||
//主程序传入的参数,系统标示 是否需要重新启动主程序
|
||||
private string[] args;
|
||||
//表示主程序打开时传入的参数
|
||||
private readonly static string OPEN_FLAG = "121";
|
||||
private bool isComplete = true;
|
||||
|
||||
private UpdateClass updater;
|
||||
private List<Manifest> mList = new List<Manifest>();
|
||||
private int mLen = 0;
|
||||
public Form1()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private void simpleButton1_Click(object sender, EventArgs e)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
private void simpleButton1_Click_1(object sender, EventArgs e)
|
||||
{
|
||||
for (int i = 0; i <= 100; i++)
|
||||
{
|
||||
|
||||
System.Threading.Thread.Sleep(10);
|
||||
//progressBarControl1.PerformStep();
|
||||
progressBarControl1.Position = i;
|
||||
lab_percent.Text = i + "%";
|
||||
//progressBarControl1.EditValue = i + 1;
|
||||
//处理当前消息队列中的所有windows消息,不然进度条会不同步
|
||||
System.Windows.Forms.Application.DoEvents();
|
||||
}
|
||||
}
|
||||
|
||||
private void Form1_Load(object sender, EventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
updater = new UpdateClass();
|
||||
updater.ActivationCompleted += new EventHandler<ActivationCompletedEventArgs>(ActivationCompleted);
|
||||
updater.ActivationError += new EventHandler<FileCopyErrorEventArgs>(ActivationError);
|
||||
updater.ActivationInitializing += new EventHandler<ManifestEventArgs>(ActivationInitializing);
|
||||
updater.ActivationProgressChanged += new EventHandler<FileCopyProgressChangedEventArgs>(ActivationProgressChanged);
|
||||
updater.ActivationStarted += new EventHandler<ActivationStartedEventArgs>(ActivationStarted);
|
||||
updater.DownloadCompleted += new EventHandler<DownloadCompleteEventArgs>(DownloadCompleted);
|
||||
updater.DownloadError += new EventHandler<DownloadErrorEventArgs>(DownloadError);
|
||||
updater.DownloadProgressChanged += new EventHandler<DownloadProgressEventArgs>(DownloadProgressChanged);
|
||||
|
||||
InitUpdater();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Write("更新错误:" + ex.Message);
|
||||
XtraMessageBox.Show("更新错误", "系统提示");
|
||||
}
|
||||
}
|
||||
void ActivationCompleted(object sender, ActivationCompletedEventArgs e)
|
||||
{
|
||||
//安装完成
|
||||
isComplete = true;
|
||||
lab_filename.Text = "安装完成";
|
||||
lab_percent.Text = "100%";
|
||||
if (progressBarControl1.Position != 100)
|
||||
{
|
||||
progressBarControl1.Position = 100;
|
||||
}
|
||||
if (e.Error != null)
|
||||
{
|
||||
lab_filename.Text += ",但出现错误";
|
||||
lab_filename.Update();
|
||||
}
|
||||
else
|
||||
{
|
||||
lab_filename.Update();
|
||||
System.Threading.Thread.Sleep(3000);
|
||||
string filename = GetFileName(e.Manifest.MyApplication.Location, e.Manifest.MyApplication.EntryPoint.File);
|
||||
Startup(filename, e.Manifest.MyApplication.EntryPoint.Parameters);
|
||||
//if (args != null && args.Length > 0)
|
||||
{
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
private string GetFileName(string location, string file)
|
||||
{
|
||||
return Path.Combine(Path.GetFullPath(location), file);
|
||||
}
|
||||
|
||||
void ActivationError(object sender, FileCopyErrorEventArgs e)
|
||||
{
|
||||
Log.Write("安装过程中出现错误,错误描述:" + e.Error.Message + System.Environment.NewLine + "Version:" + e.Manifest.Version);
|
||||
XtraMessageBox.Show(this, "安装错误:" + e.Error.Message, "系统提示");
|
||||
lab_filename.Text = "系统正在回滚";
|
||||
updater.Rollback(e.Manifest);
|
||||
}
|
||||
void ActivationInitializing(object sender, ManifestEventArgs e)
|
||||
{
|
||||
lab_filename.Text = "正在初始化安装,请稍后......";
|
||||
lab_filename.Update();
|
||||
lab_percent.Text = "0%";
|
||||
lab_percent.Update();
|
||||
lab_fileinfo.Text = "";
|
||||
lab_fileinfo.Update();
|
||||
//progressBar1.Value = 0;
|
||||
}
|
||||
void ActivationProgressChanged(object sender, FileCopyProgressChangedEventArgs e)
|
||||
{
|
||||
progressBarControl1.Position = e.ProgressPercentage;
|
||||
lab_percent.Text = e.ProgressPercentage.ToString() + "%";
|
||||
lab_percent.Update();
|
||||
lab_fileinfo.Text = string.Format("字节数:{0}/{1}", e.BytesToCopy, e.TotalBytesToCopy);
|
||||
lab_fileinfo.Update();
|
||||
lab_filename.Text = "正在安装:" + e.SourceFileName;
|
||||
lab_filename.Update();
|
||||
}
|
||||
|
||||
void ActivationStarted(object sender, ActivationStartedEventArgs e)
|
||||
{
|
||||
lab_filename.Text = "开始安装,请稍后......";
|
||||
lab_filename.Update();
|
||||
e.Cancel = CheckActivation();
|
||||
if (e.Cancel)
|
||||
{
|
||||
lab_filename.Text = "安装已被取消";
|
||||
isComplete = true;
|
||||
}
|
||||
}
|
||||
private bool CheckActivation()
|
||||
{
|
||||
bool cancel = false;
|
||||
//检查主程序(进程名称)是否打开,如果打开则提示
|
||||
string[] processName = { "Client", "Server" };
|
||||
foreach (string name in processName)
|
||||
{
|
||||
System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(name);
|
||||
if (processes != null && processes.Length != 0)
|
||||
{
|
||||
if (XtraMessageBox.Show(string.Format("进程{0}正在运行中,请关闭后重试。", name), "系统提示",
|
||||
MessageBoxButtons.RetryCancel, MessageBoxIcon.Information) == System.Windows.Forms.DialogResult.Cancel)
|
||||
{
|
||||
cancel = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
return CheckActivation();
|
||||
}
|
||||
}
|
||||
}
|
||||
return cancel;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 文件下载完毕执行的操作
|
||||
/// </summary>
|
||||
void DownloadCompleted(object sender, DownloadCompleteEventArgs e)
|
||||
{
|
||||
mList.Add(e.Manifest);
|
||||
if (mList.Count == mLen)
|
||||
{
|
||||
updater.Activate(mList.ToArray());
|
||||
mList.Clear();
|
||||
}
|
||||
}
|
||||
void DownloadError(object sender, DownloadErrorEventArgs e)
|
||||
{
|
||||
Log.Write("下载过程中出现错误,错误描述:" + e.Error.Message + System.Environment.NewLine + "Version:" + e.Manifest.Version);
|
||||
XtraMessageBox.Show("下载出错:" + e.Error.Message, "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
}
|
||||
|
||||
void DownloadProgressChanged(object sender, DownloadProgressEventArgs e)
|
||||
{
|
||||
progressBarControl1.Position = e.ProgressPercentage;
|
||||
lab_percent.Text = e.ProgressPercentage.ToString() + "%";
|
||||
lab_percent.Update();
|
||||
lab_fileinfo.Text = string.Format("字节数:{0}/{1}", e.BytesReceived, e.TotalBytesToReceive);
|
||||
lab_fileinfo.Update();
|
||||
lab_filename.Text = "正在下载文件:" + e.FileName;
|
||||
lab_filename.Update();
|
||||
}
|
||||
private void InitUpdater()
|
||||
{
|
||||
//从配置文件动态设置更新标题
|
||||
UpdaterConfigurationView updateCfgView = new UpdaterConfigurationView();
|
||||
|
||||
var manifests = updater.CheckForUpdates();
|
||||
mLen = manifests.Length;
|
||||
if (updater.HasNewVersion)
|
||||
{
|
||||
//显示本次更新内容
|
||||
string updateDescription = manifests[0].Description;
|
||||
this.lblUpdateLog.Text = string.Format("更新说明:{0}", updateDescription);
|
||||
|
||||
if (args != null && args.Length > 0)
|
||||
{
|
||||
#region 关闭主程序
|
||||
try
|
||||
{
|
||||
string entryPoint = manifests[0].MyApplication.EntryPoint.File;
|
||||
KillProcessDos(entryPoint);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Write(ex.ToString());
|
||||
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
isComplete = false;
|
||||
updater.DownloadAsync(manifests);
|
||||
}
|
||||
else
|
||||
{
|
||||
lab_filename.Text = "";
|
||||
XtraMessageBox.Show("您当前的版本已经是最新,不需要更新。", "系统提示", MessageBoxButtons.OK, MessageBoxIcon.Information);
|
||||
Exit();
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 使用DOS关闭进程
|
||||
/// </summary>
|
||||
/// <param name="processName">进程名称</param>
|
||||
private void KillProcessDos(string processName)
|
||||
{
|
||||
RunCmd("taskkill /im " + processName + " /f ");
|
||||
}
|
||||
/// <summary>
|
||||
/// 系统退出
|
||||
/// </summary>
|
||||
private void Exit()
|
||||
{
|
||||
this.Close();
|
||||
Environment.Exit(0);
|
||||
}
|
||||
/// <summary>
|
||||
/// 带参数启动指定的应用程序
|
||||
/// </summary>
|
||||
/// <param name="entryPoint">入口的应用程序</param>
|
||||
/// <param name="parameters">程序启动参数</param>
|
||||
private void Startup(string entryPoint, string parameters)
|
||||
{
|
||||
try
|
||||
{
|
||||
// if (args != null && args.Length > 0)
|
||||
{
|
||||
// if (args[0] == OPEN_FLAG)
|
||||
{
|
||||
//关闭主程序
|
||||
ExeCommand("taskkill /im " + Path.GetFileName(entryPoint) + " /f ");
|
||||
//启动主程序
|
||||
System.Threading.Thread.Sleep(1000);
|
||||
System.Diagnostics.Process.Start(entryPoint, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Write(ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// DOS命令运行函数
|
||||
/// </summary>
|
||||
/// <param name="commandText"></param>
|
||||
private void ExeCommand(string commandText)
|
||||
{
|
||||
Process p = new Process();
|
||||
p.StartInfo.FileName = "cmd.exe";
|
||||
p.StartInfo.UseShellExecute = false;
|
||||
p.StartInfo.RedirectStandardInput = true;
|
||||
p.StartInfo.RedirectStandardOutput = true;
|
||||
p.StartInfo.RedirectStandardError = true;
|
||||
p.StartInfo.CreateNoWindow = true;
|
||||
try
|
||||
{
|
||||
p.Start();
|
||||
p.StandardInput.WriteLine(commandText);
|
||||
p.StandardInput.WriteLine("exit");
|
||||
//p.StandardOutput.ReadToEnd();
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// 运行DOS命令
|
||||
/// DOS关闭进程命令(ntsd -c q -p PID )PID为进程的ID
|
||||
/// </summary>
|
||||
/// <param name="command"></param>
|
||||
/// <returns></returns>
|
||||
private void RunCmd(string command)
|
||||
{
|
||||
//實例一個Process類,啟動一個獨立進程
|
||||
System.Diagnostics.Process p = new System.Diagnostics.Process();
|
||||
|
||||
//Process類有一個StartInfo屬性,這個是ProcessStartInfo類,包括了一些屬性和方法,下面我們用到了他的幾個屬性:
|
||||
p.StartInfo.FileName = "cmd.exe"; //設定程序名
|
||||
p.StartInfo.Arguments = "/c " + command; //設定程式執行參數
|
||||
p.StartInfo.UseShellExecute = false; //關閉Shell的使用
|
||||
p.StartInfo.RedirectStandardInput = true; //重定向標準輸入
|
||||
p.StartInfo.RedirectStandardOutput = true; //重定向標準輸出
|
||||
p.StartInfo.RedirectStandardError = true; //重定向錯誤輸出
|
||||
p.StartInfo.CreateNoWindow = true; //設置不顯示窗口
|
||||
p.Start(); //啟動
|
||||
|
||||
//p.StandardInput.WriteLine(command); //也可以用這種方式輸入要執行的命令
|
||||
//p.StandardInput.WriteLine("exit"); //不過要記得加上Exit要不然下一行程式執行的時候會當機
|
||||
p.StandardOutput.ReadToEnd(); //從輸出流取得命令執行結果
|
||||
|
||||
while (!p.HasExited)
|
||||
{
|
||||
p.WaitForExit(1000);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,120 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" use="required" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
<xsd:attribute ref="xml:space" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows.Forms;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
internal static class Program
|
||||
{
|
||||
/// <summary>
|
||||
/// 应用程序的主入口点。
|
||||
/// </summary>
|
||||
[STAThread]
|
||||
static void Main()
|
||||
{
|
||||
Application.EnableVisualStyles();
|
||||
Application.SetCompatibleTextRenderingDefault(false);
|
||||
Application.Run(new Form1());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("Update")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2021")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2022")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
|
@ -20,7 +20,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("295218b6-0c7e-4d1b-ad85-ab0636a83323")]
|
||||
[assembly: Guid("40fb5be4-89be-4717-9378-e85de86d56dd")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
|
|
|
|||
|
|
@ -0,0 +1,71 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// 此代码由工具生成。
|
||||
// 运行时版本: 4.0.30319.42000
|
||||
//
|
||||
// 对此文件的更改可能导致不正确的行为,如果
|
||||
// 重新生成代码,则所做更改将丢失。
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Update.Properties
|
||||
{
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 强类型资源类,用于查找本地化字符串等。
|
||||
/// </summary>
|
||||
// 此类是由 StronglyTypedResourceBuilder
|
||||
// 类通过类似于 ResGen 或 Visual Studio 的工具自动生成的。
|
||||
// 若要添加或删除成员,请编辑 .ResX 文件,然后重新运行 ResGen
|
||||
// (以 /str 作为命令选项),或重新生成 VS 项目。
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")]
|
||||
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
internal class Resources
|
||||
{
|
||||
|
||||
private static global::System.Resources.ResourceManager resourceMan;
|
||||
|
||||
private static global::System.Globalization.CultureInfo resourceCulture;
|
||||
|
||||
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
|
||||
internal Resources()
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 返回此类使用的缓存 ResourceManager 实例。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Resources.ResourceManager ResourceManager
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((resourceMan == null))
|
||||
{
|
||||
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Update.Properties.Resources", typeof(Resources).Assembly);
|
||||
resourceMan = temp;
|
||||
}
|
||||
return resourceMan;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重写当前线程的 CurrentUICulture 属性,对
|
||||
/// 使用此强类型资源类的所有资源查找执行重写。
|
||||
/// </summary>
|
||||
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
|
||||
internal static global::System.Globalization.CultureInfo Culture
|
||||
{
|
||||
get
|
||||
{
|
||||
return resourceCulture;
|
||||
}
|
||||
set
|
||||
{
|
||||
resourceCulture = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<root>
|
||||
<!--
|
||||
Microsoft ResX Schema
|
||||
|
||||
Version 2.0
|
||||
|
||||
The primary goals of this format is to allow a simple XML format
|
||||
that is mostly human readable. The generation and parsing of the
|
||||
various data types are done through the TypeConverter classes
|
||||
associated with the data types.
|
||||
|
||||
Example:
|
||||
|
||||
... ado.net/XML headers & schema ...
|
||||
<resheader name="resmimetype">text/microsoft-resx</resheader>
|
||||
<resheader name="version">2.0</resheader>
|
||||
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
|
||||
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
|
||||
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
|
||||
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
|
||||
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
|
||||
<value>[base64 mime encoded serialized .NET Framework object]</value>
|
||||
</data>
|
||||
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
|
||||
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
|
||||
<comment>This is a comment</comment>
|
||||
</data>
|
||||
|
||||
There are any number of "resheader" rows that contain simple
|
||||
name/value pairs.
|
||||
|
||||
Each data row contains a name, and value. The row also contains a
|
||||
type or mimetype. Type corresponds to a .NET class that support
|
||||
text/value conversion through the TypeConverter architecture.
|
||||
Classes that don't support this are serialized and stored with the
|
||||
mimetype set.
|
||||
|
||||
The mimetype is used for serialized objects, and tells the
|
||||
ResXResourceReader how to depersist the object. This is currently not
|
||||
extensible. For a given mimetype the value must be set accordingly:
|
||||
|
||||
Note - application/x-microsoft.net.object.binary.base64 is the format
|
||||
that the ResXResourceWriter will generate, however the reader can
|
||||
read any of the formats listed below.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.binary.base64
|
||||
value : The object must be serialized with
|
||||
: System.Serialization.Formatters.Binary.BinaryFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.soap.base64
|
||||
value : The object must be serialized with
|
||||
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
|
||||
: and then encoded with base64 encoding.
|
||||
|
||||
mimetype: application/x-microsoft.net.object.bytearray.base64
|
||||
value : The object must be serialized into a byte array
|
||||
: using a System.ComponentModel.TypeConverter
|
||||
: and then encoded with base64 encoding.
|
||||
-->
|
||||
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
|
||||
<xsd:element name="root" msdata:IsDataSet="true">
|
||||
<xsd:complexType>
|
||||
<xsd:choice maxOccurs="unbounded">
|
||||
<xsd:element name="metadata">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
<xsd:attribute name="type" type="xsd:string" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="assembly">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="alias" type="xsd:string" />
|
||||
<xsd:attribute name="name" type="xsd:string" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="data">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
|
||||
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
|
||||
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="resheader">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="name" type="xsd:string" use="required" />
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:choice>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
</xsd:schema>
|
||||
<resheader name="resmimetype">
|
||||
<value>text/microsoft-resx</value>
|
||||
</resheader>
|
||||
<resheader name="version">
|
||||
<value>2.0</value>
|
||||
</resheader>
|
||||
<resheader name="reader">
|
||||
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
<resheader name="writer">
|
||||
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
|
||||
</resheader>
|
||||
</root>
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
//------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version:4.0.30319.42000
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
namespace Update.Properties
|
||||
{
|
||||
|
||||
|
||||
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")]
|
||||
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase
|
||||
{
|
||||
|
||||
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
|
||||
|
||||
public static Settings Default
|
||||
{
|
||||
get
|
||||
{
|
||||
return defaultInstance;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version='1.0' encoding='utf-8'?>
|
||||
<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)">
|
||||
<Profiles>
|
||||
<Profile Name="(Default)" />
|
||||
</Profiles>
|
||||
<Settings />
|
||||
</SettingsFile>
|
||||
|
|
@ -1,19 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>295218b6-0c7e-4d1b-ad85-ab0636a83323</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<ProjectGuid>{40FB5BE4-89BE-4717-9378-E85DE86D56DD}</ProjectGuid>
|
||||
<OutputType>WinExe</OutputType>
|
||||
<RootNamespace>Update</RootNamespace>
|
||||
<AssemblyName>Update</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
|
|
@ -23,6 +24,7 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
|
|
@ -31,24 +33,70 @@
|
|||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System"/>
|
||||
|
||||
<Reference Include="System.Core"/>
|
||||
<Reference Include="System.Xml.Linq"/>
|
||||
<Reference Include="System.Data.DataSetExtensions"/>
|
||||
|
||||
|
||||
<Reference Include="Microsoft.CSharp"/>
|
||||
|
||||
<Reference Include="System.Data"/>
|
||||
|
||||
<Reference Include="System.Net.Http"/>
|
||||
|
||||
<Reference Include="System.Xml"/>
|
||||
<Reference Include="DevExpress.Data.v19.2, Version=19.2.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\Program Files (x86)\DevExpress 19.2\Components\Bin\Framework\DevExpress.Data.v19.2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="DevExpress.Utils.v19.2, Version=19.2.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL" />
|
||||
<Reference Include="DevExpress.XtraEditors.v19.2, Version=19.2.7.0, Culture=neutral, PublicKeyToken=b88d1754d700e49a, processorArchitecture=MSIL">
|
||||
<SpecificVersion>False</SpecificVersion>
|
||||
<HintPath>..\..\..\..\..\Program Files (x86)\DevExpress 19.2\Components\Bin\Framework\DevExpress.XtraEditors.v19.2.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Deployment" />
|
||||
<Reference Include="System.Drawing" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Windows.Forms" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Class1.cs" />
|
||||
<Compile Include="Form1.cs">
|
||||
<SubType>Form</SubType>
|
||||
</Compile>
|
||||
<Compile Include="Form1.Designer.cs">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="Program.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="UpdateLog.cs" />
|
||||
<EmbeddedResource Include="Form1.resx">
|
||||
<DependentUpon>Form1.cs</DependentUpon>
|
||||
</EmbeddedResource>
|
||||
<EmbeddedResource Include="Properties\Resources.resx">
|
||||
<Generator>ResXFileCodeGenerator</Generator>
|
||||
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
|
||||
<SubType>Designer</SubType>
|
||||
</EmbeddedResource>
|
||||
<Compile Include="Properties\Resources.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Resources.resx</DependentUpon>
|
||||
</Compile>
|
||||
<None Include="Properties\Settings.settings">
|
||||
<Generator>SettingsSingleFileGenerator</Generator>
|
||||
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
|
||||
</None>
|
||||
<Compile Include="Properties\Settings.Designer.cs">
|
||||
<AutoGen>True</AutoGen>
|
||||
<DependentUpon>Settings.settings</DependentUpon>
|
||||
<DesignTimeSharedInput>True</DesignTimeSharedInput>
|
||||
</Compile>
|
||||
<None Include="updateconfiguration.config">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="App.config" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Update.Core\Update.Core.csproj">
|
||||
<Project>{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}</Project>
|
||||
<Name>Update.Core</Name>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
</Project>
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.IO;
|
||||
|
||||
namespace Update
|
||||
{
|
||||
/// <summary>
|
||||
/// 记录操作过程的信息
|
||||
/// </summary>
|
||||
public class Log
|
||||
{
|
||||
public static void Write(string msg)
|
||||
{
|
||||
Write(msg, true);
|
||||
}
|
||||
|
||||
public static void Write(string msg, bool isAppend)
|
||||
{
|
||||
try
|
||||
{
|
||||
string filename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "update.txt");
|
||||
if (!Directory.Exists(Path.GetDirectoryName(filename)))
|
||||
{
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(filename));
|
||||
}
|
||||
using (FileStream stream = new FileStream(filename, isAppend ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.None))
|
||||
{
|
||||
StreamWriter writer = new StreamWriter(stream);
|
||||
writer.WriteLine(msg);
|
||||
writer.Close();
|
||||
stream.Close();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public static void Write(Exception ex)
|
||||
{
|
||||
string msg = DateTime.Now + System.Environment.NewLine
|
||||
+ ex.Message + System.Environment.NewLine
|
||||
+ ex.Source + System.Environment.NewLine
|
||||
+ ex.StackTrace + System.Environment.NewLine
|
||||
+ ex.TargetSite.Name;
|
||||
Write(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<applicationUpdater applicationId="c3e35ff1-fc03-4c08-87fb-1ee8f3d38987"
|
||||
manifestUri="http://121.4.95.243:8888/update.xml"
|
||||
version="1.0"
|
||||
title="测试软件-版本更新">
|
||||
</applicationUpdater>
|
||||
|
|
@ -17,8 +17,8 @@ namespace WinformGeneralDeveloperFrame.Commons
|
|||
|
||||
public static DataTable SqlTable(string name)
|
||||
{
|
||||
string connstring = EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString);
|
||||
// string connstring=ConfigurationManager.ConnectionStrings["DB"].ConnectionString;
|
||||
//string connstring = EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString);
|
||||
string connstring=ConfigurationManager.ConnectionStrings["DB"].ConnectionString;
|
||||
string sql = "";
|
||||
string url = "";
|
||||
DataTable dt1 = new DataTable();
|
||||
|
|
|
|||
|
|
@ -51,7 +51,7 @@
|
|||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||
</startup>
|
||||
<connectionStrings>
|
||||
<add name="DB" connectionString="SB16Jt39MD21ugTdYbOTj5/d7+MqcDuVilvBLoJ8OAEXPbuSrV6hZrXx67xblmuQ7fKaMYG+dVdcpDz7biJQmcsuIgxY2UbQm9Be5Kg6Gt/XgxyNiyyQ/Ua7WcUFxGOhUup+z1uyRwL8WU5Gb0o6R8+flGQhYRk/O1O4dns2+sU=" providerName="System.Data.SqlClient"/>
|
||||
<add name="DB" connectionString="data source=.;initial catalog=winformdevfarme;integrated security=True;MultipleActiveResultSets=True;App=EntityFramework" providerName="System.Data.SqlClient"/>
|
||||
</connectionStrings>
|
||||
<entityFramework>
|
||||
<defaultConnectionFactory type="System.Data.Entity.Infrastructure.LocalDbConnectionFactory, EntityFramework">
|
||||
|
|
|
|||
|
|
@ -76,6 +76,14 @@
|
|||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Update.Core\Update.Core.csproj">
|
||||
<Project>{4903d5f5-ff01-426d-b5bb-aadf7c4232fa}</Project>
|
||||
<Name>Update.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Update\Update.csproj">
|
||||
<Project>{40fb5be4-89be-4717-9378-e85de86d56dd}</Project>
|
||||
<Name>Update</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WinformGeneralDeveloperFrame.Commons\Commons.csproj">
|
||||
<Project>{6f2b061d-6116-45a4-9649-49ae4981c496}</Project>
|
||||
<Name>Commons</Name>
|
||||
|
|
|
|||
|
|
@ -15,12 +15,14 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PrimordialForm", "WinformGe
|
|||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Entity", "Entity\Entity.csproj", "{524A09B1-52EE-49C6-ACD2-CEC2AEB8D2F6}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update", "Update\Update.csproj", "{295218B6-0C7E-4D1B-AD85-AB0636A83323}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CodeGeneration", "CodeGeneration\CodeGeneration.csproj", "{D7D32522-8FA4-4B12-ADB1-72A74F0B3964}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Business", "Business\Business.csproj", "{3A1FD334-A7FD-4815-A745-ACC07A7C367F}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update.Core", "Update.Core\Update.Core.csproj", "{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Update", "Update\Update.csproj", "{40FB5BE4-89BE-4717-9378-E85DE86D56DD}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
|
|
@ -51,10 +53,6 @@ Global
|
|||
{524A09B1-52EE-49C6-ACD2-CEC2AEB8D2F6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{524A09B1-52EE-49C6-ACD2-CEC2AEB8D2F6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{524A09B1-52EE-49C6-ACD2-CEC2AEB8D2F6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{295218B6-0C7E-4D1B-AD85-AB0636A83323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{295218B6-0C7E-4D1B-AD85-AB0636A83323}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{295218B6-0C7E-4D1B-AD85-AB0636A83323}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{295218B6-0C7E-4D1B-AD85-AB0636A83323}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D7D32522-8FA4-4B12-ADB1-72A74F0B3964}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D7D32522-8FA4-4B12-ADB1-72A74F0B3964}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D7D32522-8FA4-4B12-ADB1-72A74F0B3964}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
|
|
@ -63,6 +61,14 @@ Global
|
|||
{3A1FD334-A7FD-4815-A745-ACC07A7C367F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3A1FD334-A7FD-4815-A745-ACC07A7C367F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3A1FD334-A7FD-4815-A745-ACC07A7C367F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{40FB5BE4-89BE-4717-9378-E85DE86D56DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{40FB5BE4-89BE-4717-9378-E85DE86D56DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{40FB5BE4-89BE-4717-9378-E85DE86D56DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{40FB5BE4-89BE-4717-9378-E85DE86D56DD}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:Boolean x:Key="/Default/Environment/Hierarchy/EntityFrameworkOptions/IsAlreadyNotifiedAboutEntityFramework/@EntryValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||
|
|
@ -13,7 +13,8 @@ namespace WinformGeneralDeveloperFrame
|
|||
public partial class DB : DbContext
|
||||
{
|
||||
public DB()
|
||||
: base(EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
|
||||
:base("DB")
|
||||
//: base(EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ namespace MES
|
|||
public partial class MESDB : DbContext
|
||||
{
|
||||
public MESDB()
|
||||
//: base("name=DB")
|
||||
: base(EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
|
||||
: base("name=DB")
|
||||
//: base(EncodeHelper.AES_Decrypt(ConfigurationManager.ConnectionStrings["DB"].ConnectionString))
|
||||
{
|
||||
}
|
||||
public virtual DbSet<stockDataInfo> stockDataInfo { get; set; }
|
||||
|
|
|
|||
|
|
@ -742,6 +742,14 @@
|
|||
<None Include="Resources\102.ico" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Update.Core\Update.Core.csproj">
|
||||
<Project>{4903D5F5-FF01-426D-B5BB-AADF7C4232FA}</Project>
|
||||
<Name>Update.Core</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Update\Update.csproj">
|
||||
<Project>{40FB5BE4-89BE-4717-9378-E85DE86D56DD}</Project>
|
||||
<Name>Update</Name>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\WinformGeneralDeveloperFrame.Commons\Commons.csproj">
|
||||
<Project>{6f2b061d-6116-45a4-9649-49ae4981c496}</Project>
|
||||
<Name>Commons</Name>
|
||||
|
|
|
|||
|
|
@ -10,11 +10,18 @@ using System.Text;
|
|||
using System.Windows.Forms;
|
||||
using MES.Entity;
|
||||
using WinformGeneralDeveloperFrame.Commons;
|
||||
using Updater.Core;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using DevExpress.Utils;
|
||||
using DevExpress.XtraEditors;
|
||||
using Update;
|
||||
|
||||
namespace Login
|
||||
{
|
||||
public partial class LoginView : DevExpress.XtraEditors.XtraForm
|
||||
{
|
||||
private BackgroundWorker updateWorker;
|
||||
public bool bLogin = false; //判断用户是否登录
|
||||
public LoginView()
|
||||
{
|
||||
|
|
@ -45,8 +52,32 @@ namespace Login
|
|||
|
||||
private void LoginView_Load(object sender, EventArgs e)
|
||||
{
|
||||
updateWorker = new BackgroundWorker();
|
||||
updateWorker.DoWork += new DoWorkEventHandler(updateWorker_DoWork);
|
||||
updateWorker.RunWorkerAsync();
|
||||
|
||||
}
|
||||
private void updateWorker_DoWork(object sender, DoWorkEventArgs e)
|
||||
{
|
||||
try
|
||||
{
|
||||
UpdateClass update = new UpdateClass();
|
||||
bool newVersion = update.HasNewVersion;
|
||||
if (newVersion)
|
||||
{
|
||||
//if (MessageUtil.ShowYesNoAndTips(Portal.gc.DicLag["Version"].Where(p => p.Name == Portal.gc.Language).First().Value) == DialogResult.Yes)
|
||||
{
|
||||
//Thread.Sleep(1500);
|
||||
Process.Start(Path.Combine(Application.StartupPath, "Update.exe"), "121");
|
||||
Application.Exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
XtraMessageBox.Show(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
private void User_MouseEnter(object sender, EventArgs e)
|
||||
{
|
||||
skinPanel2.BackColor = Color.FromArgb(69, 159, 176);
|
||||
|
|
|
|||
Loading…
Reference in New Issue