File.WriteAllText() runs OK, or does it? - c#

I've been starting at this code for the best part of 2 hours (literally) but I can not seem to grasp why this would fail. This method below does not report any exceptions, yet it seems to return false:
public bool SaveFile(string filename, object source)
{
bool result = true;
StringBuilder exportText = new StringBuilder(source.ToString());
try {
File.WriteAllText(filename, exportText.ToString());
}
catch (Exception e)
{
OnPluginError(new ErrorEventArgs(e));
result = false;
}
return result;
}
The problem is: the file is properly written at the requested path, is complete, and readable. No exceptions are thrown, because the OnPluginError() handler invocation method isn't called - any message would be logged in that case, but there is nothing logged. It can't be a permission problem because the file does exist after the call.
And still, the method result is false.
The problem only appears in a Release build. In Debug builds, all seems to work OK. Hence, I can't use the debugger to step through.
This is called from a web application. Any ideas appreciated.

As a temporary troubleshooting step, add another try catch to block any exceptions and then see if the function is still returning false.
public bool SaveFile(string filename, object source)
{
bool result = true;
StringBuilder exportText = new StringBuilder(source.ToString());
try {
try {
File.WriteAllText(filename, exportText.ToString());
} catch(Exception e) { }
}
catch (Exception e)
{
OnPluginError(new ErrorEventArgs(e));
result = false;
}
return result;
}
If it is returning true, then you have isolated the problem and determined that an exception is being thrown, causing the block with result = false to be run.
If it is still returning false, then you can be certain the problem is outside of this function, as the rules of control flow would dictate that the result variable would never be changed.
One possibility is you have an issue with either the code you think is being run is not really being run. For example some issue with the build process not picking up your most recent code changes or redirection. Checking the versions of the website project DLLs, doing clean/rebuild, adding additoinal code to write out trace messages, are all things you should try to cross check to verify your most recent code is being run.
Another possibility is a problem in the code that is checking the return value.

Well...I do feel a bit silly here. I finally found the problem, and it is (as some posters questioned) not related to the WriteAllText() method at all.
FYI: this code ran deep inside an extensive plugin library. Not all that code was designed and written by me, and has been around for almost 2 years without running into problems.
As I mentioned, the WriteAllText() ran fine. It did. Problem was that the location of the file saved, was stored in a Dictionary, which in turn was requested from the plugin currently running. That Dictionary (containing plugin settings) turned out to be created from scratch with each call to that property! So I could add to it as much as I wanted....at the next call to that property, the newly added items would 'disappear' magically since the Dictionary was created anew.
Since it never surfaced before, and that code ran in a lot of other plugins with no problems, I didn't check that property. My bad.
Apologies to everyone that responded for wasting their time. Rest assured it won't happen any time soon! Lesson learned...

Related

Script task failed without going inside Try & Catch block

Here is the brief explanation for my script task in SSIS.
Read/Write variable LOGERROR, and it does exist in the Variables panel with string type.
Inside the script, C# code:
try
{
... //what here does is to iterate a folder and move all of them to another folder, codes here are working correctly
Dts.TaskResult = (int)ScriptResults.Success;
}
catch(Exception e)
{
Variables lockedVariables = null;
Dts.VariableDispenser.LockOneForWrite("User::LOGERROR", ref lockedVariables);
lockedVariables["User::LOGERROR"].Value = e.ToString();
lockedVariables.Unlock();
Dts.TaskResult = (int)ScriptResults.Failure;
}
The reason that I manually control the writes of the variable is that the same variable LOGERROR was added to the Event Handler for the same purpose of Point 4.
I direct the Failure to another Execute SQL task, which is trying to insert LOGERROR (Should contain the exception details) into an underlying table.
My questions:
Sometimes the SSISPackage failed at above task (not always, but at almost the same time every day, may have conflicts with the other jobs?) for not any apparent reasons (at least for now). That's why I would like to track what exactly the issue is, but if I query the target logging table. The details does not show anything, just empty.
And, I have a general logging task in Event Handler that logged all the message when task ran with errors. And that message shows nothing but Exception has been thrown by the target of an invocation.
Did I miss something when trying to log LOGERROR? Because it seems for me that the script did not go into the Try & Catch, just failed directly, otherwise it should store the Exception details. (Please correct me if I am wrong). Or, how could I track the error details?
After some investigations, I think the issue was caused by SQL Server Agent failed to access the shared folder during certain time frame.
Possible solution to my questions:
https://social.technet.microsoft.com/Forums/azure/en-US/988207fe-5a25-4da7-a8df-a38fada703da/ssis-script-task-exception-has-been-thrown-by-target-of-invocation?forum=sqlintegrationservices

throw new Exception in a test

