Enterprise Library: How to add data to Task Category in Windows Event Log entry? - enterprise-library

When using Microsoft Enterprise Library 5.0, how do we have the Logging Block enter data into the Task Category field of the event Log entry without specifically creating an event log entry in code?
My Enterprise Library categories show up just fine but that is not what we filter the Windows Event Log with so a Task Category entry would be nice.
But also I want to use the generic logging calls in code and not specifically instantiate a Windows Log entry i.e. I want to keep:
// Create a LogWriter object.
LogWriter writer = EnterpriseLibraryContainer.Current.GetInstance<LogWriter>();
// Use the LogWriter object.
writer.Write("My message", "kicks");
But somehow also have the Task Category field completed.

Related

Handle a COM event in PowerShell

I am controlling an application via its COM server from PowerShell. This is pretty simple:
# Start the application via COM
$app = New-Object -ComObject CoolApp.Application
# Start a data measurement in the application
$measurement = $app.Measurement
$measurement.Start()
Now comes the hard part: the Measurement object has an event called "OnFinished", that is invoked when the data measurement is done. I would like my powershell script to wait for the occurence of this event.
How can I subscribe to such an COM event PowerShell?
If a Primary Interop Assemblies(PIA) is provided from the developer to the COM object you are using, you can easily register event handlers by using it.
For example, refer to this description.
Registering and Catching Communicator 2007 Automation API Events
Like the above components and Office, PIA is provided for many of Microsoft's products.
Office primary interop assemblies
If there is no PIA, you can request it from the developer or you can create it yourself.
The way to make it is explained on this page.
How to: Generate Primary Interop Assemblies Using Tlbimp.exe
Is OnFinished a property of the app or measure object? If it is, and it returns a value when queried you could use a while loop to wait for that returned value to be a specific value e.g. if that property returns 'Completed' once the process has finished:
while($measure.OnFinished -ne 'Completed')
{
Sleep 5
}
Difficult to be more specific with my answer as I am not familiar with your COM object :)

VSTO Load On Demand

I have a Word 2016 VSTO that I developed using VS2015 and deployed to a Windows 10 machine using InstallShield. If I set the LoadBehavior to 3 it loads and works fine.
What I need is for it load on demand. I've tried just setting LoadBehavior to 9 but no dice. The web application that is creating the Word document (that ultimately loads the VSTO) was originally written for Word 2010 and is embedding the VSTO path in the Word document with an added GUID (C:\myAddIn.vsto|GUID|vstolocal). Opening the document created by the web application in Word 2016 throws this error when the VSTO tries to load:
Microsoft.VisualStudio.Tools.Applications.Runtime.CannotCreateStartupObjectException:
Could not create an instance of startup object myAddin.ThisAddIn
Any tutorials I've seen for VS2013/2015 do not reference embedding a GUID in the VSTO path; just set the LoadBehavior to 9.
There is no Publisher listed in File -> Options ->AddIns. The VSTO is listed under Inactive AddIns which I would expect until it is loaded on demand.
Any help is greatly appreciated.
If you want code to only execute with certain documents, such as you describe (from Comments)
I only want the AddIn to load for Word documents created by the web
application. Opening Word from the Start menu should not load the
AddIn.
then it is probably better to use a document-level customization, rather than an add-in.
The code attached to a document-level customization will load with the document, and unload when the document is closed. It's possible to create a document-level customization and distribute the document, or to attach the code at a later time using VSTO's ServerDocument class.
Since in your case the documents are being generated by a web app, using ServerDocument is indicated.
Here's the main content of the MSDN article:
=============================================
To attach managed code extensions to a document
In a project that does not require Microsoft Office, such as a console application or Windows Forms project, add a reference to the
Microsoft.VisualStudio.Tools.Applications.ServerDocument.dll and
Microsoft.VisualStudio.Tools.Applications.Runtime.dll assemblies.
Add the following Imports or using statements to the top of your code file.
using Microsoft.VisualStudio.Tools.Applications;
using Microsoft.VisualStudio.Tools.Applications.Runtime;
Call the static AddCustomization method.
The following code example uses the AddCustomization overload. This overload takes the full path of the document and a Uri that specifies the location of the deployment manifest for the customization you want to attach to the document. This example assumes that a Word document named WordDocument1.docx is on the desktop, and that the deployment manifest is located in a folder that is named Publish that is also on the desktop.
string documentPath = System.Environment.GetFolderPath(
Environment.SpecialFolder.Desktop) + #"\WordDocument1.docx";
int runtimeVersion = 0;
try
{
runtimeVersion = ServerDocument.GetCustomizationVersion(documentPath);
// Make sure that this document does not yet have any Visual Studio Tools
// for Office customizations.
if (runtimeVersion == 0)
{
string deployManifestPath = System.Environment.GetFolderPath(
Environment.SpecialFolder.Desktop) + #"\Publish\WordDocument1.vsto";
Uri deploymentManifestUri = new Uri(deployManifestPath);
ServerDocument.AddCustomization(documentPath, deploymentManifestUri);
System.Windows.Forms.MessageBox.Show("The document was successfully customized.");
}
else
{
System.Windows.Forms.MessageBox.Show("The document is already customized.");
}
}
catch (FileNotFoundException)
{
System.Windows.Forms.MessageBox.Show("The specified document does not exist.");
}
catch (DocumentNotCustomizedException ex)
{
System.Windows.Forms.MessageBox.Show("The document could not be customized.\n" +
ex.Message);
}
Build the project and run the application on the computer where you want to attach the customization. The computer must have the Visual Studio 2010 Tools for Office Runtime installed.
Did you try to set LoadBehaviour to 0x10 => Load first time, then load on demand? This should make Office load your addin the first time you execute it and internally cache it. It will then change the value to 0x9... The subsequent times, the app will load on demand.

