|
nice progress bar tip. i'll try it out.
thanks.
/\ |_ E X E GG
|
|
|
|
|
Hi,
I have a strange behavior when using an installer class to register a com+ server (Using the RegistrationHelper class). When the installer perform a new install there is no problem, the behavior appear when doing an upgrade, the old version is registered, not the new one (the Installer package is configured to remove the previous version before reinstalling a new one. "RemovePrevious Version=True").
Here is the symptom :
When installing a new version of the com+ server, the installer class first uninstall the previous version, remove the files and copy the new ones.
then, the following procedure is run :
public override void Install(System.Collections.IDictionary stateSaver)<br />
{<br />
base.Install(stateSaver);<br />
<br />
string appID = null;<br />
string typeLib = null;<br />
string assembly = GetType().Assembly.Location;<br />
<br />
RegistrationHelper regHelper = new RegistrationHelper ();<br />
regHelper.InstallAssembly (assembly, ref appID, ref typeLib,<br />
InstallationFlags.FindOrCreateTargetApplication);<br />
<br />
stateSaver.Add ("AppID", appID);<br />
stateSaver.Add ("Assembly", assembly);<br />
}
Theoritically the new com+ server must be reinstalled.
BUT, the version registered is the previous...
Because of that, the server can't provide com object access because of a mismatch in assembly effective version and declared version in registry.
I don't understand why because the assembly property refer to the new assembly with the correct version number !!!
Does anyone have an explanation for this problem or it is a bug ?
Pietro
|
|
|
|
|
Well, InstallationFlags.FindOrCreateTargetApplication tells the reg helper to install a previous version first - the installer is clearly not removing the previous version.
Look in your Add/Remove Programs control panel. Do you see two entries for your product there?
First, always make sure to NEVER change the UpgradeCode. Simply changing the installer version will prompt you to change the ProductCode and PackageCode (which is appropriate for Windows Installer, someting I've consulted on for several years).
The problem is that VS.NET's installer project sucks! It does almost everything wrong. If you choose to install the previous application on a per-machine basis (the default is per-user), the new install (remember, having the default set to per-user) won't see the prevoius version! This is because the Upgrade table is handled wrong.
If this is indeed causing the problems you are experiencing, you'll have to download the Platform SDK from MSDN for the Windows Installer SDK (the core is required). In that, there's an installer for a utility called Orca. Install that, open your .msi file and find the Property table. Add the property ALLUSERS with the value 1.
The VS.NET installer is also stupid because you can't do this before compiling the package (or much of anything else, for that matter).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Thank you for your answer,
looking in add/remove program show only one entrie after an upgrade, and as it was recommended, i never changed the upgrade code.
I don't think it is an upgrade detection problem. When I look at what is appening during the upgrade process, uninstall of the previous com+ application and deletion of previous file version occur correctly !
Finally, to workaround the problem, I have created a custom action wich call Regsvc.exe to make the registration. (It's not very nice looking but it works !)
Pietro
|
|
|
|
|
I've written a very small remoting app, a server that exposes one method from a dll, and a client that connects and calls that method. Most of the time this works fine. But if the client crashes, and I restart it, any subsequent connections to the server cause an exception. If I restart the server everything is fine. It seems to me that if the clients' connection to the server channel is disconnected improperly, the server is hosed. Is there any way to periodically check to see if a channel is 'stuck'? Otherwise I'll have to set up some kind of schedule of periodically unmarshalling/disconnecting and then re-marshalling/connecting, just in case the server is stuck. That just seems inelegant to me.
Thanks for any suggestions,
jt
|
|
|
|
|
What calling convention are you using for the remoting type? (i.e., client-activated / server-activated, single-call / singeton, etc.)
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
It's a single call, no server config file, it's all in the code
|
|
|
|
|
The only thing that I can think of is that the server is in the middle of doing something with the client and either throws an unhandled exception (that can't get passed to the client because it doesn't exist, so instead the remoting host must catch it) or tries to handle an exception and does something even more nasty.
Since it is a singleton and Remoting is supposed to be (:P) smart enough to handle disconnect situations, the remoting object itself must be doing something to screw up it's host (i.e., IIS, Windows Service, et. al.).
Since you said you're setting up the remoting object via code, check to make sure that any unhandled exceptions don't cause your entry point to continue and exit, causing your app to quit - or worse, cause the CLR to unload (like any calls to Environment.Exit(int) ).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
I think it's fixed. I wasn't checking the validity of the server name in the client app (which was throwing an exception and generally causing problems), and since then I haven't been able to duplicate the problem, but I'm still curious as to if it's possible to check the 'status'-so to speak- of a remoting session
|
|
|
|
|
Shortly after I posted my possible problem, I got to thinking: have you ever checked after this "crash" if the service was still responding? If the host for the remoting object was hosed, it shouldn't respond. This indicates an error with the host, such as the remoting object throwing an exception that could be unhandled in the host and would effectively kill the host. If so, you shouldn't get a service response.
I'm glad it's fixed, but should ever anything like this happen again, check to see if the service itself is responding (i.e., ping the service using a non-activation client like soapsuds.exe or wsdl.exe (depending on the host)). That would most definitely be interesting to know and might help you figure out who to blame (i.e., the remote object vs. remoting infrastructure vs. the host).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
OK, it happened again when I changed some of the code, here is the relevant exception info
Error: System.Runtime.Remoting.RemotingException: Server encountered an internal error. For more information, turn on customErrors in the server's .config file
.
Server stack trace:
Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage req Msg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
It seems to me the server is throwing back the exception (HandleReturnMessage). Again a restart of the server fixes the problem (no changes in the code just restarting clears it up). The problem is the server still responds locally (i.e. other parts of it still work), just the remoting is hosed.
|
|
|
|
|
Did you try using soapsuds.exe or something to see if the object still responds at all? (Or are you already sure that it doesn't.)
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
|
I'm not sure what to think, then. Either you've uncovered a major bug in the Remoting infrastructure or (no offense meant) you've put one there. The only thing I can think of is something I've stated before. The Remoting object is throwing an exception that the host isn't gracefully handling and the host, as a result, dies.
When you say "other parts of the app" - is this all in a single executable, this "app" you mention? I could be wrong if the app still lives, but still maybe not. If the exception causes the message pump to quit or die, the app will terminate. We had this happen with a Windows Service-hosted remoting object I wrote sometime back (since fixed by existing...er, better exception handling).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Let me elaborate:
I have three projects, server, client, dll
The server is a single windows app that just exports the methods in the dll through remoting. It also creates a local instance of the dll.
The dll is just two methods that both call Shell(), with different parameters.
the client is a console app that connects to the server to access the remoted methods, and calls one or the other.
When the client can't connect without an exception being thrown, the server is still running, and the local instance still functions. I have exception handling in the dll (which is where the error says it's originating), but it doesn't catch anything.
The code is extremely simple (less than 10 lines per piece) maybe it would be easier if I sent it to you and we can continue this discussion off list.
thanks for the help, btw
|
|
|
|
|
Is it possible to define an attribute that describes a property of a class at runtime?
For example, you have a class called "employee", and it has a property "name". The "name" property has an attribute that tells any calling code whether or not this property is "writable" and/or "readable", even though this property has both get/set accessors.
Maybe there is another way to do this, and I just don't have enough experience.
Any help is appreciated.
|
|
|
|
|
For what you are trying to do, I suggest that you should try to avoid using attributes
|
|
|
|
|
Is there a way to set a property of a property, at runtime, then?
This is what I REALLY want to do, but I believe this is not possible:
<br />
<br />
<br />
[AttributeUsage(AttributeTarget.Property,Inherited=true,AllowMultiple=true)]<br />
public class SecurityInfoAttribute : Attribute<br />
{<br />
private int readable;<br />
private int writable;<br />
<br />
<br />
public SecurityInfoAttribute(int readable, int writable)<br />
{<br />
this.security_readable = 0;<br />
this.security_writable = 0;<br />
<br />
}<br />
<br />
public int Readable<br />
{<br />
get<br />
{<br />
return readable;<br />
}<br />
set<br />
{<br />
readable = value;<br />
}<br />
}<br />
<br />
public int Writable<br />
{<br />
get<br />
{<br />
return writable;<br />
}<br />
set<br />
{<br />
writable = value;<br />
}<br />
}<br />
<br />
<br />
}<br />
<br />
<br />
<br />
public class employee {<br />
<br />
string name;<br />
[SecurityInfo(getReadSecurityInfo(userId), getWriteSecurityInfo(userId))]<br />
string Name{get{return name;}set{name = value;}}<br />
<br />
<br />
<br />
} <br />
|
|
|
|
|
I have a form which has a DataGrid which I bind to an ArrayList. The grid
displays fine and I can edit the values on the grid and they get passed on
to the objects in the ArrayList itself. The problem, however, is with
handling adding and remove objects from the ArrayList. It doesn't
automatically update the DataGrid to reflect the changes to the ArrayList.
So I tried this, which kind of works :
private void btnNew_Click(object sender, System.EventArgs e)
{
myAL.Add(new myClass());
MyGrid.DataSource = null;
MyGrid.DataSource = myAL;
}
private void btnDel_Click(object sender, System.EventArgs e)
{
myAL.Remove(myAL[MyGrid.CurrentRowIndex]);
MyGrid.CurrentRowIndex = 0;
MyGrid.DataSource = null;
MyGrid.DataSource = myAL;
}
This works until you try to either: remove the bottom item on the grid
(System.ArgumentOutOfRangeException) or add an item to an empty grid
(System.IndexOutOfRangeException). Plus it just doesn't seem like the right
way to do this. Can anybody help me out here and point me in the right
direction? Everything I've found online so far covers binding a grid to a
datatable or dataview only.
|
|
|
|
|
Why not bind to a dataset instead? Not sure it is the best method but if you want to stay with ArrayList try rebinding the datagrid, should "refresh" it.
|
|
|
|
|
Actually, this is correct behavior, though not always desired.
Also, remember that the DataGrid acts no differently when binding to various data sources, like DataSet , DataTable , ArrayList , etc. If you look at the DataGrid 's DataSource property, you'll see that it takes an Object that implements either IListSource , IList , or IEnumerable . It doesn't care much about the actual type.
So, any of those examples you've seen for other types will apply to the ArrayList .
One such method would be to get the CurrencyManager from the BindingContext of the DataGrid . You can receive event notification when the list changes and update the DataGrid either manually or by reassigning the list to the DataGrid.DataSource property (ps, you don't need to set it to null first).
-----BEGIN GEEK CODE BLOCK-----
Version: 3.21
GCS/G/MU d- s: a- C++++ UL@ P++(+++) L+(--) E--- W+++ N++ o+ K? w++++ O- M(+) V? PS-- PE Y++ PGP++ t++@ 5 X+++ R+@ tv+ b(-)>b++ DI++++ D+ G e++>+++ h---* r+++ y+++
-----END GEEK CODE BLOCK-----
|
|
|
|
|
Take some standard code such as shown below. It simply loops to add up a
series of terms and it produces the correct result.
// sum numbers with a loop
public int DoSumLooping(int iterations)
{
int result = 0;
for(int i = 1;i <=iterations;i++)
{
result += i;
}
return result;
}
Now translate this into a specific solution that doesn't use looping (and
use the same value for the number of iterations the loop performs). This
code returns an incorrect result. The method consists entirely of a very
straightforward code statement, but in this case .NET adds the numbers
incorrectly.
public double ComputeSum( )
{
// Brute force sum method
// For iterations == 10000
double sum = 0+ 1+ 2+ 3+ 4+ 5+ 6+ 7+ 8+ 9+ 10+ 11+ 12+ 13+ 14+ 15+ ...
+ 9997+ 9998+ 9999+ 10000;
return sum;
}
The above method returns an incorrect result with any number of terms above
about 200. It will correctly add 1 + 2 + ... + 200, but it will NOT
correctly add 1 + 2 + ... + 1000.
I have just run across this, and I have not yet researched the possible
reasons for this behavior. It may be a known issue related to either stack
size or the length of a code line, but to my knowledge it hasn't been
discussed in any of the "popular" literature on C# and .NET. I need to write
code like this, so if anyone has already encountered this issue, please
advise me.
Here's another example that also creates problems, but of a somewhat
different nature. Take the following code and translate it into a specific,
non-looping method and try to execute it using reflection. It fails.
public double LoopToCompute()
{
double sumOfProducts = 0;
double grandTotal = 0;
for (int i = 0; i < maxRows; ++i)
{
for (int j = 0; j < maxCols; ++j)
{
sumOfProducts += coeff[j] * table[i][j];
}
a_point[i] = sumOfProducts;
grandTotal += sumOfProducts;
sumOfProducts = 0;
}
return grandTotal;
}//LoopToCompute
The above code works -- but it's equivalent code with loops unrolled (shown
below) doesn't work unless the maxRows is set very small. For small values,
the 2 methods (above and below) produce identical results. There is nothing
"wrong" with the code in that sense. It's similar to the above situation. If
the "size" of the code statement or the number of code statements is too
large, .NET fails. In this case (using reflection) it doesn't return the
incorrect result, as the first example did. In this case, reflection calls
it an invalid program and refuses to run it (but only when the value of
maxRows is above about 250). The reason for this is probably
straightforward. However, I have the need to make statements like this for
performance reasons so I need a work-around. Any suggestions are
appreciated! All comments are appreciated.
public double DoBruteForceCompute()
{
double bruteForceSum = 0;
point1=coeff1*table[0][0] +coeff2*table[0][1] +coeff3*table[0][2]
+coeff4*table[0][3] +coeff5*table[0][4] +coeff6*table[0][5]
+coeff7*table[0][6] +coeff8*table[0][7] +coeff9*table[0][8]
+coeff10*table[0][9] +coeff11*table[0][10] +coeff12*table[0][11]
+coeff13*table[0][12] +coeff14*table[0][13] +coeff15*table[0][14]
+coeff16*table[0][15] +coeff17*table[0][16] +coeff18*table[0][17]
+coeff19*table[0][18] +coeff20*table[0][19] +coeff21*table[0][20]
+coeff22*table[0][21] +coeff23*table[0][22] +coeff24*table[0][23]
+coeff25*table[0][24] +coeff26*table[0][25] +coeff27*table[0][26]
+coeff28*table[0][27] +coeff29*table[0][28] +coeff30*table[0][29]
+coeff31*table[0][30] +coeff32*table[0][31] +coeff33*table[0][32]
+coeff34*table[0][33] +coeff35*table[0][34] ;
point2=coeff1*table[1][0] +coeff2*table[1][1] +coeff3*table[1][2]
+coeff4*table[1][3] +coeff5*table[1][4] +coeff6*table[1][5]
+coeff7*table[1][6] +coeff8*table[1][7] +coeff9*table[1][8]
+coeff10*table[1][9] +coeff11*table[1][10] +coeff12*table[1][11]
+coeff13*table[1][12] +coeff14*table[1][13] +coeff15*table[1][14]
+coeff16*table[1][15] +coeff17*table[1][16] +coeff18*table[1][17]
+coeff19*table[1][18] +coeff20*table[1][19] +coeff21*table[1][20]
+coeff22*table[1][21] +coeff23*table[1][22] +coeff24*table[1][23]
+coeff25*table[1][24] +coeff26*table[1][25] +coeff27*table[1][26]
+coeff28*table[1][27] +coeff29*table[1][28] +coeff30*table[1][29]
+coeff31*table[1][30] +coeff32*table[1][31] +coeff33*table[1][32]
+coeff34*table[1][33] +coeff35*table[1][34] ;
[...]
point500=coeff1*table[499][0] +coeff2*table[499][1] +coeff3*table[499][2]
+coeff4*table[499][3] +coeff5*table[499][4] +coeff6*table[499][5]
+coeff7*table[499][6] +coeff8*table[499][7] +coeff9*table[499][8]
+coeff10*table[499][9] +coeff11*table[499][10] +coeff12*table[499][11]
+coeff13*table[499][12] +coeff14*table[499][13] +coeff15*table[499][14]
+coeff16*table[499][15] +coeff17*table[499][16] +coeff18*table[499][17]
+coeff19*table[499][18] +coeff20*table[499][19] +coeff21*table[499][20]
+coeff22*table[499][21] +coeff23*table[499][22] +coeff24*table[499][23]
+coeff25*table[499][24] +coeff26*table[499][25] +coeff27*table[499][26]
+coeff28*table[499][27] +coeff29*table[499][28] +coeff30*table[499][29]
+coeff31*table[499][30] +coeff32*table[499][31] +coeff33*table[499][32]
+coeff34*table[499][33] +coeff35*table[499][34] ;
bruteForceSum =
point1 +
point2 + ... +
point499 +
point500
;
return bruteForceSum;
}//DoBruteForceCompute
|
|
|
|
|
I'd suggest you to use ILDASM and see the generated code. This will help to isolate if the problem is on JIT or on C# compiler. Also, you could try using other .NET languages, like VB.NET.
BTW, for this kind of code, managed C++ rules. With C++ you always have much more control over the compiler.
Help me dominate the world - click this link and my army will grow
|
|
|
|
|
Interesting situation
What version of .NET are u using? Are you going over the 2048 character line limit?
The did the same thing, but with a single " + xxxx" on a single line and get the proper result (50005000 for 10000). In fact the compiler does constant folding and only loads the result.
leppie::AllocCPArticle("Zee blog"); Seen on my Campus BBS: Linux is free...coz no-one wants to pay for it.
|
|
|
|
|
I found the problem. I think you could have guessed it -- it was related to the line limit. Here's what I was doing. I was using code to generate my unrolled loop code. I was then compiling this in a process and using reflection to load the assembly and invoke the method.
I was not getting any compiler errors, nor was I getting any runtime errors. I was just getting incorrect math results.
However, when I posted the code (without the reflection part) everyone else got the correct results. This prompted me to look at the reflection/compilation code more closely. It turns out the when I pasted the generated code into the IDE I discovered the line limit you mentioned.
I inserted a new line in my generated code after every 200 terms, and presto- the math results were now correct.
It's a bit disconcerting that I didn't get a compiler error from the command line compiler. I don't know why yet. Does the command line compiler have that same line limit? I assume so, given my experience.
I guess the compiler just took as many terms as it could and somehow terminated the statement and produced a runnable program ... all very strange. I wouldn't have thought that possible.
|
|
|
|
|