While browsing the code of my application I faced this:
private string[] ReadFromFile(string path)
{
string[] data = null;
try
{
data = File.ReadAllLines(path);
}
catch (Exception)
{
throw new Exception("The file is not correct");
}
return data;
}
Ok so I know this code is not good and I was about to refactor this. However, this code is used in the definition of some tests for FitNesse. This code is never used in production. The parameter given in this method is supposed to be always correct. So I feel like removing the whole try/catch block and let it crash if it should. FitNesse would give us the whole details about the exception thrown, but since it's a test fixture I'm wondering if it may be ok.
File.ReadAllLines can throw a dozen of different exceptions.
So my question: Is it acceptable to have such kind of code, outside production, even if used to test production code, and in a environment under control? Or is it bad under any circumstances?
It is even worse to have such code in unit tests than having it in production code. In production code sometimes it might make a sense to hide some exception details (though they still should be delivered via InnerException for example) but in unit tests you should always see as much as possible because they are done for you (developer, not end user). So I think this entire try/catch block should be removed.
Also if in some other case you would like to fail test then I would recommend using Assert.Fail("message") construction since it makes it more clear then tests should be treated as failed if it reached this point. Not sure whether it can be applied to FitNesse though.
I would catch it, and then throw a streamlined exception that will leverage the functionality of FitNesse
private string[] ReadFromFile(string path)
{
string[] data = null;
try
{
data = File.ReadAllLines(path);
}
catch (Exception)
{
throw new Exception("message:<<Problem reading in file: " +e.getMessage() + ">>");
}
return data;
}
If you do this, the error message will appear in context and be easier to identify. Unfortunately, an unwrapped exception will appear in a exception block separate from the fixture that had the problem. The e.printStackTrace() will give you information on the output page that can give you more details.
I agree with others that in unit test code you want the exception to occur in context of the code. However your audience is different when in a unit test. The people working with it should always be developers. In the case of FitNesse tests, you are working with BAs and Testers, who may benefit from a little extra diagnostics.
The code I added is Java, and I know this is a c# test, but the spirit is the same and the "message:<< exception" should work the same in FitSharp for slim. I work in Java and ruby, so my c# is really weak.
If you catch exception you should do something with it, write logs e.g. If you only throw your own exception you lose stack trace of a last exception.

Web Service Reconnecting pattern

