How can I protect a process I start from within my vb.net program? - vb.net

I've created a small application that basically reads and writes to a single Excel.exe process. It's basically a timer that records the time I use on projects and then store it in an Excel sheet. This works great, however, I've noticed that if I open Excel manually, work on some sheets and whatnot, save and exit etcetc, the process my software use gets broken or something. The same thing that happens if I manually close the excel.exe process and my software doesn't "know".
So I was wondering if it's possible to protect the excel.exe process somehow? To make sure it can't be closed or tampered with in the meantime?

Let me suggest an alternative approach that does not require you to have an Excel process running all the time (after all, this also consumes a lot of system resources):
Let your application record your information. Every now and then -- for example, after a work entry has been finished or a specific time has elapsed -- open the Excel sheet, write the data, and close it again (also closing the Excel process that you are automating). This save operation should not take more than a few seconds and it will (mostly) prevent the problem you are experiencing.
In fact, since Office automation is always a bit painful, an even better way would be to output your data without requiring an Excel process. To do this, you could use
one of the third-party Excel libraries available for .net,
a CSV or HTML file, which can be opened by Excel, or
open the Excel file as a database with ADO.NET.

You cannot protect a process, but you can check the process.HasExited property to find out whether the process has terminated and take action based on that.

Add an exception handler. Either call non-throw methods if possible.

Related

Dealing with SAS Sessions while running a Stored Process

Currently I am trying to run a SAS program using VBA. Using the SAS Add-In For Microsoft Office, I created a stored process that contains a generic code that creates a dummy table. Inside SAS EG, I am able to run the Stored Process normally, and also inside the Excel environment, using the InsertStoredProcess function of the SASExcelAddIn object. Regardless of the environment used to run my Stored Process, the behavior of the SAS Sessions are the same: one session is created when I start to run and another one is created during the process. However, that is where my problem comes. When the process finishes, I continue with the two sessions as active, and every time I try to run again my Stored Process, one new session is created over the ones that already existed. The sessions close only when I manually disconnect from the SAS Server I'm connected or when I close the Excel. Since my organization allows only three concurrent sessions, this is becoming a big problem for me.
I already tried to use the ABORT macro function inside my code, the rc=stpsrv_session('delete') command and delete the Stored Process from the Excel worksheet, and none of them solved my problem.
Any ideas of what I'm missing here? Is there a way to end the SAS Session after the Stored Process ends?
First of all, you shouldn't use VBA to do any of this. If in Office products, use VSTO and C#. I am in the throes of converting thousands of lines of VBA to C#/VSTO. VBA is very obsolete which is why the code is being converted.
Second, EG is built using C# so it is more natural to use. You can even create custom tasks using C# in EG.
You need to close out your sessions after they are started. See this post at SAS for how to close out your sessions in VBA: https://communities.sas.com/t5/SAS-Enterprise-Guide/Calling-SAS-through-VBA/td-p/79673
Again, you should stop using VBA and switch over. It will be much easier. VSTO is free and is made to interact with Office. Use Visual Studio to create your project. The C# code for working with SAS can be found using any of Chris Hemendinger's post (SAS community manager) or you can refer to links on my github repos here: https://github.com/savian-net

Can you schedule periodic data imports in VBA?

I have a VBA function that, when invoked via a button on a sheet, extracts a .csv file from a website and imports it into my workbook. The problem is the file is uploaded in different time intervals during the day, so I have to periodically check the website.
Is there a way in VBA that I can schedule when a function is invoked?
You can use the Application.OnTime() method which will allow you to schedule a Macro for a specific time amongst other settings. However you're probably best using VB Script or similar.
It's also important to note that the workbook would need to be open the entire time if you are going to use VBA, whereas a VBS file will run silently and can be triggered to run at startup.
If you're proficient enough with VBA then you shouldn't have a problem writing VBS.

How to close/stop a .NET application and re-execute it?