Distinguish page load and Export to Excel in CRM 2015

I'm writing a plugin which will be triggered when user press "Export to Excel" button. I'm currently hooking it up to "RetrieveMultiple" message. However, the same message is also triggered when the page is loaded. Is there anyway that I can distinguish between a page load message and a "Export to Excel" message?
Following Polshgiant's advice, I have installed CRM Snoop and found 3 differences between page load and export to excel.
At page load, context depth is 1, while at export to excel, context depth is 2.
At page load, ParentContext is null, while at export to excel, ParentContext is not null and contains the following parameters: "View", "FetchXml", "LayoutXml", "QueryApi", "QueryParameters".
When export to excel, the message of ParentContext is clearly labeled as "ExportToExcel".
Using those differences, I've been able to trigger my plugin at and only at export to excel event.
Unfortunately, there isn't a special message in the SDK for exporting to Excel that you could register your plugin against. I can think of two options:
Override the Export to Excel button in the application ribbon to call a custom JavaScript function. Your function would do whatever you want to do and then optionally pass the request on to the normal Export to Excel function.
Find some way to distinguish the RetrieveMultiple message (as you are attempting to do).
Download CRM Snoop, install it in your org, register it against RetrieveMultiple for your entity, turn it on (basic usage), and then trigger an export to excel. It will make it really easy to see the RetrieveMultiple request and inspect all of its properties. Poke around to see if anything jumps out at you that would allow you to distinguish it as an export to excel. I don't suspect you'll find anything, but it's definitely worth a shot.
Side note, I'm a smidge surprised CRM doesn't bypass the plugin execution pipeline for exporting to excel as it does for reports and charts.
You can use ExportToExcel and ExportDynamicToExcel "virtual" messages in your plugin registered for RetrieveMultiple:
public void Execute(IServiceProvider serviceProvider)
{
var executionContext = serviceProvider.GetService<IPluginExecutionContext>();
var parentContext = executionContext.ParentContext;
if (parentContext != null &&
(parentContext.MessageName == "ExportToExcel" ||
parentContext.MessageName == "ExportDynamicToExcel"))
{
// Place your logic here
}
}

Get NodeRef of a workflow task Alfresco

