Why would a process want to call DuplicateHandle from the Win32API, and get it from another process instead of just acquiring the handle on some object itself?
Is there some advantage to calling DuplicateHandle or something?
You may find the answer in Chapter 6.8 of 'Programming Applications for Microsoft Windows'.
Gaining a Sense of One's Own Identity
Sometimes you might need to acquire a real handle to a thread instead of a pseudo-handle. By "real," I mean a handle that unambiguously identifies a unique thread. Examine the following code:
DWORD WINAPI ParentThread(PVOID pvParam) {
HANDLE hThreadParent = GetCurrentThread();
CreateThread(NULL, 0, ChildThread, (PVOID) hThreadParent, 0, NULL);
// Function continues...
}
DWORD WINAPI ChildThread(PVOID pvParam) {
HANDLE hThreadParent = (HANDLE) pvParam;
FILETIME ftCreationTime, ftExitTime, ftKernelTime, ftUserTime;
GetThreadTimes(hThreadParent,
&ftCreationTime, &ftExitTime, &ftKernelTime, &ftUserTime);
// Function continues...
}
Can you see the problem with this code fragment? The idea is to have the parent thread pass to the child thread a thread handle that identifies the parent thread. However, the parent thread passes a pseudo-handle, not a real handle. When the child thread begins executing, it passes the pseudo-handle to the GetThreadTimes function, which causes the child thread to get its own CPU times, not the parent thread's CPU times. This happens because a thread pseudo-handle is a handle to the current thread— that is, a handle to whichever thread is making the function call.
To fix this code, we must turn the pseudo-handle into a real handle. The DuplicateHandle function (discussed in Chapter 3) can do this transformation
One possible use of DuplicateHandle is to duplicate a handle between a 32-bit process and a 64-bit process.
Note: cannot be used on I/O Completion ports or Sockets.
Another use of DuplicateHandle is to open a file in multiple processes when the file uses FileOptions.DeleteOnClose. (such a file cannot be opened by multiple processes if the file path is used to open the file)
See my answer at https://stackoverflow.com/a/36606283/2221472
See here on the MSDN what it has to say about the usage of 'DuplicateHandle'. The best way I can think of it is this way, an analogy if you like - suppose you open a file using the CreateHandle routine for writing only, then you call DuplicateHandle to pass the handle onto another thread in which the thread will read from the file, only the handle is duplicated hence the thread does not have to call CreateHandle again...
Related
I'm trying to use an OCR tool. This tool gets text from PDF and converts it to RTF.
Then I have to convert it to HTML, so I use:
outputText = MarkupConverter.RtfToHtmlConverter.ConvertRtfToHtml(
System.Text.Encoding.Default.GetString(response.fileData));
I put a break point in this line, cause after this row, I got an exception of:
The calling thread must be STA, because many UI components require this.
So I tried to put <STAThread()> above the function:
<STAThread()>
Public Shared Function GetFileTextByOCRTool(path As String) As String
But it doesn't work (I get the same exception)..
Doesn't it (<STAThread()>) define the function as STA?
Any help appreciated!
If you read the STAThreadAttribute documentation you will see the following remark:
Apply this attribute to the entry point method (the Main() method in C# and Visual Basic). It has no effect on other methods. To set the apartment state of threads you start in your code, use the Thread.SetApartmentState or Thread.TrySetApartmentState method before starting the thread.
So you have to mark you application entry point using the attribute (otherwise your main thread will enter the MTA), or if you are calling the component from another thread you need to call Thread.SetApartmentState to set the thread to STA before the thread is started.
Note that once a thread uses COM interop and enters an apartment it is not possible for the thread to leave the apartment and enter another one.
If you are using task or thread pool threads you will not be able to set the apartment state to STA.
I've been busy updating my brain with the TPL because I intend on using it for my new application (which uses .Net Framework 4.0). However I have some doubts that someone might clarify for me. Previously, I had a progress form which I would launch from the main (GUI) thread after I started the thread which needed to display its' progress. It looked something like this:
sortThread = New Thread(AddressOf _Sorter.Sort())
_ProgressForm = New FrmProgress()
_Sorter.ProgressForm = _ProgressForm
sortThread.Start()
progressForm.ShowDialog()
Basically it would initialize the thread, initialize a FrmProgress form object and assign it to the Sorter object which would then update the progress form (which contained a progress bar and some labels) from its Sort() sub on the separate thread. Updating these control properties was achieved by checking the InvokeRequired property of the FrmProgress form and if needed it would then use the Invoke() method of the control that was to be updated... ex:
Public Sub IncrementProgressBar(x As Integer)
If Me.InvokeRequired Then
pb_MainProgressBar.Invoke(Sub() IncrementProgressBar(x))
Else
pb_MainProgressBar.Increment(x)
End If
End Sub
Now I am interested in using TPL to launch separate worker threads (multiple) that may want to update the progress bar. Should I use the same pattern or should I consider accessing a public TaskScheduler.FromCurrentSynchronizationContext context that was obtained in the main GUI thread? In both cases I suppose I should provide some kind of locking mechanism on the form (SyncLock?)
Invoke should be sufficient, as you are doing. If two different threads try to invoke in parallel the first one will execute first, then the second when the UI thread becomes free. The UI thread cannot service two invokes simultaneously - they are naturally handled in FIFO sequence so there is no issue with thread safety. Any number of threads can invoke on the main thread without worrying about each other or using any additional locking mechanism.
Note, however, that any thread calling Invoke will block until the main thread can service the call. If you, for example, had many threads invoking heavy code at the same time then your various threads would block on the invoke calls until they got their kick at the can, so to speak. If you use BeginInvoke then the calling thread will simply continue executing and the invoked method will be placed in the UI thread's queue (which it will service as soon as it can).
How can i restrict my program to run only instance? Currently i'm running my program as daemon(starts and stops automatically), and when user clicks and tries to launch again(which is not a valid usecase), process gets launched in user context and i would like to avoid this for many reasons.
How can i achieve this?
As of now i'm getting list of processes and doing some checks and exiting at the begining itself but this method is not clean, though it solves my problem.
can someone give me a better solution?
And i'm using ps to get process list, is there any reliable API to get this done?
Use a named semaphore with count of 1. On startup, check if this semaphore is taken. If it is, quit. Otherwise, take it.
Proof of concept code: (put somewhere near application entry point)
#include <semaphore.h>
...
if (sem_open(<UUID string for my app>, O_CREAT, 600, 1) == SEM_FAILED) {
exit(0);
}
From the sem_open documentation,
The returned semaphore descriptor is available to the calling process until it is closed with sem_close(), or until the caller exits or execs.
Does anyone have any ideas of how a DLL function can be made to wait for “input”, and how to call a specific instance of a DLL export?
I’m trying to convert a Windows service to a DLL. It contains a function that logs some boot-up information and then waits until told to quit. The logging functionality is worked out, but I need to figure out two issues.
After it performs its main functions, the export needs to sit there and wait (like the classic Press any key to continue…, but minus the interface)
I need a way of having an executable subsequently tell the paused instance that it’s time to exit
For the first problem, I considered going into a loop and waiting on some sort of trigger, but of course it should not go into a 100%-CPU cycle, so maybe WaitForSingleObject or perhaps waiting for a message (eg WM_APP).
For the second, I thought of some kind of inter-process communication, but hopefully not something as messy as shared-memory or semaphores (I used shared-mem, semaphores, signals, etc. in Unix in uni, but this is on Windows). Of course I need a way of accessing the specific instance of the called export.
You can use CreateEvent, SetEvent, and WaitForSingleObject. If the dll was loaded by the executable that needs to signal the event that is all that is required. If it is from separate executables it is only slightly more complicated. When you call CreateEvent, create a named Event. This named event can be accessed by multiple processes. If it needs to work across different users logged in, prefix the name with "Global\" and it will be the same event for all processes for all users.
//in dll
HANDLE eventHandle = CreateEvent( NULL, TRUE, FALSE, "Global\\My-Unique-Trigger-Event" );
//do stuff
WaitForSingleObject( eventHandle, INFINITE);
//exit
//in executable
HANDLE eventHandle = CreateEvent( NULL, TRUE, FALSE, "Global\\My-Unique-Trigger-Event" );
SetEvent( eventHandle );
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