My application updates(running a vba script) an excel shared workbook, and since it is shared, there shouldn't be problems when someone else is using the same file at the same time. But for some reason, sometimes it simply freezes, without any error message, just freezes.
Is there a way to programatically make the application stops/closes automatically when frozen or after some minutes(In normal conditions, this updating process shouldn't take more than 1 minute)?
And, if possible, re-launch the app again automatically after some minutes for at least 5 attempts?
This way would ensure process completes succesfully.
I have had to do this same thing before but because I had an application that would look for updates to it's self on the network and then update it locally. Problem is, you cannot update the exe that is running.
What I did to get around it is to create another program that would wait a second, update the exe, then run the exe again.
Because I did this with a few different apps, I made my "Updater" generic so I could send some command line parameters and it would use those to copy and run.
If you want to try something else, you might be able to accomplish this same thing by creating a BAT file and running it. I'm not real good on BAT files so I can't help you there. But, it is another way to handle it.

VbaProject.OTM deployment

I came by this page and was thinking about the best method to distribute my VbaProject.OTM file (located into %appdata%\Microsoft\Outlook\) to a bunch of ~30 users at my office. Is it better to simply copy/paste the OTM file onto the network and then copy/paste it back to all users' computers (manually or with a .bat) OR would it be better to use the method described in the link above to generate a OPS file and import it back with Proflwiz.exe? What's the difference?
We are all on Microsoft Office Outlook 2003 actually, we might upgrade to 2007 one day but still years from now.
Finally came up with some elements to deploy a Outlook VBA Project. There are a lot of ways to do this, but the easiest way to do so without installing anything and keeping the same methodology would be to run a OTM file directly from a server. I found out that the process outlook.exe has a parameter altvba that allows to specify another path to run the OTM file from. Here is en example:
outlook.exe /altvba "\\myServer\myFolder\myFile.otm"
This allows me to update only one file to get all computers updated. Obviously, if the file is big and the server's ping is on the high side, it may delay the launch of Outlook. The other problem with this method is that everybody will have to shut down Office if you want to update the OTM file on the server (and if you do work in an office where everyone uses Outlook, you do know that it is impossible to get everyone to shut it down at the same time, except if you code a macro to do so eventually). To prevent both those problems, I could setup a batch file to copy the server OTM file clientside everytime there is a new version (just have to check the NTFS last-modify attribute). This way, Outlook will boot with a local file, the batch file take 2-3 seconds to copy the file if needed (or will launch Outlook instantaneously) and there will be no problem updating the OTM file on the server. Users will have to start Outlook with the batch file (or with the slightly different outlook.exe path with the altvba parameter, so either way they need a different shortcut/file to start off the first time). One other advantage of the altvba is that it's still easy for the user to run Outlook without it (to see if the VBA is problematic or not in case Outlook is sluggish) and the file will remain unchanged after a Outlook reinitialization.
Others solutions include a COM complement that can be developed in a lot on languages including VB6 (no conversion needed from VBA). There is also a bunch of tools included into Microsoft Office XP Developer that could help getting the job done (not free however, especially if you need the most up-to-date version).

VBA maintaining the program in memory

Sorry I don't know if this is something simple, or even where the problem fits in the greater scheme of programming.
So in my unsophisticated ways, my programs have always been of the scheme: 1. start program, 2. wait while program runs, 3. program is done and gone.
What I am doing now is creating a table from a long list of transactions (10,000s of). The table has several combo boxes for the user to select filters. Right now, every time the user changes a filter, the entire log is re-processed, which takes half a minute or a minute.
What I would rather do is have the trade log held in memory, or somehow latently but more immediately available. But not have the program "spinning" in the background. So the user could go about using Excel unaware that the program is ready in the background in case they want to update the table later, or not.
Does that make sense? If it can't be done in VBA, I'd still be curious how it would be done in another environment, say C#, if it could be. Thanks.
If the frequency of updates to the options trade is low enough you could separate reading and processing the option trades from the filtering process:
Step 1 - Refresh - read the logs and process them, storing the results in global containers (arrays, collections, dictionaries, objects ...)
Step 2 - User requests - show form - user chooses filters - show/store results extracted from the global containers.
There are several options
Firstly, is the code correctly structured? For example, do you really need to re-process everything or can a re-write be more efficient?
If you cannot avoid resource intensive code, notify the user with a progress bar or message. Also consider the use of DoEvents which frees up the operating system so that Excel can process other events.
DoEvents is slow and dirty. Even better look at this link DoEvents is slow!!! Here are faster methods
Rewrite your code to work asynchronously. Create a class, a handler and deal with each transaction asynchronously.
You could write some VBScript/Javascript and push the task out to run independently of Excel/VBA. Eg there's an example Here
Don't use VBA :)
Edit: How are you filtering? If you're iterating through thousands of items in an array testing for criteria it can be very slow. Excel's Advanced Filter is very quick and could process hundreds of thousands of rows with multiple criteria quickly.
When a macro in Excel VBA runs, the user cannot use Excel anymore, running the VBA "stucks" the whole program.
Here are a few tips to find a workaround for your problem :
Keep the vba running : load the data a first time when launching the combobox and then display results to the user every time he asks for but keep a combobox loaded so that vba keeps its context and memory
Load the data in Excel Worksheet, even hidden and then use it when the user asks for some data
Give us more info on what you are doing, from where you are loading the data, how you can cache it, what is your current code, what you tried... so that we can help you more
Regards,
Max