I create a workflow, and when I go to the task-edit page:
I'm trying to obtain the nodeRef of the file (latexexemplo-2.pdf) of the workflow task:
http://localhost:8080/share/page/task-edit?taskId=activiti$20649
I'm trying to make this way:
var taskId = args.taskId
var task = workflow.getTaskById(taskId);
nodeRef = task.getPackageResources()[0].nodeRef;
But I obtain "args is not defined" ... "workflow is not defined" ... "task is not defined".
How can I get the nodeRef with another way?
Unfortunately, you cannot access in the browser information that is in the repository.
A quick and dirty solution is to use directly the information that is already in the page.
I have started a workflow and opened the task page as you did.
Using the browser debug tool, I have inspected the html.
As you can see in the image attached below, Alfresco stores the documents attached to the task in an hidden input. You could use YAHOO to get it.
Search for an element with the id "page_x002e_data-form_x002e_task-edit_x0023_default_assoc_packageItems".
If there is more than one document associated, the value will be a comma separated list of noderefs. I am getting the first element. This of course works, as is, only if there is one and only one document associated. You should probably take into account also the case when no document is associated or there is more than one.
var nodeRef = YAHOO.util.Selector.query("#page_x002e_data-form_x002e_task-edit_x0023_default_assoc_packageItems")[0].value;
You can get all the current task details which are assigned to you by using
Workflow API in Freemarker.
So you can get the task id or noderef of tasks.

VSTO Word add-in - new document event not firing if Word is launched from the executable

In my add-in, I need to create a task pane for each open document. In the add-in's startup method, I subscribe to the ApplicationEvents4_Event.NewDocument and Application.DocumentOpen events, and then create a task pane for each opened document:
((ApplicationEvents4_Event)Application).NewDocument += CreateTaskPaneWrapper;
Application.DocumentOpen += CreateTaskPaneWrapper;
foreach (Document document in Application.Documents)
{
CreateTaskPaneWrapper(document);
}
This covers cases for opening or creating a document through Word's menu, or opening an existing document file in the OS. However, if Word is already opened, launching WINWORD.EXE (or accessing it through a shortcut, which is a pretty common scenario) doesn't trigger either event, despite a new window with a new document being opened. How can I react to this scenario and create a task pane for a document created this way? I'm using VSTO 3 and Visual Studio 2008, targeting Word 2007.
If Word is started, a new document is created BEFORE the Add-In loads, therefore this event can not be trapped.
If you need to work with the initially created document, just take a look at the Documents collection - if Count is greater zero, this document is the one created by Word before your Add-In was loaded.
So I solved this problem in my solution, although I'm not sure it will be cross applicable. Sadly, mine is in VB.Net, so there may need to be some translation.
First, I ended up not using ApplicationEvents4_Event Instead there are other built in event triggers you can use via "ThisAddIn"
Private Sub Application_NewDocument(ByVal Doc As Word.Document) Handles Application.NewDocument
'MsgBox("I opened something")
myCustomTaskPane = Me.CustomTaskPanes.Add(New MyCustomTaskPaneClass, "TaskPane", Doc.ActiveWindow)
myCustomTaskPane.Visible = True
End Sub
Using this method I did have a similar challenge. Running winword.exe, and thereby opening a new word document, did not trigger the NewDocument event. Luckily, there was another event to use - Document change.
Private Sub Application_DocumentChange() Handles Application.DocumentChange
'function to test if the ActiveDocument has a taskpane from my add-in, and then a function to add one
If Not HasMyCustomTaskPane() then AddCustomTaskPane()
End Sub
So - bottom line, regardless of if you keep using ApplicationEvents4_Event you should see if you can use the DocumentChange event. It triggers when a new word window is selected.
Handling task panes for more than one window in Word is fairly complicated, because of how Word loads and re-uses open windows. To do it correctly, you have to consider different actions:
The user takes an action to display or hide a task pane.
The user creates a new document.
The user opens an existing document.
The user closes an open document.
There's a tutorial that explores all the details, both in VB and C#: https://msdn.microsoft.com/en-us/library/bb264456%28v=office.12%29.aspx
I also found a similar answer on SO.