Winform program is relatively
For the web program, the function is more powerful, more convenient programming, but the software update is quite troublesome, and it is necessary to upgrade a place to the client. This article combines the actual situation, through the software implementation automatic upgrade, make up for this lack, there is better Reference value.
WINFORM programs are more powerful, more convenient, but software updates are quite troubles, and they are upgraded to the client. This paper combines the actual situation, and automates automatic upgrade through software, it makes up for this lack, Have better reference value.
Since the program cannot override yourself with a new version at runtime, we use the login window to a executable file. When the user logs in, it has a new main program from the Internet. If there is, then download and overwrite from the background. The old version, the user enters the correct username and password, passed the necessary information (such as username, password, etc.) through the parameter to the main program, implement the login, and we are still illustrative. Create a project, you may wish to name
Mainpro, as the main program, switch to the code window, see the following code:
///
/// The main entry point for the application.
///
[Stathread]
Static void main ()
{
Application.run (New Form1 ());
}
In order to receive parameters, we add two static variables m_username and m_password to store usernames and passwords, and modify the main function: private static string m_username, m_password;
///
/// The main entry point for the application.
///
[Stathread]
Static void main (string [] args)
{
IF (args.length == 2) // has parameter input, you can also pass more parameters according to the actual situation
{
// Record the username and password for software
m_username = args [0];
m_password = args [1];
Application.run (New Form1 ());
}
Else
{
Messagebox.show ("Cannot start from here");
}
}
In order to display whether the login is correct, the code of the LOAD event is modified to: Private Void Form1_Load (Object Sender, System.EventArgs E)
{
String msg = string.format ("User Name: {0}, password: {1}", m_username, m_password;
Messagebox.show (MSG);
}
In this way, our sample main program is complete, only the parameter can run the main program, for example, we use "MainPro User Pass" in the DOS window to start the software.
Since this project involves more than one program, in order to ensure that the operation is correct, you need to put the compiled executable to the same folder. Although we can compile it to the same folder, but each time Copying a more abundant, here is a simple way. Create a folder in the hard disk, such as D: / Output, select menu "Item" → "Properties", pop up a dialog box, select "All Configuration" after configuring (c), select the configuration of the configuration properties, Enter "D: / Output" in the output path, when you compile, you will find that the output can be run to D: / Output below. Next, you will be uploaded to upload the latest version to the server. For simple, we use the Access database here, of course, you can use SQL Server in the web version, the principle is exactly the same.
In D: / Output, create a new Access database, name myDatabase.mdb, create two tables, one for the operator, used to store the name and password of the operator, and the other is the version, used to store the main program The latest version, the structure of the two tables is as follows:
Operator table version Table field name type Purpose Field name Type Up number long integer key number long integer key name character User name version number long integer storage Current version file name character This record corresponding file name Password character password file content OLE Object, the specific content of the image stored in SQL
We entered some usernames and passwords manually, as follows:
Don't close the main program, select the menu "File" → "Add Project" → "New Project", enter the project name "Upload", as shown below:
Point "OK", similarly, configure the output path to D: / Output.
Put three buttons (BTNBROW), determine (btnok), and cancel (btncancel)), two text boxes (txtFilename, txtversion), and corresponding text descriptions, as shown below:
In the Solution Explorer window, select the "UPLOAD" project, right-click, select "Set to Start Item", you can run the program.
The response code to add the browsing button is as follows: Private void btnbrow_click (Object Sender, System.Eventargs E)
{
OpenFileDialog myform = new openfiledialog ();
MyForm.filter = "Application (* .exe) | * .exe | All programs (*. *) | *. *";
IF (MyForm.Showdialog () == DialogResult.ok)
{
this.txtFilename.text = myform.filename;
}
}
The function of this button is to get the file name (in practical application, can also be filed from the database from the database, automatically fill the new version of the version number, automatically fill the new version of the version number, automatically fill in the version number of the database. Reference at the time).
Add the cancel button response code, the purpose is to close the window: Private void btncel_click (Object sender, system.eventargs e) {
THIS.CLOSE ();
}
Add two references: using system.data.oledb;
Using system.io;
Add two variables again: private dataset m_dataset = new dataset ();
Private string m_tablename = "version";
The following functions remove the path in the file name: ///
/// Separate the file name from a file name containing the path
///
// / contain file names
/// Remove the file name of the path
Private string getFileNameFromPath (String p_path)
{
String strresult = "";
INT NSTART = p_path.lastIndexof ("//");
IF (nStart> 0)
{
Strresult = p_path.substring (nStart 1, p_path.length-nstart-1);
}
Return Strresult;
}
Add certain button response code (including comments): Private Void BTNOK_Click (Object Sender, System.EventArgs E)
{
/ / Check if the version number is legal
Try
{
Decimal.Parse (this.txtversion.text);
}
Catch
{
Messagebox.show ("Invalid version number!");
THIS.TXTVERSION.FOCUS ();
THIS.TXTVERSION.SELECTALL ();
Return;
}
IF (this.txtFileName.Text.trim (). Length> 0)
{
/ / Check if the file exists
IF (! file.exists (this.txtFilename.text.trim ())))
{
Messagebox.show ("" File does not exist! ");
Return;
}
//Connect to the database
String strconnection = "provider = microsoft.jet.Oledb.4.0; jet oledb: Database password =; data source ="
Application.startuppath.toString (). Trim () "// mydatabase.mdb";
OLEDBConnection myconnect = new OLEDBCONNECTION (STRCONNECTION);
OLEDBCommand mycommand = new oledbcommand ("Select * from version", myconnect);
OLEDBDataAdapter mydataadapter = new OLEDBDataAdapter ();
MyDataAdapter.selectCommand = mycommand;
OLEDBCommandbuilder mycommandbuilder = new oledbcommandbuilder;
MyConnect.open ();
/ / Get existing data
m_dataset = new dataset ();
Try
{
MyDataAdapter.fill (m_dataset, this.m_tablename); // If it is uploaded for the first time, add a record
IF (m_dataset.tables [m_tablename] .rows.count == 0)
{
DataRow newrow = m_dataset.tables [m_tablename] .newrow ();
NEWROW ["Sequence Number" = "1";
m_dataset.tables [m_tablename] .Rows.Add (newrow);
}
DataRow Row = m_dataset.tables [m_tablename] .rows [0];
// Fill in the file name of the path to the path
Row ["file name"] = this.getFileNameFromPath (this.txtFileName.Text.trim ());
/ / Fill in the version number
Row ["Version Number"] = this.txtVersion.Text.trim ();
// Deposit the actual file into the record
FILESTREAM FS = New FileStream (this.txtFileName.Text.trim (), FileMode.Open;
Byte [] mydata = new byte [fs.length];
fs.position = 0;
fs.read (MyData, 0, Convert.Toint32 (fs.length));
Row ["File content"] = mydata;
fs.close (); // Close file
/ / Update the database
MyDataAdapter.Update (this.m_dataset, this.m_tablename);
MyConnect.close ();
Messagebox.show ("" file update is successful! ");
}
Catch (Exception EE)
{
Messagebox.show (Ee.Message);
}
}
Else
{
MessageBox.show ("Please enter the file name");
}
}
At this point, uploading tools are completed, through the program, can be uploaded by the master file, of course, the tool is for the software development provider to publish new software, do not give users.
Finally, the login program is written. Add a project according to the method written by the Upload Tool, the project name is login, set the output path to D: / Output, and set the item to start the project.
Add a combusername, set the dropdownStyle to DropDownload, to select the existing user name, add a text box for entering a password (txtpassword), set the passwordchar property to "*", and join the appropriate text Label, add a determination (BTNOK) and cancel the (BTNCANCEL) button, and set the enable property of the determined button to false, the purpose is if the new software is not downloaded, it is not allowed to log in, arrange it as shown below:
Switch to the code window, add a reference: use system.data.oledb;
Using system.threading;
Using system.io;
USING Microsoft.win32;
Add the following variables to: ///
// / Store the operator and password Dataset
///
PRIVATE DATASET M_DATASET;
///
// / This function is used by the database table
///
Private string m_tablename = "operator"; private dataable m_table;
In order to avoid downloading the main program each time, we will save the version number of the main program, I use the way to save to the registry, to this, write two functions, used to read / write registry, as follows: ///
/// Define the company name and software name under Software in the registry.
///
Private string m_companyname = "lqjt", m_softwarename = "autological";
///
/// read information from the registry;
///
// The key value to read
/// Read the key value string, if it fails (if there is no information in the registration form), ""
Private string readinfo (String p_keyname)
{
RegistryKey SoftwareKey = registry.localmachine.OpensubKey ("Software", true);
RegistryKey CompanyKey = SoftwareKey.Opensubkey (m_companyname);
String strign = ""
IF (CompanyKey == NULL)
""; "
RegistryKey SoftwareNameKey = CompanyKey.Opensubkey (m_softwarename); // Establishment
IF (SoftwareNameKey == null)
""; "
Try
{
Strvalue = SoftwarenameKey.getValue (p_keyname) .tostring (). Trim ();
}
Catch
{}
IF (strValue == null)
Strvalue = ""
Return Strvalue;
}
///
/// Write the information to the registry
///
/ / / Key name
/ / / Key value
Private void writeInfo (String p_keyname, string p_keyvalue)
{
RegistryKey SoftwareKey = registry.localmachine.OpensubKey ("Software", true);
RegistryKey CompanyKey = SoftwareKey.createSubkey (m_companyname);
RegistryKey SoftwareNameKey = CompanyKey.createSubkey (m_softwarename);
// Write the corresponding information
SoftwareNameKey.SetValue (p_keyname, p_keyvalue);
}
Write a function, the user gets the username / password and update the main program version: ///
/// Get an operator situation while updating the main program version
///
Private void getInfo ()
{
THIS.M_DataSet = New Dataset ();
This.combusers.Items.clear ();
String strsql = string.format ("SELECT * FROM ORDER BY Name);
//Connect to the database
String strconnection = "provider = microsoft.jet.OleDb.4.0; Jet OLEDB: Database password =; data source =" application.startuppath.toString (). Trim () "// myDatabase.mdb";
OLEDBConnection myconnect = new OLEDBCONNECTION (STRCONNECTION);
OLEDBCommand mycommand = new oledbcommand (strsql, myconnect);
OLEDBDataAdapter mydataadapter = new OLEDBDataAdapter ();
MyDataAdapter.selectCommand = mycommand;
Try
{
MyConnect.open ();
/ / Get operator information
MyDataAdapter.Fill (this.m_dataset, this.m_tablename);
// fill the username of the query to the combo box for users to choose
THIS.M_TABLE = this.m_dataset.tables [this.m_tablename];
Foreach (DATAROW ROW IN M_DATASET.TABLES [M_TABLENAME]. ROWS)
{
This.combusers.Items.Add (Row ["Name"]). TOSTRING (). Trim ();
}
/ / Check if there is a new version
DataSet DataSet = New DataSet ();
String Tablename = "TableName";
/ / To reduce data transfer time, do not get file content
STRSQL = "SELECT file name, version number from version";
Mycommand = new oledbcommand (strsql, myconnect);
MyDataAdapter = new oledbdataadapter ();
MyDataAdapter.selectCommand = mycommand;
MyDataAdapter.Fill (Dataset, Tablename);
IF (dataset.tables [TABLENAME] .rows.count == 1) // has files
{
String filename = dataset.tables [tablename] .rows [0] ["file name"] .tostring ();
String version = dataset.tables [tablename] .ROWS [0] ["version number"] .tostring ();
/ / Read the version number of the main program
String oldversion = this.readInfo (filename);
IF (OldVersion.Length == 0) // does not exist
OldVersion = "0";
IF (Decimal.Parse (Version)> Decimal.Parse (OldVersion)) // has a new version
{
// Remove the file content
DataSet = new dataset ();
strsql = "SELECT * FROM version";
Mycommand = new oledbcommand (strsql, myconnect);
MyDataAdapter = new oledbdataadapter ();
MyDataAdapter.selectCommand = mycommand;
MyDataAdapter.Fill (Dataset, TableName); // Download file to the local
DataRow Row = Dataset.tables [TableName] .rows [0];
IF (row ["file content"]! = dbnull.value)
{
Byte [] byteblobdata = new byte [0];
Byteblobdata = (byte []) row ["file content"];
Try
{
FILESTREAM FS = New FileStream (Application.Startuppath "//" FileName, FileMode.Openorcreate;
fs.write (Byteblobdata, 0, Byteblobdata.length);
fs.close ();
// Write the current version number for the next time
THIS.WRITEINFO (FileName, Version);
}
Catch (Exception EE)
{
Messagebox.show (Ee.Message);
}
}
} // has a new version
} // has a file
// Close connection
MyConnect.close ();
}
Catch (Exception EE)
{
Messagebox.show (Ee.Message);
Return;
}
// Allow login
this.btnok.enabled = true;
}
In order not to wait too long, pass through a thread when starting, let the user information and update completed in the background, that is, in the window load event, the window LOAD code is as follows: Private Void Form1_Load (Object Sender, System.EventArgs E)
{
/ / To speed up the display speed, put the database connection and other threads
Thread thread = New Thread (New ThreadStart (GetInfo));
Thread.start ();
}
With the above preparation, let's write a determination button response code as follows: Private void btnok_click (Object Sender, System.Eventargs E)
{
/ / According to the selection of the combo box, get the current user in the DataSet specifically physical location
IF (this.combusers.selected "@ 0) // No choice
Return;
DATAROW ROWNOW = NULL;
Foreach (DATAROW ROW IN THIS.M_DATASET.TABLES [THIS.M_TABLENAME] .ROWS)
{
IF (Row ["Name"] .tostring (). Trim () == this.combusers.text.trim ())
{
Rownow = ROW;
Break;
}
}
IF (rownow == null)
Return;
// Get the current correct password
String strpassword = rowerw ["password"] .tostring (). Trim ();
THIS.TXTPASSWORD.TEXT = this.txtPassword.text.trim ();
IF (this.txtpassword.text == strpassword) // password correct
{
// Main program name
String filename = Application.Startuppath "//" "mainpro.exe";
//parameter name
String arg = this.combusers.text "" this.txtpassword.text; // Run the main program
System.Diagnostics.process fun = system.diagnostics.Process.start (filename, arg);
// Close the login box
THIS.CLOSE ();
}
Else
{
Messagebox.show ("Password error! If you are confident that the password is entered correct, / N can try to check if the uppercase letter button is pressed.",
"Warning", MessageBoxButtons.ok, MessageBoxicon.warning;
THIS.TXTPASSWORD.FOCUS ();
THIS.TXTPASSWORD.SELECTALL ();
}
}
The code for the cancel button is very simple, that is, close the login window: Private void btncel_click (Object Sender, System.EventArgs E)
{
THIS.CLOSE ();
}
Pack Login and MainPro software together into an installer, put the login in a shortcut to the desktop or start menu for users (of course, the shortcut name can be taken casually), the user will automatically update the software after running login .
All code in this example please ftp://qydn.vicp.net/ download, the file name is update.rar, don't forget to decompress in d: / create an Output folder, and copy myDatabase.mdb to that In the folder.
Description: This article only plays the role of tiles, through which the idea can be extended to complete a number of functions. In this case, the update to the login box is not enabled. The way I use is to update the login window in the CLOSIING event of the main program, because the login window is already closed. In the login window, you can put a "Save Password" check box, if the user selects the combo box, you can save the username and password to the registry, and read it directly when logging in, the user can click the button to click the button. , Eliminate the troubles of the username and loss password each time.
In this example, we can see that the database is connected, inquiry, etc. is a repetitive labor, and the database used in the three projects, the company name, etc. are the same. In actual work, we can build a new one alone. CS file, you may wish to name myTools.cs, make some common functions and variables (such as database connections, company names, etc.), link this file in each specific project, then use directly, we only need to modify MyTools.cs The related variables or functions in each project do not have to change in each project, which is convenient and not omission, myTools.cs reference is as follows: ///
/// Pre-compiled option, if the networkVersion is defined, the representation is a network version, uses the SQL2000 database, otherwise, use Access2000 database
///
// # Define NetworkVersion
Using system;
Using system.drawing;
Using system.collections;
Using system.componentmodel;
Using system.windows.forms;
Using system.drawing.image;
Using system.io; using system.data;
#if networkversion
Using system.data.sqlclient;
#ELSE
Using system.data.oledb;
#ENDIF
Using system.reflection;
USING Microsoft.win32;
Namespace OA
{
Public Class Tool
{
Public Tool ()
{
}
///
/// The file name of the main program
///
Public const string filename = "oa.exe";
Public const string g_titlename = "Ri Auto Group Office Automation System";
Public Static String g_username;
Public static void writeInfo (String p_keyname, string p_keyvalue)
{
......
}
// Other similar code slightly ...
}
}
If you want to use the content in MyTools in a project, you can do it as follows:
In the Solution Explorer window, select the menu "Item" → Add Existing Item, "At this point, the file dialog box is pop-up, the file type is set to all files (*. *), Find MyTools. CS, don't open the button directly, see "↓" behind the open button? Click it to pop up a menu, select "Link file (L)", which is only a link, which does not generate a copy (as shown below).
When using, add MyTools applications, use public functions in the Tool class, such as:
Using OA;
private void myfun ()
{
String s = Tool.FileName;
}
If the unit name has changed, we only need to modify the variables in MyTools.cs, and do not have to be modified in each project.
We also pay attention to a detail: ///
/// Pre-compiled option, if the networkVersion is defined, the representation is a network version, uses the SQL2000 database, otherwise, use Access2000 database
///
// # Define NetworkVersion
We know, in addition to Access or SQL Server, except for connection, the rest is almost exactly the same, so we define an option (such as the comment above), if #define networkversion, indicating is a network version, using the SQL Server database, Otherwise (drop #define networkversion note) is a stand-alone version, use the Access database, in MyTools, we have two ways to say different ways, you can generate a single-machine version and network by not comment out? The version software, the reference code is as follows: ///
/ // Returns a query result according to the SQL statement, mainly used to only require a result of returning a field
///
/// Query the SQL statement used
/// Queined the result, return empty ""
Public Static String getAvalue (String p_sql)
{
String strresult = "";
Tool.openConn ();
// Design the content of the data set to return
Try
{
/ / Open point to database connection
#if networkversion // Online version
SQLCommand ACOMMAND = New Sqlcommand (p_sql, m_connect);
SqlDataReader areader = acommand.executeReader ();
#ELSE // stand-alone version, note variable name acommand and areader are the same in two versions, which is conducive to programming
OLEDBCOMMAND ACOMMAND = New OLEDBCOMMAND (p_sql, m_connect);
OLEDBDATAREADER AREADER = Acommand.executeReader ();
#ENDIF
// Returns the required data set content is not divided into the machine version or the network version, the argument name is the same
is (areader.read ())
Strresult = areader [0] .tostring ();
AReader.close ();
}
Catch (Exception EE)
{
Messagebox.show (Ee.Message);
}
Return Strresult;
}
There are still many similar tips above, pay attention to summarize, and there are many revenues.