|
Cool solution. I like it.
A little more work than SetItemData used to be, but it is the best idea so far. Thanks.
Michael
Time flies like an arrow. Fruit flies like a banana
|
|
|
|
|
I am trying to use some functions and structs from Shell32.DLL in my C# project. I have VS create a RCW by adding the COM DLL to my project references. However, after doing this I can only see the Classes, Interfaces, and Delegates from the DLL; I can not see the functions or structs. (Or any of the other NON-CLASS related items)
I understand I can use DllImport to extern the functions I want, but I could not figure out how to use DllImport to extern the Structs I want.
I do not care which method I use to gain access to the features I want of this DLL. If anyone can point me in the right direction, or just flat out let me know how to do what I want.
Thanks in advance…
Aalst
|
|
|
|
|
Well you'll have to code the structures by hand, below is an example
using System;
using System.Runtime.InteropServices;
namespace OSInfo
{
class Class1
{
[ StructLayout( LayoutKind.Sequential )]
public class OSVersionInfo
{
public int dwOSVersionInfoSize;
public int dwMajorVersion;
public int dwMinorVersion;
public int dwBuildNumber;
public int dwPlatformId;
[ MarshalAs( UnmanagedType.ByValTStr,
SizeConst=128 )]
public String szCSDVersion;
}
Each unmanaged DWORD corresponds to a managed int. The embedded fixed-length string TCHAR szCSDVersion[128] must be marshaled by value. The MarshalAs attribute can set the type of string marshaling to use as well as the length of the string. The most appropriate unmanaged type for this case is ByValTStr, which was designed specifically to be used for in-line fixed length character arrays that appear within a structure.
Note the StructLayout Attribute and the MarshalAs Attributes. You'll need to refer to MSDN to find out which UnmanagedType you need to Marshal you Data Members as.
Hope this helps.
May the Source be with you
Sonork ID 100.9997 sijinjoseph
|
|
|
|
|
This answer is great and fine. It deserves a good article on CodeProject, since I believe many people are going to get caught by this marshalling frenzy.
Btw, the MSDN doc completely sucks about this topic. It is barely a reference for internal MS people,
And I swallow a small raisin.
|
|
|
|
|
Agreed.
I think I have an easy solultion.
When defining structs , use the Platform Invoke Types table, but DWORD dont have to be uint like WORD dont have to be ushort, all u need to make sure is the width (bit size) corresponds to c++ unmanaged width.
EG: DWORD is 32bits wide, so u can use uint or int, whatever suites your needs. Int seems to be the prefered for DWORD and short seems for WORD. This seems logical as unsigned intergers will just require alot of extra casting.
However, I am not so sure about return values from functions e.g BOOL , which is 32bits wide, but i'm not really sure about the width of a Managed Boolean.
Hope this helps.
PS: Anyone who has some good experience with this might wanna write a comprehensive article for us C# only dummies .
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
What users would really love to see IMHO is a table with a mapping between C types (BOOL, HWND, DWORD, LPSTR, BSTR, SAFEARRAY, ...) and the corresponding managed type,
And I swallow a small raisin.
|
|
|
|
|
StephaneRodriguez wrote:
What users would really love to see IMHO is a table with a mapping between C types (BOOL, HWND, DWORD, LPSTR, BSTR, SAFEARRAY, ...) and the corresponding managed type,
That is exactly what the Platform Invoke Data Types table provides, but again like alot of MSDN, not clearly
For those that cant find the table: ms-help://MS.VSCC/MS.MSDNVS/cpguide/html/cpconplatforminvokedatatypes.htm
Sorry I dont have a weblink
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
|
I have a new idea
Now that we have the table of all simple types, and rules for structures, interfaces, enum, ... a great new little thingie would be a Marshall replace tool that takes for instance the WIN32 API method call as input in an edit box, and returns the equivalent call in managed code. Doing this, people will stop losing their valuable time wondering how to do it.
I guess that's time to explore VS.Net addins...
And I swallow a small raisin.
|
|
|
|
|
I was thinking of starting a project on converting all of the SDK headers into enums and structs and DllImported functions by running them thru a parser, but it just seems to be alot of work for one person...but if I can find a couple ppl to help, then we can do it !
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
In fact, the tools for conversion are already there. For instance, TLBIMP converts an IDL interface to a marshalled managed interface. All we need to do, when facing a WIN32 method call to be translated, is wrap it inside a fake IDL file, and launch TLBIMP.
The beauty of it is that I believe TLBIMP can be run seamlessly inside a C# app.
Once done, just launch ILDASM, it shows the marshalled managed interface.
Well, may be not everyone will agree that's simple enough ,
And I swallow a small raisin.
|
|
|
|
|
But this seems to be only for COM and not for unmanaged functions. Ideally what I want is a tool to convert any header file into static structures accessable via C#.
EG: nice.dll comes with nice.h and is NOT a COM dll, then all I need to do is run header file thru tool and TADA there is all the functions from library. It will still be up to you to implement your own managed structure implementation.
BTW TLBIMP gets autoinvoked when referencing a COM dll in a project, so it is transparent to the user .
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
IDL is 90% a wrapper on top of unmanaged functions, that's why only a few types MAY not be translated. But you're right in the end, a nice automatic tool with no IDL sh*t at all is just as well. I am thinking about it,
And I swallow a small raisin.
|
|
|
|
|
Check GotDotNet's user submissions for one called APIViewer, it translates the API file that shipped with VB6 into C# DLL import stuff. Unfortunately it lacks a lot of stuff that came out since VB6; but its a start.
James
"And we are all men; apart from the females." - Colin Davies
|
|
|
|
|
James T. Johnson wrote:
Check GotDotNet's user submissions for one called APIViewer
Thanx James , searching for it returns 0 resluts
UPDATE: the search page seems broken, it remembers the previous query
UPDATE 2: still no links to it, will search and post link if i find it.
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
APIViewer.zip (93.1 Kb)
Its in VB and it appears to be from one of the beta's but it shouldn't take too much work to get it working again.
James
"And we are all men; apart from the females." - Colin Davies
|
|
|
|
|
Compiles fine, but doesnt seem to load the header file in the viewer, i will look at it though. Also there seems to be various versions (all the same really) of this file. Dont you just hate it when people rip off code like that?
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
leppie wrote:
but doesnt seem to load the header file in the viewer
I should have said that it doesn't parse header files, but it loads a specially formatted text file to get the definitions.
You can find this file at Microsoft Visual Studio .NET\Common7\Tools\Bin\Win32API.Txt
James
"And we are all men; apart from the females." - Colin Davies
|
|
|
|
|
O dear my reply musta been washed away
Thx James that works beautifully with Win32API.txt. I will have a look at modifying it for headers, or start a new one based on the code.
MYrc : A .NET IRC client with C# Plugin Capabilities. See
http://sourceforge.net/projects/myrc for more info.
|
|
|
|
|
I get the following compile error:
The type or namespace name 'DllImport' could not be found (are you missing a using directive or an assembly reference?)
on this:
[DllImport "user32.dll",EntryPoint="SendMessage",ExactSpelling=false,SetLastError=true)]
private static extern int SendMessage(int hwnd,int wMsg,int wParam,int lParam);
What am I missing? Should I be "using" something?
|
|
|
|
|
System.Runtime.InteropServices
|
|
|
|
|
I am about to start work on an app that will use DirectShow to capture video from a number of web cams and ASP.NET to generate a page for viewing them. There's more to it than that, but that's the core of it. I know there are some samples here on CP, but I wonder if anyone can advise me - would I be better off using DirectShow from MC++ or from C# ? My main worry is how the actual stream gets moved around, getting the video feed data from MC++ to C#.
Christian
We're just observing the seasonal migration from VB to VC. Most of these birds will be killed by predators or will die of hunger. Only the best will survive - Tomasz Sowinski 29-07-2002 ( on the number of newbie posters in the VC forum )
Cats, and most other animals apart from mad cows can write fully functional vb code. - Simon Walton - 6-Aug-2002
|
|
|
|
|
Christian Graus wrote:
would I be better off using DirectShow from MC++ or from C#
MC++, definitely. Otherwise you go through COM interop, blech, yuck, ugly, evil, etc., etc.
Of course, you could wait for DirectX 9 (this November, I think), so you could use fun DirectX from beautiful C#!
-Domenic Denicola- [CPUA 0x1337]
MadHamster Creations
"I was born human. But this was an accident of fate - a condition merely of time and place. I believe it's something we have the power to change..."
|
|
|
|
|
Consider this C# code:
///////
public class Worker
{
public ManualResetEvent MyEvent;
private Thread t;
private string message = "nothing now";
//Constructor
public Worker(string name)
{
t = new Thread(new ThreadStart(this.Work));
t.Name = "Worker: " + name;
t.Start();
//I don't like the following line:
while(t.ThreadState == ThreadState.Unstarted){}
}
//Property
public string Message
{
get{return message;}
set{message = value;}
}
//Thread function
public void Work()
{
MyEvent = new ManualResetEvent(false);
for(;;)//Loop forever
{
MyEvent.Reset();
MyEvent.WaitOne(); //Wait until "MyEvent" is Set
Console.Write("Message:" + message + ".\r\n");
}
}
//terminate the thread
public void kill()
{
t.Abort();
}
}
//////
Worker w = new Worker("Thread 1");
w.Message="Something";
w.MyEvent.Set();
....
w.Message="Something else";
w.MyEvent.Set();
...
w.kill();
----------------------------------------------------------------
Q1: Is encapsulating the thread in the class like this bad practice?
Q2: Assuming that there is nothing wrong with encapsulating the thread, is there anyway I can terminate it in a destructor? I would like to see this thread die when the instance of the class goes out of scope. I think explicitly calling the kill method is lame. (Or do I just have to get used to the way things are destroyed in C#?)
Q3: What is the “approved” method of waiting for a thread to start?
i.e. is there anything better than this:
while(t.ThreadState == ThreadState.Unstarted){}
-----
Any other comments would be appreciated.
Thanks,
-Kevin
|
|
|
|
|
ke5in wrote:
Q1: Is encapsulating the thread in the class like this bad practice?
No. It looks reasonable enough.
ke5in wrote:
Assuming that there is nothing wrong with encapsulating the thread, is there anyway I can terminate it in a destructor? I would like to see this thread die when the instance of the class goes out of scope. I think explicitly calling the kill method is lame. (Or do I just have to get used to the way things are destroyed in C#?)
Since GC is non-deterministic in .NET you could never be sure when the destructor of your class is run. If you don't mind the thread hanging around for some time after the class goes out of scope you could put the kill() call in the destructor. Although i wouldn't advise it.
May the Source be with you
Sonork ID 100.9997 sijinjoseph
|
|
|
|