On Windows 10, I am trying to write VBA code to list the Unicode code point ranges in a font.
I was able to use GetFontUnicodeRanges in gdi32.dll, but it does not handle code points beyond xFFFF.
Further research uncovered GetUnicodeRanges (as part of DirectWrite), in Dwrite_1.dll, which should handle all Unicode code points, but that is not on my system (although I have Dwrite.dll which does NOT contain GetFontUnicodeRanges.
I searched SO, the internet at large and Microsoft's web sites but could not find that dll.
Question: Does anyone know how/where I can get a copy of Dwrite_1.dll?
There is no DWrite_1.dll. You're mixing up the dll with the header file: the GetUnicodeRanges method is implemented in the IDWriteFont1 and IDWriteFontFace1 interfaces, which are supported in the DWrite_1.h header file.
DWrite makes use of COM. You start by calling the DWriteCreateFactory function to get a factory interface — that is, an object that implements the requested factory interface. DWrite has multiple factory interfaces which correspond to different versions --- IDWriteFactory (v1), IDWriteFactory1 (v2), etc., each adding new functionality.
IIRC, VBA makes use of COM, but I've never tried to call into DWrite.dll from VBA. I'd search for discussions on VBA calling into COM interfaces.
Do you really need to do this programmatically? There are tools you can use to inspect fonts. I've long used SIL ViewGlyph; also check out BabelMap.
Related
Is it possible to have modules be external to the actual Excel file and call the functions/subs within them externally?
My thinking is if there are multiple Excel files that use the same module, instead of updating each one of those files separately when I make a change, can I just update the one module stored on a server or something?
I have doing something like you describe for years. You can move your VBA code to a VB6 ActiveX dll, organize it into classes, and load that dll as a reference from Excel VBA.
This is a good way to reuse non-workbook specific code. For instance, I have code that queries a mainframe. I like to call it from Excel, but the details of the connection and how data is passed are contained in a dll that I can load from Excel, VB6, Word, .NET, wherever. I have a similar dll for reading data from AutoCAD drawings, one for interfacing with a product DB on a MySQL server, etc.
The code that remains in Excel tends to be simple formatting stuff. Say I return a variant array of strings (technically a COM SAFEARRAY) from some library that I wrote. I would then output it into Excel, maybe do a text-to-columns, and have a list of results returned to the user.
You can also pass and return more complex data structures. The beauty of VB6/COM Automation (and I didn't appreciate this until I learned to do it the harder way in VB.NET or C#) is that the data will flow in and out of your components seamlessly and all the necessary interfaces will be created for you.
The main change to your code will be replacing things like ThisWorkbook or ActiveSheet with explicit parameters like (Byval sht as Excel.Worksheet). These will be caught at compile time in VB6 (since it doesn't know what ThisWorkbook is), so you cannot overlook them; you are forced to pass an explicit reference.
I also notice that my code inside the dll becomes more paranoid if it receives a Worksheet or other Excel object as a parameter. In VBA you might have had more assurance that you were passing a good object since it was private to a given workbook. The dll does not know who is calling it, so I view the passed-in object with more suspicion (check if Nothing, sheet name, formatting clues to ensure I am using what I think I am using).
The only downside I see is that you will have to get a copy of Visual Basic 6.0. I bought mine in 1998. It is no longer available from Microsoft, but surely there is someone out there who will sell it to you. The latest service pack is SP6.
You will also have to become familiar with "regsvr32" and "regsvr32 /u" to deal with the "ActiveX can't create component" errors as you open your workbooks on various computers. I just publish my dlls to a mapped network drive and re-register them on the user's computers whenever there is a significant change. Obviously this is a intranet/single company solution. Publishing the updated versions is much more of a pain the farther you are distributed.
Not sure if this would satisfy your needs, but you could create your common module as an "add-in" and so install it so that all files that you open in the same instance of excel would have access to the add-in code.
It would not be my recommended way of doing it because I would be worried about suitable testing of all the excel files that use it, when you make a change, plus the added complexity of getting users to install your add-in (this may not be an issue for you). I have a "developersToolkit" module I use across 8 different Workbooks, but I import the module into each workbook so its stand alone and I can also test changes for compatibility with each of the 8 workbooks.
I'm a complete VBA newbie, having decided to teach myself over a weekend, so forgive the stupid question(s). I'm trying to automate some routine tasks involving generating Word documents or emails from an Excel Spreadsheet. Because there will be multiple software versions involved, I am using late binding to open Word and Outlook. My question is: Where can I find a simple reference telling me what the index numbers are that correspond to the application constants? I have killed a lot of time googling to learn that, for example, the Outlook foldertype for "Contacts" is "10". Maybe someone knows of a web link that could save me countless hours of searching?
Update: http://msdn.microsoft.com/en-us/library/office/gg278936%28v=office.14%29.aspx seems to have some of the information I need, although it's not always intuitive where the information is. For example, if it contains the outlook folder type constants, I haven't found them yet.
See here
Enumeration http://msdn.microsoft.com/en-us/library/office/ff860961(v=office.15).aspx
OlDefaultFolders Enumeration http://msdn.microsoft.com/en-us/library/office/ff861868(v=office.15).aspx
I would recommend to add the relevant object libraries to your project as References during development time. You do this by using the Tools - References Menu in the VBA Editor. This makes developing a lot easier as you can use intellisense while writing the code.
If you need only a few Enums or single Constants in your code the easiest way to get their values is to hit [F2] in in VBA Editor while the object libraries are still referenced. Then search for the constants name and copy its value to your code.
Just using the numeric values of the constants in your code makes the code pretty hard to read. So I would recommend to re-declare all the Enums/Constants you actually use in a module in your own project. That massively improves the readability of your code.
So, instead of just copying the value from the VBA Object Browser, I suggest you copy the name and the value and put it your own code as a constant declaration. For your example of the Outlook contacts folder this will look like this:
Public Const olFolderContacts = 10
You can then use the constant in your procedures as you would do with Early Binding.
Should you work on a larger automation project using many of the constants from any one of the Office Object Libraries, you can download ready-made VBA modules containing all the Office constants from my website. You can then just import the relevant modules into your project and are ready to go.
After you finished the main development work, you remove the linked libraries from your project and declare the relevant object variables As Object instead of the actual type.
Always remember to compile your project not to miss any declaration that does not work late binding.
I'm trying to interact with a .dll which will allow me to receive information from a variety of devices (Eye Gaze to be specific). The .dll is called ETUDriver and can be found at http://www.sis.uta.fi/~csolsp/projects.php however it does not come with an accompanying .h file.
I am struggling to actually load, interact and invoke functions from the .dll. A manual is supplied but it is of no help whatsoever with regards to actually setting up the code to start it off. There are three accompanying example apps (with source code) but only two of these work and one of which is in C# so is not helpful. The one that works however loads up the .dll via MFC and this is not a viable option with my code (which is intended to be used with many other projects and as such can't enforce MFC or any other libraries that are not as standard to projects).
Essentially, within the .dll is a series of classes which I need to create within my code and invoke the relevant functions of that class.
I've tried to use HRESULT hr = CoInitialize(NULL);
hr = CoCreateInstance(__uuidof(ETUDSink), NULL, CLSCTX_INPROC, __uuidof(IETUDSink), (LPVOID*)&pETUDSink);
if(pETUDSink)
{
pETUDSink->Start();
} however it always returns an error saying that the class is not registered. I can't use MFC to call the relevant .rgs file and am completely stuck on how to get this to work otherwise.
Is there a given format to doing this that I am unaware of and has anyone had experience in using the ETUDriver (or is able to get it working in C++ without use of MFC)?
Thank you for any help you can provide on this subject :)
I am not familiar with the specific DLL in question, but it sounds like you did not register the DLL on the target machine. You can do this by running regsvr32.exe or by calling the DLL's exported DllRegisterServer function or by using side-by-side assemblies. You need to do register the DLL on each machine that needs to leverage the COM functionality within it, so when you distribute your application, make sure that your installer registers the DLL if you go the regsvr32.exe route.
You can use the #import directive in Microsoft Visual C++ to load the information contained within the DLL without using a header file or rewriting it yourself based on documentation.
I'm new to the .NET platform (old-time ASPer) and for a project have a simple pair of .aspx scripts that take some querystring data and process it. They both make use of the same Subs, Functions in them, so naturally I'd like to move the code to a common resource.vb file. Having done some reading, it looks like my options are a Code-Behind type setup, and placing the Subs, Functions in a .vb file and placing that file in App_Code.
So, the Code-Behind model doesn't seem to make sense here, as the functions are shared by both files. Placing the Subs and Functions in /App_Code/resources.vb and I am getting the following error when trying to call any of the routines:
Statement is not valid in a namespace
Reading this answer, I thought the last solution would be fine, but not so. Any pointers? This whole solution is meant to be simple and portable, something someone can deploy into their domain by simply uploading the files, so portability is also important.
Thanks,
Paul
The basic building block of VB.NET is the class, or alternatively a module. You cannot just dump functions into a code file, you need to associate them with a class or module.
For an easy fix, just put them inside a module:
Module FooBar
' Your methods here
End Module
But that is code smell and you shouldn’t let it get out of hand. .NET is inherently object oriented so you should put some thought into developing a consistent architecture where each class has one responsibility and performs the according actions.
(See SOLID principles)
I have a pointer to a COM object that implements an undocumented interface. I would really, really like to be able to use said interface. All I have is the IID though. Master software analyst Geoff Chappell has documented a host of these undocumented COM interfaces on his site; see IListView for example. Somehow he even managed to get the function names and signatures. How is something like that even possible? Are they guesses?
Can someone point me in the right direction as to how I would go about something like this? I know the risks of using anything undocumented.
To elaborate, the object I'm interested in is ExplorerFrame.dll's notoriously undocumented ItemsView. By setting an API hook on CoCreateInstance, I can see that the object is created with a certain undocumented IID as its main interface. I'm assuming this is the interface that through which the control is manipulated, hence my interest in figuring out its members.
You know, you could write to me and ask! There was a time when I would write explicitly that the names and prototypes come from Microsoft's public symbol files, but I long ago abandoned that as verbiage. What sort of reverse engineer would I be if I was always explaining how I got my information! I'd be insulting those of my readers who are reverse engineers and I'd risk boring those who just want the information (which, let's face it, is typically not riveting).
If you don't have the public symbol files, then typelibs are the next best thing. But, of course, not all interfaces appear in the typelibs - not even all that implement IDispatch.
Given that you have an executable and its public symbol file, getting the IID and listing the methods is very nearly the simplest reverse engineering. It's maybe just a bit too complex for reliable automation - though I'd love to be proved wrong on that.
You likely know of the interface because you have a virtual function table for an implementation. Most likely, you found this because you're reverse engineering a class, in which case you find the virtual function tables for all its interfaces by working from the constructor or destructor. The virtual function table is an array of pointers to functions. The public symbol files give you the decorated names of these functions. A competent reverse engineer can undecorate these symbols by sight, mostly, and Visual C++ provides an UNDNAME tool (and your debugger or disassembler may anyway do the work for you). Finding the IID typically requires inspection of the QueryInterface method, matching against the known offset of the interface's virtual function table from the start of the class.
For a simple interface of, say, half a dozen methods, the whole exercise of writing up just a basic listing of IID, offsets and prototypes takes maybe 10 minutes on a good day, and no more than 30 if you're being lazy. Of course, with a lot of these undocumented interfaces, you may then want to check that the implementation and IID are the same in multiple versions - which can quickly turn a good day into a bad one.
By the way, if I guess something or hypothesise, I try to be sure of saying so. For instance, near the end of the documentation you cite of the otherwise undocumented IListView interface, I speak of a window message: you can know the name I give is made up by me because I say "perhaps named something like".
The definitive interpreter of PDB files is MSPDBxx.DLL. The primary tool for interpreting PDB files is the debugger, and by extension nowadays also the Microsoft Visual C++ linker in its guise as the DUMPBIN disassembler. These do not show everything from the PDB files, but they do all the basic stuff, such as listing all the symbols, labelling code and data, and summarising from whatever type information is in the file (which is typically none in public symbol files).
As usual, a competent - well, accomplished - reverse engineer can read these files by sight for information not shown by the standard tools. The most notable example is the section contribution information, which is as close as the public symbol files come to matching code to source files.
How you point the debuggers at symbol files is well documented. My practice for making a listing with DUMPBIN is just to copy both the binary and the corresponding PDB file to the current directory. As long as the filename of the PDB file matches the filename in the binary's debug directory, DUMPBIN works with the PDB file automatically. It really couldn't be easier.
I imagine that non-Microsoft disassemblers and decompilers are at least as capable of using whatever PDB file happens to be available for the target binary.
If your pointer impls IDispatch (which is quite likely) you can QueryInterface for that and then GetIDsOfNames. You likely end up guessing what interfaces it might use and calling QI just to see what works :)