Say in front
COM This word we listen to a lot of, it is what it is, whether it has practical value. If it works for us, then how to write COM components in Visual FoxPro. The author will stand on the position of Visual FoxPro developers, with you to discuss the above issues, I hope to help you. Perhaps this is a domestic difficult to see the article about Visual FoxPro and COM, so superficial, improper place is unavoidable, I will do my best!
More than two years ago, when I had a headache for an extremely complex report, I came across the great writing tool of word-what else could be written in Word! So I used DDE to control word, and it was a nightmare that I couldn't implement complex functions because I didn't know the syntax for communicating with Word. Just when I was in a quandary, providential opportunity, I participated in the United States an industrial ERP training, that set of ERP is actually a group of VC + + written control logic, then use VB to call them in the example. Foreigner told me, with Delphi, PB can be called ... They can do it, then Visual FoxPro should also do, and try, as expected. I was a VBA born (poor level), so I know that word is actually a set of components, then the Visual FoxPro and Word communication is not a problem ... Soon I wrote a great set of dedicated reporting procedures, I was deeply attracted by COM technology, I know a new era has come!
My first COM experience was this: Visual FoxPro acts as a COM client program, and Word provides related services. This is a client of Visual FoxPro acting as COM, controlling other COM components, and I've done a lot of applications in the past two years, such as Excel, Power Point, WHS (the scripting components provided by Windows systems), ADO ... Sometimes I even use VB to write a component for Visual FoxPro call, this application is often used in the API calls, Visual FoxPro does not support the structure type of variables, so call a lot of API functions is very difficult, with VB to the relevant API functions to encapsulate, will be able to solve the problem. Now that I encounter a problem that Visual FoxPro cannot solve, always consider whether the operating system provides the appropriate COM component or if there are any third-party components that can be invoked ...
What does COM bring to visual FoxPro
Visual FoxPro can also write COM servers that can be invoked in other COM-enabled languages to implement features they do not realize, most of which are database-related issues. I use Visual FoxPro to write COM components also because of an industrial control project, when industrial data was collected to the PC client, customers want to save data to the database, and provide the corresponding query, report function. This requirement is not excessive, but it is difficult for industrial control software (different software division, the developers have their own expertise).
I know in the past, there are basically two approaches to the same kind of problem: one is to access the underlying Fox library in C, and the other is to execute the FOX program externally. The previous requirement for developers is high and it is difficult to achieve a variety of features, such as accessing SQL Server databases and DBC at the same time. The latter effect is not good, stability is too bad, I have seen many such applications, give me the feeling is always wrong!
Here, you may understand that COM actually solves the integration of the application, you can unknowingly in the customer, using a lot of other language advantages, very simple to complete the task. From the interface effect, what others see is the main interface of the program, there will be no other window to affect the screen, from the control of the program is more good, have the external call EXE file, people know that it is difficult to control its running process, know its operation results, like "The Kite Broken Line"-only by it! Now that you have a COM component, you can completely get out of the way, call its method, set its properties, and respond to its events, so it's obedient, just like a part of the client program itself. Another benefit of COM is the expansion of the scope of Visual FoxPro, now we can simply spread the FOX program to a variety of occasions (business, industry, the Internet, as long as there is a database processing business), and other systems seamless integration, I do that the industrial application is this.
COM technology can also bring new ideas for software development, different language programmers can work together, different modules can be made into separate components, so easier to maintain, upgrade the software as long as the replacement part of the components. Here I think of the domestic now more popular software development business-for financial software to do interface, many customers want their own MIS system and financial software together, data sharing. Now the practice is "hard to connect the database, direct manipulation of data", which is not good-financial data is not secure, two of the system development has become only financial software companies can do, because the structure of the database, business records only they know. If the financial software package is a set of components, and the financial software is just the implementation of this component, then this two-time development becomes safe and easy. (Comments on financial software are only from the point of view of COM technology, regardless of other factors)
COM's flaws
COM is so good, but not without flaws. I think the most important is the version of the problem, is commonly known as "Dll Hell", the common ActiveX control people on this problem must be experienced, COM is the same. For example, the code that controls word must be careful about the version of Word, or even the kind of language, otherwise the program will go wrong ... Another disadvantage of COM is that COM components are running efficiently, mainly in the creation of entity objects when it seems a bit slow, this problem we can through "early binding", connection pool to solve, even if not a good improvement, I think this problem is not insignificant, after all, the benefits of COM is too big ...
Visual FoxPro and three-tier architecture
According to the normal logic, write COM must write a three-tier application, in fact, the Visual FoxPro configuration in the three-tier structure of the middle tier to write COM is the only way, but you must understand that COM components are not only for the three-tier architecture, the various applications I mentioned above are basically not in the category of three applications.
The three-tier architecture divides the whole software system into three levels: User interface, business logic and data storage. The three-tier architecture is characterized by the fact that the user interface does not deal directly with the database, and all customer requests must be updated through the middle-tier component to the database. There are two great benefits: the first advantage is the unified maintenance of business logic code, and one benefit is to solve the problem of large numbers of users accessing the database at the same time.
All business logic is written in the middle tier, so that when the business logic changes, it can update the middle-tier procedures, the customer interface does not have an impact. This is a kind of ideal, I think the user interface design and data correlation is very big, everyone in the design of single-layer structure, double-layer structure should have this experience: what kind of data source must have what kind of interface with it; the three-tier application user interface and the middle layer, the same interface must follow the middle layer to go, If the business logic of the middle tier obviously changes the user interface is unlikely to be unchanged. So the unified maintenance of the code does not bring all kinds of user interface is relatively stable, so the unified maintenance of the code is just a tempting fruit, eat is not necessarily sweet.
The most tempting place for a three-tier structure is to address the problem of large numbers of users accessing the database at the same time. We know that the current best Oracle database can support 500 connections at the same time, unfortunately, it is proven that database servers are often not affordable when the number of active connections is reached. 500 requests to access the database at the same time, which is very trivial in the Web field, in large enterprises. The solution is nothing more than to reduce the pressure of the database server at a certain moment, in the further said is to assign work to different database servers, so that customer requests to wait in line, don't rush to the database there, this is dynamic load balancing and queuing mechanism, then who to complete the work? The user interface is certainly impossible, the database has been very difficult, of course, can not trouble it, only the middle tier to be competent. Now MTS, COM + is such a tool, the Visual FoxPro components support MTS, COM +, so we write the components in MTS, COM +, we enjoy the characteristics of MTS, COM +, we do not need to worry about.
Why Microsoft emphasizes the application of visual FoxPro in Web server
The Web services component is the most typical middle-tier application, characterized by the fact that the user interface is less likely to interact with the server through a component, such as when we query a batch of data on the client, the middle tier gets the request to retrieve the database return cursor, and the instant HTML document is returned to the customer, The same behavior, in Single-layer, two-tier applications may be very complex, we may need to maintain the results of the query, then update to the server, and then refresh the cursor ... The database under Web application emphasizes the query, which produces the query result according to the complex logic, and the maintenance of the data is not very fancy. (This is why Web-dedicated database MySQL does not support transaction processing, stored procedures ...). )
For this application, as a professional database development program, Visual FoxPro can be said to be extremely easy, not easy to develop, there is no difficulty, so Microsoft stressed that the Visual FoxPro on the Web application is very reasonable.
There is also a three-tier application is enterprise-class application, which is characterized by the use of a three-tier architecture to implement two or single-tier applications, while using a three-tier architecture to solve the maintenance of commercial Code and a large number of data access problems. It can be imagined that this enterprise-class application requirements for the development of components is very high, in foreign countries often have professional companies to develop such components, users only need to do two development according to the actual application. As far as I know, Delphi's third party products have such things, prices are unusually expensive, more expensive than the Delphi ... Visual FoxPro can also develop such a component, which is just a matter of difficulty ... In business terms, Microsoft does not mention the use of Visual FoxPro in this regard is reasonable, after all, compared with other tools we have no advantage ...
The COM basics of Visual FoxPro
To tell the truth, there are a lot of people who use COM, and few people write COM components. I have only experienced two practical applications, once mentioned above, once again is a friend of mine to do: Delphi to do the interface, Visual FoxPro developed Data Processing program (great application, the opportunity to ask him to talk about). Due to the work of the relationship, I do not use Fox to do development, the future of this development opportunities may be less, writing this article is also hope that the vast number of Fox friends to play their own wisdom, play the role of Visual FoxPro Xeon. Would like to be a person!
Types of components that Visual FoxPro can write
COM is a shorthand for Component Object model, which is based on object-oriented programming thinking, and natural to meet multiple layers of distribution is applied. In Visual FoxPro, we can write two types of COM servers (COM server): out-of-process components (out-of-process) and in-process components (in-process). The Out-of-process component takes an EXE as the suffix name, and the in-process component takes the DLL as the suffix, in which the in-process component is divided into single-threaded (single-threaded) components and multithreaded (multi-threaded) components. In the end, we made the program into such a component, completely by Visual FoxPro to complete the compilation work, the following figure:
Figure 1: Even Compiling Entry dialog box
The in-process component runs in the same memory space as the client, so that the data is communicated faster, but if the component crashes, it affects the client program. Because the in-process component runs in the same memory space as the client, if the update component is to be replaced, the entire application must be removed, which is indifferent to common applications, but has an impact on Web applications. The replacement component must be swung down the entire Web server (everyone is not aware of VFP Yellow Pages: http:// Www.universalthread.com often publishes notices and updates the site in a few hours; Out-of-process components run in different memory spaces with the client, so the data exchange slows down, but the two don't interfere, which is a bit like visual FoxPro calls Word (Word is an out-of-process COM component), if Word goes wrong, Visual FoxPro is not affected by the client program, at most, by triggering an error.
Component and Component user interface
In-process components cannot have interface elements, and out-of-process components can have interface elements, which is why word looks like a normal exe but is a COM component. Here I have a little idea to communicate with you both as an out-of-process component, it can take the interface, but in development we try to reduce the pattern form, because the COM component is often in the unattended state, out of the mode form to allow users to confirm is not realistic, if the mode form is not user response, COM program process will be blocked, The request from a later client will not be able to respond. Visual FoxPro stipulates that when a developed program is compiled into an in-process component, the interface element is ignored and the new Vfp6t.dll Runtime Library (only the process component can use the runtime), many user interface commands and functions have been deleted, including the old FoxPro 2.x READ and @ ... Get/say support. In addition, some designers that exist in the Vfp6r.dll runtime, such as the Table Designer and Report Designer, have been deleted. Visual classes such as forms are still supported at the Vfp6t.dll run time. This shows that the "unattended state" problem is not prominent when calling components within the design process, and the problem is with out-of-process components. If we can determine that a user can respond to a modal form (as Word does) at any time, the problem will not be a problem, but the problem that the component does run in "unattended state" has to be considered, and Visual FoxPro provides SYS (2335) function to handle the unattended state of an out-of-process component, as this article focuses on the development of the in-process components, and there is no more to talk about.
Our first COM component
In 98, when Visual FoxPro 6 was launched, visual FoxPro could only develop out-of-process components and single-threaded inline components, taking into account that in-process components were not functioning well, and the operational stability was not good, and foreign fox experts warned us: do not use Visual FoxPro development in-process components. With the introduction of the first service pack of Visual FoxPro 6, Visual Studio SP3, visual FoxPro has the ability to develop multithreaded components, and the lightweight, dedicated support for in-process components that were mentioned earlier Vfp6t.dll also launched, and visual FoxPro in the compilation of COM components tend to be multithreaded in-process components, of course, each type of components have their own characteristics, in different occasions each has its own rationality. This article assumes that the user uses the SP3 version of Visual FoxPro 6 to compile the sample code into multithreaded in-process components so that no patched visual FoxPro can be adapted to this article, of course, if you have visual FoxPro 7, you will obviously feel that both the development efficiency and operational efficiency are much better than the 6.0 version, even the beta version.
Now let's take a look at our first COM component, which is a very simple program, and its function is to add a record to the table, if the addition of failure will produce a hint. Perhaps you are not satisfied with the weak function of the formation, then you play your intelligence, here we just express a meaning ...
There are two tables in the database DEMO.DBC, respectively, the ITEM.DBF and SYS_ID.DBF,ITEM.DBF structures are as follows:
Field name |
Field type |
Width |
Default value |
Field validation rules |
Id |
I |
4 |
Getid (1) |
|
First_Name |
C |
6 |
|
! Empty (first_name) |
Last_Name |
C |
6 |
|
! Empty (last_name) |
Sex |
C |
2 |
|
Inlist (Sex, "male", "female") |
Birthday |
D |
8 |
|
Year (birthday) <1980 |
Desc |
M |
4 |
|
|
Where the default value of the field ID is the return value of the database stored procedure Getid (), Getid () can return unique integer data from the sys_id table as follows:
Procedure GetID
Lpara Ltableid
Local Lcurrid[1]
Update sys_id set curr_id=curr_id+1 where Tableid=ltableid
Select curr_id from sys_id where Tableid=ltableid into array lcurrid
If select (' sys_id ') >0
Use in sys_id
endif
return lcurrid[1]
Endproc
This code is simple, the only thing worth mentioning is that the data table is closed in time. I personally believe that this should be a feature of COM programming-reducing the connection time between the database and the component. Although our application here is not a three-tier architecture, I would like to convey this spirit to everyone. Maybe someone has a question: will multiple connections be time-consuming or system resources? This problem is very complex, in general, the key to optimizing efficiency in the three-tier application is that the database server should not save the state of each connection, and to do so must ensure that the connection is instantaneous. However, the instantaneous connection will often lead to increased frequency of connections, for large server-type databases (Oracle, SQL Server, etc.) to connect to them is often slow, or even the speed of the connection to be counted in minutes, so that "instantaneous connection" seems to be unworthy, So people put forward various optimization schemes (such as connection pool) to solve the problem of continuous speed. However, for a file-type database such as DBC, every time you connect to the database (open the table) quickly, especially with Fox's own data engine, it's not important to close the connection (table) in a timely manner, but when we write a connection to a large database build, especially for a three-tier system component , this problem must be considered carefully, because this is the key to optimizing the efficiency of the system!
Then there is our component code, and COM must be written based on OOP (object-oriented), and the behavior COM component itself is an object. The way we build a COM component in Visual FoxPro is to define a olepublic class that we can build from the Class Designer or build it through PRG files, but with the advent of visual FoxPro 7, the latter may be more prevalent, The reason for this is that session classes that support private working periods (the form class also supports private working periods, but have a large resource consumption) can only be defined through PRG; classes defined through PRG can be debugged directly in Visual Studio.NET, while others are not; due to visual FoxPro designed COM components with no interface, so the class designer's "visualization" is not an advantage, in addition to the visual FoxPro 7 of the efficient development environment, PRG's simplicity more advantages.
Needless to say, here is the complete code for our COM component:
#define CL chr (+CHR) (10)
Define class Vfpcomtest as session Olepublic
datasession=2
PROCEDURE SetPath
Lparameters Cnewval
IF Right (cnewval,1) <> ' \ '
cnewval=cnewval+ ' \ '
ENDIF
OPEN DATABASE cnewval+ ' Demo.dbc ' SHARED
Endproc
Procedure Destroy
IF dbused (' demo ')
Close DATABASES
ENDIF
Endproc
function Add_item
Lpara Cfirst_name,clast_name,csex,dbirthday,mdesc
Local Dbirthday
If Pcount () <5
Error ' Add operation missing parameter '
Return
endif
INSERT into item (FIRST_NAME,LAST_NAME,SEX,BIRTHDAY,DESC) value (M.cfirst_name,m.clast_name,m.csex,m.dbirthday, MDESC)
If select (' Item ') >0
Use in item
endif
Endfu
Procedure error (Lerror,lmethod,lline)
Local Ctext
If select (' Item ') >0
Use in item
endif
ctext=;
' Error time: ' +transform (DateTime ()) +cl+;
' Error code: ' +str (lerror,4) +cl+;
' ERROR hint: ' +message () +cl+;
' Wrong way: ' +lmethod+cl+;
' ERROR line number: ' +transform (lline) +cl+cl
Strtofile (Ctext, ' c:\com.txt ',. T.)
Comreturnerror ("Visual FoxPro COM Server", Ctext)
Endproc
Enddefine
1. We define a Olepublic class, its name is: Vfpcomtest, its base class is: Session class. The session class, which is provided after visual FoxPro 6 SP3, features a small footprint and supports a private working period, and becomes the best choice for defining COM components (especially in-process components that cannot be used if you want to develop an out-of-process component with an interface) We added the Olepublic keyword, which is the key to compiling COM components, and must not be omitted. In the code we use the following statement to do the work.
Define class Vfpcomtest as session Olepublic
Enddefine
2. Then we set the default value of the class's DataSession property to: 2, which means that using a private working period, if you set its value of 1 to use the default working period, this is the same as the DataSession property of the form.
3. Because we use the DBC database demo, the path to the database is important to the system. Here we provide a SetPath method to locate and open the database:
PROCEDURE SetPath
Lparameters Cnewval
IF Right (cnewval,1) <> ' \ '
cnewval=cnewval+ ' \ '
ENDIF
OPEN DATABASE cnewval+ ' Demo.dbc ' SHARED
Endproc
4. The key method of this class is Add_item, and its code is as follows:
function Add_item
Lpara Cfirst_name,clast_name,csex,dbirthday,mdesc
Local Dbirthday
If Pcount () <5
Error ' Add operation missing parameter '
Return
endif
INSERT into item (FIRST_NAME,LAST_NAME,SEX,BIRTHDAY,DESC) value (M.cfirst_name,m.clast_name,m.csex,m.dbirthday, MDESC)
If select (' Item ') >0
Use in item
endif
Endfu
Quite simply, one thing to say is that when there are fewer than 5 parameters, we use the error command to produce a user-defined error, the new Addition command in Visual FoxPro 6 when the error command is used, and you can refer to the information in more detail. Here's another thing to say is that in the visual FoxPro class, the process (procedure) is the same as the function (functions), which is chosen according to your preference.
5. When the COM component is released we must do some cleanup work, which can be written in the Destroy event, and if you want to do some initialization when the COM component is built, you can write the code in the Init event.
6. Then there is the most critical piece of code for our COM component: Error traps. COM components are always running in the background, even sometimes in unattended state, so robust error-trapping procedures are important. COM components can be very simple, just like our example, but must be robust, write COM programs, the first method to write the program is the error method. The error method is a self-contained method program for the session class, which is triggered when an error is generated. Our code is as follows:
Procedure error (Lerror,lmethod,lline)
Local Ctext
If select (' Item ') >0
Use in item
endif
ctext=;
' Error time: ' +transform (DateTime ()) +cl+;
' Error code: ' +str (lerror,4) +cl+;
' ERROR hint: ' +message () +cl+;
' Wrong way: ' +lmethod+cl+;
' ERROR line number: ' +transform (lline) +cl+cl
Strtofile (Ctext, ' c:\com.txt ',. T.)
Comreturnerror ("Visual FoxPro COM Server", Ctext)
Endproc
In this piece of code, we first sort out the battlefield--close the datasheet; then we generate a string that records the information about the error and writes it to a text file and registers it as a history record; Finally we used the Comreturnerror () function to tell the client that the COM component was wrong. !
Here we discuss error handling for COM components.
Situation one: If we do not write any error trap programs in the assembly (such as the error method of the class or the On error routine), you must understand that this is extremely stupid unless you can guarantee that the program is not wrong. In this case, if there is an error in the COM component, the client program can get information about the component error. The problem here is that the COM component is not going to work properly after the error, I am afraid that we have to deal with the pieces to be able to re-enter the fight, the problem in general programming, we should have understood.
Case two: There is an error trap in the COM component, but the Comreturnerror () function is not used to tell the client that the COM component has made an error. Once an error occurs, the error handler is triggered, and the error handler adjusts the state of COM to return to normal, which is consistent with the idea and practice of the common program. When the error is processed, the COM component returns to its normal state, and the COM component's client does not know that the COM component has been wrong. This is not an ideal situation, which reduces the interaction between COM components and client programs. Take our routines. If an error occurs while adding a record, the record is clearly not joined to the data table, but because the client does not get a COM component error message, it is likely to prompt the user record to add success, and there is a misunderstanding.
Situation three: When we analyze the previous two scenarios, we understand the meaning of the Comreturnerror () function: It is a two-way thing to use error-handling trap-fault tolerance and comreturnerror () to tell the client that the COM component is wrong. The following is about the use of Comreturnerror ():
Comreturnerror (Cservername,cerrormessage)
1.cservername:com the name of the service program, optionally specified.
2.cErrorMesage: Error message text, which can generally be filled in with the return value of the messages () function. If you want to get more detailed information, you can organize the text in this case, first.
COM component is a specification under Windows system, its error message is actually a structure type variable, let the client program know COM component error, just fill in this structure. Visual FoxPro for us to save trouble, we can use Comreturuerror () easy to complete this work ...
The component error information that the client gets is actually just an afterthought, and if we've already handled the error in COM (which is normally the case), the client will not have to worry about COM's running state and still be able to continue using the component. So the whole error handling process is summed up: COM components must handle their own errors, error handling, and then use the Comreturnerror () function to return an error message to the client.
Compiling our COM components
In general, we should set up information about the project before we compile it, but there seems to be a slight shortage of Visual FoxPro-the Olepublic class created by PRG file, which is not available on the service page of the project information dialog before the first connection. So before the "formal" link, you can compile any of the following, so you can set the properties of the COM component.
Service Program page for Project Information dialog box
Here are two attributes that are important: instance and project name.
Instance
There are three options for an instance: not to be created, used alone, multiple-use.
1. If we choose not to create, the component cannot be used as a COM object, even if the code is compiled into a COM component (in-process or out-of-process), and can only be used within the Visual FoxPro as a normal Visual FoxPro class;
2. The difference between individual use and multiple use is in how many instances of a component in a system are set up to meet customer requests. This option is valid only for out-of-process components or in-process components of a single thread. Here we use an out-of-process component to illustrate the problem: we compile our code into an out-of-process component that we use separately, and call it in Visual FoxPro:
Ox1=ctreateobject ("Vfpcomtest.vfpcomtest")
Ox2=ctreateobject ("Vfpcomtest.vfpcomtest")
When you open the Task Manager for Window 2000, you will see:
When used alone, COM components produce multiple instances.
We compile our code into a multiple-use out-of-process component that is invoked in Visual FoxPro:
Ox1=ctreateobject ("Vfpcomtest.vfpcomtest")
Ox2=ctreateobject ("Vfpcomtest.vfpcomtest")
When you open the Task Manager for Window 2000, you will see:
When multiple uses, the COM component produces an instance of the pair.
3. For multithreaded components in the process, always create "multiple use" components, "use alone" is always ignored.
Project name
This setting involves how to invoke COM components, by default, this is the class name +.+olepublic the project name, which is: Vfpcomtest.vfpcomtest. When you call it, you are:
Ox1=ctreateobject ("Vfpcomtest.vfpcomtest")
Formal joint compilation
Like this in the diagram (regenerate the component ID check also can), click OK. The error that may occur here is that the file cannot be updated. When we develop components, we often debug and iterate over and over again, so that if we are gradually in the state of the call, the binder will go wrong, as soon as the component is released, in Visual FoxPro, as follows:
Rele Ox
* Assuming previous execution: Ox=createobject (' vfpcomtest.vfpcomtest ')
To apply our COM components
Applying in Visual FoxPro
Ox=createobject ("Vfpcomtest.vfpcomtest") && establish COM objects
Ox.setpath (' D:\First_com\ ') && setting the location of the database
Ox.add_item (' F1 ', ' L1 ', ' 1 men ', {^1975-12-26}, ' Test ') && add a record
Rele ox&& Release Component
Application in Delphi
I have written a simple test program that everyone can look at.