Two-way communication between VSTO add-in and a Task Pane app (JS/HTML) - vsto

Is it possible to have a VSTO add-in and a JS/HTML based Task Pane app talk to each other when running inside desktop Office application?
The goal would be to bridge capabilities not yet present (or never will be present) in the x-platform Office APIs using VSTO.

As Evgene mentioned, there is no out-of-the-box functionality for this (though the topic has certainly come up in internal discussions, so I would be very curious to hear your scenario, and particularly how you would handle the VSTO-only-on-the-desktop case).
If you wanted to try this now, you probably still could with a bit of a creative solution. Imagine you have a hidden sheet with a named range on it, which you use as a communication buffer between VSTO and your taskpane app.
For VSTO => JS communication: have the taskpane create a binding over the named range, then use the binding-data-changed event to listen to an incoming message from your VSTO add-in.
For JS => VSTO communication: have the JS set data to the binding (which, as above, was created over the named range). On the VSTO side, listen to data changed event, intersect the incoming range with the named range's range, and if the intersection is not null, fetch the text to get the incoming message.
If you do end up trying out this approach, do keep the thread posted on how it went -- I'd be quite curious to hear.
~ Michael Zlatkovsky (developer on Office Extensibility team)

Need to admit that VSTO based add-ins can be run only on Windows and desktop clients. Other platforms can't be supported with such scenario.
Anyway, VSTO nor Mail Apps (based on Office JavaScript API) don't provide anything for that out of the box.

Related

Should I use SetupApi or CfgMgr32 in 2022?

I have a lot of experience with libusb, libudev, and SetupAPI for writing Windows drivers, but it's totally unclear to me what CfgMgr32 offers over SetupAPI for Windows USB applications. Microsoft outlines how one would port from SetupAPI to CfgMgr32, but, I don't really understand the trade-offs or if there are gotchas.
Specifically, most of the time my work involves communicating to bespoke devices with isochronous endpoints, devices with bulk endpoints and HID devices. Is there any clear reason to do one or the other?
One reason is stated at the top of the Microsoft page describing how to port from SetupApi to CfgMgr32 found here https://learn.microsoft.com/en-us/windows-hardware/drivers/install/porting-from-setupapi-to-cfgmgr32.
Excerpt with pertinent part in bold:
This topic provides code examples that show how to port code that uses Setupapi.dll functionality to use Cfgmgr32.dll instead. Porting your code allows you to run your code on the Universal Windows Platform (UWP), which does not support SetupApi. A subset of CfgMgr32 is supported on UWP, specifically functionality exposed through the api-ms-win-devices-config-l1-1-0.dll API set (Windows 8 and later) or the api-ms-win-devices-config-l1-1-1.dll API set (Windows 8.1 and later). In Windows 10 and later, simply link to onecore.lib.
Another reason is that the CfgMgr API provides a specific return status code for operations whereas SetupApi returns a value to indicate success/error but a further call is required to GetLastError to get the specific error code of the last operation.

How to improve the performance of an VSTO Outlook addin at startup / prevent Outlook from disabling AddIns

As described in How to programmatically set registry setting to prevent Outlook from removing the VSTO Addin Outlook disables automatically AddIns which show poor performance on startup.
Microsoft describes basic rules for Addins which the developer should comply with: https://learn.microsoft.com/de-de/office/vba/outlook/concepts/getting-started/support-for-keeping-add-ins-enabled
Although what I don't understand is which code is executed when the startup gets loaded (during startup of Outlook)
The following 3 things get executed during startup of the Addin:
1.) All initialization of global variables
2.) The c'tor of the AddIn class (ThisAddIn)
3.) The method ThisAddIn_Startup
Is this correct?
Furthermore, I use
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
to initialize logging. Is this an expensive method regarding startup performance?
How can I find out which part (procedure calls) of this startup process takes most of the time? How do I use the profiler on an Addin? Do I guess I have to trace the Outlook.exe, correct? How can I extract the profiling info just for my AddIn?
I chose to explore this topic even deeper and removed the complete code in ThisAddIn_Startup, switched to Release (instead of Debug) in Visual Studio:
Guess what? The Add-in is still too slow! There are no c'tors, no initialization of any framework whatsoever, so we talk about a complete blank Add-in ... and still, Outlook fires up the message: This add-in is too slow!! Furthermore, I saw that you have to start OUtlook (without VisualStudio) several times so that OUtlook calculates a meantime for the startup of the add-in. But still, my complete clean Add-in takes 0,61sec to load which is too slow for Outlook. I have no idea what makes an empty Add-in take 0,61sec to start. I run OUtlook on an i7-CPU intel laptop (16 GB) so there see no reason for this.
It might not be you - keep in mind that that you get penalized for using .Net run-time; there is nothing you can do about that except switch to an unamanged language, such as VC++ or Delphi. I has success before with creating a stub COM addin in Delphi (load time about 20 ms) which loads a VSTO addin asynchronously (when Outlook is not looking) using IManageAddin interface.
Also keep in mind that VSTO run-time will validate the certificate used to sign your addin unless it resides in a secure location that requires admin rights to install to, such as a subfolder of the Program Files folder.
Is this correct?
You are absolutely right. You need to move any long-running or time-consuming tasks to another thread. Or just wait until everything is initialized by running a timer. In the timer's event, you can do any initialization stuff. Be aware that .NET includes four classes named Timer, each of which offers different functionality:
System.Timers.Timer: fires an event at regular intervals. The class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Threading.Timer: executes a single callback method on a thread pool thread at regular intervals. The callback method is defined when the timer is instantiated and cannot be changed. Like the System.Timers.Timer class, this class is intended for use as a server-based or service component in a multithreaded environment; it has no user interface and is not visible at runtime.
System.Windows.Forms.Timer (.NET Framework only): a Windows Forms component that fires an event at regular intervals. The component has no user interface and is designed for use in a single-threaded environment.
System.Web.UI.Timer (.NET Framework only): an ASP.NET component that performs asynchronous or synchronous web page postbacks at a regular interval.
Please remember that the Outlook object model should be accessed from the main thread only. Based on this knownledge you must choose the timer class.
Another approach is to handle Outlook's events, for example, the Startup event is fired when Microsoft Outlook is starting, but after all add-in programs have been loaded. So, you can finish your initialization there.

