I have a project using SharpShell for an Icon Handler. It peeks inside APKs in order to find and display their icon. I've got it working but there are a few side effects. If I try to rename an APK to something else, say from A.apk to B.apk, then Explorer crashes and I can't find a reason for why.
Here's the main section and the logging bits:
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using ApkDetails;
using SharpShell.Attributes;
using SharpShell.SharpIconHandler;
namespace ApkIconHandler {
[ComVisible(true)]
[COMServerAssociation(AssociationType.ClassOfExtension, ".apk")]
public class ApkHandler : SharpIconHandler {
protected override Icon GetIcon(bool smallIcon, uint iconSize) {
try {
APK apk = new APK(SelectedItemPath);
using (Bitmap icon = apk.GetIcon()) {
IntPtr icH = icon.GetHicon();
Icon ico = Icon.FromHandle(icH);
return ico;
}
} catch (Exception ex) {
File.AppendAllText(#"C:\APKError.txt", ex.Message + Environment.NewLine + ex.StackTrace);
return Icons.DefaultIcon;
}
}
protected override void LogError(string message, Exception exception = null) {
base.LogError(message, exception);
String err = message;
if (exception != null) err += Environment.NewLine + exception.StackTrace;
File.AppendAllText(#"C:\APKError.txt", err + Environment.NewLine);
}
protected override void Log(string message) {
base.Log(message);
File.AppendAllText(#"C:\APKLog.txt", message + Environment.NewLine);
}
}
}
My APK code runs aapt d badging "path.apk" and parses the output to get icon information and GetIcon opens the APK as a zip to get that file. I wrap it all in a try/catch and tied into SharpShell's LogError method but I never get any output. I disabled UAC. I don't think there's a permissions issue on writing to the root of the drive because APKLog.txt DOES show up but with no useful information.
I get the window "Windows Explorer has stopped working" and it lists this information as the "Problem signature"
Problem Event Name: CLR20r3
Problem Signature 01: explorer.exe
Problem Signature 02: 6.1.7601.17567
Problem Signature 03: 4d672ee4
Problem Signature 04: mscorlib
Problem Signature 05: 4.0.30319.18047
Problem Signature 06: 5155314f
Problem Signature 07: 326
Problem Signature 08: 5d
Problem Signature 09: System.AccessViolationException
OS Version: 6.1.7601.2.1.0.256.48
Locale ID: 1033
Additional Information 1: 59cf
Additional Information 2: 59cf5fdf81b829ceb8b613f1f092df60
Additional Information 3: 6d90
Additional Information 4: 6d903bfb0ab1d4b858654f0b33b94d7f
I see that it says System.AccessViolationException but none of my code is catching that. Can somebody offer a little insight into what's going on here?
Can I suggest making sure that you've built the server in debug mode and then running the 'server manager' tool from sharpshell. Once you've done that, enable logging from the tools menu. From this point on, any time that the sharpshell code catches an exception that may have been thrown from your code, it'll log it to the event log.
You can use LogMessage and LogError in your own SharpShell server to write messages or errors to the event log, this'll make it easier to diagnose what's going on!
Related
I have a Xilinx ZCU106 with a Petalinux build I created that includes an application using SignalR-Client-Cpp. Despite trying a number of things, I'm continually getting an "Error in SSL handshake" exception after calling start() on my signalr::hub_connection.
This application runs fine on other Linux systems like Ubuntu. I think the problem is it's having trouble finding the ca-certificates.crt file which is usually in /usr/local/ssl on more normal Linux distro's like Ubuntu. In the Petalinux build it's located here: /etc/ssl/certs/ca-certificates.crt.
The best I can tell, I need to do something like this to configure the signalr::hub_connection to use the certificate file:
web::http::client::http_client_config httpConfig;
httpConfig.set_ssl_context_callback([](boost::asio::ssl::context& ctx) {
ctx.load_verify_file("/etc/ssl/certs/ca-certificates.crt"); });
web::websockets::client::websocket_client_config wsConfig;
wsConfig.set_ssl_context_callback([](boost::asio::ssl::context& ctx) {
ctx.load_verify_file("/etc/ssl/certs/ca-certificates.crt"); });
signalr::signalr_client_config signalrConfig;
signalrConfig.set_http_client_config(httpConfig);
signalrConfig.set_websocket_client_config(wsConfig);
auto hubConn = signalr::hub_connection_builder::create(signalrURI).build();
hubConn.set_client_config(signalrConfig);
std::promise<void> task;
hubConn.start([&task](std::exception_ptr exception) {
// Code that checks the exception, etc
Yet, even when doing this, the exception that is passed into start() is populated, stating "Error in SSL handshake".
I've tried some other things like using web::credentials and setting those on the signalr_client_config before giving it to the hub_connection but I get the same results.
I'm out of ideas as to how to get this to work and I'm hoping someone else might have some ideas?
I'm implementing an UWP application for the HoloLens which streams a point cloud over a MessageWebSocket to a companion PC. If I launch the app on the HoloLens while the server on the companion PC is not yet running, calling the ConnectAsync method of MessageWebSocket triggers an exception (because it can't connect to the server) which causes my app to crash. However, I can't figure out how to catch this exception.
Inspired by the example code shown in the official documentation of MessageWebSocket, this is a small sample which reproduces the issue:
void TryConnectToWebsocket()
{
Windows::Networking::Sockets::MessageWebSocket^ websocket = ref new Windows::Networking::Sockets::MessageWebSocket();
websocket->Control->MessageType = Windows::Networking::Sockets::SocketMessageType::Utf8;
try
{
::OutputDebugString(L"Trying to connect...\n");
auto connectTask = Concurrency::create_task(websocket->ConnectAsync(ref new Windows::Foundation::Uri(L"ws://192.168.0.38:9090")));
connectTask.then([this, websocket]
{
::OutputDebugString(L"Connected successfully!");
websocket->Close(1000, "Application caused the connection to close.");
});
}
catch (...)
{
::OutputDebugString(L"Couldn't connect to websocket!");
}
}
Please note, that the original example code from the docs catches exceptions of type Platform::Exception. I chose to catch exceptions of all types in this code snippet to assert that I don't miss the exception in case it is not a Platform::Exception (or a subtype of it).
If I run this code snippet (without the server being started), I would expect the following console output:
Trying to connect...
Couldn't connect to the websocket!
However, what I get is the following: (Console outputs about loaded and unloaded DLLs have been left out. Some of the messages describing what went wrong were originally in German, so I've translated them.)
Trying to connect...
Exception thrown at 0x76B34592 (KernelBase.dll) in Test.exe: WinRT originate error - 0x80072EFD : 'A connection with the server could not be established.'.
Exception thrown at 0x76B34592 in Test.exe: Microsoft C++ exception: Platform::COMException ^ at memory location 0x0C5AE500. HRESULT:0x80072EFD The message for this error code could not be found.
WinRT information: A connection with the server could not be established.
Stack trace:
>[External Code]
As you can see, the catch block isn't being executed at all. Furthermore, the very short and unprecise stack trace makes it appear as if the exception is thrown somewhere in a background thread where I don't even have a chance of catching it.
I'd really like to handle this exception instead of having the application crash. Is there any way how I can do this?
From the official sample, it doesn't put every operation that might throw within a try…catch block. Instead, it adds a task-based continuation at the end of the chain and handles all errors there. You can try the following code to catch the exception.
create_task(messageWebSocket->ConnectAsync(ref new Windows::Foundation::Uri(L"ws://192.168.0.38:9090")))
.then([this](task<void> previousTask)
{
try
{
previousTask.get();
::OutputDebugString(L"Connected successfully!");
websocket->Close(1000, "Application caused the connection to close.");
}
catch (Exception^ ex)
{
::OutputDebugString(L"Couldn't connect to websocket!");
}
});
I recently switched from using the BlackBerry Facebook SDK jar to using the project's source code (checked out from the tag that the jar was built from).
Ever since this switch, I've experienced BrowserField problems:
On a device, the loading graphics persists until I back out.
On a simulator I see:
Error requesting content for
https://www.facebook.com/dialog/oauth?scope=user_about_me,user_activities,user_birthday,user_education_history,user_events,user_groups,user_hometown,user_interests,user_likes,user_location,user_notes,user_online_presence,user_photo_video_tags,user_photos,user_relationships,user_relationship_details,user_religion_politics,user_status,user_videos,user_website,user_work_history,email,read_friendlists,read_insights,read_mailbox,read_requests,read_stream,xmpp_login,ads_management,user_checkins,friends_about_me,friends_activities,friends_birthday,friends_education_history,friends_events,friends_groups,friends_hometown,friends_interests,friends_likes,friends_location,friends_notes,friends_online_presence,friends_photo_video_tags,friends_photos,friends_relationships,friends_relationship_details,friends_religion_politics,friends_status,friends_videos,friends_website,friends_work_history,manage_friendlists,friends_checkins,publish_stream,create_event,rsvp_event,offline_access,publish_checkins,manage_pages&redirect_uri=http://www.facebook.com/connect/login_success.html&display=wap&client_id=[APPLICATION_ID]&response_type=token
Error message null.
where APPLICATION_ID is my correct application ID.
The above URL opens fine in my PC browser, and I have debugged for a while through the Facebook sdk's source and found nothing.
It is possible that the application id might have changed recently without me knowing, and my next step is to revert back to using the .jar just for testing purposes.
Has anyone seen similar behavior with the BlackBerry SDK before?
I'm not sure if this is what happened in your case, but I've seen that error when the ProtocolController is set before the BrowserField is initialized. Like so:
private BrowserField bf;
...
BrowserFieldConfig bfc = new BrowserFieldConfig();
// bf not initialized yet but no compiler error
bfc.setProperty(BrowserFieldConfig.CONTROLLER, new ProtocolController(bf){
public void handleNavigationRequest(BrowserFieldRequest request) throws Exception {
super.handleNavigationRequest(request);
}
public InputConnection handleResourceRequest(BrowserFieldRequest request) throws Exception {
return super.handleResourceRequest(request);
}
});
bf = new BrowserField(bfc);
add(bf);
bf.requestContent("http://www.google.com");
...
Simply setting the ProtocolController after the BrowserField is initialized but before content is requested solves it.
i'm not sure that what im going to do is the right so i first of all tell you my issue.
I have TFS as Bugtracking System and another system for tracking the worktime. I want that if a workitem status changes the other system changes the status too.
What i did until now is the following.
I wrote a plugin for the TFS web service were i catch the WorkItemChangedEvent.
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs,
out int statusCode, out string
statusMessage, out ExceptionPropertyCollection properties)
{
statusCode = 0;
properties = null;
statusMessage = String.Empty;
try
{
if (notificationType == NotificationType.Notification && notificationEventArgs is WorkItemChangedEvent)
{
WorkItemChangedEvent ev = notificationEventArgs as WorkItemChangedEvent;
EventLog.WriteEntry("WorkItemChangedEventHandler", "WorkItem " + ev.WorkItemTitle + " was modified");
}
}
catch (Exception)
{
}
return EventNotificationStatus.ActionPermitted;
}
I droped the DLL in C:\Program Files\Microsoft Team Foundation Server 2010\Application Tier\Web Services\bin\Plugins
but i looks like the extension is never called. So nothing apears in the event log.
But if i try to debug the service like in this post http://geekswithblogs.net/jakob/archive/2010/10/27/devleoping-and-debugging-server-side-event-handlers-in-tfs-2010.aspx
i cant hook on the process. So debugging does not work.
Why i cant debug the service? And is there a better way to do this?
Not sure if you fixed this but to me it looks like you are missing the Subscription method in the class.
public Type[] SubscribedTypes()
{
return new Type[1] {typeof(WorkItemChangedEvent)};
}
Without this your plugin will never get hit thus you will be unable to debug.
To debug the w3wp.exe process, you need to be running Visual Studio as an administrator.
From the menu, select Debug > Attach to process (or Ctrl-Alt-P)
Select Show processes from all users and Show processes in all sessions.
Find the w3wp.exe process that corresponds to your TFS Application Pool, and attach to it.
I notice that you're using EventLog.WriteEntry() - have you registered the event source previously in your code? To avoid the registration (which requires admin permissions), you might try using the TFS logger:
TeamFoundationApplication.Log("WorkItem " + ev.WorkItemTitle + " was modified", 0, System.Diagnostics.EventLogEntryType.Information);
I have a server application which I am debugging which basically parses scripts (VBscript, Python, Jscript and SQl) for the application that requests it.
This is a very critical application which, if it crashes causes havoc for a lot of users. The problem I am facing is how to handle exceptions so that the application can continue and the users know if something is wrong in their scripts.
An example: In the SQL scripts the application normally returns a set of values (Date, Number, String and Number). So the scripts have to have a statement at the end as such:
into dtDate, Number, Number, sString. These are values that are built into the application and the server application knows how to interpret these. These fields are treated in the server app as part of an array. The return values should normally be in a specific order as the indexes for these fields into the array are hardcoded inside the server application.
Now when a user writing a script forgets one of these fields, then the last field (normally string) throws an IndexOutofBoundsException.
The question is how does one recover from exceptions of this nature without taking down the application?
Another example is an error in a script for which no error parsing message can be generated. These errors just disappear in the background in the application and eventually cause the server app to crash. The scripts on which it fails don't necessarily fail to execute entirely, but part of it doesn't execute and the other parts do, which makes it look fairly odd to a user.
This server app is a native C++ application and uses COM technologies.
I was wondering if anyone has any ideas on what the best way is to handle exceptions such as the ones described above without crashing the application??
You can't handle problems like this with exceptions. You could have a top-level catch block that catches the exception and hope that not too much state of the program got irrecoverably munched to try to keep the program alive. Still doesn't make the user happy, that query she is waiting for still doesn't run.
Ensuring that changes don't destabilize a critical business app requires organization. People that sign-off on the changes and verify that they work as intended before it is allowed into production. QA.
since you talk about parsing different languages, you probably have something like
class IParser //parser interface
{
virtual bool Parse( File& fileToParse, String& errMessage ) = 0;
};
class VBParser : public Parser
class SQLParser : public Parser
Suppose the Parse() method throws an exception that is not handled, your entire app crashes. Here's a simplified example how this could be fixed at the application level:
//somewhere main server code
void ParseFileForClient( File& fileToParse )
{
try
{
String err;
if( !currentParser->Parse( fileToParse, err ) )
ReportErrorToUser( err );
else
//process parser result
}
catch( std::exception& e )
{
ReportErrorToUser( FormatExceptionMessage( err ) );
}
catch( ... )
{
ReportErrorToUser( "parser X threw unknown exception; parsing aborted" );
}
}
If you know an operation can throw an exception, then you need to add exception handling to this area.
Basically, you need to write the code in an exception safe manner which usually uses the following guidelines
Work on temporary values that can throw exceptions
Commit the changes using the temp values after (usually this will not throw an exception)
If an exception is thrown while working on the temp values, nothing gets corrupted and in the exception handling you can manage the situation and recover.
http://www.gotw.ca/gotw/056.htm
http://www.gotw.ca/gotw/082.htm
It really depends on how long it takes to start up your server application. It may be safer to let the application crash and then reload it. Or taking a cue from Chrome browser run different parts of your application in different processes that can crash. If you can safely recover an exception and trust that your application state is ok then fine do it. However catching std::exception and continuing can be risky.
There are simple to complex ways to baby sit processes to make sure if they crash they can be restarted. A couple of tools I use.
bluepill http://asemanfar.com/Bluepill:-a-new-process-monitoring-tool
pacemaker http://www.clusterlabs.org/
For simple exceptions that can happen inside your program due to user errors,
simply save the state that can be changed, and restore it like this:
SaveStateThatCanBeAlteredByScript();
try {
LoadScript();
} catch(std::exception& e){
RestoreSavedState();
ReportErrorToUser(e);
}
FreeSavedState();
If you want to prevent external code from crashing (possible untrustable code like plugins), you need an IPC scheme. On Windows, I think you can memory map files with OpenFile(). On POSIX-systems you can use sem_open() together with mmap().
If you have a server. You basically have a main loop that waits for a signal to start up a job. The signal could be nothing and your server just goes through a list of files on the file system or it could be more like a web server where it waits for a connection and executes the script provided on the connection (or any thing like that).
MainLoop()
{
while(job = jobList.getJob())
{
job.execute();
}
}
To stop the server from crashing because of the scripts you need to encapsulate the external jobs in a protected region.
MainLoop()
{
// Don't bother to catch exceptions from here.
// This probably means you have a programming error in the server.
while(job = jobList.getJob())
{
// Catch exception from job.execute()
// as these exceptions are generally caused by the script.
try
{
job.execute();
}
catch(MyServerException const& e)
{
// Something went wrong with the server not the script.
// You need to stop. So let the exception propagate.
throw;
}
catch(std::exception const& e)
{
log(job, e.what());
}
catch(...)
{
log(job, "Unknown exception!");
}
}
}
If the server is critical to your operation then just detecting the problem and logging it is not always enough. A badly written server will crash so you want to automate the recovery. So you should write some form of heartbeat processes that checks at regular intervals if the processes has crashed and if it has automatically restart it.