I'm developing a .Net Webform application, with heavy use of web services to communicate with an outside-server database.
So, I'm trying to find the best way to deal with disconnections and failures when calling a WS method.
For now, I've made a proxy function -kind of a layer- for every WS method I call, that repeats the specific WS call in a loop until it cames out successfully.
For Both Sync and Async calls, I've solved my problem, but I added an annoying extra layer to my WebService layer, with extra maintenance, and a lot of redundant code.
I refuse to believe there's not an existing solution for this standard situation, but can't find it anywhere.
Any Ideas?
Following, an example of my extra layer (Sync):
public static int WsMethod(string param1, int param2)
{
while(true)
{
try
{
return new Webpoint().WsMethod(param1, param2);
}
catch (Exception)
{
Thread.Sleep(new TimeSpan(0, 0, sleep_seconds));
}
}
}
And Async:
public static void WsMethodAsync(string param1, int param2, WsMethodCompletedEventHandler handler)
{
while (true)
{
try
{
var server = new Webpoint();
server.WsMethodAsyncCompleted += delegate(object sender, WsMethodAsyncCompletedEventArgs args)
{
if (args.Error != null)
{
Thread.Sleep(new TimeSpan(0, 0, sleep_seconds));
this.WsMethodAsync(param1, param2, handler);
}
else
{
handler(sender, args);
}
};
server.WsMethodAsyncAsync(param1, param2);
return;
}
catch (Exception)
{
Thread.Sleep(new TimeSpan(0, 0, sleep_seconds));
}
}
}
I would not recommend this pattern. If there is some problem with the parameters on your call this will run forever.
Normaly I would catch the few expected exceptions (CommunicationException, SocketException, whatever you need) and return some status-code for this (Ok, or NoNetwork, or whatever).
Or wrap up all expected exceptions into a MyCommunicationException and throw this (to hide implementation details from the caller and make exception-handling easier for it)
But give the control back to the caller and let the caller decide how to go on. Don't catch the other unexpected exceptions or rethrow them.
The caller can then decide to try time and again or 3-times or whatever.
If something were genuinely wrong with the service, or the connection thereto, or the request being made, then this would repeat indefinitely without ever telling you what's wrong.
What are the implications of the service call failing? How often does it really fail? And, most importantly, for what reason does it fail? If the reason is something that can be fixed, it should be fixed. Not worked around.
As a simple example, if this back-end service call is something initiated by a user of the website (say, they're trying to fetch some data to edit) then if the call fails you just present an error to the user. Something like:
"I'm sorry, but that data is not available at this time. The support team has been notified of this problem. Please try your request again. If the problem persists, contact the help desk at 800-555-1234."
Now, this shouldn't just be a single generic error to show the user no matter what happens. The code needs to be robust enough to discern one kind of error from another. If the service is unreachable, this error applies. If the service is saying that the request is invalid, then there's something wrong either with that the user is doing or what your code is doing, and that needs to be fixed. Etc.
How you deal with the errors and maintain a usable application is ultimately up to you and the business overall. But I honestly can't recommend the approach you outline on the question. That approach doesn't solve anything, it just ignores the problem until it gets worse. You need to determine the root cause of the errors and address that, not ignore them.
Also, any time an error is suppressed/ignored, a kitten dies.

Exception not being caught

I have a very simple application, we feed it a list of our websites, and it does a parallel foreach on them and inside each action it does an http post to it.
Similar to below:
static int success = 0
static void Main(string[] args) {
try {
Parallel.ForEach(sites, site=> {
try{
if(DoWebPost(site)) {
Console.Write("Posted {0} - {1}", ++success, site);
}
} catch {}
});
} catch {}
}
I can't figure out why it will throw an OutOfMemoryException, let alone why that will cause the entire application to crash, and not just catch and continue.
EDIT: Not exactly sure where the exception occurs, since it doesn't locally, only when running in production... meaning no debugging available. The Application is 64bits, and rarely uses more than 100 megs.
In the words of Marc Gravell
If you "fix" your code by handling this exception you are burying your head in the sand.
You mentioned the code that is posted is somewhat the same as the code you used.
Can you actually post the full code or the exact code that is causing this.
Something tells me you have some sort of memory leak, you need to address this first.

Can't add Schedule task in Win XP, limited user

I've built a program in C# Windows Forms, now on the first load up it tries to create scheduled tasks. If it raises an exception and it's in main computer then this is the first time the softwere loads (you can intall this program on many computers but one computer is the main with the scheduled tasks).
I've tried this program on many computers and it worked perfectly (XP-SP1/2, Vista-SP1/2, Win7), now when I try to install it on a limited user (on Win XP Pro SP2) it tries to create the scheduled tasks. I get an Argument Null Reference and when I enter the admin user, it installs the scheduled task on the admin user and won't run if the limited user is logged in (which is 99.9% of the time) .Why do I get this exception? I've looked for hours on the code searching for the reason of this exception but I can't find it!
Thanks a lot!
Amit
MainOrSec = true;
User and Pass are public variables whice return from FirstTimeUp.
private bool CreateNoExit()
{
try
{
RegistryKey key = Registry.CurrentUser;
key = key.OpenSubKey("Crm");
MainOrSec = Convert.ToBoolean(AESIMP.Decrypt((string)key.GetValue(AESIMP.Encrypt("MorS"))));
}
catch (ArgumentNullException)
{
MainOrSec = true;
}
if (MainOrSec)
{
ScheduledTasks sc = new ScheduledTasks();
Task task;
try
{
task = sc.CreateTask("NoExit");
FirstTimeUp f = new FirstTimeUp(this);
f.ShowDialog();
}
catch (ArgumentException)
{
return false;
}
if (!CreatT)
return false;
task.ApplicationName = #"C:\Program Files\Triffon\Crm Setup
2.0.0002\noexit.exe";
task.Comment = "Check For no exit on the database.";
task.SetAccountInformation(User, Pass);
task.IdleWaitMinutes = 10;
task.Triggers.Add(new DailyTrigger(5, 0));
try
{
task.Save();
task.Close();
sc.Dispose();
}
catch (COMException ex)
{
MessageBox.Show(ex.Message);
return false;
}
return true;
}
return false;
}
OK, so if you get an exception, the best thing to do is to run your program under Visual Studio's debugger so you can see exactly where the exception is called. Here, Ctrl-Alt-E is your friend: turn on the checkbox in the "Thrown" column next to "Common Language Runtime Exceptions" and you'll break to the debugger no matter what.
If you are testing your application on a user's computer without Visual Studio then you have some other options. One (if you're using Pro and above) is to run the Remote Debugger on the remote PC. Then you can attach to the running program and see the exception.
If you don't have Pro, or can't easily use the remote debugger, then it is definitely worth using a decent logging framework like log4net to make sure that all exceptions are caught, trapped, and written to a log file. Frankly no production application should be released until this is done.
When you've done this, take a careful look at the exception trace to see where the problem is caused. I'd be willing to bet that that ScheduledTasks class is throwing an exception somewhere that you're not expecting.
Finally, you'll be getting downvotes because the culture here is "we'll help if you let us know everything we need to know to help." There's been a couple of requests in the comments for the full stack trace, which hasn't appeared, so people here will consider that rude, I'm afraid.
It's hard to figure this out without a stack trace, but there is a suspicious line of code.
According to MSDN RegistryKey.GetValue() returns:
The value associated with name, or a
null reference (Nothing in Visual
Basic) if name is not found.
Here you pass the result of that function directly to another function:
MainOrSec = Convert.ToBoolean(AESIMP.Decrypt((string)key.GetValue(AESIMP.Encrypt("MorS"))));
Try to call it in a few steps instead, checking for null where needed:
string s = key.GetValue(AESIMP.Encrypt("MorS")) as string;
if(!string.IsNullOrEmpty(s))
MainOrSec = Convert.ToBoolean(AESIMP.Decrypt(s));
else
MainOrSec = true;

Categories