I've inherited a hoary old piece of code (by hoary, I mean warty with lots of undocumented bug fixes than WTF-y) and there's one part that's giving me a bit of trouble. Here's how it connects to the remote registry to get the add/remove programs key:
try
{
remoteKey = RegistryKey.OpenRemoteBaseKey(
RegistryHive.LocalMachine, addr.Value).OpenSubKey(
"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall");
return 1;
}
catch (IOException e)
{
IOException myexception = e;
//Console.WriteLine("{0}: {1}: {2}",
// e.GetType().Name, e.Message, addr.Value);
return 2;
}
catch (UnauthorizedAccessException e)
{
UnauthorizedAccessException myexception = e;
//Console.WriteLine("{0}: {1}: {2}",
// e.GetType().Name, e.Message, addr.Value);
return 3;
}
catch (System.Security.SecurityException e)
{
System.Security.SecurityException myexception = e;
//Console.WriteLine("{0}: {1}: {2}",
// e.GetType().Name, e.Message, addr.Value);
return 4;
}
Now, I have two problems:
I know why the IOException - if it's a non-Windows machine it'll throw that. The difference between UnauthorizedAccessException and SecurityException I'm not so clear on. Anyone got any ideas?
This entire bit of code was designed before anyone had thought you might not use your local logon for everything. I can't work out how you do authentication for remotely connecting to the registry, anyway, and this code looks like it's only used in one case, when it can't get this information from WMI.
Any help with either would be great.
You probably have to use impersonation to change the credentials of the thread that calls the remote registry methods. See here (linky) for some information on MSDN. Basically, your thread has a security context that is used to make managed and unmanaged calls.
According to MSDN, UnauthorizedAccessException is not thrown by OpenSubKey. So I think it's not needed.
John's pointer to MSDN answered what UnauthorizedAccessException is for - it only appears when you try to access a key remotely, using OpenRemoteBaseKey.
We're a little wary about changing the security context on the computer - I've found a reference here about using WMI (which we're already using for the vast majority of the heavy lifting) to access the registry, so I might try that instead.
Related
I am creating a server for a game that deals with lots of TCP connections, and I need to deal with a sudden loss of connection (pc crash, game process killed, internet connection lost, ectect). The problem I currently have is that I can't tell apart a read error from a write error since both throw an IOException. even the underlying exception is the same (SocketException), the only difference being that one occurs on Socket.Send() and the other on Socket.Receive() respectively. I could of course compare the exception message, but that would become a problem as soon as the system language changes (and lets be honest, that would be a pretty messy approach anyway).
I tried comparing the Hresult but since the underlying exception is the same, so is the Hresult. I also tried getHashCode() but this one changes from player to player.
Any other ways I could tell apart those 2 situations?
To clarify, we're talking about the exception that comes up when using TcpClient.read() or TcpClient.write() on a TcpClient whose connection has been unexpectedly closed.
You could try wrapping the send and receive functions in a try-catch block, and use the Data property to tell exceptions from read and write apart:
enum ReadOrWrite { Read, Write }
void Foo()
{
try
{
socket.Receive();
}
catch (IOException ex)
{
ex.Data.Add("readOrWrite", ReadOrWrite.Read);
throw;
}
}
And this is where you later catch it:
try
{
Foo();
}
catch (IOException ex) when (ex.Data.Contains("readOrWrite"))
{
var readOrWrite = ex.Data["readOrWrite"];
}
I have a confusing problem and I could not any way to workaround it. I have a couple of lines of codes, and at some point, the Send function throws a System.Net.Sockets.SocketException. However, even though try has the catch block, it does not catches the exception and continue with normal flow. When I try to run the case where it needs to throw same exception, catch captures it pretty well.
Things I have tried:
Trying to change VS debugging settings 'Enable Only For My Code', but
it is already disabled.
I tried to both Debug and Release modes.
I tried using general Exception catcher, but none of them worked.
Here is the code, at some point, the connection from the server closes and the c Socket disconnects. It returns the System.Net.Sockets.SocketException, but below catch does not capture it.
try
{
// Some code here . . .
c.Send(clientData);
Print("Started uploading the file " + uploadFilename + ".");
upBox.Text = "";
Print("Finished uploading the file " + uploadFilename + ".");
}
catch (System.Net.Sockets.SocketException)
{
Print("You are disconnected from server!");
}
The reason you're not getting an exception ...
... is that no exception has occurred!
TCP/IP itself won't necessarily "notice" a disconnect ... unless you explicitly try to write to a closed socket.
Definitely check out Beej's Guide to Network Programming:
http://www.beej.us/guide/bgnet/.
See also:
http://stefan.buettcher.org/cs/conn_closed.html,
How to detect a TCP socket disconnection (with C Berkeley socket)
The following C# code fails at line "File.WriteAllText("test_a.cmd", "timeout 15")" sometimes, anyone who knows why and how to solve it? Thanks.
for (int i = 0; i < 100; i++)
{
File.WriteAllText("test_a.cmd", "rem timeout 1");
var p = Process.Start("test_a.cmd");
p.WaitForExit();
p.Dispose();
p = null;
//GC.Collect();
//GC.WaitForPendingFinalizers();
File.Delete("test_a.cmd");
// Somtetimes it causes System.UnauthorizedAccessException: Access to the path 'XXX\test_a.cmd' is denied.
File.WriteAllText("test_a.cmd", "timeout 15");
}
There's another process that has the file opened with delete sharing. Which allows your File.Delete() call to succeed. But not the subsequent File.WriteAllText(). Because the file still exists after you deleted it. It will not disappear until the other process has closed its handle on the file. Any attempt to overwrite the file while it is still in limbo like this will fail with an "access denied" error.
Such are the vagaries of running a program on a multi-tasking operating system where other processes may be interested in the files that you manipulate. There's always a good candidate for such a process on most any Windows install, disable your anti-virus program to see if that solves the problem.
Beyond just sleeping for a while and trying again, there's a decent way to minimize the lossage. You can rename the file, much lower odds that you'll be hit with this exception:
File.Delete("test_a.cmd.bak");
File.Move("test_a.cmd", "test_a.cmd.bak");
for (int attempt = 0; ; ++attempt) {
try {
File.WriteAllText("test_a.cmd", "timeout 15");
break;
}
catch (System.UnauthorizedAccessException ex) {
if (attempt > 10) throw;
System.Threading.Thread.Sleep(1000);
}
}
try {
File.Delete("test_a.cmd.bak");
}
catch (Exception ex) {}
Since File.WriteAllText() creates/overwrites a file, the call to Delete is not needed. In fact, that is what, probably, causes your issue.
So, my solution is to:
Remote File.Delete
Add Thread.Sleep(100) before last WriteAllText
The sleep part is to allow Windows to do processing and that is what basically causes your exception.
I'm constantly getting the following exception which is caused by a user initiating a download and it consequently failing (or being cancelled):
Error Message : The remote host closed
the connection. The error code is
0x80072746. Stack Trace : at
System.Web.Hosting.ISAPIWorkerRequestInProcForIIS6.FlushCore(Byte[]
status, Byte[] header, Int32
keepConnected, Int32 totalBodySize,
Int32 numBodyFragments, IntPtr[]
bodyFragments, Int32[]
bodyFragmentLengths, Int32
doneWithSession, Int32 finalStatus,
Boolean& async) at
System.Web.Hosting.ISAPIWorkerRequest.FlushCachedResponse(Boolean
isFinal) at
System.Web.Hosting.ISAPIWorkerRequest.FlushResponse(Boolean
finalFlush) at
I've searched all over the internet, and found an interesting article, however there doesn't seem to be a definitive answer as the best way to prevent this filling up the logs.
The user sees no error and there's no actual problem in the app as it occurs only (to my understanding) in situations out of its control (user cancelling download or loss of connection) but there has to be a way to prevent such an exception being reported.
I hate to say it but I'm tempted to check for this exception and empty catch block its ass away - but this makes me feel like a dirty programmer.
So - what is the accepted method of preventing this exception filling up my mailbox?
The error occurs when you try to send a response to the client but they have disconnected. You can verify this by setting a breakpoint on the Response.Redirect or wherever you are sending data to the client, wait for Visual Studio to hit the breakpoint, then cancel the request in IE (using the x in the location bar). This should cause the error to occur.
To capture the error you can use the following:
try
{
Response.Redirect("~/SomePage.aspx");
Response.End();
}
catch (System.Threading.ThreadAbortException)
{
// Do nothing. This will happen normally after the redirect.
}
catch (System.Web.HttpException ex)
{
if (ex.ErrorCode == unchecked((int)0x80070057)) //Error Code = -2147024809
{
// Do nothing. This will happen if browser closes connection.
}
else
{
throw ex;
}
}
Or in C# 6 you can use Exception filters to prevent having to re throw the error:
try
{
Response.Redirect("~/SomePage.aspx");
Response.End();
}
catch (System.Threading.ThreadAbortException)
{
// Do nothing. This will happen normally after the redirect.
}
catch (System.Web.HttpException ex) when (ex.ErrorCode == unchecked((int)0x80070057))
{
// Do nothing. This will happen if browser closes connection.
}
Which is a better debugging experience since it will stop on the statement throwing the exception with the current state and all local variables preserved instead of on the throw inside the catch block.
You cannot prevent a remote Host to close anything.
And in some protocols this is the normal (or at least accepted) way to say goodbye.
So you will have to handle this specific exception.
From a practical perspective, there is nothing wrong with cancelling a download by virtue of a dead computer or a killed web session, therefore catching remote host closed exceptions is perfectly acceptable.
I'm working on two apps that connect to eachother using TCP. At one point, one of them is trying to connect using a TcpClient, but the other app is not guaranteed to have started listening yet (using TcpListener).
My first attempt was this:
TcpClient c = null;
while (true)
{
try
{
c = new TcpClient();
c.NoDelay = true;
c.Connect( ip, port );
break;
}
catch (SocketException ex)
{
Console.WriteLine(string.Format("Could not connect to {0}:{1}, retrying...", ip, port));
Thread.Sleep( 500 );
}
}
However, the problem with this is that it relies on exception handling which is a bit of a nuisance for me, because I have VS set up to catch any thrown exceptions ("Debug -> Exceptions..." menu). So every time it tries to connect, it breaks into VS and I have to press continue.
The exception I get is:
No connection could be made because the target machine actively refused it 127.0.0.1:50000
I would imagine that there would be a way to check if a server is listening on a specific port without actually trying to connect to it. I understand that just checking wouldn't be enough anyway - the server could go down between the check and the connect attempt, but it would still be much better for me while I'm developing it.
Or something like this:
TcpClient tcpClient = new TcpClient();
while ( !tcpClient.TryConnect(....) )
{ Thread.Sleep(1000); }
Analogous to this:
if (bool.TryParse( "false" ))
{ ... }
I also tried using async methods (Begin/End Connect) and setting the timeout for the ManualResetEvent manually, but that didn't work either. I've scoured the internets but I haven't been able to find a solution to this problem, which is why I'm finally posting here :)
The problem being that VS is breaking on the Exception? You you can always have VS ignore a specific family of Exceptions.
In VS, in the Debug Menu, choose "Exceptions..." and in the dialog presented you can control this.
I was going to suggest not catching an exception, so before I suggested that I test it myself, and if you set it to throw all exceptions even if you don't throw an exception its all exceptions are still being thrown. I will have to agree with Shiv Kumar, either adjust your settings while you debug your application, or accept the limitations of what you are doing.
The reason bool.TryParse works is it verifys each and every character, similarly to how Int32.TryParse makes sure that each character in the string is 0-9 or any other valid numerical symbol.
You could of course write your own networking class and not throw an exception when the connection fails.
TryParse will not throw an exception, you must catch any exception that is thrown if you use bool.Parse by try{}catch{} otherwise if you attempt to parse something that is not a boolean value it will throw an unhandled exception. TryParse was added later in the history of .NET, Parse is more of the classic method, allowing the programmer to handle all unexpected input and to validate input before trying to parse the data.
I should add that TryParse will return false if its unable to parse the value at both the method's result is false and the out variable I do believe is false.This is at least the case with Int32
http://msdn.microsoft.com/en-us/library/system.boolean.tryparse.aspx
I guess the point of pointing out how TryParse and Parse works is that they are entirely different beasts compare to TcpClient. I suppose I should clarify that the basic validation process is similar, except one throws an exception and the other one doesn't and of course one returns what was actually parsed.