I am new to working with Windows and I am trying to understand the APIs. Windows Runtime API provides the property CoreDispatcher.HasThreadAccess, but the description in the docs of what it is is very vague:
"Gets a value that specifies whether the event dispatcher provided by this instance of CoreWindow has access to the current thread or not."
What does it mean when it returns false? When and why would a user-engineer use this method?
It tells you whether the thread that your code is running on can safely update the UI. Compare it to Control.InvokeRequired in Winforms and Dispatcher.CheckAccess in WPF.
When it returns false, you must use Dispatcher.RunAsync() to make sure your code runs on the right thread.
Related
I want to change the ASPNETCORE_ENVIRONMENT value from code while initializing the application. This is done with
Environment.SetEnvironmentVariable("ASPNETCORE_ENVIRONMENT", [newValue]);
and happens very early on startup of the application, prior to any calls to Use[XY].
If I check the value with Environment.GetEnvironmentVariable("ASPNETCORE_ENVIRONMENT") throughout the lifetime of the application, it returns the desired value.
However, the Environment-Tag helper always uses the initial value which was set at the application's very startup (the old value).
While googling, I found a lot of posts on how to change the "ASPNETCORE_ENVIRONMENT" value from outside of the application, but none on how it is done from within the application.
The background of this question is, that we have the information about which stage the application runs, saved within the database and we want to use this information.
Update
It seems, that I have found the solution, will post it, if it is reliable.
Asp.net Core initializes at the application’s start the IWebHostEnvironment implementing instance and registers it as a singleton. This interface has a read/write property EnvironmentName, which is then used throughout the application’s lifetime as the “environment” value.
Hence the solution was:
var webHostEnvironment = [ServiceCollection].GetRequiredService<IWebHostEnvironment>();
webHostEnvironment.EnvironmentName=[my value];
Important is surely, that the assignment is as early as possible, so that in the Configure-method of the application, it is already set to its target value.
I tested some scenarios and up to now, I haven’t found any problems.
In our company, repository objects must be created with original language EN.
Is there a way to check the logon language in case of creating a new object in the ABAP repository?
Desired behaviour:
SE80 - Create program/class/data element/table/....
==> user exit/badi checks the logon language. When it is not 'EN', the creation will be refused.
regards,
Umar Abdullah
I know there is a exit for this but I haven't remember exact name. You can use general purpose for finding exit. Go to SE24 and open CL_EXITHANDLER class, find GET_INSTANCE method and add break point. Then start creating item, it will pause on debugger multiple times, try to find suitable one.
As #mkysoft suggested, you may implement a check in the BAdI CTS_REQUEST_CHECK, method CHECK_BEFORE_ADD_OBJECTS, which is invoked when the object is about to be attached to a transport request. Raise the exception CANCEL to make the attachment fail (and so the object is not created too).
EDIT: sorry, ignore my answer, "this method is NOT released for Customer usage" as said in note 2150125 - Method CHECK_BEFORE_ADD_OBJECTS not triggered
DISCLAIMER: THE METHOD DESCRIBED HERE IS ABSOLUTELY NOT RECOMMENDED.
As correctly pointed out by the other members there is no standard and customer-exposed method to achieve your requirement, but if you absolutely must enable this check during creation you can use the below method. As well as the previously offered to you, it also involves modification of SAP standard.
There is a system BAdi CTS_TADIR_SUBSCREEN that is located inside enhancement point CTS_ES_TADIR_POPUP. They are SAP internal and not released for customer usage, so do this at your own risk.
Implementation procedure:
Step 0. First thing you need to change is a SAP internal usage flag, for which you need Object Access key which can be obtained from SAP or from SAP partner that made the implementation in your org. In virgin state this BAdi throws the error if you try to implement it
So hereinafter we assume that you already ticked off this checkbox in BAdi settings
Step 1.
In order to implement the BAdi one need to implement enhancement spot prior to that. This is the most complicated part, because despite we disabled internality flag the SAP-namespaced enhancements must be stored only in SAP-namespaced objects. By SAP namespace I mean non-Z, non-Y and non-T (Test). This means to implement this enhancement, besides modifying the enhancement definition, one need to create, for example, CTS_ES_TADIR named enh.impl., and save it to non-Z package, which you also need to create. Your enhancement implementations selector should look somehow like this
On the above screen only the second will work, all the rest Z will not.
Every non-Z object need Object Access Key, remember? Too bad. But just to show the proof-of-concept, I will proceed.
Step 2. After you created the enh. implementation in SAP-namespace it will propose you to create the BAdi implementation. The same principle applies here: only SAP-namespaced container for SAP-namespaced objects, hence CTS_TADIR_SUBSCREEN should have implementing class for example CL_TADIR_SUBSCREEN. During the creation of enhancement you will see many warnings
but finally you should have something like this, where all system-named objects are created and the enhancement/BAdi is activated.
Step 3. In order to get the BAdi working we need to enable this subscreen processing
during the playing with enhancement I found out that BAdi class is not being triggered standalone, without screen events not enhanced, so to make it work you need to touch a screen enhancement for screen 100
If you do not wanna modify screen elements logic, just put the dummy enhancement in SHOW_TADIR dialog module in the end of the include LSTRDO18
PROCESS BEFORE OUTPUT.
MODULE SHOW_TADIR. "<-- create the dummy enhancement here
CALL SUBSCREEN subs_info INCLUDING gv_badi_prog gv_badi_dynnr.
for example declaration statement like I did
Step 4. Activate your created BAdi class and put the necessary logic there. I wasn't able to trigger method GET_DATA_FROM_SCREEN, but PUT_DATA_TO_SCREEN worked fine
If we put this simple processing for your requirement
METHOD cts_if_tadir_subscreen~get_data_from_screen.
IF object_data-l_mstlang <> 'E'.
MESSAGE 'Objects in non-English languages are not allowed!' TYPE 'A'.
ENDIF.
ENDMETHOD.
it will not allow creating objects in languages other than English.
The check in method get_data_from_screen is being done before showing the screen so language is determined from system logon settings. If to play more with this BAdi, I suppose the method GET_DATA_FROM_SCREEN can also be enabled, which will make it possible to check user input, i.e. the case when the user gonna change the default language.
Is there a way to find out how much of a GET request has been received? I can't do Len(.ResponseBody) until it's complete, so that's not possible.
I was researching how you could bind to IWinHttpRequestEvents. The OnResponseDataAvailable event is exactly what you need. It would give you the data as it came in. Then, you could handle it however you like.
Unfortunately, trying to bind to that event interface causes VBScript to crash with a C0000005 GPF. I also found a reference to it crashing in a different language. So, I can't say whether this would work in VBA or VB6 or any other language. Details are discussed in following question.
WScript.CreateObject crashes Windows Scripting Host when event handler prefix is specified for WinHTTPRequest
The alternative is to switch to Msxml2.XMLHTTP or Msxml2.ServerXMLHTTP. These objects come with a property named readyState that will give you some idea of what is happening to the download. It won't give you the current number of bytes downloaded, but it's something.
Additionally, there you can trap the onReadyStateChange event, which will let you know when the readyState on the object has changed. Microsoft has even provided sample code for trapping the event.
I am writing a filewatcher windows application which will look for changes in a specified folder and then logs the details in a txt file.
I followed exactly what is mentioned in this article below
http://www.codeproject.com/KB/dotnet/folderwatcher.aspx
When I hit F5 from my application and then create or modify a file in the folder that is being watched it throws the below mentioned error.
Please help
Cross-thread operation not valid: Control 'txtFolderActivity' accessed from a thread other than the thread it was created on.
You have to use the Invoke method on the form e.g. with an anonymous delegate to make your changes in reaction to the event.
The event handler is raised with another thread. This 2nd thread cannot access controls in your form. It has to "Invoke" them to let the thread do all control work that initially created them.
Instead of:
myForm.Control1.Text = "newText";
you have to write:
myForm.Invoke(new Action(
delegate()
{
myForm.Control1.Text = "newText";
}));
You are trying to update the UI from a non-UI thread. UI has a thread affinity and can only be updated from a thread that created it. If you're using WinForms, check out How to: make thread-safe calls to Windows Forms Controls MSDN article. Basically you will need to update the UI via Control.Invoke method. For WPF, you need to use DispatcherObject.
Basically you must have two threads in your application, at least, and the thread that your control logic is on is different, so you get this error, as the controls are not threadsafe.
This is to protect you from problems that could be caused by multiple threads changing the same control at the same time.
You can find considerably more detail by looking here:
http://msdn.microsoft.com/en-us/library/ms171728%28VS.80%29.aspx
I'm working on a small application using C++/wxWidgets, where several parts of the GUI need to be updated based on e.g. received UDP datagrams. More specifically, a secondary thread tries to keep a list of available "clients" in the network (which may come and go away) and e.g. corresponding comboboxes in the UI need to be updated to reflect the changes.
The documentation mentions that for this kind of thing EVT_UPDATE_UI would be a good choice. As far as I can understand from the sparse documentation, this event is sent automatically by the system and provides some support for assisted UI change.
However, I'd feel more comfortable using a more direct approach, i.e. where e.g. a window object could register/subscribe to receive notifications (either events or callbacks) upon particular events and another part of the code is sending out these notifications when required. I could do this in C++ using my own code, however I guess if wxWidgets already supports something like that, I should make use of it. However I haven't found anything in that regards.
So, the question is: does wxWidgets support this kind of notification system (or similar alternatives) or would I be best served coding my own?
AFAIK there is nothing directly usable in wxWidgets, but doing it on your own seems easy.
What I would do:
Create a wxEvtHandler-descendent class to hold the list of available "clients" in the network. Let this class have a wxCriticalSection, and use a wxCriticalSectionLocker for that in all methods that add or delete "clients".
Create a worker thread class by inheriting wxThread to handle your UDP datagrams, using blocking calls. The thread should directly call methods of the client list object whenever a client has to be added or removed. In these methods update the list of clients, and ::wxPostEvent() an event to itself (this will execute the whole notification calls in the main GUI thread).
Handle the event in the client list class, and notify all listeners that the list of clients has changed. The observer pattern seems to me a good fit. You could either call a method of all registered listeners directly, or send a wxCommandEvent to them.
Have you tried calling Update() on the widget(s) that change? Once you update the contents of the combo box, call Update(), and the contents should update.