|
They both have their own command-line applications. MySQL's is simply mysql.exe, but I don't know what Oracle's is. I would suggest either looking it up with google or find an Oracle newsgroup.
Might I recommend a better alternative, though? Nothing gaurantees that those command shells will be resolvable (in fact, IIRC, mysql.exe is not - it's in a directory that is not in the PATH env. var.). A better way might be to use a connection to their master databases (might have different names for each major database, but for SQL Server it is called "master") and then use whatever IDbCommand implementations that are appropriate for the database you're accessing (like SqlCommand , OleDbCommand , etc.) to build database objects. This is a pretty typical solution and doesn't rely upon command shells that may or may not exist.
Another scenario is if you're building database objects on a remote machine. The local machine may not the database installed so the command shell won't be present anywhere on the local machine.
For this reason, we use the method I outlined to build and update SQL Server databases, which should work just fine with any other RDBMS.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Thanks Heath. We have our own script runner which does this, but thing is, it doesn't handle certain situations well. For instance, comment block - while we can take out the commments, it makes the scripts a hell lot harder to read and to maintain.
|
|
|
|
|
HI~
I would like to ask
How do I change the data in C++ dll by a C# program?
I have ever tried this.
I wrote a dll with VC++. There is a variable in the dll (e.g "m_string"). "m_string" is a LPCTSTR type and it's inital value set by constructor is _T("Hello World"). I also wrote a function for setting the variable. The function is declared like this:
extern "C" _declspec(dllexport) void set(LPCTSTR s)
{
m_string = s;
}
Afterward, I wrote a C# dll assembly. The C# dll import the dll written by C++. The import the dll like this:
#region DLLImports
[DllImport("Test.dll")] //test is the C++ dll filename
private static extern void Set(string s);
#endregion
Finally, I wrote a form to call the method "Set". After the method have finished executing, the value "m_string" does not change. The "m_string" is still "Hello World".
My question is, how to change a variable in dll permanently by a C# library or exe?
Thanks
|
|
|
|
|
First of all, using LPTSTR or LPCTSTR uses an ANSI or Unicode string depending on whether or not the UNICODE (or sometimes _UNICODE) symbol is defined. Unicode is only natively supported on Windows NT (4.0, 2000, XP, 2003, and all newer versions). So, you need to change your declaration like so:
[DllImport("Test.dll", CharSet=CharSet.Auto)]
private static extern void set(string s); Also notice how set uses a lower-case "s"? Your method signatures have to match (minus the "A" or "W" at the end, if you do that for different sigs for different platforms) character-for-character and case-for-case, otherwise you have to set the actual function name to P/Invoke in the DllImportAttribute 's EntryPoint field in the attributed P/Invoke method.
Finally, make sure that Test.dll is in the same directory as the executing process (not just the same as the assembly that uses it) or in another directory specified in your PATH environment variables. Native executables use this to find DLLs (and other executable files) at runtime, so the Test.dll must be resolved.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
HI~
I am sure the function work properly.
My situation is that
The dll is loaded will windows startup. The dll is used to so a string on the screen when the windows startup. The string is a variable of the dll. When the dll is loaded, a WM_PAINT message is sent and the OnPaint function is called. The OnPaint function draw the window and text on the screen. I would like to use C# program to make changes to the string so that the screen can show different string dynamically.
I use the code above and try to achieve this result. However, the variable within the extern function is changed but after the function is complete, the string on the screen still not been changed.
So, how to achieve the correct result?
Thanks~
|
|
|
|
|
Changing the variable is not enough. You have to invalidate the client area in your unmanaged DLL so that when the WM_PAINT message is called the invalidated region is redrawn. In your OnPaint handler, get the string value and draw it on the screen.
There are many ways to invalidate a region in C/C++, and since I'm guessing that you're using MFC (judging by the OnPaint event), you can use Invalidate or InvalidateRect , both inheritted from CWnd .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Yes
The dll will send a message to itself every 2 or 3 second call a function. The function is written by me, which use to check whether the variable have been changed or not. If there is any variable change, the function will return true, otherwise, it will return false. If true is returned, a refresh message will be sent to the dll and force to redraw the screen. However, the screen is refreshed by the variable which shown on the screen still not changed.
I think that there may be a solution. There is a handle for the variable. First, the C# program call the extern function of the unmanaged dll and return the handle of the variable to C#. And then C# program use this handle and pass it to the extern function of the unmanaged dll as argument and call it to set the variable value. However, I do not know the unmanaged dll code well.
Can anyone tell me how to solve it?
Thanks
|
|
|
|
|
There is a solution, and that's what I've been trying to tell you. This is actually quite an easy problem and I deal with interop problems more difficult than this almost daily.
The big problem is that I'm not really understanding what you're trying to do, so let me pose what I'm hearing and tell me if I'm right:
You've defined a set function (C-style export?) in a native DLL that is resolvable and being P/Invoked by a managed assembly written in C#. The C# code calls set which changes a variable. This native function returns true or false (1 or 0, respectively). The C# code then sends WM_PAINT to the HWND that displays the string. Your handler for the WM_PAINT message draws the string value.
If I'm right and if the string value is truly being changed unmanaged process space, then the only problem could be invalidation of the client area. Depending on the WM_PAINT handler, only invalidated regions may be redrawn (this is common for most controls - only redraw what needs to be redrawn). If you don't invalidate the area of the control that displays the string, it may not get redrawn. This is why you must invalidate the region as I mentioned before.
You can try a simple test, too. After the variable is changed, minimize or otherwise hide the window (perhaps with another window). Then show it again. Is the correct string displayed now? If so, it's definitely a drawing problem and you need to invalidate the area. It could also be that, if you're using double-buffering, you're not clearing the back buffer so that even though the client area is invalidated the old back buffer is still being rendered with the old string.
All this talk about handles now is confusing me. Before you said you had a simple function declared (IIRC) like bool set(int) , correct? Now you're talking about handles (addresses).
If you need to set the address of a string, you should pin it and use something liket his:
GCHandle handle = GCHandle.Alloc("Some string or variable");
IntPtr ptr = handle.AddrOfPinnedObject();
set(ptr);
handle.Free(); If the string is to be allocated in a certain way (either using GlobalAlloc or COM's CoTaskMem object), then you can use the respective methods defined on the Marshal class to help.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Sorry
I mean there is a handle in the unmanaged dll for the variable. C# program can call a the extern function to get the handle of the variable. Then the C# program call the set (handle, new_value) to set the variable. Actually, I don't know how to implement the dll as I am familiar with it.
Can it works?
Thanks~
|
|
|
|
|
I am using HWnd handler to handle the window.
So I cannot use Invalidate or InvalidateRect function
|
|
|
|
|
Sure you can - how do you think it's done in native C/C++ applications? MFC also does it, and MFC is just wrapper classes for native Windows APIs.
P/Invoke InvalidateRect :
[DllImport("gdi32.dll")]
private static extern bool InvalidateRect(IntPtr hWnd,
ref RECT lpRect, bool bErase);
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
HI,
I want to extend Windows.Forms.DataGrid class so I can add buttons to data grid's columns.
I haven't found any good sample of this over the internet... if any body has link to a better example/sample - please forward me that URL
thanx in advance
|
|
|
|
|
You mean in the headers, or in the columns themselves? You don't need to "extend the DataGrid" to do this, though. You simply implement a DataGridColumnStyle derivative. If you look at the class documentation[^] for the DataGridColumnStyle , it even gives you a completely example that hosts a DateTimePicker control in the data columns.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
how to insert icon into text box and like yahoo messenger ?
|
|
|
|
|
TextBox doesn't support it, but a RichTextBox does...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
I want to write a Windows Service application that will detect and then perform some tasks whenever a client logs on to the domain. This service will be running on a server with Active Directory. Can someone point me to the right set of .NET (C#) classes or methods that I would need to use for detecting a domain logon event?
|
|
|
|
|
The concept your describing is a Logon Script. It runs whenever a user logs on. You can write them in any script language, JScript, VBScript, .NET Script, ...
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Actually, I initially did try to use logon scripts. However, logon scripts always run in the context of the client (ie. from the client's point of view). My goal is to write a script or app that can retrieve each client's computer information when they log on, and record that information into a single database located on the server. However, since the script thinks it running on the client machine, it requires the ADO/OBDC/OLE stuff installed on the client to perform the data access tasks. This is not practical in a network with many client computers.
So, after that I tried to do a workaround. That is, instead of making that logon script connect to the database directly, the script will spawn a new process ON THE SERVER (this process is now definitely running from the server's point of view). This requires the data access software to only be installed on the server. This process running on the server will now connect back TO THE CLIENT, uses WMI to obtain client's system info, and then write the info onto the database on the server.
The concept is good, but I ran into a bunch of security issues. Connecting back and forth like this makes the network think that there are THREE computers involved (but there actually only two). When making connections among 3 or more computers, the delegation of tasks is involved. Delegation require more special permissions and authority, and the configuration is hard for me. Sadly, I never got it to work.
http://www.mcse.ms/message289939.html
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/connecting_to_a_3rd_computer-delegation.asp
So, I have now decided to create a Windows (NT) Service, and avoid logon scripts. The service will run on the server and hopefully have a way to trap and handle all logon events by clients. So when a client logs on, the service can connect to it, obtain system info, and then write it to the database. This avoids making so many back and forth connections, and thus reduces security complication issues. OK, so now I'm trying to create such a service using C#.NET. Which classes should I use that can provide with such logon event trapping methods?
|
|
|
|
|
Well, the problem with running this on the server and having WMI connect back to it is now your running an expensive process on the server and using some very expensive resources to connect back to the client. Writing a service to do this will not be any easier since you'll be running into the exact same security and connection problems. The only difference between a normal Windows app and a Service is a Service runs on a hidden desktop.
I've been in the situation your in now. Believe me, you do NOT want to be spawning a process like this on the server. You'll have one of these running for each login that occurs, and .NET Framework apps are a little heavy on the memory. The less you have running on the server, the better off you'll be.
This is better accomplished with a client side utility that inventories everything you need on the client, running on the client, out of the login script. Then it writes a record to some file file on the server. I used a straight .CSV text file. Then, once a night, when the demand for server resources is lowest, the server kicks off a process that parsed up the .CSV file and dumps all the data to an SQL server database. Actually, when I did it, I used a dedicated process on the SQL Server that went to each domain controller and picked up a copy of the file, deleted the original, and then parsed it locally on the SQL server. I kicked my process off once a night, but you could kick it off at any interval you want.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
Yes, I absolutely agree with you that spawning a process on the server for each logon event is very resource-consuming. However, if I make a Windows Service, then won't it be running on the server as just one copy? (ie. there's only one MySQL service running all the time). The service just sits there quietly in the background and will perform some desired task only when it detects a client logging on. I dont think multiple copies of the service are made, one for each logon event. Also, the connection/security issues only gets complicated (for me) when I have to make many back and forth connections. If it's just the service application connecting the a client, then I believe it should be relatively easy.
I also did think about the idea of having each client write its own info to some file on the server. However, if many clients happen to log on at about the same time, then would it be a problem if they all try to access the same file on the server? Now, if I let each client write its info to a separate file, then it would avoid this problem. However, the problem now is that there will be too many I/O operations over a short period of time. That will make it slow.
Using the files method, initially I was thinking of writing just a simple application for the server's desktop that would then read the file (or all the files) and dump the info to a database. To get an updated database, the server administrator would just have to double click the app whenever he/she wants. But now, I like your idea of having a process that automatically "kicks off" at any certain time of day. How can I make such an application that will run at any desired time?
|
|
|
|
|
lnong wrote:
However, if I make a Windows Service, then won't it be running on the server as just one copy?
True, but now you'll have all of your logoons running through a single service on the machine collecting data in a time-consuming fashion (remote WMI). Unless you make you service multi-threaded you'll bottleneck client logons. Now, your spawning multiple threads to do the same job multiple processes would have done. In reality, there's no difference.
No, file concurrancy is not a problem. If you have the client inventory app running out of the login script, the client will launch the app just like any other Windows process and the login script will continue on it's merry way. The inventory app will be running while the client finishes it's logon sequence. When it comes to writing the record to the file, you open the file as Deny Share Read and Deny Share Write. If the client can't get the opened, it waits a random number of milliseconds and tries again. In may version, I had a 10 retry limit with a maximum random delay of 2000 milliseconds. The number of file I/O operations was low. I tested this mthod, before I deployed it of course, with 10 machines running 10 processes each, trying to write to the same file with the mentioned scheme. Not one hiccupp or failure was ever experienced over a one hour period with over 2,000,000 records and not one record was lost.
How can you make an app that launches at a specific time? Easy, just write it as a console app and use the Scheduled Tasks control panel app to run it. The app doesn't have to worry about a timer or the current system time at all. At the end of the record collection, it quits on it own.
RageInTheMachine9532
"...a pungent, ghastly, stinky piece of cheese!" -- The Roaming Gnome
|
|
|
|
|
at runtime, an unknown amount of objects will be created in which i would like to assign each a different color. i will want to either randomize this or maybe better yet, choose about 20 colors of my choice, and linearly cycle through them assigning them to objects starting at the beggining if the last color was assigned. is there an easy way to do this?
|
|
|
|
|
One idea would be to create an array of the possible colours that you want to use. I assume each of these "objects" are of the same type (or share the same base type) in which case you can create a private static field in the class (or base class) which contains the current index into the array. In your constructor you take the current index, get the colour from the array and increment in the index (remembering to reset to zero if you run off the end of the array)
Does this help?
"You can have everything in life you want if you will just help enough other people get what they want." --Zig Ziglar
The Second EuroCPian Event will be in Brussels on the 4th of September
Can't manage to P/Invoke that Win32 API in .NET? Why not do interop the wiki way!
My Blog
|
|
|
|
|
How about something as simple as this:
public Color GenerateRandomColor()
{
Random rand = new Random();
Color c;
int r, b, g;
r = rand.Next(0, 255);
b = rand.Next(0, 255);
g = rand.Next(0, 255);
c = Color.FromArgb(r, g, b);
return c;
}
- Nick Parker My Blog | My Articles
|
|
|
|
|
i like both ideas! thanks!
|
|
|
|
|