I have a .Net Console Application that emails documents using Redemption with Outlook. I attach the "Items.ItemAdd" event to the relevant folder. The event never fires.
But in my test harness which is a WPF application, using the same method and the same references etc, it does work.
Does the event actually work in a console app? Is there an example of the correct way, or of an alternate way?
Your app needs to run the Windows message loop for the events to work.
OK thanks for that hint. I tried various things and eventually it seems to work as below:
DispatcherOperation op = System.Windows.Threading.Dispatcher.CurrentDispatcher.BeginInvoke((Action)(() => { SomeMethod(someArgs); }));
DispatcherOperationStatus status = op.Status;
while (status != DispatcherOperationStatus.Completed && status != DispatcherOperationStatus.Aborted)
{
status = op.Wait(TimeSpan.FromMilliseconds(10000));
if (status == DispatcherOperationStatus.Completed || status == DispatcherOperationStatus.Aborted)
{
// do your final code
}
}
Related
I would like to use transaction in wolkenkit-eventstore when saving events to eventstore and be able to rollback those events if something else fail, is it possible ?
I saw in source code (in saveEvents method) that you are releasing connection pool:
try {
const result = await connection.query({ name: `save events ${committedEvents.length}`, text, values });
for (let i = 0; i < result.rows.length; i++) {
committedEvents[i].event.metadata.position = Number(result.rows[i].position);
}
} catch (ex) {
if (ex.code === '23505' && ex.detail.startsWith('Key ("aggregateId", revision)')) {
throw new Error('Aggregate id and revision already exist.');
}
throw ex;
} finally {
connection.release();
}
at the finally step, so i can't gain this connection pool in any way.
Is there any way i can do transaction based system with wolkenkit-eventstore ?
I'm one of the core developers of wolkenkit, so first of all thanks for bringing up this question 😊
Right now what you want is actually not possible, but nevertheless it could be a good idea to support this use case.
In wolkenkit the procedure is that the command handler publishes the events, and only if the command handler succeeds, the events are stored in the event store in an all-or-nothing approach.
To be able to understand your use case better – you said, you would like:
to rollback those events if something else fail[s]
What would this "something else" be?
Since this could be the start for a longer discussion, I think StackOverflow is probably not the perfect place to do this, so if you would like to talk to us about this feature, could you please open a feature request for this?
I have the following security rule set up in Firestore:
match /ads/{adId} {
allow read: if true;
allow write: if (request.auth.uid == request.resource.data.ownerId) ||
(request.auth != null &&
request.resource.data.size() == 1 &&
request.resource.data.keys().hasAll(['markedFavoriteBy']));
}
The owner of the document has all write permissions but other users can only write in one field - which is called 'markedFavoriteBy'. It seems to work in the Firestore simulator but not in Xcode (with iPhone simulator).
Important to note that the path does not go down to the document field - just to the document. I know that it is not possible to attach a security rule to a single field. However, with this workaround it should still work.
The iOS client code to update the field is the following:
let adRef = Firestore.firestore().collection("ads").document(ad.key!)
let value: FieldValue = ad.isFavorite ? FieldValue.arrayUnion([uid]) : FieldValue.arrayRemove([uid])
adRef.updateData([DatabaseKeys.markedFavoriteBy : value]) { (error) in
if let error = error {
print(error.localizedDescription)
}
}
The error printed to the console is of course: "Missing or insufficient permissions."
I can't find an error in the code - is this a bug that is somehow related to the very recent iOS Firestore SDK update? the functions arrayUnion and arrayRemove have been added only in that recent update.
Sanity check: I have changed the write rule to
allow write: if true;
Result: The array 'markedFavoriteBy' can be changed without any problem.
thanks for any hints in the right direction.
I'm not able to reproduce the entire scenario as I'm not sure of the actual contents of your database. However, what I suspect is the problem is that it doesn't grant permission because request.resource.data represents the new version of the entire document (which will be stored after the update is approved).
You probably want to use request.writeFields doc
Bear in mind that request.writeFields is not available in the simulator.
I'm working on a VTiger 6.4.0 Extension Module that is used to get company data when entering a company name in the Accounts module.
The module is almost finished, i retrieve data from a API and enter them in the input fields using JQuery.
But the problem is that i have some data that is not relative to the existing fields in the account information, so i'm trying to create some new custom fields.
Only i can't seem to figure out how to create a custom field for the Accounts module from within my Extension module.
I googled around and watched some posts on stackoverflow.
I came up with the following part of code, but this doesn't seem to work.
public function addKvkfield(){
$module = new Vtiger_Module();
$module->name = 'Accounts';
$module = $module->getInstance('Accounts');
$blockInstance = new Vtiger_Block();
$blockInstance->label = 'LBL_ACCOUNT_INFORMATION';
$blockInstance = $blockInstance->getInstance($blockInstance->label,$module);
$fieldInstance = new Vtiger_Field();
$fieldInstance->name = 'KvKNummer';
$fieldInstance->table = $module->basetable;
$fieldInstance->column = 'kvknummer';
$fieldInstance->columntype = 'VARCHAR(100)';
$fieldInstance->uitype = 2;
$fieldInstance->typeofdata = 'V~M';
$blockInstance->addField($fieldInstance);
}
The addKvkfield function is being called in the vtlib_handler module.postinstall (Couldn't find any information if this is the right way of doing this within a Extenstion Module)
vtlibhandler:
function vtlib_handler($modulename, $event_type) {
global $log;
if($event_type == 'module.postinstall') {
$this->addJSLinks();
$this->createConfigTable();
$this->addSettingsMenu();
$this->addKvkfield();
$this->updateLabels();
// TODO Handle post installation actions
} else if($event_type == 'module.disabled') {
// TODO Handle actions when this module is disabled.
} else if($event_type == 'module.enabled') {
// TODO Handle actions when this module is enabled.
} else if($event_type == 'module.preuninstall') {
// TODO Handle actions when this module is about to be deleted.
} else if($event_type == 'module.preupdate') {
// TODO Handle actions before this module is updated.
} else if($event_type == 'module.postupdate') {
$this->updateLabels();
// TODO Handle actions after this module is updated.
}
}
Hopefully someone can give me a push in the right direction.
Thanks in advance :)
I managed to succeed in creating the custom fields that i needed in the Accounts Module.
Thanks to the Vtiger Mailing List! :)
What did the trick was a small alteration of the code I've written:
public function addKvkfield(){
$module = Vtiger_Module::getInstance('Accounts');
$blockInstance = Vtiger_Block::getInstance('LBL_ACCOUNT_INFORMATION', $module);
$fieldInstance = new Vtiger_Field();
$fieldInstance->label = 'KvKNummer';
$fieldInstance->name = 'kvknummer';
$fieldInstance->column = $fieldInstance->name; // Good idea to keep name and columnname the same
$fieldInstance->columntype = 'VARCHAR(100)';
$fieldInstance->uitype = 1; // No need to use 2 anymore. Setting "M" below will introduce the Red asterisk
$fieldInstance->typeofdata = 'V~O';
$blockInstance->addField($fieldInstance);
}
The above code will create a (optional)Custom Field in the Account module.
If your writing a new module and never installed this module before you can just call the function in the vtlib_handler as i did in my question.
But in my case this did not work because I've already installed the plugin before adding the code to create the customfields.
So what i needed to do is call the function above on the vtlib_handler module.postupdate (this will add the custom field on a module update)
Only problem with this is that it'll get run every time the extenstion is updated.
So i suggest creating a if statement in the function to check if the field already exists in the vtiger_field dbtable if not run the script.
Hopefully i saved someone else some time by writing this all down :P
Goodluck!
Please refer below link
Add New Field in existing Module
Copy code from My Answer and create a new PHP file with ay name. Place that in CRM's root directory and Run into browser. Your Field will be added into your Module. You have to make sure about the parameters you set in code which you copy.
Probably looking for an answer to an age-old question, but I would like to block script execution. In my use-case blocking the browser is acceptable.
Also, in my use-case I am trying to do this from a Firefox extension, which means my code is "Chrome code", running in the browser environment.
This can easily be done by using a modal window, then programmatically closing the window. So this demonstrates that there is a blocking mechanism that exists.
Is there any way to achieve modal blocking without actually creating or opening the modal window? Some way to tap into the blocking mechanism used for modal windows?
I've done a lot of searching on this subject, but to no avail.
Using nsIProcess you can block the thread.
You can create an executable which has a sleep or usleep method or equivalent. Then run the process synchronously (nsIProcess.run) and set blocking argument to true.
Of course for portability you will need to create an executable appropriate for each platform you wish to support, and supply code for discrimination.
Basic code is something like the following. I have verified on 'nix (Mac OS X) this code to work, using a bash script with only the line sleep .03:
let testex = Components.classes["#mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsIFile);
testex.initWithPath("/Users/allasso/Desktop/pause.sh");
let process = Components.classes["#mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(testex);
let delay = 30; // convert this to milliseconds in the executable
process.run(true,[delay],1); // `run` method runs synchronously, first arg says to block thread
In an extension you probably would want to make your nsIFile file object more portable:
Components.utils.import("resource://gre/modules/FileUtils.jsm");
let testex = FileUtils.getFile("ProfD",["extension#moz.org","resources","pause.sh"]);
Of course keep in mind that Javascript is basically single-threaded, so unless you are blocking a thread spawned using Web Workers you will be freezing the entire UI during the sleep period (just like you would if you opened a modal window).
References:
https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIProcess
https://developer.mozilla.org/en-US/docs/Mozilla/Tech/XPCOM/Reference/Interface/nsIFile
https://developer.mozilla.org/en-US/Add-ons/Code_snippets/File_I_O#Getting_special_files
https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/basic_usage
OPTION 1
There is enterModalState and leaveModalState in nsIDOMWindowUtils here: MDN :: nsIDOMWindowUtils Reference
However they don't seem to work for me. This topic might explain why: nsIDOMWindowUtils.isInModalState() not working they topic says isInModalState is marked [noscript] which I see, but enterModalState and leaveModalState are not marked [noscript] I have no idea why it's not working.
What does work for me though is suppressEventHandling:
var utils = Services.wm.getMostRecentWindow('navigator:browser').
QueryInterface(Components.interfaces.nsIInterfaceRequestor).
getInterface(Components.interfaces.nsIDOMWindowUtils);
utils.suppressEventHandling(true); //set arg to false to unsupress
OPTION 2
You can open a tiny window with the source window as the window you want to make modal and as dialog but open it off screen. Its dialog so it wont show a new window the OS tab bars. However hitting alt+f4 will close that win, but you can attach event listeners (or maybe use the utils.suppressEventHandling so keyboard doesnt work in it) to avoid the closing till you want it closed. Here's the code:
var sDOMWin = Services.wm.getMostRecentWindow(null);
var sa = Cc["#mozilla.org/supports-array;1"].createInstance(Ci.nsISupportsArray);
var wuri = Cc["#mozilla.org/supports-string;1"].createInstance(Ci.nsISupportsString);
wuri.data = 'about:blank';
sa.AppendElement(wuri);
let features = "chrome,modal,width=1,height=1,left=-100";
if (PrivateBrowsingUtils.permanentPrivateBrowsing || PrivateBrowsingUtils.isWindowPrivate(sDOMWin)) {
features += ",private";
} else {
features += ",non-private";
}
var XULWindow = Services.ww.openWindow(sDOMWin, 'chrome://browser/content/browser.xul', null, features, sa);
/*
XULWindow.addEventListener('load', function() {
var DOMWindow = XULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
DOMWindow.gBrowser.selectedTab.linkedBrowser.webNavigation.stop(Ci.nsIWebNavigation.STOP_ALL);
DOMWindow.gBrowser.swapBrowsersAndCloseOther(DOMWindow.gBrowser.selectedTab, aTab);
//DOMWindow.gBrowser.selectedTab = newTab;
}, false);
*/
I have searched for quite a while, but I have not found any thread explaining how exactly to find out which Tenant is the current one in code. For example, I want to change some logic based off of what Tenant is active like so:
IQueryable<ContentPartRecord> getContentPartDates;
if (Tenat == ExampleTenant)
{
getContentPartDates = GetContentPartDates((int)Id)
.Where(ss => ss.SalesStatus == "Guaranteed")
.OrderBy(x => x.start_date);
}else {
getContentPartDates = GetContentPartDates((int) Id).OrderBy(x => x.start_date);
}
What exactly is the best way to do this?
Thanks in advance.
Inject ShellSettings in ctor. This object contains all data (from Settings.txt file) about the shell (ie. tenant) in which current unit of work executes.