|
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!
|
|
|
|
|
Pciking a random color may return you the same (or similar enough for most people to not notice) color. Using Colin's idea (perhaps even extending this to a non-coded color map file that is read in dynamically) will help you ensure that for 1-N people 1-N unique colors are used. Of course, you should pick contrasting colors to make it easy. I've seen this in quite a few applications and the colors are always picked in the same order, so this seems to be the common approach.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Here is some code to do what you want.
<br />
private int color = -1;<br />
<br />
private Color [] myColors = {Color.Red,Color.Yellow,Color.Blue,Color.Green};<br />
<br />
private Color getColor()<br />
{<br />
color = ++color % myColors.Length;<br />
return myColors[color];<br />
}<br />
Enjoy,
Karl
|
|
|
|
|
Is it possible to obtain somehow [domain name] of machine running
the code ?
If the machine is not logged into domain, I would like to get
workgroup name of the machine (but this is not so important to me)
note: I would like to get name of the domain that the _machine_
has been logged into, regardless of currently logged user
(regardless of whether the guy has logged onto local account,
account of domain that i'm looking for, or any other domain)
and regardless of whether anybody has logged in interactively
maybe there is something simillar to Environment.MachineName
(this returns host name)
... ?
Thanks for help
Michał
|
|
|
|
|
michalJ wrote:
maybe there is something simillar to Environment.MachineName
You mean like Environment.UserDomanName ? The domain into which the machine account isn't really helpful. Code is executed in a user context (even system services) so the user domain is what is necessary.
Environment.MachineName - if you read the documentation - returns the NetBIOS name, so it will never include a domain name (like with Active Directory machines). For that you have to P/Invoke the right Network Management APIs - but like said, that information really isn't useful. A user is executing the code, not a machine (as far as security contexts go).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Ok - here's the story:
c++ supports a coclass (CLSID_DragDropHelper ) with 2 interfaces; IDropTargetHelper and IDropSourceHelper . The IDropTargetHelper has 4 methods, DragEnter, DragLeave, DragOver and Drop . Calling these methods is what gives c++ the ability to display a drag image created by the shell. In other words, you can drag from Windows Explorer and your form/control will display the drag image.
C#, on the other hand, doesn’t have the ability to do this natively. I’ve found an old VB6 project that allows anything with a valid Windows handle to be subclassed, thereby supporting the Explorer drag image. I created an RCW (Runtime Callable Wrapper) of the project's ATL library and attempted to get the same effect in c#. Sadly, I could not get it to work. Something that VB’s internals hide from developers allows the subclassing to work, and I have no idea how to get it to work in c# (seems like an OLE problem??)
I would be grateful if anyone can make the following VB6 project work with either c# or vb.net:
Download the project at:
http://www.glimt.dk/code/clipx.zip (Run the project and drag something from Explorer over the Drag/Clip button)
More info can be found on MSDN: http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnwui/html/ddhelp_pt1.asp
|
|
|
|
|
Don't interop the VB6 project - that's a waste (requires two phases of marshaling for a one-way call and requires extra DLLs/OCXs that need to be registered). Declare the COM interfaces in C# (as I mentioned to you before) along with a skeleton implementation with the same GUID as the CLSID_DragDropHelper. You can then use Activator.CreateComInstanceFrom and instantiate the COM coclass but treat it as the skeleton type you created. Now your C# code is directly using the COM coclass provided by the shell.
If you need to pass HWND s, then use Control.Handle (like your main Form 's Handle property). That IntPtr (native-size integer) is your HWND for that Control .
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath,
I appreciate you trying to help, but you're missing the boat here. It's not shell programming/COM interfacing I'm having a problem with. I can't find the GUIDs for the helper class or the interface definitions. I can't declare the com interface without the GUIDs, and I can't stub out the interfaces without knowing how the COM interface looks. Since I found a pre-existing project I was looking to port the implementation to c# using a wrapper for the library. I wasn't trying to interop vb6 code. If I had the GUIDs and interfaces (or could find them) I never would have posted this or my previous post in the first place......
|
|
|
|
|
That's a simple problem, and that VB control won't help you. Download and install the Platform SDK if you don't have it already. Search for the GUIDs. I personally use GViM (Graphics VI iMproved) with a tags file created for each INCLUDE. This makes it fast to find things like this.
The interfaces you mentioned are documented in the Platform SDK, and you can always look at their declaration in the header files (which gives you the order of methods so you can get the VTBL order right for IUnknown -inheritted or dual interfaces. I do it all the time with poorly documented interfaces or to find orders or to find the pre-proc defs or GUIDs for anything.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm writing a class library which contains a couple dlls. Is it possible to have one combined dll of my class libary and the other dlls i'm using. I just want to make a single redistributable dll. Is it possible?
Note: I don't have the code for the dlls i'm using in the class library. Only have the dll itself
Thanks in advance
|
|
|
|
|
Yes, but call them what they are: assemblies. An assembly contains a manifest at the very least. It can also contained 0 or more embedded resources, assembly attributes, and modules. Those modules are what contains your IL (intermediate language) that the compiler generates.
Unfortunately, VS.NET won't help. You can only compile to modules using the command-line compilers. For the C# compiler, this uses the /t:module switch. When you compile the last project, you use an assembly switch (everything else but /t:module, like /t:library for a class library) and then use /addmodule:<path> to add the other modules. This will create an assembly with multiple modules.
By why are you worried about sending out multiple DLLs? You should install them into the GAC anyway, which takes care of versioning problems. By distributing the Types, this also gives you more flexible control over independently versioning assemblies. You can redirect assembly bindings using a publisher policy - a specify type of assembly that gets installed into the GAC.
So, if class library A depends on B, but you had to change B and don't need to change A, then you must tell assembly A to look at the new version of B. This is assembly version redirection. When you start having larger projects (I managed a product with over 60 possible assemblies, depending on the edition someone buys), this is a must since you don't always need to recompile everything (especially a problem when you're doing touchless-deployment over the Internet like we are).
Just something to consider.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
|
They can, but modules and assemblies have to be compiled with a single command. csc.exe can produce multiple output files at the same time, but the first /out: has to contain the manifest. If you do it that way (or use pre-proc defs and a two-stage build, which is what I did a while back), modules can even access internal types in other modules within that assembly.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
We are attempting to deploy what should have been a very simple implementation. Our VS 2003 WinForm application has the need to edit XHTML. Our approach is simple:
We write an ASPX app that exposes the XHTML editor and takes the file to edit as the query string.
We create a form in the WinForm application which contains the IE control and serves as the container serving up the ASP.NET application.
---
What we expected to have happen was that the ASP.NET app would function undisturbed within the ie control context.
---
What we experience is that populated data does not show up when posted to the server side.
Controls that work fine when executing the form directly don't allow editing when inside the IE control.
Is there something I'm missing here? It seems to me that an ASPX application should function identically in the IE control as well as it does directly in the browser!!!!
|
|
|
|
|
You should take a look at the Comzept NetRIX Editor[^], which wraps MSHTML and can write XHTML and has all the bells and whistles you'd expect from an HTML editor, plus it also saves you from such an elaborate and tightly-coupled system.
As far as your problem goes, just because yo'ure embedding the WebBrowser control doesn't mean that the WebBrowser control and iexplore.exe or explorer.exe (when hosting the WebBrowser control) will function the same. The container provides a lot of services to the MSHTML control, and any scripted calls to window.external will break as well.
You can provide services to the MSHTML and WebBrowser controls, however (the WebBrowser control does provide some service to MSHTML). Read the article Using MSHTML Advanced Hosting Interfaces[^] as well as the articles linked to MSDN which describe the hosting interfaces in depth.
To provide such services to the WebBrowser control, you really have to be familiar with COM and COM Interop with .NET. There's a lot to do, which NetRIX has already done for you (at a decent price).
No, I'm not trying to peddle NetRIX. There are other solutions (though not as good, I assure you, since we've tried to look at them all here). I have done this interop to a degree but I was spending far too many man-hours adding more interop functionality (trust me, it's not so easy with when one interface recursively requires many others) than what it cost to buy NetRIX. You might want to take a look.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Hi
I want to convert the unicode string ( in DotNet) to extended ascii bytes.
I tried UTF8Encoding and ASCIIEncoding.
But in UTF8Encoding i am two bytes for the £ ( character value 163)
In ACSIIEncoding I am getting question mark (?).
How can I convert the character £ to a ascii byte value
Please Help
Regards
|
|
|
|
|
You have to specify a codepage. Any characters about 127 in ASCII (since ASCII defines 7-bit characters, not 8-bit) depend upon a codepage for what those characters represent
byte[] ubuf = Encoding.Unicode.GetBytes(
"This is a string stored as Unicode in .NET.");
Encoding enc = Encoding.GetEncoding(1252);
byte[] abuff = Encoding.Convert(Encoding.Unicode, enc, ubuf);
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|