|
theRealCondor wrote:
You may not like this answer
Actually, it's a great answer! I hadn't even thought about doing my own lifetime service management. I guess sometimes I can't see the forest for the trees!
Thanks!
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|
|
Great!
It works well for me. The 15 minute thread on the client dynamically updates a box on their workstation showing them who is on the server in real-time.
Once I got all of the remoting working, implementing this addition was so simple I could never let management know. (You'll get lots of kudos for implementing something so simple yet looks so complex)
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
I've been struggling with a remoting problem that is somewhat similar. In general terms:
- N number of clients talking to a server.
- Any client can alter privileged data but only one can do it at a time.
Sounds deceptively simple right? The trick is that being remoted over the web transport the server can't "ping" the client because of network topology routing isn't guarenteed (thinks like NAT are a good but often a necessary evil). Some of the operations can be a little long so just keying in on "time on CPU" isn't sufficient.
So Client 0 grabs the privileged resource to manipulate locking out other clients but something goes hiddeously wrong. Wrong to the point where no exception can be caught. This might happen if the machine is disconnected or the CLR is just plainly forced to unload. The server still thinks Client 0 is the only one altering the privileged resource and won't let any of the other clients access it.
I can't come up with a clean way to keep the system sane from unnatural disconnects. Because of other parts of the application and because ultimately the CLR unloading is beyond the scope of any runtime code the only way to "fix" hanging connections is to manulally kick dead connections.
I've tried but failed to find a way to handle this beyond handling it manually. What good are machines if I have to contantly fix things for them? If anyone has any good insight into how to handle this type of problem I'd love a good hint.
|
|
|
|
|
Tom Larsen wrote:
The trick is that being remoted over the web transport the server can't "ping" the client because of network topology routing isn't guarenteed
Hmmm. You can't do what's suggested here?
http://www.codeproject.com/script/comments/forums.asp?msg=735472&forumid=1649#xx735472xx[^]
Notice that the server doesn't do the pinging. Rather the client does and automatic, erm "echo?".
Anyways, what you say is interesting also from the point of view of what I'm working on, which gives the server the ability to call client components as well. I wonder how well it works across a firewall or other devices.
I guess I have a couple questions about your architecture--why is client 0's transaction partitioned in such a way as to hold the lock across transactions? It seems that the server should either not allow that or buffer the transactions until they can be all executed. Barring that, what if you put a timeout wrapper around such transactions that cancels them if they fail to complete within a specified time?
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|
|
Sorry about the vagueness in the example. I would like to give out the exact nature of the application but I'm not at liberty to give out the fine deatils. Besides its a boring application.
In general it behaves like this your standard transactioned setup
LimitedRemoteResource res = null;
try
{
res = new LimitedRemoteResource();
res.Allocate();
this.MethodDoesSomething(res,argsA);
this.SomeOtherMethodDoesSomething(res,argsB);
....
....
}
finally
{
if(res != null)
res.Release();
}
If LimitedRemoteResource is a remoted type, there seems little that can be done to to be absolutely sure the finally block is reached and the resource is unallocated. Even if the code all works but the network is disconnected, calling Release won't work because server isn't reachable.
The example I gave was just supposed to highlight a general problem I'm constantly running into in remoted frameworks. A client in the remoting framework requests a resource from a pool from the server but the client ends up disconnecting before the resource is returned. Because its in a disconnected state there is no way for the client to contact the server to tell them of this problem (duh, it wouldn't be in a disconnected state if it could).
On the server side, you can't guarentee when if at all any of the server representation of the objects will be disposed and behaves more like the CLR is just unloaded/killed than it is asked to quit when the web server recycles threads. I've tried implementing crazy watching schemes like mentioned in the link where one thread watches for signs of life from the other but the it behaves on cleanup like th CLR is just unloaded instead of asked to exit/dispose. I get no indications at all that Dispose on any remoted object is being called when the web server does its normal thread cleanup or is forced to (ie. server reset).
So I am stumped. I *think* I need a "CLR Unloading" type event on the server.
|
|
|
|
|
Tom Larsen wrote:
In general it behaves like this your standard transactioned setup
I see your problem! Do you have to do it that way, where the client locks the resources on the server? Can't you buffer the whole transaction on the server?
Marc
Latest AAL Article
My blog
Join my forum!
|
|
|
|
|
The reason why the code is laid out like this is to take advantage of polymophism between different versions. LimitedRemoteResource is derived from a general BaseResource object. For one configuration you use a different object that uses different network protocols than the Remote version with the same BaseResource behavior.
I keep seeing the ultimate solution is to transact the thing on the server side but that ruins some of the code reuse (or at least force people to majorly rewrite their stable systems). It can be done but if I could just flat out avoid it if I got the right event.
One other thing I've noticed at least with IIS 5 and ASP.Net: Dispose isn't assured. I implement IDisposable on the resource object but the destructor is never called. So if in the normal operation on the server the lifetime of an object has expired I don't see a Dispose. In a more extreme case, if the server has to be reset or the machine is rebooted there is no way to Dispose opened resources. This seems to indicate that the web server recycles threads and resources by outright killing processes. The CLR just stops what it is doing and no more code is given a chance to execute. Its kind of a double headed problem. If the CLR is ever unloaded on either the client or server then the whole thing breaks down.
So here I am. If the server did a clean exit on the CLR I suspect that the system would just work out. Since I'm never given the chance to Dispose object properly I'm kind of sunk. I guess the lesson is to somehow work managed resources on only one side of any parallel system.
|
|
|
|
|
I just jumped into this conversation.
I assume that the change of priveledge (or whatever the change is) occurs via a method (or collection of methods) executed on the server. To guarantee that only one gets at the object, and only one, yet users are not blocked, then just use the lock{} command.
public bool UpdateThePriveledge(object orignalValue, object newValue)
{
lock
{
try{
res = new LimitedRemoteResource();
res.Allocate();
this.MethodDoesSomething(res,argsA);
this.SomeOtherMethodDoesSomething(res,argsB);
....
....
}
finally
{
if(res != null)
res.Release();
}
}
public bool PublishIdentity(string name)
{
}
public void NotifyServer(string name)
{
}
The lock will single thread, yet outstanding users will wait for the unlock. This is the standard way to make multi-updates thread-safe. Even if the code craps out, once you leave the method via the finally{}, you will unlock the method for the next user.
The NotifyServer call is what I mean by 'pinging' the server. If you can remote to call UpdateThePriveledge, you can call to NotifyServer that you are alive. No real 'ping' is meant here.
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
The client code is not the real issue. If something bad happens to cause a disurption in the network or the client application crashes, it effects other client users. This type of locking will work for multi-threaded applications, not for multi-user applications. The client side code snippet shows Marc why I was having issues with remoted objects when they disconnect. In this case if the CLR Is unloaded on the client side there is never a clean up for the resource.
The fastest solution seems to be catching some "unloading CLR" event. The best solution would be to rewrite the code so that resource doesn't span mulitiple application domains.
|
|
|
|
|
This is a really cheap method but it had worked for me. You simply allow a ressource for a certain time.(Like 3 minutes). In this case it will become the client problem. (Also this will prevent some clients of abusing of their privilegies and of keeping the same ressource for too long.)
|
|
|
|
|
How can I get and for that matter set the paper name, or as my Canon printer properties calls it 'Media Type', I'm writing a program where I have to keep setting my printer paper type to 'High resolution' so I was hoping to save the exact name to a config file and then set the printer paper to the same name if it exists.
I do find the printer stuff really hard going so any help would be great.
|
|
|
|
|
We are building a huge application for use by both business and developers. We chose the propertyGrid UI as the best interface for these two roles.
In our mapping sessions, we defined that business changes would be allowed only on fields that changed look-and-feel, but not anything that changes the behaviour. I have two NT groups established so security defines the role each user is in (business vs. developer).
We have the initial property object defined with everything set for
ReadOnly(false) Does anyone know of a way to dynamically alter the attribute for the various fields so that I can set fields to ReadOnly if userType=Business ????
Thanks
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
We have an application I architected that does something similar. The answer lies in implement ICustomTypeDescriptor . In your implementation of GetProperties , you can return a PropertyDescriptorCollection with derived PropertyDescriptor classes, where the implementation for the PropertyDescriptor.ReadOnly uses the Thread.CurrentPrincipal (set to a WindowsPrincipal for WindowsIdentity.GetCurrent ) to see if a user is in one role or another (or some other similar means, though role-based security is easy and effective in .NET applications). You could further extend this by making your own attribute that contains a group or groups required to edit the attributed property (using the params keyword in the attribute constructor would be helpful here).
There's a lot of other great things you can do by implementing ICustomTypeDescriptor . Read and docs for it and I'm sure you'll agree! Note that for methods you don't want to have to "implement", you can use the appropriate TypeDescriptor method that takes a bool that dictates whether ICustomTypeDescriptor should be used:
public class MyClass : ICustomTypeDescriptor
{
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
}
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I'm lost. I searched everywhere and could find no articles on ICustomTypeDescriptor. I tried deploying my own TypeDescriptor but I'm getting lost in all of the methods I have to create and not really understanding when the attribute methods and property methods apply to my TypeConverter and when they apply to the property I am a part of.
My attempt, in general, is this:
public class Secure : ICustomTypeDescriptor
{
private bool isSecure;
public Secure(bool state)
{
isSecure = state;
}
.. now I'm lost trying to deploy everything
}
I also cannot find PropertyDescriptor.ReadOnly or when I should use it or add it or whatever. I found an abstract conversation on one site and this is similar to what they showed. My attempt:
namespace myCompany.Attributes
{
internal class Secured : ICustomTypeDescriptor
{
private bool secured;
private bool readonlyState;
public Secured(bool state)
{
secured = state;
}
System.ComponentModel.PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(System.Attribute[]
attributes)
{
PropertyInfo[] propInfos =
this.classType.GetProperties(BindingFlags.Public | BindingFlags.Static);
ArrayList props = new ArrayList(propInfos.Length);
foreach(PropertyInfo propInfo in propInfos)
{
props.Add( new ReflectPropertyDescriptor(propInfo) );
}
if (CheckReadOnlyState())
props.Add(new ReflectProperty(???));
return new PropertyDescriptorCollection(
(PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor)) );
}
System.ComponentModel.PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{
ArrayList props = new ArrayList();
if (CheckReadOnlyState())
props.Add(new ReflectPropertyDescriptor(PropertyDescriptor.ReadOnly));
return new PropertyDescriptorCollection((PropertyDescriptor[])props.ToArray(typeof(PropertyDescriptor)));
}
TypeConverter ICustomTypeDescriptor.GetConverter()
{
return TypeDescriptor.GetConverter(this, true);
}
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{
return TypeDescriptor.GetAttributes(this.secured, true);
}
public bool GetPropertiesSupported(ITypeDescriptorContext context)
{
return true;
}
object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
{
}
}
public class bool CheckReadOnlyState()
{
readonlyState = true;
SecurityManager sec = new SecurityManager();
if (sec.CheckUserGroup("D-U-TCAEDIT") && !this.secured)
{
readonlyState = false;
}
if (sec.CheckUserGroup("D-U-TCA"))
{
readonlyState = false;
}
return readonlyState;
}
public class PropertyDescriptor ReflectPropertyDescriptor : PropertyDescriptor
{
private PropertyInfo propInfo;
public ReflectPropertyDescriptor(PropertyInfo propInfo) :
base(propInfo.Name, null)
{
this.propInfo = propInfo;
}
}
I'm just not understanding what this is doing and how I define the ReadOnly(true/false) attribute.
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
You don't define the attribute, you extend the PropertyDescriptor class and override the ReadOnly property. What this property does to determine if true or false should be returned is up to your implementation. If you're setting the Thread.CurrentPrincipal to the current Windows principal (rather, the current WindowsIdentity with a WindowsPrincipal), you can use <code>IPrincipal.IsInRole (actually, you could do this without setting Thread.CurrentPrincipal , but this opens you up for role-based code access security as well). You could also attribute your properties subject to this condition with an attribute that dictates which roles are required.
The point is, in your ICustomTypeDescriptor.GetProperties implementation, you return a collection of your derived PropertyDescriptos that override the ReadOnly property.
For more information about ICustomTypeDescriptor , merely type it in your help index in VS.NET (if you installed the documentation, which is installed by default).
As far as all the methods, as I mentioned earlier you can provide the default implementation by using the appropriate TypeDescriptor method. I put that in my previous post. Each method declared by ICustomTypeDescriptor has a corresponding method defined by TypeDescriptor that takes a bool as (typically) the last parameter. Set this to true so that the implementation does NOT query your Type for the ICustomTypeDescriptor implementation (which would cause an infinite loop).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Okay....I'm a very visual person so it takes some time to absorb some things. Our Security Manager handles the group determination by WindowsIdentity.
I think I've got it now:
namespace myCompany.Attributes
{
internal class SecuredProperty : PropertyDescriptor
{
private bool readonlyState;
public bool IsReadOnly
{
get{return readonlyState;}
}
public SecuredProperty()
{
SecurityManager sec = new SecurityManager();
if (sec.CheckUserGroup("D-U-TCAEDIT") && !secured)
{
readonlyState = false;
}
if (sec.CheckUserGroup("D-U-TCA"))
{
readonlyState = false;
}
}
}
internal class SecureDescriptor : ICustomTypeDescriptor
{
AttributeCollection ICustomTypeDescriptor.GetAttributes()
{ return TypeDescriptor.GetAttributes(this.secured, true); }
string ICustomTypeDescriptor.GetClassName()
{ return TypeDescriptor.GetClassName(this, true); }
string ICustomTypeDescriptor.GetComponentName()
{ return TypeDescriptor.GetComponentName(this, true); }
TypeConverter ICustomTypeDescriptor.GetConverter()
{ return TypeDescriptor.GetConverter(this, true); }
EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
{ return TypeDescriptor.GetDefaultEvent(this, true); }
PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
{ return TypeDescriptor.GetDefaultProperty(this, true); }
object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
{ return TypeDescriptor.GetEditor(this, editorBaseType, true); }
EventDescriptor ICustomTypeDescriptor.GetEvents(System.Attribute[] attribs)
{ return TypeDescriptor.GetEvents(this, attribs, true); }
PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
{ return new PropertyDescriptorCollection(new SecuredProperty(secured)); }
}
}
I also understand that I can create a public class Secured:Attribute and have it indicate if the particular property should be secured to just developers. There are just two things I am not completely clear on which is not covered in the help files.
1) In my PropertyDescriptor class or within my CustomTypeDescriptor how do I determine that the Secured Attribute is set to (true) ?
2) When I define all of this in my properties, I'm not clear how I define my CustomTypeDescriptor.
[Description("..."), Secured(true), TypeEditor(typeof(myEditor)),
Category("Viewing"), ...]
Do I specify a CustomTypeDescriptor, or a TypeDescriptor(typeof(SecureDescriptor)) ?
Thanks very much for your assistance!
Michael
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
You don't have to attribute you class with anything to make use of the ICustomTypeDescriptor . Any object that uses the TypeDescriptor to get information - like the PropertyGrid - will automatically benefit from the ICustomTypeDescriptor implementation.
As far as the attribute goes, I would do something like this:
public class RequiredGroupsAttribute : Attribute
{
private string[] groups;
public RequiredGroupsAttribute(params string[] groups)
{
this.groups = groups;
}
public string[] Groups
{
get { return this.groups; }
}
public bool IsInGroup(string group)
{
if (this.groups == null) return false;
foreach (string s in this.groups)
if (string.Compare(s, group, true) == 0) return true;
return false;
}
} In your derived PropertyDescriptor , you can get the attributes of the property like so:
public override bool IsReadOnly
{
get
{
RequiredGroupsAttribute attr = (RequiredGroupsAttribute)
this.Attributes[typeof(RequiredGroupsAttribute)];
if (attr == null) return true;
return !attr.IsInGroup("Developers");
}
} This is just a very simple example, though. You could most likely improve upon it.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
Heath,
Thanks much for your help. I have the ICustomTypeDescriptor mostly done and implemented in my property objects. I have the Secured() Attribute defined and recognized by the system. I am lost still with implementing the PropertyDescriptor. It is not a simple process of just overriding IsReadOnly. There are about 10 methods and properties that need to be implemented. Some of these I can just pass to the base class. Some are not definable. And I cannot see how I can implement these PropertyDescriptors completely.
For example: I assume that if I call TypeDescriptor.GetProperties I have the initial collection of properties with all of their attributes. But some of the properties (such as Category, Description, etc.) are not accessible as anything but get in the base class and I cannot set the properties from the original.
I have read what little is in the help files and all they do is provide a 1-line description. I cannot find a tutorial anywhere that implements even a simple example of this.
So how exactly do I define my own property descriptor, get it implemented for all my properties, and get a properly deployed PropertyDescriptorCollection returned when the GetProperties method is called since I cannot tell TypeDescriptor to use my PropertyDescriptor object and I cannot set my base properties internally nor can I override them.
I appreciate your patience and help on this!
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
PropertyDescriptor has a protected constructor that you should override that takes and initializes the PropertyDescriptor from a MemberDescriptor , which you can get with TypeDescriptor.GetProperties(this, true) . In your override for IsReadOnly , you can use metadata to determine if the user can set them or not. I do this very thing in our application based on dynamic properties pulled form a database. As I mentioned before, it you utility role-based security, this gets very easy. That attribute I mentioned before would have the groups (or roles) that can set the property. Your IsReadOnly override gets the list, calls IPrincipal.IsInRole and if it returns true for any of those roles, you return false . If not, return true (read-only).
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I am almost there....just can't get the last pieces defined.
My CustomTypeDescriptor.GetProperties calls
TypeDescriptor.GetProperties(this,attributes,true);
I then create a new PropertyTypeCollection and make each PropertyDescriptor my custom PropertyDescriptor. I pass the PropertyDescriptor as the MemberDescriptor object.
protected PropertyDescriptorCollection GetFilteredReadonlyProperties(Attribute[] attributes)
{
PropertyDescriptorCollection properties = TypeDescriptor.GetProperties(this, attributes, true);
PropertyDescriptorCollection newProperties = new PropertyDescriptorCollection(new PropertyDescriptor[0]);
foreach (PropertyDescriptor property in properties)
{
DynamicPropertyDescriptor newProp = new DynamicPropertyDescriptor(property);
newProperties.Add(newProp);
}
return newProperties;
}
I cannot figure out what I code, though within these abstract methods:
PropertyDescriptor.PropertyType()
PropertyDescirptor.GetValue()
PropertyDescriptor.SetValue()
PropertyDescriptor.ComponentType()
Since these are abstract....I cannot do a base.method().
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
PropertyType returns the Type of the property. Just return obj.GetType() . ComponentType returns the Type of the component that the property belongs to. GetValue and SetValue set the property for the object to which the property belongs. You can use reflection to achieve this.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
I finally got it WORKING!!! Thank you Heath.
While the help files provided no help looking up PropertyDescriptor, I found more help looking up the PropertyDescriptor.{method name} where they had some more useful info under the Note to Inheritor: sections. That combined with Reflection finished it off.
I think in my freetime ( ????) I will put together a sample application and publish it as a visual aid for those developers who are like me and need more visual assistance!
_____________________________________________
Of all the senses I could possibly lose, It is most often the one called 'common' that gets lost.
|
|
|
|
|
When I tell people to look in the documentation for some class, I do mean everything about that class. Remember, it's Research and development. The latter without the former is what separates the developers from the code-monkeys.
I'm glad you have it working. The important thing is to understand what a MemberDescriptor does so you can utilize it to its full potential. For instance, I have a derivation that uses rows from a couple tables in a database for a completely object-oriented and extensible way of managing preferences. Those properties work great with a PropertyGrid but also have a parent collection that can get and set different property containers using a singleton pattern. All this is done with classes and interfaces in the System.ComponentModel namespace. It's a very cool namespace to fully understand when dealing with component development because there are so many things supported by designers that ship with the .NET Framework and with common IDEs like VS.NET and SharpDevelop.
Just thought I'd mention this more as an exmaple of what else you can do with PropertyDescriptor s and related classes.
Microsoft MVP, Visual C#
My Articles
|
|
|
|
|
can you tell me how to pass a integer command line parameter in C# I am struggling with this
Please let me know at the earliest
Praveen
|
|
|
|
|
Only strings can be passed, hence an string[] array being passed to your entry point method (typically Main ) or Environment.GetCommadLineArgs() returning a string[] . Therefore, you should be looking for a way to convert the string. There are many ways to do this, such as Int32.Parse and Convert.ToInt32(String) .
Microsoft MVP, Visual C#
My Articles
|
|
|
|