|
Is there any way in C# or other languages to detect the dependent DLLs of an existing non-DotNET DLL (regular DLL)? For i.e. if XXXX.DLL is using AA.DLL and BB.DLL, the last two DLLs are detected by the small piece of code after passing XXXX.DLL name.
Thank you.
Arash Sabet
Computer Engineer
E-mail: afifi@sympatico.ca
|
|
|
|
|
There is no reason to repost your problem.....
You will need to look at dependancy walker or something like that, or read the import table of the dll. Ask in C++ forum, and find out what to do, and the use pinvoke.
leppie::AllocCPArticle("Zee blog"); Seen on my Campus BBS: Linux is free...coz no-one wants to pay for it.
|
|
|
|
|
Thanks, I was about to reply the same way about the repost.
Since he originally didn't state which DLLs he meant, I replied with regard to dependent assemblies. But in either the case of IL or Win32 modules, this information is not in the import table. It is contained in the assembly manifest and requires that the manifest be read and parsed. If you run depends on most assemblies (barring some of the lower-level BCL assemblies like mscorlib), the only libary in the import table is mscoree, despite whatever externally or internally referenced modules are in the manifest.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
I'm trying to develop a system tray application that invokes CTRL-F6 at certain intervals to switch between windows within an application. For testing purposes, I've been trying to send CTRL-F6 to WinWord.exe as a means to iterate through open documents. Have been using FindWindow("OpusApp", null), PostMessage() and SendMessage() with various combinations of
const int WM_KEYDOWN = 0x0100;
const int WM_KEYUP = 0x0101;
const int WM_CHAR = 0x0102;
oonst int WM_SYSCOMMAND = 0x112;
const int SC_NEXTWINDOW = 0xF040;
const int VK_CTRL = 0x0011;
const int VK_F6 = 0x0075;
I've had no successs. Anyone's help with this would be greatly appreciated.
casey
|
|
|
|
|
You could always use SendKeys.Send (see docs for formatting) to send keyboard events to the open application. Just make sure that Word's active.
Are you getting a return value (IntPtr ) back from FindWindow ?
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thanks Heath...
I considered SendKeys.Send but wasn't sure how to get the active window. So I used the IntPtr from FindWindow as handle for SendMessage and PostMessage since they don't seem to require the window to be active. Maybe I need to reference a different ClassName/Window Handle, or missing the whole idea of this.
If SendKeys.Send is used, how do I determine active application windows before invoking CTRL-F6? Again, testing with multiple open, Word documents.
casey
|
|
|
|
|
If you can't be sure, it's best to use PostMessage (keyboard input is usually handled by message pump). Are you getting a return value for the IntPtr return from FindWindow ? If so, use Spy++ (should be installed with VS.NET if you installed the Platform SDK) to see if that matches the window handle of Word (use the Windows finder (like a crosshair)).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Heath Stewart wrote:
If you can't be sure, it's best to use PostMessage (keyboard input is usually handled by message pump).
I agree - why not send the messages directly to the window, rather than relying on it being active?
|
|
|
|
|
IntPtr doc1 = FindWindow("OpusApp", "Document1 - Microsoft Word");
IntPtr doc2 = FindWindow("OpusApp", "Document2 - Microsoft Word");
return correct window handles verified with Spy++. Spy++ message logging also shows the Post for the following but no document window action is initiated.
PostMessage(doc1, WM_KEYDOWN, VK_CONTROL, 0)
PostMessage(doc1, WM_KEYDOWN, VK_F6, 0)
PostMessage(doc1, WM_KEYUP, VK_CONTROL, 0)
PostMessage(doc1, WM_KEYUP, VK_F6, 0)
If I manually invoke CTRL-F6 to switch between documents, Spy++ doesn't show KEYDOWN/UP commands but does show WM_ACTIVATE, WM_ACTIVATEAPP among other window refresh commands. Changed my code to invoke the following in a loop and the document windows toggle as if using CTRL-F6. It works.
PostMessage(doc1, WM_ACTIVATE, 0x1, 0x056C)
PostMessage(doc2, WM_ACTIVATE, 0x1, 0x056C)
It seems manually depressing CTRL-F6 is handled by a process or other window handle, which send WM_ACTIVATE to the window handles I'm referencing. I'll continue to use WM_ACTIVATE unless something else is suggested.
casey
|
|
|
|
|
Glad you got it to work! The only thing that makes me curious is why the keyboard messages didn't work. When messages are passed via PostMessage , they go to the application pump. In that pump (loop), TranslateMessage is called on the message to translate virtual key codes. Word must have an app pump associated with some other handle, but I can't fathom how that's even possible or why.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Hi,
I am trying to make some c# in memory data to look like a file to windows.
The functionality i would like to implement is
- open the "file" with the registered application for this filetype (like winword for .doc files)
- capture modifications after saving the data from the application.
Is there a smarter way than writing the data into a tempfile ? And if a tempfile is the only solution - how is it possible to find out if the application has finished modifying the data ?
As you might guess, I am more familiar with Un*x variants, where a pipe would have been the solution.
many thanks in advance
|
|
|
|
|
What you're talking about is monikers and custom views, which is all part of shell programming and probably not worth it (dozens of interfaces are required in multiple objects as well as a lot of registry handling). For starters, you can look up IMoniker in the PSDK and the entire "User Interface / Shell Programming" section in the MSDN Library.
One other option is to look into file fragment programming. I haven't seen these used in a long time. An example would be dragging and dropping a block of text from a Word document to a folder. It creates a fragment (requires monikers). Double-clicking that fragment would open your app (if not already open, which again reqiures monikers) and load the referenced stream (or other STG). If you wanted to custom that scrap icon, you could add an icon handler which is another shell extension.
I can't really think of an easier way to do it than what would be possible in *nix. You're talking of block devices, right?
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Depending on what you want to do, you could use a memory mapped file (a solution also available on *nix).
All POSIX features like pipes are also available on Windows NT and later and you can use them easily. Pipes can be implemented using the Console class. You can even start another application (like the system() function call) and redirect its std input and output to streams (which can be, e.g., a memory stream).
The only *nix thing that's not so easy to emulate is fork().
HTH.
Trying to make bits uncopyable is like trying to make water not wet.
-- Bruce Schneier
By the way, dog_spawn isn't a nickname - it is my name with an underscore instead of a space. -- dog_spawn
|
|
|
|
|
Is there any way in C# or other languages to detect the dependents DLLs of an existing DLL? For i.e. if XXXX.DLL is using AA.DLL and BB.DLL, the last two DLLs are detected by the small piece of code after passing XXXX.DLL name.
Thank you.
Arash Sabet
Computer Engineer
E-mail: afifi@sympatico.ca
|
|
|
|
|
Yeah, reflection. Within the assembly you want to inspect, use this.GetType() (or typeof(SomeClass) to get a Type . You can get an Assembly reference from that, from which you can get dependent assemblies:
Type t = this.GetType();
AssemblyName[] names = t.Assembly.GetReferencedAssemblies();
foreach (AssemblyName name in names)
Console.WriteLine("Dependency: {0}", name.FullName);
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Actually I meant non-DotNET DLLs like the regular Windwos DLLs. Any idea?
Arash Sabet
Computer Engineer
E-mail: afifi@sympatico.ca
|
|
|
|
|
You should specify that next time. Assemblies also have the same extensions, even though they actually contain zero or more modules with the same extensions.
To do this requires much more work and is not provided by the .NET BCL. You actually have to read the assembly as a binary file and parse the IL (in binary format). This is far too lengthy to post here, but you should download .NET Reflector and take a look at the Reflector.Disassembler.ModuleReader.GetReferencedModules() method.
If you want to see with your own human eyes, open the assembly in ildasm.exe and look at the MANIFEST node (which is the actually assembly manifest). The externally referenced modules are listed at the top.
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
I'm aware that I can go myForm.TopMost = true to make a form be the topmost window in my app. However, setting this property to true also makes myForm the topmost window for all processes running; for example if I run a new instance of Internet Explorer, myForm will still be the top most window.
How do make a form be the topmost window ONLY for my app?
The graveyards are filled with indispensible men.
|
|
|
|
|
TopMost makes the dialog a system modal dialog. To make a application modal dialog, use Form.ShowDialog as opposed to Form.Show .
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thank you Heath for your reply. I am also aware of the .ShowDialog method, but unfortunately that's not the functionality I'm looking for; I want to be able to work in the other background windows while some other Form is the top-most.
An example of what I want:
Visual Studio's Find & Replace dialog box - it is top-most ONLY when Visual Studio is the active app, and it allows you to still work in the background window.
The graveyards are filled with indispensible men.
|
|
|
|
|
Judah H. wrote:
Visual Studio's Find & Replace dialog box - it is top-most ONLY when Visual Studio is the active app, and it allows you to still work in the background window.
o Make sure TopMost = false in your modeless form.
o Call SetTopLevel(true) in your modeless form's constructor.
o In the parent form, to display the new form:
frmAppTopMost frm = new frmAppTopMost();
this.AddOwnedForm(frm);
frm.Show();
I have this working in an MDI app -- haven't tried it in a dialog based app.
Roger Stewart
"I Owe, I Owe, it's off to work I go..."
|
|
|
|
|
Wonderful, works beautifully, Roger thank you.
The graveyards are filled with indispensible men.
|
|
|
|
|
Hi,
I need to pass a timespan value in a RowFilter expression of a DataView (in the format hh.mm.ss) but i don't know which is the correct sintax to do that ...
I tryed enclosing the value in # (like for date values) but it doesn't work
...
any idea??
thanks in advance
|
|
|
|
|
A TimeSpan itself is not valid in an expression. See the DataColumn.Expression documentation for details about valid expressions.
Depending on your needs, though, you could calculate a particular pair of dates then do a filter like:
myDataView.Filter = "PurchaseDate >= #1/1/2000# AND PurchaseDate < #1/1/2004#"; substituting the given dates with your variables (use string.Format or a StringBuilder rather than multiple concatenations which is very ineffecient).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
thanks for the answer...
however my problem is not for date value but Time values...
for example :
The db type of the information is TIME (ex. 12.23.45) and it is stored in DataSet as Timespan when i retrive it by Fill Method (DataAdapter) at the beginning...
My problem is to retrieve one or more record from DataTable filtering with an expression like this
myDataView.Filter = "TIME = 12.23.45"; (TimeSpan Value???)(like this dont work)
thanks
|
|
|
|