Include sql scripts in a VB6 application - sql

I am maintaining an old VB6 application, and would like to include SQL scripts directly in part of the project. The VB6 application should then extract the text of this script and execute it on the server.
The reasons for this approach are various - among others, we want to deliver only an updated executable rather than a complete update/installation package. Hence, the SQL scripts need to be compiled into the application just like a resource file. And, obviously, one has to be able to get at the content from code, in order to send it to the database server.
Does anyone have a good way to do this?

The simplest solution is to just create a VB module with the scripts as strings.
If you want to use a resource file instead, you can do that too. You can associate a resfile with a VB project (I don't remember how to do this directly in the VB IDE but the VBP file supports a ResFile32 parameter).
EDIT: It seems like the issue here is mostly about formatting -- you don't want to store SQL queries as one long string, but formatting the query nicely inside VB is tedious because you have to add quotes, add string concatenation operators to join the lines together, etc.
I would recommend placing the SQL in a text file and formatting it in whatever way you like. Write a script that will take the text and convert it into a VB module. The build process would be modified to always apply this script first before compiling the application.
For scripting, use your favorite scripting language; if you don't have a favorite scripting language, this is an easy enough task that you could do it in VB, C#, or any other language. If it were me, I'd probably use awk (gawk) or Python.

If you want to use a resource (.RES) to store your SQL, go to the menu:
Add-ins > Add-in Manager...
and select VB 6 Resource Editor. Configure the add-in to be loaded and to load at startup.
From the editor add-in, VB provides a simple interface to add resource strings. You will refer to these using the provided constant values. To load the strings at runtime, use the LoadResString function:
Public Const SQL_INSERT As Integer = 101
Dim strSQL As String
strSQL = LoadResString(SQL_INSERT)
(replace "101" with the constant value of the string you wish to load)

Just another thought on your approach. Because I find myself tweaking the program's behavior or UI for customers I might be in the middle of a change that either is not ready or has not yet been tested and approved. So if I have properties that change from time to time, but I want to maintain control of, for instance connection settings to our ftp server, I will create a resource only dll exposing my properties and use a resource file in the dll to supply the values. When my network manager changes something on the ftp server I change the strings in the resource maanger, recompile the dll and release just the updated dll. I'm sure there are many more solutions, but that is how I do it. If you don't think you might have to change your SQL scripts at the same time you are changing you exe this probably only complicates your work. It has worked well enough for me that now this is pretty much standard for me.

Related

VB.NET Localization of strings

I've been successful in using form.location.resx files to localize the strings associated with form controls. However, I don't see how to (safely!) add strings to the .resx file(s) and then access them for such things as message boxes.
If I try to add a string to the .resx file using Visual Studio (2017), I get a warning dialog pop-up telling me that this could corrupt the "project item" (form) or my changes could be lost if I change the associated form.
Also, if I use this method, would I need to manually add my strings to each language file separately?
Alternatively, I could create a bunch of Labels to the form with visible=false and then edit their strings in the .resx files and use something like:
msgbox(LabelSampleMessage.text,MsgBoxStyle.Information,LabelSampleMessage2.text)
But that seems like it would be massively inefficient.
For Windows Forms, the best way to do this is to go into the Designer and set the Language property on the form. This will create a formName.Designer.languagecode.resx file for you. Then you just edit the Text properties of the controls. The changes will go to the resx file for the language you're editing. You can even have different layout and control spacing for each language (useful if a label is short in English but translates to something long in German).
For MessageBox messages, you do the same thing with the Resources.resx file. Just put all the messages in your Resources and duplicate the resx file for each language. Then use the Resource editor to translate the message in the other languages. You can then look up the message using My.Resources.Default.SomeMessageKey
#David: Note that I'm the author of a commercial ".resx" localization program for VS (in the interest of full disclosure). Yes, dwilliss is correct, though the names he used are a little off. For Windows forms, you can't manually update the ".resx" files yourself (directly), hence the warning from VS (don't know why they did things this way - go figure). You won't get that warning for strings you put in "Resources.resx" however. Just manually add "Resources.[LangCode].resx" and update it on your own. You have to add the keys yourself (again, no warnings). You can then simply access each string via the static properties seen in the "code-behind" file "Resources.Designer.cs" (one static property exists for each string you add). These are what MSFT calls "strongly typed" resources. If you access, say, "YourApp.Properties.Resources.SomeMessage" for instance (from "Resources.Designer.cs"), it will be returned in whatever language is currently set in "System.Threading.Thread.CurrentThread.CurrentUICulture" (assuming that language's satellite assembly is installed of course). This is all a pain and highly error-prone for other reasons as well, hence the reason I wrote my program (shameless plug but MSFT's way does work, though it's very primitive for handling translation in general - a professional organization relying on an external translator will save a lot of problems and $ in the long run by using a 3rd-party translation program, not mine necessarily though it would be my tool of choice of course, but anything is better than handling it manually).

Best way to internationalise VBA project

I develop quite complex Excel VBA application (several thousands lines of code spread across modules, class modules and form modules). There is a need to translate it to multiple languages, which means to replace (almost) all of the strings in application and use some kind of hash-table with records for each language.
My question is what is the most efficient and convenient way to gather all strings used in application and replace them with some kind of language variables. Could anybody recommend some kind of best practices for this type of task for VBA project environment? Thanks in advance.
One option is to use source tools addin to export all your code into source files under one folder. Example below:
Now you can write scripts to modify the files, and also now you can put them in source control. When done you can re-import them into the VBA project with changes.

Implement a self extracting archive?

I know i can use 7z or winrar but i want to learn this for myself.
How would i implement a self extracting archive? I can use C# or C++ but let me run down the problem.
When i open the exe i need some kind of GUI asking where to extract the files. Once the user says ok I should obviously extract them. I implemented a simple example in C# winforms already BUT my problem is HOW do i get the filenames and binary of the files into an exe?
One upon a time i ask Is it safe to add extra data to end of exe? and the answer suggested if i just add data to the end of the exe it may be picked up by a virus scanner. Now its pretty easy to write the length of the archive as the last 4bytes and just append the data to my generic exe and i do believe my process can read my own exe so this could work. But it feels hacky and i rather not have people accuse me of writing virus just because i am using this technique. Whats the proper way to implement this?
Note: I checked the self-extracting tag and many of the question is how to manipulate self extracting and not how to implement. Except this one which is asking something else Self-extracting self-checking executable
-edit- I made two self extracting with 7z and compared them. It looks like... well it IS the 7z.sfx file but with a regular 7z archive appended. So... there is nothing wrong with doing this? Is there a better way? I'm targeting windows and can use the C# compiler to help but i don't know how much extra work or how difficult it may be programmatically and maybe adding data to end of exe isnt bad?
It is possible. I used the following technique once, when we needed to distribute updates for the application, but the computers were configured so that the end user had no permissions to change application files. The update was supposed to log on to administrator account and update required files (so we came across identical problem: how to distribute many files as a single executable).
The solution were file resources in C#. All you need to do is:
Create a resource file in your C# project (file ending with .resx).
Add new resource of type "file". You can easily add existing files as byte[] resources.
In program you can simply extract resource as file:
System.IO.FileStream file = new System.IO.FileStream("C:\\PathToFile",
System.IO.FileMode.OpenOrCreate);
System.IO.BinaryWriter writer = new System.IO.BinaryWriter(file);
writer.Write(UpdateApplication.Data.DataValue, 0, UpdateApplication.Data.DataValue.Length);
(Here UpdateApplication.Data denotes binary resource).
Our solution lacked compression, but I believe this is easily achieved with libraries such as C#ZipLib.
I hope this solution is virus-scanner-safe, as this method creates complete, valid executable file.

VB.NET combobox persistence?

I'm fairly new to VB.NET, and I've mainly been doing ASP programming up 'til now, and I have a pretty simple question.
I'm creating a program that will copy a selected file to a selected directory, and I want to store recent files/dirs so that they can be selected from a combo box. I was planning to just create a settings with "files" and "dirs", and just store the strings as | separated values (since that's an illegal file character).
Is there anything wrong with this approach, or are there any better methods?
I think your approach is fine as it seems to be simply a local cache of recent directories. You can persist the data in the application at the module level(create a module with a public object essentially is a global variable) but it goes away when the application is terminated.
This article is using a similar approach to what you were thinking although the example is in C#