Visual basic.net Send strings between computers on LAN

I'm attempting to make a program to control the basic functions of a computer through a server/client method. I just need to send a string from the server to the client and vice versa. Every example I've found is really old and no longer works, or is poorly explained, or is in C#.
I almost have a working example as is, but I'm running into a threading issue where it won't let me modify elements in the UI after I've opened my thread for the connection from server to client or client to server. No idea how to fix this and I'm out of options.
Essentially I need a method of sending text from one IP/port to another in a server/client architecture.
The clue to solving your issue is probably here: "I almost have a working example as is, but I'm running into a threading issue where it won't let me modify elements in the UI after I've opened my thread for the connection from server to client or client to server."
You cannot access controls (UI elements) created on one thread directly from another thread. So if you have another thread and you want to update an element in the UI, you need to use the Control.BeginInvoke Method.
You didn't post any code, so I won't try and give you an example that may be utterly useless in your case, but there's a good article on MSDN here - How to: Make Thread-Safe Calls to Windows Forms Controls. This is for Windows Forms, nut the principals are the same for any application.

Sending keys silently

I'm trying to pass messages between a vba application (in powerpoint- during a slideshow) and a .net application I wrote.
The only method I could think of, is sending keystrokes.
However, this method causes the powerpoint to lose focus.
can you suggest a solution ?
If all happens on the same machine, the easiest way maybe is to let the PPT write its status into the registry from where the other application reads it out (GetSetting(), SaveSetting()).
If PTT and the other process run on different machines, you could think of writing out the status into a small text file which can be read out asynchronously.
Another way of (synchronous) communication between two processes/applications on different machines is to use sockets and send information across the network.
I found an interesting way of communication between vba and .net, without file system manipulation, sockets or external objects.
First, We register powerpoint evets, as such:
http://www.vbaexpress.com/kb/getarticle.php?kb_id=327
Second, We update the clipboard in VBA on the presentation-start event:
http://word.mvps.org/faqs/macrosvba/ManipulateClipboard.htm
Third, We use a clipboard a listener on .net:
How do I monitor clipboard content changes in C#?
Last, We restore the original clipboard value on presentation-end event

Unattended application best practice question

We have an unattended app w/o a user interface that is is periodically run.
It is a VB.NET app. Instead of it being developed as a service, or a formless Windows application, it was developed with a form and all the code was placed in the form_load logic, with an "END" statement as the last line of code to terminate the program.
Other than producing a program that uses unneeded Windows form resources, is there a compelling reason to send this code back for rework to be changed to put the start up logic in a MAIN sub of a BAS file?
If the program is to enter and exit the mix (as opposed to running continuously) is there any point in making it a service?
If the app is developed with a Form do I have to worry about a dialog box being presented that no one will respond to even if there are no MessageBox commands in the app?
I recall there used to be something in VB6 where you could check an app as running unattended, presumably to avoid dialogs.
I don't know whether there are conditions where this will not run.
However, if the code was delivered by someone you will work with going forward, I would look at this as an opportunity to help them understand best practices (which this is not), and to help them understand that you expect best-practice code to be delivered.
First of all, you don't need it to be run in a Form.
Forms are there for Presentation, so it should not be done there.
If you don't want to mess with converting the application a Service (not difficult, but not very easy neither), you shoud create a Console Application, and then, schedule it with Windows Task Scheduler.
This way, you create a Console Application, with a Main function, that does exactly what you need.
Anyway, the programmer could show windows, so there should not be any messagebox. Any communication should be done via Logging to: local files, windows events, database.
If you want more information on any of them, ask me.
If you don't want it to be a service, nothing says that it has to be a windows service. Scheduling it to run via the Task Scheduler or something similar is a valid option.
However, it does sound like the developer should have choose a "Console App" project, instead of a "Windows Forms" project to create this app.
Send it back. The application is bulkier and slower than it needs to be, although that won't be much of an issue. It is somewhat more likely to run out of resources. But the main reason: converting it to a console app is very easy.
If you don't prefer for the Console window to popup, simply do the following.
Create a new class "Program.vb", add a public shared Main() method, and move the "OnLoad" logic from the form to this method.
Next delete the form, and change the project start up object (Available in the project properties window) to use the Program.Main instead of the Form.
This will have the same effect, without the windows forms resources being used. You can then remove the references to System.Windows.Form and System.Drawing.