https://www.codeproject.com/Articles/2487/Discover-WEB-HTTP-GET-POST-Utility
https://www.codeproject.com/Articles/1040510/Grab-and-Parse-HTML-Data-Through-POST-in-Csharp
https://www.codeproject.com/Articles/2830/Macro-Scripting-Language-Support-MFC
Giới thiệu
Viết các ứng dụng lưu trữ một công cụ tập lệnh cho phép mọi người viết tập lệnh để tùy chỉnh và mở rộng các ứng dụng đã được chứng minh là rất thành công. Có hàng nghìn nhà phát triển đang sử dụng công cụ Windows® Script trong các ứng dụng của họ và không mắc sai lầm về nó, việc triển khai của Microsoft là khá phù hợp nếu bạn muốn thêm khả năng tập lệnh (macro) vào ứng dụng của mình. Một lựa chọn tốt là sử dụng công nghệ Active Scripting. Trước hết, công nghệ Active Scripting sử dụng ngôn ngữ kịch bản hiện có, vì vậy bạn không cần phải học bất kỳ ngôn ngữ mới nào. Nếu bạn biết cách lập trình với VBScript, JavaScript hoặc thậm chí PerlScript, đó là tất cả những gì bạn cần. Trong bài viết này, tôi sẽ trình bày một giải pháp thay thế đơn giản cho phép bạn thêm hỗ trợ Scripting vào ứng dụng của mình (thậm chí cả ứng dụng hiện có).
Sự miêu tả
Kiến trúc Active Scripting bao gồm một họ các giao diện COM xác định một giao thức để kết nối một công cụ viết kịch bản với một ứng dụng chủ. Trong thế giới của Active Scripting, một công cụ tập lệnh chỉ là một đối tượng COM có khả năng thực thi mã tập lệnh một cách động để phản hồi phân tích cú pháp trực tiếp hoặc tải các câu lệnh tập lệnh, các lệnh gọi rõ ràng đến giao diện IDispatch của công cụ tập lệnh hoặc các lệnh gọi phương thức đi (sự kiện) từ các đối tượng của ứng dụng chủ. Ứng dụng chủ có thể hiển thị các giao diện tự động hóa của nó với không gian tên của công cụ tập lệnh, cho phép các đối tượng của ứng dụng được truy cập dưới dạng các biến lập trình từ bên trong các tập lệnh được thực thi động. Ứng dụng khách cần thêm hỗ trợ tập lệnh chỉ cần triển khai phần Máy chủ của công nghệ này. Các nhà cung cấp khác nhau có thể triển khai việc triển khai Engine của riêng họ, cung cấp cho bạn sự thay thế để sử dụng ngôn ngữ khác mà bạn đã biết. Một ví dụ điển hình là công cụ PerlScript. Một công ty có thể quyết định sử dụng nó thay vì sử dụng JavaScript hoặc VBScript để duy trì cơ sở mã hiện có.
Hình 1: Kiến trúc Active Scripting
Hình 2: Tương tác COM Scripting Active
Hình 1 cho thấy kiến trúc cơ bản của Active Scripting và Hình 2 cho thấy chi tiết sơ đồ tuần tự của các giao diện COM được xác định bởi kiến trúc. Ứng dụng khách của bạn cần sử dụng công nghệ Active Scripting, tạo và khởi tạo công cụ tạo tập lệnh dựa trên ngôn ngữ tập lệnh mà bạn muốn phân tích cú pháp và bạn kết nối ứng dụng của mình với công cụ thông qua SetScriptSite
phương thức này. Sau đó, bạn có thể cung cấp mã script engine mà nó có thể thực thi ngay lập tức (không phải một hàm) hoặc tại một thời điểm nào đó trong tương lai (lệnh gọi hàm), dựa trên nội dung script engine và trạng thái của nó. Ví dụ: văn bản tập lệnh sau chỉ chứa các câu lệnh toàn cục và do đó có thể thực thi tại thời điểm phân tích cú pháp:
ScriptHost.Display("Hello CodeProject guru around the world.");
Câu lệnh này sẽ buộc ứng dụng hiển thị hộp thông báo với văn bản cung cấp (sử dụng Ứng dụng MFCScriptHost.exe ) nhưng:
function HostDisplay() { ScriptHost.Display("Hello CodeProject guru around the world."); }
sẽ buộc ứng dụng chỉ hiển thị thông báo này khi HostDisplay()
được gọi. Nhưng tin tốt là phương pháp mới này cũng có thể được ứng dụng của bạn truy cập bất cứ khi nào bạn muốn. Để thực hiện chức năng này, ứng dụng khách của bạn (đối tượng Site) cần gọi GetIDsOfNames
và Invoke
củaIDispatch
con trỏ của công cụ tập lệnh đang được sử dụng để buộc thực thi chức năng này. Một tính năng thú vị khác của công nghệ Active Scripting là bạn có thể thêm bất kỳ đối tượng tự động hóa nào vào danh sách các mục của công cụ tập lệnh và truy cập các phương thức và thuộc tính của nó từ tập lệnh của bạn. Trên thực tế, các tính năng này đang được sử dụng bên trong các ứng dụng Microsoft Office, Internet Explorer và Visual Studio. Ví dụ: bạn có thể có một mục có tên là 'Tài liệu' và hiển thị danh sách các tài liệu đã mở trong ứng dụng của bạn. Việc triển khai Trang web Tập lệnh của bạn sẽ gọi AddNamedItem("Documents")
trên con trỏ giao diện công cụ tập lệnh. Ví dụ: trong ví dụ cuối cùng của chúng tôi, công cụ tập lệnh nhận được một con trỏ điều phối của mục có tên "ScriptHost" và gọi phương thức "Hiển thị". Nhưng bên trong rất nhiều quá trình này phụ thuộc vào trạng thái của Scripting Engine. Đó là trạng thái của động cơ phải được khởi động ( SCRIPTSTATE_STARTED
). Tại thời điểm này (khi công cụ được khởi động), công cụ sẽ truy vấn đối tượng ActiveScriptSite để phân giải một mục có tên thành một IDispatch
con trỏ giao diện. Sau đó, nó sẽ truy cập các thuộc tính và phương thức giao diện đó bằng cách gọi GetIDsOfNames
và Gọi. Mục mới này sau đó trở thành giống như một biến nội bộ có thể được truy cập bất cứ khi nào nó cần. Ngoài ra, nó trở nên rõ ràng là nó đơn giản như thế nào để công cụ tập lệnh truy cập vào các thuộc tính và phương thức được đặt tên nhờ vào haiIDispatch
các phương thức giao diện.
Nhưng việc kết nối chức năng sự kiện với công cụ tập lệnh khó hơn một chút vì nhiều lý do. Lý do rõ ràng hơn là công cụ tập lệnh phải có khả năng hỗ trợ sự kiện ràng buộc muộn trên một mục được đặt tên. Để hỗ trợ các sự kiện ràng buộc với mục có tên là máy chủ lưu trữ, các công cụ Active Scripting sử dụng các điểm kết nối để ánh xạ các cuộc gọi / sự kiện phương thức gửi đi từ các đối tượng của ứng dụng máy chủ vào các hàm script. Cách gọi hàm sự kiện có tên-mục phụ thuộc vào ngôn ngữ tập lệnh. VBScript sử dụng một cách tiếp cận hoàn toàn khác để ràng buộc cuộc gọi sự kiện so với JavaScript. Bài viết về Sự kiện kịch bản của Andrew Clinick cung cấp rất nhiều chi tiết hơn những gì tôi có thể trình bày ở đây, vì vậy bạn có thể muốn xem nó.
Tôi nghĩ điều này có thể đủ để giúp bạn bắt đầu, bây giờ nếu bạn muốn tìm hiểu thêm, trước tiên hãy xem phần Tham khảo sau ở cuối bài viết này. Bài viết này đã được cập nhật để chỉ ra cách đối tượng ScriptHost có thể kích hoạt sự kiện cho tập lệnh.
Thêm hỗ trợ tập lệnh vào ứng dụng của bạn
Bây giờ tôi đã xây dựng quy trình này mà bạn có thể sử dụng để thêm hỗ trợ tập lệnh vào ứng dụng MFC mới hoặc hiện có.
- Bước đầu tiên bao gồm tạo tệp .ODL (nếu ứng dụng của bạn không có). Các nhà phát triển MFC nâng cao cũng có thể giả mạo quy trình này bằng một số cách khác (vì chúng tôi sẽ không đăng ký thư viện này) nhưng tôi sẽ không đề cập đến vấn đề này ở đây. Bạn sẽ phải tạo GUID bằng cách sử dụng GUIDGen.exe (có sẵn trong thư mục công cụ của Visual Studio). Một tệp .ODL điển hình sẽ trông như thế nàySao chép mã
// YourAppName.odl : type library source for YourAppName.exe // This file will be processed by the MIDL compiler to produce the // type library (YourAppName.tlb). [ uuid(XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX), version(1.0) ] library YourAppName { importlib("stdole32.tlb"); importlib("stdole2.tlb"); //{{AFX_APPEND_ODL}} //}}AFX_APPEND_ODL}} };
- Sử dụng ClassWizard (Ctrl + W) để tạo một đối tượng Tự động hóa có nguồn gốc từ
CCmdTarget
đó sẽ là đối tượng chủ (đối tượng khách của ActiveScriptSite). Xác định các phương pháp mà bạn muốn cung cấp từ máy chủ của mình. Ví dụ, bạn có thể có các phương pháp như:CreateActiveX(strProgID)
,DisplayMessage(strMessage)
vv Thông thường, các phương pháp công văn mới sẽ được gọi từ một kịch bản. - Trong các tệp lớp mới của bạn, hãy thay thế tất cả các tham chiếu của
CCmdTarget
bằngCActiveScriptHost
. Tại thời điểm này, bạn sẽ phải đưa ActiveScriptHost.h / cpp vào dự án của mình. - * CẬP NHẬT * Ghi đè chức năng ảoSao chép mã
HRESULT GetClassID( LPCLSID pclsid )
. Nó phải trả về thành công CLSID của đối tượng máy chủ của bạn. CSLID có thể được tìm thấy trong tệp .ODL sau khi bạn tạo đối tượng tự động hóa ở bước 2. Triển khai điển hình sẽ giống như sau:Sao chép mãHRESULT CHost_Proxy::GetClassID( LPCLSID pclsid ) { *pclsid = CLSID_Host_Proxy; return S_OK; }
Cũng lưu ý rằng tại thời điểm này, đối tượng của chúng ta thực sự là một đối tượng COM và điều khiển ActiveX nhưng chúng ta sẽ không đăng ký như bình thường. - * CẬP NHẬT * Bạn sẽ cần khai báo loại thư viện mà bạn đang sử dụng. Bước này là khó nhưng sử dụng macro MFC, nó sẽ dễ dàng hơn rất nhiều. Chỉ cần thêm
DECLARE_OLETYPELIB(CYourHost_Proxy)
vào tệp tiêu đề của lớp proxy của bạn vàSao chép mãIMPLEMENT_OLETYPELIB(CYourHost_Proxy, _tlid, _wVerMajor, _wVerMinor)
trong tệp .cpp._tlid
là HƯỚNG DẪN của chứng từ đánh máy (bước 1) và_wVerMajor
/_wVerMinor
đại diện cho số phiên bản của văn bản đánh máy của bạn. Ngoài ra, hãy sử dụng trình soạn thảo bao gồm tài nguyên để thêm các chỉ thị này.Sao chép mã#ifdef _DEBUG 1 TYPELIB "DebugYourAppName.tlb" #else 1 TYPELIB "ReleaseYourAppName.tlb" #endif
- * MỚI * Bây giờ Thêm một đối tượng nguồn sự kiện, ví dụ:Sao chép mã
[ uuid(740C1C2D-692F-43F8-85FF-38DEE1742819) ] dispinterface IHostEvent { properties: methods: [id(1)] void OnRun(); [id(2)] void OnAppExit(); }; // Class information for CHost_Proxy [ uuid(F8235A29-C576-439D-A070-6E7980C9C3F6) ] coclass Host_Proxy { [default] dispinterface IHost_Proxy; [default, source] dispinterface IHostEvent; };
Như bạn có thể thấy trong ví dụ này, Máy chủ của chúng tôi hiện hỗ trợ hai sự kiện mà chúng tôi có thể kích hoạt trực tiếp từ mã của mình bằng cách sử dụngCOleControl::FireEvent
hàm. Các chức năng như vậy rất đơn giản. Ví dụ:Sao chép mãvoid FireOnRun() {FireEvent(eventidOnRun,EVENT_PARAM(VTS_NONE));} void FireOnAppExit() {FireEvent(eventidOnAppExit,EVENT_PARAM(VTS_NONE));}
- Tạo một phiên bản của đối tượng máy chủ của bạn (cũng có thể là một lớp được tạo động bằng cách sử dụng macro MFC) và gọiSao chép mã
CYourHostProxy::CreateEngine( 'Language ProgID' )
có thể là 'JavaScript' hoặc 'VBScript' nếu bạn muốn sử dụng các công cụ này. - Thêm mã triển khai vào các phương thức proxy của bạn để thực hiện những gì bạn muốn để người dùng nâng cao thực hiện với ứng dụng của bạn.
- Thêm bất kỳ đối tượng mục có tên bổ sung nào mà bạn muốn truy cập từ ngôn ngữ script
- Cung cấp cách để người dùng tạo tập lệnh hoặc tải văn bản tập lệnh từ đĩa.
CActiveScriptHost
lớp cung cấp các chức năng trợ giúp mà bạn có thể muốn sử dụng lại dựa trên các chức năng mà bạn muốn cung cấp trong ứng dụng của mình. Nhân tiện, sẽ không an toàn khi cho phép người dùng tạo đối tượng Inproc-ActiveX nhưng Local-server nói chung là tốt. Một lý do chính đáng để không cho phép người dùng tạo điều khiển ActiveX là, nếu sự cố xảy ra bên trong ActiveX, ứng dụng của bạn sẽ không. Máy chủ cục bộ cung cấp cho bạn loại an toàn này một cách thoải mái.
Lịch sử sửa đổi
//////////////////////////////////////////////////////// // Version history // v1.01 : Bug fix with accessing object info (ITypeInfo) // v1.10 : Add 'InvokeFuncHelper' allows to call script // function directly from c++ // v1.5 : Add support for Host event (now derive from COleControl // instead of CCmdTarget) ////////////////////////////////////////////////////////
Một số lưu ý khi bình luận
Mọi bình luận sai nội quy sẽ bị xóa mà không cần báo trước (xem nội quy)
Bấm Thông báo cho tôi bên dưới khung bình luận để nhận thông báo khi admin trả lời
Để bình luận một đoạn code, hãy mã hóa code trước nhé