Architecture for easy update of application

I have a system in place which applies calculations to a set of numbers (the specifics aren't really relevant). There are a number of sets of calculations which can be applied by the system users and new sets are added frequently. Currently when a new set of calculations need to be added to the system they are added in to the code base and a new version of the system released. I'd like to be able to add new calculation sets into the system without having to release a whole new version and also to have these new calculations become visible to system users automatically. Currently a new function is created for each set of calculations and a record containing the appropriate function name is added to a system table. These records are visible to system users (function names are aliased of course!) who then select them from a list. The system uses the Eval() function to run the appropriate calculations.
This is a VB6/Access app that I inherited and am currently re-writing in VB.NET and SQL Server.
Does anyone have any advice on how best to do this?
Since you're redoing it in .Net, just put the calculations in plugins. Use reflection to load and examine these assemblies at runtime and present the user with functions.
Divil has a good (but fairly old now) article on writing plugin based applications. It will help you out: http://divil.co.uk/net/articles/plugins/plugins.asp (+ it's in VB.Net)
If you do it this way, all you have to do is drop a dll into the right directory and it just works.
If you are using a standard set of mathematical functions you can use use allow the user to write their own mathematical functions in a textbox.
Then use a grammar parser such as :TinyPG on CodeProject
With this you can then break down the expression into :Reverse Polish Notation
This can then be easily stored and recalled from the database in a varchar field.
Once this is setup you won't need to republish the application unless you need to add new mathematical functionality.