|
No, the compiler does not check these things (as you've found). Just make sure that the functions are exported from the DLL you're referencing.
As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa.
If you want to see what exports are available, I recommend using depends.exe (the Dependency Walker) from the Platform SDK (installed by default with VS.NET).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath Stewart wrote:
As far as work flow, I really don't see why anyone would just "blindly" P/Invoke a function if they didn't know it was exported. Seems like a backward way of thinking. Typically, you P/Invoke a function because it's there, not vice versa.
Agreed, I don't know about you, but I have never written a program perfectly with out any mistakes before I just wanted to avoid the case five months from now where I am trying to track down a bug and it turns out I was just passing the wrong data type in (Cause it seems like it doesn't do data type checking either) so guess that was my concern.
We basiclly have DLLs that we want to tie into because C# has such and easy way to design interfaces and that stuff. We have a lot of DLL's so it will be done on a fairly large scale.
|
|
|
|
|
But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse.
Data-type checking isn't supported because you're marshaling to an unmanaged platform. C/C++ doesn't perform any type checking, either, except for what the compiler can perform at compile-time. In an unmanaged world, arguments and return values are only pointers on the stack (most usually). There would be no way to determine this using a managed compiler.
The best way to avoid errors is to truly understand the unmanaged and managed types, like that an unmanaged int is platform-dependent, i.e. 32 bits on a 32-bit processor and 64 bits on a 64-bit processor,thus you should use an IntPtr . A LONG is always 32 bits, hence is a managed Int32 (C#'s int primitive). A char* is a managed string (no ref or out ) and should use CharSet.Ansi , where an LPTSTR is also a string but should use CharSet.Auto , etc. etc.
One thing to note is that currently in the .NET FCL Microsoft uses int where it should be an IntPtr because .NET 1.x does not support the 64-bit platform (it will in 2.0). I suspect they will either change to using IntPtr internally or maintain two different builds specifying an int for 32-bit platforms and a long for 64-bit platforms. I honestly don't know, but making your code use an IntPtr now will ensure that when it is compiled for the 2.0 framework and run on a 32- or 64-bit platform that it will work correctly.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath Stewart wrote:
But again, why would you P/Invoke a method before seeing if it either exists? That's like putting the cart before the horse.
So is there a way to do this in code? I am not the programmer writing the DLL's so while I'll try to keep my eye out the chances that something with the function (Data types etc) might change without me knowing right away.
|
|
|
|
|
This is what internal processes are for. Some version control systems alert you of changes, such as the upcoming Microsoft Team System. If something changes, the compiler won't know - it's P/Invoking an unmanaged API so there is no type metadata, plain and simple.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am using the calendar control available with the webforms. Is there a way to get a week count (ie) I would like to have the count from 1-52.. I will display the corresponding week no in a label next to each week. Is there a way to calculate it, or is there a function that can be used.
Tarakeshwar
CCIE Q(Routing and Switching), MCSE Security
|
|
|
|
|
You can use the System.Globalization.Calendar class. The best way is to get the Calendar for the current CultureInfo :
CultureInfo ci = Thread.CurrentCulture;
Calendar cal = ci.Calendar;
int week = cal.GetWeekOfYear(dt, CalendarWeekRule.FirstDay,
DayOfWeek.Sunday);
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm having a little problem with receiving messages from a thread of mine.
let's say i have this thread method :
private void DoSomething()
{
for (i=0;i<10000;i++)
{
sleep(100);
}
}
How could i send this message back to the calling thread ? Don't misunderstand me : i know all about postmessage, I just don't want to use it. There must be something in the framework to achieve the same goal in a .net fashion.
Thanks for any ideas.
Sacha
|
|
|
|
|
The thread can call a delegate:
<br />
public delegate void Message(string parameter); <br />
public event Message SendMessage; <br />
...<br />
this.Message += new Message( thread_SendMessage );<br />
<br />
private void thread_SendMessage( string parameter ){<br />
Console.WriteLine(parameter);<br />
}<br />
<br />
...<br />
<br />
private void DoSomething(){<br />
for (i=0;i<10000;i++) {<br />
if(Message != null){ SendMessage("hello"); }<br />
sleep(100);<br />
}<br />
}<br />
|
|
|
|
|
Thanks for your answer Corinna,
But i'm afraid this doesn't quite answer my question. using this delegate, the call will be synchronous (at least i think so). Besides, it will be executed on the DoSomething thread instead of being executed on the "calling thread". So, if i have several DoSomething threads active, i would need to lock the content of your thread_SendMessage method, which is precisely what i want to avoid.
Thanks though.
Sacha
|
|
|
|
|
That where Control.Invoke comes in, if you're calling this on a Control (or anything that implements ISynchroniseInvoke ). This invokes the delegate in the thread in which the Control was created. Read more about it in the .NET Framework SDK.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
So, if i understand well, the target object for my call needs to implement the ISynchronizeInvoke interface (I'm not working with controls), then my thread method would look like this :
private void DoSomething()
{
for (i=0;i<10000;i++)
{
EventTargetObject.BeginInvoke(new MyEventDelegate(EventTargetObject.OnEvent), null)
sleep(100);
}
}
public EventTargetClass
{
private void OnEvent()
{
//do stuff on EventTargetObject without taking care of locking
}
}
does this sound right ?
Looks like we're approaching the solution! Thanks for your answer
|
|
|
|
|
i found an example on how to implement ISynchronizeInvoke.
http://www.componentware.net/idesign/DesktopDefault.aspx?tabindex=5&tabid=8
That's the only example i could find using google.
Thanks for pointing this interface out.
Sacha
|
|
|
|
|
Given something like the two classes below, I would like to be able to catch (in SimpleClassList) whenever the Position property is set from the SimpleClassList indexer, i.e. myList[3].Position = 1.0.
My first thought was to try something like below in SimpleClassList, (which obviously doesn't work):
public double this[int index].Position {
set {
list[index].Position = value;
Stuff_I_Need_To_Do_If_Position_Is_Changed();
} // set
} // [].Position
How can I do this?
--------------------
public class SimpleClass : IComparable {
double position;
public double Position {
... get and set
} // Position
... more stuff here
} // class SimpleClass
public class SimpleClassList {
private ArrayList list;
public SimpleClass this[int index] {
get {
return (SimpleClass) list[index];
} // get
set {
list[index] = value;
} // set
} // indexer
... more stuff here
} // class SimpleClassList
|
|
|
|
|
The easiest way is to define an event on SimpleClassList and fire that in the set indexer:
public class SimpleClassList
{
private ArrayList list;
public event ItemChangedEventHandler ItemChanged;
protected virtual void OnItemChanged(ItemChangedEventArgs e)
{
if (ItemChanged != null)
ItemChanged(this, e);
}
public SimpleClass this[int index]
{
get { return list[index] as SimpleClass; }
set
{
list[index] = value;
OnItemChanged(new ItemChangedEventArgs(index));
}
}
}
public class ItemChangedEventArgs : EventArgs
{
public ItemChangedEventArgs(int index)
{
this.index = index;
}
private int index;
public int Index
{
get { return index; }
}
}
public delegate void ItemChangedEventHandler(object sender,
ItemChangedEventArgs e); Then just have some class handle the SimpleClassList.ItemChanged event:
simpleClassList1.ItemChanged +=
new ItemChangedEventHandler(OnItemChanged);
private void OnItemChanged(object source, ItemChangedEventArgs e)
{
SimpleClassList list = source as SimpleClassList;
if (list != null)
{
Console.WriteLine(list[e.Index].Position);
}
} There is already an ItemChangedEventHandler and ItemChangedEventArgs defined in System.Windows.Forms , but the constructor is internal (private to other assemblies) so you can't really use it, which is why I define a similar one here.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hello i'm a developer of a C# game design Project on Sourceforge and i'm looking for anyone wishing to help create a revolutionary opensource Game engine
RealmForge GDK is a cross-platform game development framework and toolkit written in Mono/C# and powered by the Axiom 3D engine. It will allow for the rapid development of cutting-edge software with advanced graphics, audio, and networking capabilities.
but for this to happen we need good programmers to help us create this project
if your interested contact dan@xeonxstudios.com
for more information visit the forums at:
http://www.xeonxstudios.com/
http://sourceforge.net/projects/realmforge
|
|
|
|
|
Dragging a file from explorer to my application is fairly easy, but I have a problem figuring out how to drag a file from my app to explorer, so explorer copy the file, from the filename i give it, and to the place where i drop the file...
Any hints?
- Anders
Money talks, but all mine ever says is "Goodbye!"
ShotKeeper, my Photo Album / Organizer Application
[^]
My Photos[^]
|
|
|
|
|
Use the DataFormats.FileDrop with a filename or array of filenames:
DataObject do = new DataObject(DataFormats.FileDrop, filename);
this.DoDragDrop(do, DragDropEffects.Copy); This file has to exist. If you want to stream the file to Explorer, there is a lot of work involved because you must implement IStream or IStorage , define the STGMEDIUM and FORMATETC structs, and P/Invoke the DoDragDrop API from the Structure Storage APIs.
I have had a long, drawn-out (overly drawn-out) conversation about this in this forum with someone not familiar with structure storage, which is a must to understand this properly. If you want to find that threat, I'd say search the comments for either of the structs I mentioned above, since those don't get mentioned much. That should help you find those threads.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks,
It was this line:
DataObject do = new DataObject(DataFormats.FileDrop, filename);
I needed
I dont need to stream the files to explorer, only to tell explorer to copy the files.
BTW, when working with stuff like structure storage and the like, it's easier when comming from a C(++) background so I'm not afraid of that, I just don't need it
- Anders
Money talks, but all mine ever says is "Goodbye!"
ShotKeeper, my Photo Album / Organizer Application
[^]
My Photos[^]
|
|
|
|
|
Hi,
I'm trying to find a way of associating a form with a window.
ie. when a user opens a particular window or document, an associated
form will popup displaying detail in regard to this document/window.
At the moment, I'm looking at the processes running on a machine to
determine the currently opened apps/windows and running through a
collection of objects to determine if any of these objects are related
to the app or window (from file name)
ie.
I check the processes periodically using a timer
foreach (Process process in Process.GetProcesses()) {
if (onlyApplications) {
if (process.MainWindowHandle != IntPtr.Zero)
get the associated file
feed this into a collection
blah blah blah
if the list changes through a timer tick, refresh the collection.
It seems that this is only way I can determine and keep a relatively accurate list of the currently running processes.
My question is basically, is there an event that fires when a new process
starts up or the content of the currently running processes change.
or
Is there a better way of doing this?
Thanks very much
|
|
|
|
|
No. You pretty much hit the nail on the head...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
When serializing a class, i'm getting the following invalid xml header
<?xml version=\"1.0\" encoding=\"utf-8\"?>
the contents is formated perfectly, however the header and namespaces become cluttered with back-slashes preceeding all double-quotes.
Where are these backslahes coming from and how can i get rid of them???
The code i used for the serialization is as follows;
private string SerialiseXml( DocumentSearchResponse docSearchResponse )
{
// Declare the XML Serializer.
XmlSerializer oSerializer = new XmlSerializer( typeof( DocumentSearchResponse ) );
MemoryStream ms = new MemoryStream();
XmlTextWriter tw = new XmlTextWriter( ms, new System.Text.UTF8Encoding() );
// Serialize the proxy class into the writer.
oSerializer.Serialize(tw, docSearchResponse);
string s = System.Text.Encoding.UTF8.GetString( ms.GetBuffer() );
// Close the writer.
tw.Close();
ms.Close();
return s;
}
|
|
|
|
|
Is this in the file itself or when you read the string into the s variable and examine it in the debugger? The debugger will escape quotes when using the Autos, Locals, and This debugger windows.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
At the point that the class object is serialized into say a TextWriter, if you examine the string then it is littered with escape chars. Which obviously gets carried through when i set a string to the output of the textwriter. What i was trying to do was create a web method which returns a string, which is the xml document.
I've actually solved the problem now, firstly by using a memory stream (so i can set the encoding) i got rid of the /r/n escape characters within the document body. Secondly by setting the quotechar to a single quote i got rid of the escape chars preceeding each ocurance of a quote (as they became single quotes) in the xml header and namespace declaration.
Am i missing something pretty fundemental here or is the practice of returning an xml document as a string not the done thing!! Serializing directly to a file (as in every example on the web) works fine, but in my particular requirement this is pretty useless.
You say the debugger escapes quotes in the Autos, Locals, this windows. does this apply to outputing the string to the immediate window too, as the escape chars where still there.
|
|
|
|
|
Yes, it does apply to the output window as well. A simple test would be to use a StringWriter as the param to an XmlTextWriter , then you already have your string. Output it to a text file and you won't see those escapes. It's just the debugger doing it to you.
Microsoft MVP, Visual C#
My Articles
|
|
|
|